Exemplo n.º 1
0
 /**
  * Generate clustered GEOJSON from incidents
  * 
  * @param ORM_Iterator|Database_Result|array $incidents collection of incidents
  * @param int $category_id
  * @param string $color
  * @param string $icon
  * @return array $json_features geojson features array
  **/
 protected function clusters_geojson($incidents, $category_id, $color, $icon)
 {
     $json_features = array();
     // Extra params for clustering
     // Start date
     $start_date = (isset($_GET['s']) and intval($_GET['s']) > 0) ? intval($_GET['s']) : NULL;
     // End date
     $end_date = (isset($_GET['e']) and intval($_GET['e']) > 0) ? intval($_GET['e']) : NULL;
     // Get Zoom Level
     $zoomLevel = (isset($_GET['z']) and !empty($_GET['z'])) ? (int) $_GET['z'] : 8;
     $distance = (10000000 >> $zoomLevel) / 100000;
     // Get markers array
     if ($incidents instanceof ORM_Iterator) {
         $markers = $incidents->as_array();
     } elseif ($incidents instanceof Database_Result) {
         $markers = $incidents->result_array();
     } else {
         $markers = $incidents;
     }
     $clusters = array();
     // Clustered
     $singles = array();
     // Non Clustered
     // Loop until all markers have been compared
     while (count($markers)) {
         $marker = array_pop($markers);
         $cluster = array();
         // Handle both reports::fetch_incidents() response and actual ORM objects
         $marker->id = isset($marker->incident_id) ? $marker->incident_id : $marker->id;
         if (isset($marker->latitude) and isset($marker->longitude)) {
             $marker_latitude = $marker->latitude;
             $marker_longitude = $marker->longitude;
         } elseif (isset($marker->location) and isset($marker->location->latitude) and isset($marker->location->longitude)) {
             $marker_latitude = $marker->location->latitude;
             $marker_longitude = $marker->location->longitude;
         } else {
             // No location - skip this report
             continue;
         }
         // Compare marker against all remaining markers.
         foreach ($markers as $key => $target) {
             // Handle both reports::fetch_incidents() response and actual ORM objects
             if (isset($target->latitude) and isset($target->longitude)) {
                 $target_latitude = $target->latitude;
                 $target_longitude = $target->longitude;
             } elseif (isset($target->location) and isset($target->location->latitude) and isset($target->location->longitude)) {
                 $target_latitude = $target->location->latitude;
                 $target_longitude = $target->location->longitude;
             } else {
                 // No location - skip this report
                 continue;
             }
             // This function returns the distance between two markers, at a defined zoom level.
             // $pixels = $this->_pixelDistance($marker['latitude'], $marker['longitude'],
             // $target['latitude'], $target['longitude'], $zoomLevel);
             $pixels = abs($marker_longitude - $target_longitude) + abs($marker_latitude - $target_latitude);
             // If two markers are closer than defined distance, remove compareMarker from array and add to cluster.
             if ($pixels < $distance) {
                 unset($markers[$key]);
                 $cluster[] = $target;
             }
         }
         // If a marker was added to cluster, also add the marker we were comparing to.
         if (count($cluster) > 0) {
             $cluster[] = $marker;
             $clusters[] = $cluster;
         } else {
             $singles[] = $marker;
         }
     }
     // Create Json
     foreach ($clusters as $cluster) {
         // Calculate cluster center
         $bounds = $this->calculate_center($cluster);
         $cluster_center = array_values($bounds['center']);
         $southwest = $bounds['sw']['longitude'] . ',' . $bounds['sw']['latitude'];
         $northeast = $bounds['ne']['longitude'] . ',' . $bounds['ne']['latitude'];
         // Number of Items in Cluster
         $cluster_count = count($cluster);
         // Get the time filter
         $time_filter = (!empty($start_date) and !empty($end_date)) ? "&s=" . $start_date . "&e=" . $end_date : "";
         // Build query string for title link, passing through any GET params
         // This allows plugins to extend more easily
         $query = http_build_query(array_merge(array('sw' => $southwest, 'ne' => $northeast), $_GET));
         // Build out the JSON string
         $link = url::site("reports/index/?{$query}");
         $item_name = $this->get_title(Kohana::lang('ui_main.reports_count', $cluster_count), $link);
         $json_item = array();
         $json_item['type'] = 'Feature';
         $json_item['properties'] = array('name' => $item_name, 'link' => $link, 'category' => array($category_id), 'color' => $color, 'icon' => $icon, 'thumb' => '', 'timestamp' => 0, 'count' => $cluster_count);
         $json_item['geometry'] = array('type' => 'Point', 'coordinates' => $cluster_center);
         array_push($json_features, $json_item);
     }
     // Pass single points to standard markers json
     $json_features = array_merge($json_features, $this->markers_geojson($singles, $category_id, $color, $icon, FALSE));
     //
     // E.Kala July 27, 2011
     // @todo Parking this geometry business for review
     //
     /*
     //Get Incident Geometries
     $geometry = $this->_get_geometry($marker->incident_id, $marker->incident_title, $marker->incident_date);
     if (count($geometry))
     {
     	foreach ($geometry as $g)
     	{
     		array_push($json_features, $g);
     	}
     }
     */
     Event::run('ushahidi_filter.json_cluster_features', $json_features);
     return $json_features;
 }