source: pmb4.2/trunk/fuentes/pmb/classes/map/map_holds_reducer.class.php @ 815

Last change on this file since 815 was 815, checked in by jrpelegrina, 4 years ago

Initial release of pmb 4.2

  • Property svn:executable set to *
File size: 7.8 KB
Line 
1<?php 
2// +-------------------------------------------------+
3// © 2002-2014 PMB Services / www.sigb.net pmb@sigb.net et contributeurs (voir www.sigb.net)
4// +-------------------------------------------------+
5// $Id: map_holds_reducer.class.php,v 1.12 2015-04-17 12:49:17 vtouchard Exp $
6
7if (stristr($_SERVER['REQUEST_URI'], ".class.php")) die("no access");
8
9
10require_once($class_path."/map/map_hold_point.class.php");
11
12class map_holds_reducer {
13       
14
15        /**
16         * Emprise de la carte
17         * @var map_hold_polygon
18         * @access protected
19         */
20        protected $map_hold;
21       
22        /**
23         * Emprises des éléments à afficher sur la carte
24         *
25         * @access protected
26         */
27        protected $holds;
28       
29        /**
30         * Box des emprises des éléments à afficher sur la carte
31         *
32         * @access protected
33         */
34        protected $holds_box;   
35       
36        protected $map_area;
37       
38        protected $clusters;
39       
40        protected $map_distance;
41       
42        protected $displayed_holds;
43       
44        protected $clustered_holds;
45        /**
46         * Constructeur
47         *  @param map_hold_polygon map_hold Emprise courante de la carte
48         *  @param Array() ids Liste des identifiants des objets
49         *  @param int hold_max Nombre maximum d'emprise présentes sur une couche de la carte
50       
51         * @return void
52         */
53       
54        function __construct($map_hold,$holds) {
55                $this->map_hold = $map_hold;
56                $this->holds = $holds;
57                $this->clusters = array();
58                $this->init();
59                $this->map_hold->get_coords();
60        }
61       
62       
63        public function init(){
64                global $dbh, $pmb_map_hold_distance;
65                $coords = $this->map_hold->get_coords();
66               
67                $query = "select Area(geomfromtext('".$this->map_hold->get_wkt()."')) as area";
68                $result = pmb_mysql_query($query, $dbh);
69                if(pmb_mysql_num_rows($result)){
70                        $row = pmb_mysql_fetch_object($result);
71                        $this->map_area = $row->area;
72                }
73                $map_coords = $this->map_hold->get_coords();
74                /**
75                 * La fonction SQL enveloppe renvoi une emprise normalisée telle que: POLYGON((MINX MINY, MAXX MINY, MAXX MAXY, MINX MAXY, MINX MINY))
76                 * La distance mini se trouve donc entre les points 0 et 3 (le point 4 étant le point de fermeture du polygone)
77                 */
78                $this->map_distance = (sqrt(pow(($map_coords[0]->get_decimal_long() - $map_coords[3]->get_decimal_long()),2) + pow(($map_coords[0]->get_decimal_lat() - $map_coords[3]->get_decimal_lat()),2)))/$pmb_map_hold_distance;
79        }
80       
81        /**
82         * Retourne les emprises correspondantes à la réduction
83         *  @param int hold_max Nombre maximum d'emprise présentes sur une couche de la carte
84       
85         * @return void
86         */
87        public function get_reduction(){
88               
89                global $pmb_map_hold_ratio_max, $pmb_map_hold_ratio_min;
90//              $high_val = $pmb_map_hold_ratio_max;
91//              $low_val = $pmb_map_hold_ratio_min;
92
93               
94                $this->dicho($pmb_map_hold_ratio_min, $pmb_map_hold_ratio_max);
95               
96                foreach($this->clustered_holds as $key => $hold){
97                        $clustered = false;
98                        if(!count($this->clusters)){
99                                $this->clusters[$key] = $hold;
100                        }else{
101                                foreach($this->clusters as $keyC => $holdC){
102                                        if($this->shouldCluster($holdC, $hold)){
103                                                if(is_array($holdC->get_num_object())){
104                                                        $num_obj = $holdC->get_num_object();
105                                                        if(!in_array($hold->get_num_object(), $num_obj)){
106                                                                $num_obj[] = $hold->get_num_object();
107                                                                $holdC->set_num_object($num_obj);
108                                                        }
109                                                }else{
110                                                        if($holdC->get_num_object() != $hold->get_num_object()){
111                                                                $holdC->set_num_object(array($holdC->get_num_object(), $hold->get_num_object()));
112                                                        }
113                                                }
114                                                $clustered = true;
115                                                break;
116                                        }
117                                }
118                                if(!$clustered){
119                                        $this->clusters[$key] = $hold;
120                                }
121                        }
122                }
123                //
124                foreach($this->clusters as $key => $hold){
125                        $wkt = $hold->get_center();
126                        $this->clusters[$key] = new map_hold_point("point", $hold->get_num_object());
127                        $this->clusters[$key]->set_wkt($wkt);
128                }
129               
130                //
131                        //var_dump(count($displayed_holds));
132                uasort($this->displayed_holds, array('self', 'cmp_area'));
133                return array_merge($this->displayed_holds,$this->clusters);
134                //return $this->displayed_holds;
135        } 
136       
137        public function get_occupation_percentage($hold){
138                        return ($hold->get_normalized_bbox_area()/$this->map_area)*100;
139        }
140       
141        public function get_point_center($hold){
142                global $dbh;
143                $query = "select AsText(Centroid(geomfromtext('".$hold->get_wkt()."'))) as center";     
144                $result = pmb_mysql_query($query, $dbh);
145                if(pmb_mysql_num_rows($result)){
146                        $row = pmb_mysql_fetch_object($result);
147                        $hold_wkt = $row->center;
148                        return $hold_wkt;
149                }
150        }
151       
152        public function shouldCluster($cluster, $hold){
153                $coords_cluster = explode(" ",substr($cluster->get_center(),strpos($cluster->get_center(),"(")+1,-1));
154                $coords_hold = explode(" ",substr($hold->get_center(),strpos($hold->get_center(),"(")+1,-1));
155               
156                $distance = sqrt(pow(($coords_cluster[0] - $coords_hold[0]),2) + pow(($coords_cluster[1] - $coords_hold[1]),2));       
157                return ($distance <= $this->map_distance);
158        }
159       
160        public function check_wkt($holds, $wkt_string){
161                foreach($holds as $num => $hold){
162                        if($hold->get_wkt() == $wkt_string){
163                                return $num;
164                        }
165                }
166                return false;
167        }
168       
169        public function simplify_polygon($wkt){
170                $parts = explode(',', $wkt);
171                $new = "";
172                $start = array_shift($parts);
173                $stop = array_pop($parts);
174                for($j=0 ; $j<=count($parts) ; $j++){
175                        if($j % 2)
176                                $new.= ",".$parts[$j];
177                }
178                if(!(count($parts) % 2)){
179                        $new.=",";
180                }
181                $wkt = $start.$new.$stop;
182                return $wkt;
183        }
184       
185        public function dicho($min, $max){
186                global $pmb_map_max_holds, $pmb_map_hold_ratio_min;
187                $params = explode(",", $pmb_map_max_holds);
188                if($params[1] == "1" && count($this->holds)>$params[0]){
189                        $min = $max;
190                }
191                //print " min ".$min." max ".$max;
192                $nb_emprise_min = $this->calc_empr($min);
193                $nb_emprise_max = $this->calc_empr($max);
194                if($nb_emprise_max >= $params[0]){
195                        //Avec le seuil max, on a déjà trop d'emprise, on ne continue pas.
196                        return;
197                }
198                if($nb_emprise_min <= $params[0]){
199                        $this->calc_empr($min);
200                        //On a un nombre convenable d'emprise avec le seuil min, on s'arrête
201                        return;
202                }
203               
204                $mid = (($max-$min)/2)+$min;
205                if((($max-$min)/2) <= $pmb_map_hold_ratio_min){
206                        $this->calc_empr($mid);
207                        //On s'arrête car le seuil est inférieur au seuil mini
208                        return;
209                }
210                $nb_emprise_seuil = $this->calc_empr($mid);
211                if($nb_emprise_seuil < $params[0]){
212                        return $this->dicho($min, $mid);
213                }else if($nb_emprise_seuil == $params[0]){
214                        return;
215                }else{
216                        return $this->dicho($mid, $max);
217                }
218        }
219       
220        public function calc_empr($seuil_min){
221                global $pmb_map_hold_ratio_max;
222                $this->displayed_holds = array();
223                $this->clustered_holds = array();
224                $this->clusters = array();
225       
226                foreach($this->holds as $key => $hold){
227                        if($this->get_occupation_percentage($hold) > $seuil_min){//ces emprises doivent être affichées
228                                if ($this->get_occupation_percentage($hold) < $pmb_map_hold_ratio_max){
229                                        $existant_key = $this->check_wkt($this->displayed_holds, $hold->get_wkt());
230                                        if($existant_key != false){
231                                                if(is_array($this->displayed_holds[$existant_key]->get_num_object())){
232                                                        $num_obj = $this->displayed_holds[$existant_key]->get_num_object();
233                                                        $num_obj[] = $hold->get_num_object();
234                                                        $this->displayed_holds[$existant_key]->set_num_object($num_obj);
235                                                }else{
236                                                        $this->displayed_holds[$existant_key]->set_num_object(array($this->displayed_holds[$existant_key]->get_num_object(), $hold->get_num_object()));
237                                                }
238                                        }else{
239                                                $this->displayed_holds[$key] = $hold;
240                                                if(count($this->displayed_holds[$key]->get_wkt())>1000 && $this->displayed_holds[$key]->get_hold_type()=="POLYGON"){
241                                                        $this->displayed_holds[$key]->set_wkt($this->simplify_polygon($this->displayed_holds[$key]->get_wkt()));
242                                                }
243                                        }
244                                }//Trop grandes non affichées
245                        }else{//celles ci doivent etre reduite a un point
246                                $this->clustered_holds[$key] = $hold;
247                        }
248                }
249                return count($this->displayed_holds);
250        }
251        public static function cmp_area($a, $b) {
252                if ($a->get_normalized_bbox_area() == $b->get_normalized_bbox_area()) {
253                        return 0;
254                }
255                return ($a->get_normalized_bbox_area() > $b->get_normalized_bbox_area()) ? -1 : 1;
256        }
257}
Note: See TracBrowser for help on using the repository browser.