root/g-map/files/lib/data/gmap/GmapCluster.class.php @ 1236

Revision 1236, 4.0 kB (checked in by d0nut, 3 years ago)

may finish gmap 2.0.0 RC 3

RevLine 
[1223]1<?php
2
3/**
4 * gets several positions and returns a clustered array
5 *
6 * @author      Torben Brodt
7 * @license     GNU General Public License <http://opensource.org/licenses/gpl-3.0.html>
8 */
9class GmapCluster {
[1224]10
[1223]11        const OFFSET = 268435456;
12        const RADIUS = 85445659.4471; /* $self::OFFSET / pi() */
13       
14        protected $distance;
15        protected $zoom;
16       
17        /**
18         *
19         * @param       $distance       Distance in pixel inside which markers will be clustered.
20         * @param       $zoom           Current map zoom level.
21         */
22        public function __construct($distance, $zoom) {
23                $this->distance = $distance;
24                $this->zoom = $zoom;
25        }
26       
27        protected function lonToX($lon) {
28                return round(self::OFFSET + self::RADIUS * $lon * pi() / 180);         
29        }
30
31        protected function latToY($lat) {
32                return round(self::OFFSET - self::RADIUS * log((1 + sin($lat * pi() / 180)) / (1 - sin($lat * pi() / 180))) / 2);
33        }
34
35        protected function pixelDistance($lat1, $lon1, $lat2, $lon2, $zoom) {
36                $x1 = $this->lonToX($lon1);
37                $y1 = $this->latToY($lat1);
38
39                $x2 = $this->lonToX($lon2);
40                $y2 = $this->latToY($lat2);
41               
42                return sqrt(pow(($x1-$x2),2) + pow(($y1-$y2),2)) >> (21 - $zoom);
43        }
44       
45        /**
46         * Return average center of markers
47         *
48         * @return   object Google_Maps_Coordinate
49         */
[1236]50        protected function getCluster(array $markers, $return_ids = false) {
[1223]51                $count = count($markers);
[1236]52                $ids = array();
[1223]53
54                /* Calculate average lat and lon of markers. */
55                $lat_sum = $lon_sum = 0;
56                foreach ($markers as $marker) {
57                   $lat_sum += $marker['lat'];
58                   $lon_sum += $marker['lon'];
[1236]59                   if($return_ids) {
60                        $ids[] = $marker['id'];
61                   }
[1223]62                }
63                $lat_avg = $lat_sum / $count;
64                $lon_avg = $lon_sum / $count;
65               
[1236]66                $data = array(
[1223]67                        'count' => $count,
68                        'lat' => $lat_avg,
69                        'lon' => $lon_avg
70                );
[1236]71                if(count($ids)) {
72                        $data['ids'] = $ids;
73                }
74               
75                return $data;
[1223]76        }
77
78        /**
79         *
80         * @param       $markers        Array of lat and lon locations.
81         */
[1236]82        public function getMarkers(array $markers, $pick = array()) {
[1223]83                $clustered = array();
84
85                /* Loop until all markers have been compared. */
86                while (count($markers)) {
87                        $marker  = array_pop($markers);
88                        $cluster = array();
89
90                        /* Compare against all markers which are left. */
91                        foreach ($markers as $key => $target) {
[1226]92                                $pixels = $this->pixelDistance($marker['lat'], $marker['lon'], $target['lat'], $target['lon'], $this->zoom);
[1223]93
94                                /* If two markers are closer than given distance remove */
95                                /* target marker from array and add it to cluster.        */
[1226]96                                if ($this->distance > $pixels) {
[1223]97                                        unset($markers[$key]);
98                                        $cluster[] = $target;
99                                }
100                        }
101
102                        /* If a marker has been added to cluster, add also the one  */
103                        /* we were comparing to and remove the original from array. */
104                        if (count($cluster) > 0) {
105                                $cluster[] = $marker;
106                                $clustered[] = $this->getCluster($cluster);
107                        } else {
108                                $clustered[] = $marker;
109                        }
110                }
111                return $clustered;
112        }
[1236]113
114        /**
115         *
116         * @param       $markers        Array of lat and lon locations.
117         */
118        public function getIDs(array $markers, $lat, $lon) {
119
120                /* Loop until all markers have been compared. */
121                while (count($markers)) {
122                        $marker  = array_pop($markers);
123                        $cluster = array();
124
125                        /* Compare against all markers which are left. */
126                        foreach ($markers as $key => $target) {
127                                $pixels = $this->pixelDistance($marker['lat'], $marker['lon'], $target['lat'], $target['lon'], $this->zoom);
128
129                                /* If two markers are closer than given distance remove */
130                                /* target marker from array and add it to cluster.        */
131                                if ($this->distance > $pixels) {
132                                        unset($markers[$key]);
133                                        $cluster[] = $target;
134                                }
135                        }
136
137                        /* If a marker has been added to cluster, add also the one  */
138                        /* we were comparing to and remove the original from array. */
139                        if (count($cluster) > 0) {
140                                $cluster[] = $marker;
141                                $cluster = $this->getCluster($cluster, true);
142                                if(abs($cluster['lat'] - $lat) < 0.000000001 && abs($cluster['lon'] - $lon) < 0.000000001) {
143                                        return $cluster['ids'];
144                                }
145                        } else {
146                                if(abs($marker['lat'] - $lat) < 0.000000001 && abs($marker['lon'] - $lon) < 0.000000001) {
147                                        return array($marker['id']);
148                                }
149                        }
150                }
151                return null;
152        }
[1223]153}
Note: See TracBrowser for help on using the browser.