def radius_filter(self, x: float, y: float, radius: float) -> QuerySet: """ Makes a Point object out of the x and y WGS84 coordinates, transforms it to 98334, and filters the Stop objects by distance, fetching the ones that are at the radius distance or less. :param x: longitude :param y: latitude :param radius: radius in meters :return: QuerySet """ center_point = point_4326_to_98334(x, y) distance_obj = D(m=radius) return self.model.objects.filter(geom_98334__distance_lte=(center_point, distance_obj))
def spatial_distance(lhs: Union[F, Value], rhs: Union[F, Value], op: str, distance: float, units: str) -> Q: if not isinstance(lhs, F): lhs, rhs = rhs, lhs # if neither lhs and rhs are fields, we have to fail here if not isinstance(lhs, F): raise ValueError(f'Unable to compare non-field {lhs}') # TODO: maybe use D.unit_attname(units) d = D(**{UNITS_LOOKUP[units]: distance}) if op == "DWITHIN": return Q(**{"%s__distance_lte" % lhs.name: (rhs, d, 'spheroid')}) return Q(**{"%s__distance_gte" % lhs.name: (rhs, d, 'spheroid')})
def nodes_minimum_distance_validation(self): """ if minimum distance is specified, ensure node is not too close to other nodes; """ if self.layer and self.layer.nodes_minimum_distance: minimum_distance = self.layer.nodes_minimum_distance # TODO - lower priority: do this check only when coordinates are changing near_nodes = Node.objects.exclude(pk=self.id).filter( geometry__distance_lte=(self.geometry, D(m=minimum_distance))).count() if near_nodes > 0: raise ValidationError( _('Distance between nodes cannot be less than %s meters') % minimum_distance)
def get_queryset(self): result = super(NearbyView, self).get_queryset() self.qs = Event.objects.all() lat = self.request.GET.get('latitude') lng = self.request.GET.get('longitude') if lat and lng: geo = Point(float(lat), float(lng)) distance = 500 self.qs = (self.qs.filter(point__distance_lte=(geo, D( m=distance))).distance(geo).order_by('distance')) result = self.qs return result
def test_distance_lookups(self): """ Test the `distance_lt`, `distance_gt`, `distance_lte`, and `distance_gte` lookup types. """ # Retrieving the cities within a 20km 'donut' w/a 7km radius 'hole' # (thus, Houston and Southside place will be excluded as tested in # the `test02_dwithin` above). for model in [SouthTexasCity, SouthTexasCityFt]: qs = model.objects.filter(point__distance_gte=(self.stx_pnt, D( km=7))).filter(point__distance_lte=(self.stx_pnt, D(km=20)), ) cities = self.get_names(qs) self.assertEqual(cities, ['Bellaire', 'Pearland', 'West University Place']) # Doing a distance query using Polygons instead of a Point. z = SouthTexasZipcode.objects.get(name='77005') qs = SouthTexasZipcode.objects.exclude(name='77005').filter( poly__distance_lte=(z.poly, D(m=275))) self.assertEqual(['77025', '77401'], self.get_names(qs)) # If we add a little more distance 77002 should be included. qs = SouthTexasZipcode.objects.exclude(name='77005').filter( poly__distance_lte=(z.poly, D(m=300))) self.assertEqual(['77002', '77025', '77401'], self.get_names(qs))
def get_context_data(self, **kwargs): context = super(EventUpdateView, self).get_context_data(**kwargs) lng = self.object.latitude lat = self.object.longitude localities = Locality.objects.filter(owner=self.request.user.profile) reference = Point(lng, lat) close = Locality.objects.filter(point__distance_lte=(reference, D(m=1000))) context.update({'localities': localities, 'close': close}) return context
def get_users_around(self, user): if not user.location: return [] # Filtering and serializing users users_query_set = User.objects.filter( location__distance_lte=(user.location, D(km=1))).filter(~Q(pk=user.pk)) users = UserSerializer(instance=users_query_set, many=True, context=self.context, fields=['url']).data return users
def filter_queryset(self, request, queryset, view): """ Limit queryset to all spots within user specified radius (in miles) from curr_loc. """ radius = parse_int(request.query_params.get("radius", None)) curr_loc = parse_float_list(request.query_params.get("curr_loc", None)) if radius and len(curr_loc) == 2: return queryset.filter( location__distance_lte=(Point(curr_loc[0], curr_loc[1]), D(mi=radius))) return queryset
def test_dwithin(self): from django.contrib.gis.geos import Point p = Point(0, 0) distance = D(mi=500) sqs = self.search_index.objects.dwithin("location", p, distance) self.assertTrue(isinstance(sqs, SearchQuerySet)) params = sqs.query.build_params() self.assertIn("dwithin", params) self.assertDictEqual( params["dwithin"], {"field": "location", "point": p, "distance": distance} )
def get_context_data(self, **kwargs): context = super(EventCreateView, self).get_context_data(**kwargs) lng = self.request.GET.get('lng') or self.kwargs.get('lng') or None lat = self.request.GET.get('lat') or self.kwargs.get('lat') or None localities = Locality.objects.filter(owner=self.request.user.profile) reference = Point(float(lng), float(lat)) close = Locality.objects.filter(point__distance_lte=(reference, D(m=150))) context.update({'localities': localities, 'close': close}) return context
def testInit(self): "Testing initialization from valid units" d = Distance(m=100) self.assertEqual(d.m, 100) d1, d2, d3 = D(m=100), D(meter=100), D(metre=100) for d in (d1, d2, d3): self.assertEqual(d.m, 100) d = D(nm=100) self.assertEqual(d.m, 185200) y1, y2, y3 = D(yd=100), D(yard=100), D(Yard=100) for d in (y1, y2, y3): self.assertEqual(d.yd, 100) mm1, mm2 = D(millimeter=1000), D(MiLLiMeTeR=1000) for d in (mm1, mm2): self.assertEqual(d.m, 1.0) self.assertEqual(d.mm, 1000.0)
def get_queryset(self): # start off with all walks queryset = Walk.objects.all() # check we have search parameters in the session search_params = self.request.session.get("search", {}) if ( not search_params or not search_params.get("lat") or not search_params.get("long") ): # show all the walks if there are no search params to filter by return queryset # if here, we have a set of search params. # We can build a Point to search from search_location = Point( srid=4326, x=float(search_params.get("long")), y=float(search_params.get("lat")), ) # get the search_parameters search_attributes = search_params.get("attributes", []) search_radius = search_params.get("search_radius") or 200 maximum_length = search_params.get("maximum_length") or 250 # we can annotate and filter # fmt: off return queryset.annotate( distance=Distance("start", search_location) ).annotate( attribute_match_count=Count( "attributes", filter=Q(attributes__in=search_attributes), ) ).filter( start__distance_lte=( search_location, D(mi=float(search_radius)), ) ).filter( route_length__lte=float(maximum_length) ).order_by( "-attribute_match_count", "route_length", "distance", )
def get(self, request, *args, **kwargs): longitude = self.kwargs['long'] latitude = self.kwargs['lat'] hazard_title = self.kwargs['hazard'] try: distance_parm = self.kwargs['distance'] except: distance_parm = 5000 try: count = int(self.kwargs['count']) except: count = 20 user_location = GEOSGeometry('POINT({} {})'.format( longitude, latitude), srid=4326) #Hazard_object = Hazard.objects.get(title=hazard_title) #Hresources = Hazard_object.hazardresources_set.all() api_json = {} if (hazard_title == 'flood'): resource_array = ['Hospital', 'School', 'Policestation', 'Bridge'] elif (hazard_title == 'landslide'): resource_array = ['Policestation', 'Hospital', 'School'] elif (hazard_title == 'fire'): resource_array = [ 'Policestation', 'Hospital', 'School', 'MarketCenter' ] elif (hazard_title == 'earthquake'): resource_array = ['Policestation', 'Hospital', 'School'] resource_object = [] print(distance_parm) for resource in resource_array: model_x = apps.get_model('risk_profile', resource) print("model_x", model_x) resource_queryset=model_x.objects \ .filter(location__distance_lte=(user_location,D(km=distance_parm))) \ .annotate(distance=Distance('location',user_location)) \ .order_by('distance')[0:count] print(resource_queryset) resource_json = HospitalSerializer(resource_queryset, many=True) json = JSONRenderer().render(resource_json.data) stream = io.BytesIO(json) data = JSONParser().parse(stream) api_json[resource] = data return Response(api_json)
def post(self, request): geo = { 'lat': request.POST.get('geo[lat]'), 'lng': request.POST.get('geo[lng]'), 'name': request.POST.get('geo[name]'), 'range': request.POST.get('geo[range]'), } geo_range = int(geo['range'] or self.DEFAULT_RANGE) if not any([geo.get('lat'), geo.get('lng')]): return self.render_not_found(request) cat = request.POST.get('category') pnt_str = 'SRID=4326;POINT({} {})'.format(geo['lng'], geo['lat']) pnt = GEOSGeometry(pnt_str) # geo-filtering if geo_range > 0: # short version # photos = Photo.objects.filter( # photographer__locations__point__distance_lte=( # pnt, D(km=geo_range))) # debug-able version locations = Location.objects.filter(point__distance_lte=(pnt, D(km=geo_range)))\ .distance(pnt).order_by('distance') photographers = Photographer.objects.filter( locations__in=locations) photos = Photo.objects.filter( photographer__in=photographers).order_by('?') else: photos = Photo.objects.exclude( photographer__locations__point__isnull=True) # category filtering if cat and cat != settings.SEARCH_DEFAULTS['category']: photos = photos.filter(photographer__categories__slug__exact=cat) page = int(request.POST.get('page', 0)) or 0 # paginate and add exposure metric batch = self.paginate(photos, page) self.add_impressions(batch, request) context = { 'photos': batch, 'geo': geo, 'total': len(photos) if not page else None, } return render(request, self.TEMPLATE_NAME, context)
def handle_GET(self, request, context, entity=None): point = get_point(request, entity) if point is None: return self.render(request, {'entity': entity}, 'places/entity_without_location') if entity: return_url = reverse( 'places:entity-nearby-list', args=[entity.identifier_scheme, entity.identifier_value]) else: return_url = reverse('places:nearby-list') # Get entity types to show on nearby page entity_types = EntityType.objects.filter(show_in_nearby_list=True) for et in entity_types: # For each et, get the entities that belong to it et.max_distance = humanise_distance(0) et.entities_found = 0 es = et.entities_completion.filter( location__isnull=False, location__distance_lt=(point, D( km=5))).distance(point).order_by('distance') for e in es: # Selection criteria for whether or not to count this entity if (e.distance.m**0.75) * (et.entities_found + 1) > 500: break et.max_distance = humanise_distance(e.distance.m) et.entities_found += 1 categorised_entity_types = defaultdict(list) for et in filter(lambda et: et.entities_found > 0, entity_types): categorised_entity_types[_(et.category.name)].append(et) categorised_entity_types = dict( (k, sorted(v, key=lambda x: x.verbose_name.lower())) for k, v in categorised_entity_types.items()) context.update({ 'entity_types': categorised_entity_types, 'entity': entity, 'return_url': return_url, # entity is None => we've searched around the user's location 'exposes_user_data': entity is None, }) if entity and not entity.location: return self.render(request, context, 'places/entity_without_location') return self.render(request, context, 'places/nearby_list')
def load_data(self, request, bounds, **args): resp = self._base_response(bounds) # contaminated pnt = fromstr('POINT(%s %s)' % (bounds.lon, bounds.lat), srid=4326) qs = Site.objects.filter(point__distance_lte=(pnt, D(mi=5))) sites = sorted(qs.distance(pnt), cmp=lambda x, y: cmp(x.distance, y.distance)) if sites: resp['data'].update({ "contaminated": { "distance": "%.1f" % sites[0].distance.mi, "url": sites[0].url, } }) # Dark Sky ds = darksky.forecast(bounds.lat, bounds.lon) if 'hourSummary' in ds: forecast = ds['hourSummary'].lower() if forecast == 'clear': ds['forecast_code'] = 'sun' elif 'sprinkling' in forecast: ds['forecast_code'] = 'rain' elif 'sleet' in forecast: ds['forecast_code'] = 'sleet' elif 'sun' in forecast: ds['forecast_code'] = 'sun' elif 'rain' in forecast: ds['forecast_code'] = 'rain' elif 'cloud' in forecast: ds['forecast_code'] = 'cloud' resp['data']['darksky'] = ds # Wunderground resp['data']['wunderground'] = wunderground.almanac( bounds.lat, bounds.lon) return resp
def get(self, request, **kwargs): """ If params are provided, first find restaurants with distance within 1.5 km after that order them by online status then order by distance, launch date, popularity to get nearest, newest, most popular restaurants sequentially finally, take at most 10 restaurants from each lists else return missing params """ required_params = {'lon', 'lat'} missing_params = required_params.difference( self.request.query_params.keys()) if missing_params: return Response( {'error': f'Missing parameters: {", ".join(missing_params)}'}) try: longitude = float(self.request.query_params.get('lon')) latitude = float(self.request.query_params.get('lat')) except ValueError: return Response({'error': 'Values not convertable to float'}) location = Point(x=longitude, y=latitude, srid=4326) restaurants = Restaurant.objects.annotate( distance=Distance('location', location)).filter(distance__lte=D( km=1.5)) nearest = restaurants.order_by('-online', 'distance')[:10] newest = restaurants.order_by('-online', '-launch_date')[:10] most_popular = restaurants.order_by('-online', '-popularity')[:10] nearest_data = RestaurantSerializer(nearest, many=True).data newest_data = RestaurantSerializer(newest, many=True).data most_popular_data = RestaurantSerializer(most_popular, many=True).data context = { 'sections': [ { "title": "Popular Restaurants", 'restaurants': most_popular_data }, { "title": "New Restaurants", 'restaurants': newest_data }, { "title": "Nearby Restaurants", 'restaurants': nearest_data }, ] } return Response(context)
def distance_from_coastline(lon, lat): """ Calculate the distance from coastline. If the distance is greater then 100 mile, we will return None. :param lon: float :param lat: float :return: float (unit is mile) """ point = Point(lon, lat, srid=4326) coastlines = Coastline.objects.filter( m_line_string__distance_lte=(point, D(mi=100))).annotate( distance=Distance('m_line_string', point)) distance_list = [c.distance.mi for c in coastlines] if distance_list: return min(distance_list)
def near_list(self, point, distance=None, field='point__distance'): """ Annotate queryset with distances for activities from some particular point. Can also perform filtering based on distance if `distance` argument is specified. :param point: Point to use as a center :param distance: Perform filtering on distance (optional) :param field: Field to use for distance calculation (optional) :return: Annotated (and possibly filtered) queryset """ if distance is None: distance = settings.SPHAX_CONFIG['DISTANCE_MIN'] queryset = self.filter(**{ '{}_lte'.format(field): (point, D(km=distance)) }) if queryset.count() < 10: while queryset.count() < 10: if distance >= settings.SPHAX_CONFIG['DISTANCE_MAX']: break distance += settings.SPHAX_CONFIG['DISTANCE_STEP'] queryset = self.filter(**{ '{}_lte'.format(field): (point, D(km=distance)) }) return queryset
def get_queryset(self): queryset = self.queryset qs_lat = self.request.query_params.get('lat', None) qs_lng = self.request.query_params.get('lng', None) qs_radius = self.request.query_params.get('radius', None) desired_radius = {'mi': float(qs_radius)} user_location = fromstr("POINT(%s %s)" % (qs_lng, qs_lat)) if qs_lat and qs_lng and qs_radius: pnt = GEOSGeometry(user_location, srid=4326) qs = queryset.filter( parking_lot_location__distance_lte=(pnt, D( **desired_radius))).annotate(distance=Distance( 'parking_lot_location', pnt)).order_by('distance') return qs
def search(request): if request.method=='GET': lat = float(request.GET.get('user_lat')) lng = float(request.GET.get('user_long')) radius = float(request.GET.get('user_radius')) point = Point(lng,lat) restos = Resto.objects.filter(address__distance_lte=(point, D(m=radius))) if request.GET.get('user_veg_only'): dishes = Dish.objects.filter(resto__in=restos,veg=True) else: dishes = Dish.objects.filter(resto__in=restos) dishes=dishes.annotate(null_rating=Count('rating')).order_by('-null_rating','-rating') return render(request,'resto/result.html',{'dishes':dishes})
def list(self, request): user = self.request.user if user.is_customer: customer = Customer.objects.get(user=user) lat = float(customer.location.x) lng = float(customer.location.y) point = Point(lat, lng) radius = 500 queryset = Dealer.objects.filter(location=(point, D(km=radius))) serializer = DealerSerializer(queryset, many=True) return Response(serializer.data) else: queryset = Dealer.objects.get_queryset() serializer = DealerSerializer(queryset, many=True) return Response(serializer.data)
def nearest(request, srid, x, y, format='json'): location = Point(float(x), float(y), srid=int(srid)) set_timeout(format) try: postcode = Postcode.objects.filter( location__distance_gte=(location, D( mi=0))).distance(location).order_by('distance')[0] except QueryCanceledError: return output_error(format, 'That query was taking too long to compute.', 500) except DatabaseError, e: if 'canceling statement due to statement timeout' not in e.args[0]: raise return output_error(format, 'That query was taking too long to compute.', 500)
def closest(self, request): distance = 1000 point_string = request.query_params.get('point', None) if not point_string: raise ValidationError({ 'point': 'The point need to be provided in the form \'?point=lon,lat\'' }) point = parse_point(point_string) tree = Tree.objects.filter(location__distance_lte=(point, D( m=distance))).annotate(distance=Distance( 'location', point)).order_by('distance').first() return Response(TreeSerializer(tree).data)
def testMultiplication(self): "Test multiplication & division" d1 = D(m=100) d3 = d1 * 2 self.assertEqual(d3.m, 200) d3 = 2 * d1 self.assertEqual(d3.m, 200) d3 *= 5 self.assertEqual(d3.m, 1000) d4 = d1 / 2 self.assertEqual(d4.m, 50) d4 /= 5 self.assertEqual(d4.m, 10) a5 = d1 * D(m=10) self.assert_(isinstance(a5, Area)) self.assertEqual(a5.sq_m, 100 * 10) try: d1 *= D(m=1) except TypeError, e: pass
def stops_near(request): ''' Returns stop within 'distance' of Point(center_lon, center_lat) as GeoJSON ''' distance = Decimal(request.GET.get("distance", "1")) d = D(km=distance) center_lat = float(request.GET.get("center_lat", "19.04719036505186")) center_lon = float(request.GET.get("center_lon", "72.87094116210938")) pt = Point([center_lon, center_lat]) tup = (pt, d,) stops = [stop.get_geojson() for stop in Stop.objects.filter(point__distance_lte=tup)] return render_to_json_response({ 'type': 'FeatureCollection', 'features': stops })
def instances_closest_to_point(request, lat, lng): """ Get all the info we need about instances near a given point Includes only public instances the user does not belong to. If a user has been specified instances that user belongs to will also be included in a separate list. Unlike instance_info, this does not return the field permissions for the instance """ user = request.user user_instance_ids = [] if user and not user.is_anonymous(): user_instance_ids = InstanceUser.objects.filter(user=user)\ .values_list('instance_id', flat=True)\ .distinct() point = Point(float(lng), float(lat), srid=4326) try: max_instances = int(request.GET.get('max', '10')) if not (1 <= max_instances <= 500): raise ValueError() except ValueError: raise HttpBadRequestException( 'The max parameter must be a number between 1 and 500') try: distance = float( request.GET.get('distance', settings.NEARBY_INSTANCE_RADIUS)) except ValueError: raise HttpBadRequestException( 'The distance parameter must be a number') instances = Instance.objects.distance(point).order_by('distance') nearby_predicate = Q(bounds__distance_lte=(point, D(m=distance))) personal_predicate = Q(pk__in=user_instance_ids) return { 'nearby': _contextify_instances( instances.filter(is_public=True).filter(nearby_predicate).exclude( personal_predicate)[0:max_instances]), 'personal': _contextify_instances(instances.filter(personal_predicate)) }
def mejores(self, producto, ciudad=None, punto_o_sucursal=None, radio=None, dias=None, limite=5): """ devuelve una lista de instancias Precio para el producto, ordenados por menor precio (importe) para un determinado producto y un radio de distancia o ciudad. Sólo considera el último precio en cada sucursal. """ if not one((ciudad, radio)): raise ValueError( 'Debe proveer una ciudad o un radio en kilometros') if one((radio, punto_o_sucursal)): raise ValueError( 'Si se especifica radio debe proveer el punto o sucursal') qs = super(PrecioManager, self).get_queryset().filter(producto=producto, activo__isnull=False) if dias: desde = timezone.now() - timedelta(days=dias) qs = qs.filter(created__gte=desde) if radio: if isinstance(punto_o_sucursal, Sucursal): punto = punto_o_sucursal.ubicacion else: punto = punto_o_sucursal cercanas = Sucursal.objects.filter( ubicacion__distance_lte=(punto, D(km=radio))) cercanas = cercanas.values_list('id', flat=True) qs = qs.filter( sucursal__id__in=cercanas).distinct('sucursal')[:limite] elif ciudad: if isinstance(ciudad, City): ciudad = ciudad.id qs = qs.filter( sucursal__ciudad__id=ciudad).distinct('sucursal')[:limite] if qs.exists(): return sorted(qs, key=lambda i: i.precio) return []
def populate_areas_lineareas(apps, schema_editor): Allegation = apps.get_model('data', 'Allegation') Area = apps.get_model('data', 'Area') LineArea = apps.get_model('data', 'LineArea') distance = D(m=10) for allegation in tqdm( Allegation.objects.all(), desc='Updating areas and line_areas' ): if allegation.point is None: allegation.areas.set([]) allegation.line_areas.set([]) else: allegation.areas.set(Area.objects.filter(polygon__covers=allegation.point)) allegation.line_areas.set(LineArea.objects.filter(geom__distance_lte=(allegation.point, distance)))
def sold_data(request): radius = request.REQUEST.get('radius', 3) object_id = request.GET['id'] obj = Auction.objects.filter(id=object_id) if obj: obj = obj[0] item = obj.to_json() item['icon'] = '../../static/auction/images/green-pin.png' data = SoldPrice.objects.filter( point__distance_lte=(obj.point, D(mi=radius))) data = [d.to_json() for d in data] data.append(item) data = json.dumps(data) return HttpResponse(data)