def __cluster_events(data, cluster_threshold=None): if cluster_threshold: # clustered incidents data clustered_data = [] # Consider each node as root for now for root in data: # If is clustered flag is not present if not root.get('isClustered', False): # Loop though the points for child in data: # Base case if child['key'] == root['key']: continue # If node is not clustered if not child.get('isClustered', False): # Calculate the distance temp_distance = distance(root['lat'], root['long'], child['lat'], child['long']) # If two points are too close on map cluster them if temp_distance < cluster_threshold: # Update root root['isClustered'] = True root['lat'] = (root['lat'] + child['lat']) / 2 root['long'] = (root['long'] + child['long']) / 2 # Mark child child['isClustered'] = True clustered_data.append(root) return clustered_data return data
def get_events_around(center, max_distance, cluster_threshold, db, collection_name='incidents'): events_around = [] result_count = 0 match_count = 0 queries = Event.__get_queries_for_events_around( db.collection(collection_name), center, max_distance) # print("queries", queries) for query in queries: docs = query.get() for doc in docs: result_count += 1 event_dict = doc.to_dict() # print("event_dict", event_dict) dist = distance(center['latitude'], center['longitude'], event_dict['location']['coords'].latitude, event_dict['location']['coords'].longitude) if dist < max_distance: match_count += 1 temp = { 'key': doc.id, 'lat': event_dict['location']['coords'].latitude, 'long': event_dict['location']['coords'].longitude, 'category': event_dict['category'], 'title': event_dict['title'], 'datetime': event_dict['datetime'] } events_around.append(temp) print("result_count", result_count) print("match_count", match_count) print("diff (result_count - match_count)", result_count - match_count) return Event.__cluster_events(events_around, cluster_threshold)
def get(self, request): """Returns events within a certain radius for a given location POST request parameters: [REQUIRED] lat: latitude of the location long: longitude of the location dist: maximum radius of the location Arguments: request {[type]} -- [ Contains the django request object] Returns: [HttpResponseBadRequest] -- [If any of the required parameters is not given.] [JsonResponse] -- [Containing the event data] """ # Should use API View here lat = float(request.GET.get('lat', '')) lng = float(request.GET.get('long', '')) thresold = float(request.GET.get('dist', '')) if lat == '' or lng == '' or thresold == '': return HttpResponseBadRequest("Bad request") incidents = DB.child('incidents').get() data = [] # Find events which are inside the circle # This method is highly inefficient # In takes O(n) time for each request # Should use a GeoHash based solution instead of this for incident in incidents.each(): event = dict(incident.val()) temp = {} temp['key'] = incident.key() temp['lat'] = event['location']['coords']['latitude'] temp['long'] = event['location']['coords']['longitude'] temp['category'] = event['category'] temp['title'] = event['title'] temp['datetime'] = event['datetime'] tmplat = float(event['location']['coords']['latitude']) tmplng = float(event['location']['coords']['longitude']) dist = distance(tmplat, tmplng, lat, lng) if dist < thresold: data.append(temp) # Cluster the events cluster_thresold = float(request.GET.get('min', 0)) # This code should also be present on client side if cluster_thresold: # clustered incidents data clustered_data = [] # Consider each node as root for now for root in data: # If is clustered flag is not present if not root.get('isClustered', False): # Loop though the points for child in data: # Base case if child['key'] == root['key']: continue # If node is not clustered if not child.get('isClustered', False): # Calculate the distance temp_distance = distance(root['lat'], root['long'], child['lat'], child['long']) # If two points are too close on map cluster them if temp_distance < cluster_thresold: # Update root root['isClustered'] = True root['lat'] = (root['lat'] + child['lat']) / 2 root['long'] = (root['long'] + child['long']) / 2 # Mark child child['isClustered'] = True clustered_data.append(root) return JsonResponse(clustered_data, safe=False) return JsonResponse(data, safe=False)