Esempio n. 1
0
    def get_distance(self, dist_val, lookup_type):
        """
        Returns a distance number in units of the field.  For example, if
        `D(km=1)` was passed in and the units of the field were in meters,
        then 1000 would be returned.
        """
        # Getting the distance parameter and any options.
        if len(dist_val) == 1: dist, option = dist_val[0], None
        else: dist, option = dist_val

        if isinstance(dist, Distance):
            if self.geodetic:
                # Won't allow Distance objects w/DWithin lookups on PostGIS.
                if SpatialBackend.postgis and lookup_type == 'dwithin':
                    raise TypeError('Only numeric values of degree units are allowed on geographic DWithin queries.')
                # Spherical distance calculation parameter should be in meters.
                dist_param = dist.m
            else:
                dist_param = getattr(dist, Distance.unit_attname(self._unit_name))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = dist

        if SpatialBackend.postgis and self.geodetic and lookup_type != 'dwithin' and option == 'spheroid':
            # On PostGIS, by default `ST_distance_sphere` is used; but if the
            # accuracy of `ST_distance_spheroid` is needed than the spheroid
            # needs to be passed to the SQL stored procedure.
            return [gqn(self._spheroid), dist_param]
        else:
            return [dist_param]
Esempio n. 2
0
    def get_distance(self, f, dist_val, lookup_type):
        """
        Retrieve the distance parameters for the given geometry field,
        distance lookup value, and the distance lookup type.

        This is the most complex implementation of the spatial backends due to
        what is supported on geodetic geometry columns vs. what's available on
        projected geometry columns.  In addition, it has to take into account
        the geography column type.
        """
        # Getting the distance parameter
        value = dist_val[0]

        # Shorthand boolean flags.
        geodetic = f.geodetic(self.connection)
        geography = f.geography

        if isinstance(value, Distance):
            if geography:
                dist_param = value.m
            elif geodetic:
                if lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are '
                                     'allowed on geographic DWithin queries.')
                dist_param = value.m
            else:
                dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = value

        return [dist_param]
Esempio n. 3
0
    def get_distance(self, value, lookup_type, connection):
        """
        Returns a distance number in units of the field.  For example, if
        `D(km=1)` was passed in and the units of the field were in meters,
        then 1000 would be returned.
        """
        return connection.ops.get_distance(self, value, lookup_type)

        if isinstance(dist, Distance):
            if self.geodetic(connection):
                # Won't allow Distance objects w/DWithin lookups on PostGIS.
                if connection.ops.postgis and lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are allowed on geographic DWithin queries.')

                # Spherical distance calculation parameter should be in meters.
                dist_param = dist.m
            else:
                dist_param = getattr(dist, Distance.unit_attname(self.units_name(connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = dist

        if connection.ops.oracle and lookup_type == 'dwithin':
            dist_param = 'distance=%s' % dist_param

        if connection.ops.postgis and self.geodetic(connection) and lookup_type != 'dwithin' and option == 'spheroid':
            # On PostGIS, by default `ST_distance_sphere` is used; but if the
            # accuracy of `ST_distance_spheroid` is needed than the spheroid
            # needs to be passed to the SQL stored procedure.
            return [self._spheroid, dist_param]
        else:
            return [dist_param]
Esempio n. 4
0
 def distance_att(self, connection):
     dist_att = None
     if self.geo_field.geodetic(connection):
         if connection.features.supports_distance_geodetic:
             dist_att = 'm'
     else:
         units = self.geo_field.units_name(connection)
         if units:
             dist_att = DistanceMeasure.unit_attname(units)
     return dist_att
Esempio n. 5
0
 def get_distance_att_for_field(self, field):
     dist_att = None
     if field.geodetic(self.connection):
         if self.connection.features.supports_distance_geodetic:
             dist_att = 'm'
     else:
         units = field.units_name(self.connection)
         if units:
             dist_att = DistanceMeasure.unit_attname(units)
     return dist_att
Esempio n. 6
0
 def get_distance(self, f, value, lookup_type):
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             raise ValueError(
                 'Only numeric values of degree units are allowed on '
                 'geodetic distance queries.'
             )
         dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 7
0
 def convert_value(self, value, expression, connection, context):
     if value is None:
         return None
     geo_field = GeometryField(srid=self.srid)  # Fake field to get SRID info
     if geo_field.geodetic(connection):
         dist_att = 'm'
     else:
         units = geo_field.units_name(connection)
         if units:
             dist_att = DistanceMeasure.unit_attname(units)
         else:
             dist_att = None
     if dist_att:
         return DistanceMeasure(**{dist_att: value})
     return value
Esempio n. 8
0
 def get_distance(self, f, value, lookup_type):
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             raise ValueError('SAP HANA does not support distance queries on '
                              'geometry fields with a geodetic coordinate system. '
                              'Distance objects; use a numeric value of your '
                              'distance in degrees instead.')
         else:
             dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 9
0
    def find_in_radius_as_geo_json(self, request):
        try:
            radius, point = get_radius_point_from_request(request)
        except:
            return Response(
                'missing required parameter, radius, lat or lng is invalid',
                status=status.HTTP_400_BAD_REQUEST)

        filtered_locations = Location.objects.filter(
            point__distance_lt=(point, Distance(km=radius)))
        data = djangoSerializer('custom_geojson',
                                filtered_locations,
                                geometry_field='point',
                                fields=('id', 'point', 'info', 'farm_id',
                                        'location_type'))
        return Response(data)
Esempio n. 10
0
 def get_queryset(self):
     user = self.request.user
     lon = self.request.query_params.get('longitude')
     if lon is not None:
         lon = float(lon)
     lat = self.request.query_params.get('latitude')
     if lat is not None:
         lat = float(lat)
     rad = self.request.query_params.get('radius')
     if rad is not None:
         rad = float(rad)
     if lon is not None and lat is not None and rad is not None:
         collect_point_within_radius = CollectPoint.objects.filter(
             location__distance_lt=(Point(lon, lat), Distance(m=rad)))
         return collect_point_within_radius.filter(user=user)
     return CollectPoint.objects.filter(user=user)
Esempio n. 11
0
 def get_queryset(self):
     lat = self.request.query_params.get('lat')
     lon = self.request.query_params.get('lon')
     if not self.request.query_params.get(
             'lat') or not self.request.query_params.get('lon'):
         raise ValidationError(detail='invalid request',
                               code=status.HTTP_400_BAD_REQUEST)
     queryset = self.queryset
     if self.request.query_params.get('name'):
         queryset = queryset.filter(
             name__istartswith=self.request.query_params['name'])
     if self.request.query_params.get('is_active'):
         queryset = queryset.filter(is_active=True)
     queryset = queryset.filter(
         location__distance_lt=(f'Point({lat} {lon})', Distance(km=.2)))
     return queryset
Esempio n. 12
0
 def convert_value(self, value, expression, connection, context):
     if value is None:
         return None
     geo_field = GeometryField(
         srid=self.srid)  # Fake field to get SRID info
     if geo_field.geodetic(connection):
         dist_att = 'm'
     else:
         units = geo_field.units_name(connection)
         if units:
             dist_att = DistanceMeasure.unit_attname(units)
         else:
             dist_att = None
     if dist_att:
         return DistanceMeasure(**{dist_att: value})
     return value
Esempio n. 13
0
    def within_distance_from(self, lat, lng, **distance):
        '''Find shops within given distance from given point.

        Arguments:
            - lat: Latitude of reference point.
            - lng: Longitude of reference point.
            - **distance: `Distance` arguments. For supported units see:
                https://docs.djangoproject.com/en/2.1/ref/contrib/gis/measure/#supported-units

        Example:
            ```
            shops = Shop.objects.within_distance_from(39.89, 22.18, km=10)
            ```
        '''
        return self.filter(coordinates__dwithin=(Point(lng, lat),
                                                 Distance(**distance)))
Esempio n. 14
0
    def get_queryset(self):
        latitude = self.request.query_params.get('latitude', None)
        longitude = self.request.query_params.get('longitude', None)
        max_distance = self.request.query_params.get('max_distance', None)

        if latitude and longitude:
            point_of_user = Point(float(longitude), float(latitude), srid=4326)

            # Here we're actually doing the query, notice we're using the Distance class fom gis.measure
            queryset = Bike.objects.filter(location__distance_lte=(
                point_of_user, Distance(km=float(max_distance)))).annotate(
                    distance_to_user=DistanceModel("location", point_of_user)
                ).order_by('distance_to_user')
        else:
            queryset = Bike.objects.all()
        return queryset
Esempio n. 15
0
def jsonGen(result):
    bufferMAX = Distance(m=500)
    googlePoint = Point(result["location"]["lng"], result["location"]["lat"])
    postcode = result["postcode"]
    vmPoint = AddressPoint.objects.filter(postcode=postcode).filter(
        geometry__distance_lt=(
            googlePoint,
            bufferMAX)).distance(googlePoint).order_by('distance').first()
    feature = {}
    if vmPoint:
        feature["geometry"] = vmPoint.prop.geometry.json
        feature["properties"] = {
            "id": vmPoint.prop.prop_pfi,
            "address": result['formatted_address']
        }
    return feature
    def handle(self, *args, **options):
        localities = Locality.objects.all()
        total = localities.count()
        for index, locality in enumerate(localities):
            data = locality.repr_dict()
            osm_type = None
            osm_id = None
            certainty = False
            print '%s/%s' % (index, total)
            try:
                # this is obviously from osm
                osm = data['source_url'].split(
                    'www.openstreetmap.org/')[1].split('/')
                osm_type = osm[0]
                osm_id = osm[1]
                certainty = True
            except (IndexError, KeyError):
                name = data['name']
                # TODO: Update how to match this locality and osm
                # check by name match
                by_names = LocalityOSMView.objects.filter(name__iexact=name)
                name_match = True if by_names.count() >= 1 else False

                # check by name location
                by_geom = LocalityOSMView.objects.filter(
                    geometry__distance_lt=(locality.geom, Distance(m=100)))
                if by_geom.count() == 0:
                    by_geom = LocalityOSMView.objects.filter(
                        geometry__contains=locality.geom)
                geom_match = True if by_geom.count() >= 1 else False

                # if geom match and name match, it is same locality
                # if name is not match, certainty is false
                if geom_match:
                    osm_id = by_geom[0].osm_id
                    osm_type = by_geom[0].osm_type
                    if name_match:
                        certainty = True

                print '%s : [%s , %s]' % (name, name_match, geom_match)

            instance, crt = LocalityHealthsitesOSM.objects.get_or_create(
                healthsite=locality)
            instance.osm_id = osm_id
            instance.osm_type = osm_type
            instance.certainty = certainty
            instance.save()
Esempio n. 17
0
def filtered_gas_stations(update: Update, context: CallbackContext):
    chat_id = update.message.chat_id
    user, created = User.objects.get_or_create(
        external_id=chat_id,
        defaults={'username': update.message.from_user.username}
    )
    context.user_data['user_id'] = chat_id
    if not user.active_filter:
        context.bot.send_message(
            chat_id=update.effective_chat.id,
            text='Сначала выберите активный фильтр'
        )
        choose_active_filter(update, context, new=True)
        return
    point = Point(update.message.location.latitude, update.message.location.longitude)
    context.user_data['user_location'] = point
    active_filter = user.active_filter

    filtered_property = {}
    for field in GasStationProperties._meta.get_fields():
        value = getattr(active_filter, field.name)
        if value:
            filtered_property[field.name] = value

    fuel_price_sq = Subquery(FuelPrice.objects. \
                             filter(gas_station=OuterRef('id')). \
                             filter(Q(fuel_type=active_filter.target_fuel) | Q(fuel_type__isnull=True)). \
                             order_by('-date').values('price')[:1])
    search_radius = active_filter.search_radius
    gas_stations = []
    #extend search radius until find at least one gas_station
    for r in range(active_filter.search_radius, active_filter.search_radius * 10):
        gas_stations = GasStation.objects.filter(
            location__distance_lt=(point, Distance(km=r)),
            **filtered_property). \
            annotate(price=fuel_price_sq).order_by('price')
        if gas_stations.count():
            break
        search_radius = r
    message = ('Выберите АЗС' if search_radius == active_filter.search_radius
               else f'В радиусе {active_filter.search_radius} км. нет АЗС. '
                    f'Радиус поиска расширен до {search_radius} км.')
    update.message.reply_text(
        text=message,
        reply_markup=choose_target_gas_station_keyboard(gas_stations)
    )
Esempio n. 18
0
 def get_queryset(self):
         latitude = self.request.query_params.get('latitude', None)
         longitude = self.request.query_params.get('longitude', None)
         max_distance = self.request.query_params.get('max_distance', None)
         if latitude and longitude:
             point_of_user = Point(float(longitude), float(latitude), srid=4326)
             # Here we're actually doing the query, notice we're using the Distance class fom gis.measure
             queryset =Package.objects.filter(
                 location__distance_lte=(
                     point_of_user,
                     Distance(km=float(max_distance))
                 )
             )
             # .annotate( geom=Cast('location', PointField())).filter(geom__within=point_of_user)
         else:
             queryset =Package.objects.all()
         return queryset
Esempio n. 19
0
def result2(request, lat, lon='33.00'):

    if float(lat) < -180 or float(lat) > 180:
        return HttpResponseBadRequest('Error 400')
        #return HttpResponse(status=400);
        #AEN: THIS DOESN'T WORK! Maybe it was, but was just sending an empty page. I WANT THE DEFAULT!
        #raise Http404; #This SHOULD be 400

    pt = 'POINT(%s %s)' % (lon, lat)
    country = WorldBorder.objects.filter(mpoly__contains=pt)

    countriesNearUS = filter(lambda x: x.closeToUS(),
                             WorldBorder.objects.all())

    if not country:
        context = {
            'lat': lat,
            'lon': lon,
            'countriesNearUnitedStates': countriesNearUS
        }
        return render(request, 'world/result.html', context)

    d = Distance(m=500)
    touching = WorldBorder.objects.filter(mpoly__touches=country[0].mpoly)
    neighbors = WorldBorder.objects.filter(
        mpoly__distance_lte=(country[0].mpoly, d))
    neighbors = filter(lambda x: x.id != country[0].id, neighbors)

    t = tasks.getArea.delay(country[0].id)
    t.wait()
    #This should be something far more complicated, like a long pull,Perhaps USING rabbitmq to check based on the task.id!
    area = str(t.result)

    context = {
        'country': country,
        'lat': lat,
        'lon': lon,
        'touching': touching,
        'neighbors': neighbors,
        'distance': d,
        'area': area,
        'countriesNearUnitedStates': countriesNearUS
    }

    return render(request, 'world/result.html', context)
    '''if not country:
Esempio n. 20
0
    def get(self, request, format=None):
        radius = self.request.query_params.get('radius', None)
        point = self.request.query_params.get('point', None)
        bbox = self.request.query_params.get('bbox', None)
        from_date = self.request.query_params.get('from', None)
        to_date = self.request.query_params.get('to', None)
        user = self.request.query_params.get('user', None)
        phenomenon = self.request.query_params.get('phenomenon', None)
        phenomenon_id = self.request.query_params.get('phenomenon_id', None)
        category = self.request.query_params.get('category', None)
        category_id = self.request.query_params.get('category_id', None)

        observations = MetadataObservation.objects.all()
        if (radius and point) and len(point.split(',')) == 2:
            # value in meters
            longitude, latitude = point.split(',')
            point_within = Point(float(longitude), float(latitude))
            observations = observations.filter(
                geometry__distance_lte=(point_within, Distance(m=radius)))
        if bbox and len(bbox.split(',')) == 4:
            # (xmin, ymin, xmax, ymax)
            observations = observations.filter(
                geometry__intersects=Polygon.from_bbox(bbox.split(',')))
        if from_date and to_date:
            observations = observations.filter(
                send_date__gte=datetime.strptime(from_date, '%Y-%m-%d'),
                send_date__lte=datetime.strptime(to_date, '%Y-%m-%d').replace(
                    hour=23, minute=59, second=59))
        if phenomenon:
            observations = observations.filter(
                values__phenomenon__name__iexact=phenomenon)
        if phenomenon_id:
            observations = observations.filter(
                values__phenomenon__id=phenomenon_id)
        if category:
            observations = observations.filter(
                values__phenomenon__category__name__iexact=category)
        if category_id:
            observations = observations.filter(
                values__phenomenon__category__id=category_id)
        observations = observations.distinct()

        paginator = PageNumberPagination()
        result_page = paginator.paginate_queryset(observations, request)
        serializer = MetadataObservationSerializer(result_page, many=True)
        return Response(serializer.data)
    def get_homes_locations_near(lat=chicagolatlng[0],
                                 lng=chicagolatlng[1],
                                 radius=5) -> models.QuerySet:
        """Given `lat`, `lng`, and `radius`, return a list of dicts of

        [
            {
                'home': homes,
                'location': homeLocation,
                'distance': 1.23,
            },
            (...)
        ]

        that are within `radius` miles of `lat`,`lng`.
        """
        bpoint = Point(x=lat, y=lng)

        ret = []  # return dict

        dist = Distance(mi=radius)
        print(dist)

        # all within x miles
        homeLocations = HomeLocation.objects.filter(
            point__distance_lte=(bpoint, dist))

        homeLocation: HomeLocation
        for homeLocation in homeLocations:  # construct return dict
            homepoint = homeLocation.point

            print(bpoint)
            print(homepoint)

            dist = calc_dist_p_miles(bpoint, homepoint)

            ret.append({
                'home': homeLocation.get_home(),
                'location': homeLocation,
                'distance': dist,
            })

        pprint(ret)

        return ret
Esempio n. 22
0
def erp_details(request, commune, erp_slug, activite_slug=None):
    base_qs = (Erp.objects.select_related(
        "accessibilite",
        "activite",
        "commune_ext",
        "user",
    ).published().with_votes().filter(commune_ext__slug=commune,
                                      slug=erp_slug))
    if activite_slug:
        base_qs = base_qs.filter(activite__slug=activite_slug)
    erp = get_object_or_404(base_qs)
    nearest_erps = (Erp.objects.select_related(
        "accessibilite", "activite", "commune_ext").published().nearest(
            erp.geom).filter(distance__lt=Distance(km=20))[:10])
    geojson_list = make_geojson(nearest_erps)
    form = forms.ViewAccessibiliteForm(instance=erp.accessibilite)
    accessibilite_data = form.get_accessibilite_data()
    user_vote = (request.user.is_authenticated and
                 not Vote.objects.filter(user=request.user, erp=erp).exists()
                 and request.user != erp.user)
    user_is_subscribed = request.user.is_authenticated and erp.is_subscribed_by(
        request.user)
    url_widget_js = f"{settings.SITE_ROOT_URL}/static/js/widget.js"

    widget_tag = f"""<div id="widget-a11y-container" data-pk="{erp.uuid}" data-baseurl="{settings.SITE_ROOT_URL}"></div>\n
<a href="#" aria-haspopup="dialog" aria-controls="dialog">Accessibilité</a>
<script src="{url_widget_js}" type="text/javascript" async="true"></script>\n"""
    return render(
        request,
        "erp/index.html",
        context={
            "accessibilite_data": accessibilite_data,
            "activite": erp.activite,
            "commune": erp.commune_ext,
            "commune_json": erp.commune_ext.toTemplateJson(),
            "erp": erp,
            "geojson_list": geojson_list,
            "nearest_erps": nearest_erps,
            "widget_tag": widget_tag,
            "url_widget_js": url_widget_js,
            "root_url": settings.SITE_ROOT_URL,
            "user_is_subscribed": user_is_subscribed,
            "user_vote": user_vote,
        },
    )
Esempio n. 23
0
    def validate(self, attrs):
        if not attrs['lat'] or not attrs['lng']:
            raise serializers.ValidationError(
                "Dacă nu ești la turn, nu poți face provocarea!")

        if not attrs['tower']:
            raise serializers.ValidationError("Trebuie un turn!")

        point = Point(attrs['lng'], attrs['lat'])
        try:
            Tower.objects.filter(pk=attrs['tower'].id,
                                 location__distance_lt=(point, Distance(m=50)))
        except Tower.DoesNotExist:
            raise serializers.ValidationError(
                "Trebuie să fii la maxim 50 de metri de turn pentru a putea face provoarea!"
            )

        return attrs
Esempio n. 24
0
def buffer_geometry(geometry, extent_in_nm):
    """
    Buffer geometry by projecting it to a coordinate system
    in meters.

    Buffer the geometry by extent_in_nm.

    Reproject the geometry back into WGS84
    """
    extent_in_m = Distance(nm=extent_in_nm).m
    projected = geometry.transform(PROJ_4326_TO_7314, clone=True)
    buffered = projected.buffer(extent_in_m)
    buffered.srid = 7314
    unprojected = buffered.transform(PROJ_7314_TO_4326, clone=True)
    unprojected.srid = 4326
    multipolygon = unwrap_multipolygon(MultiPolygon(unprojected))
    multipolygon.srid = 4326
    return multipolygon
Esempio n. 25
0
 def convert_values(self, value, field):
     """
     Using the same routines that Oracle does we can convert our
     extra selection objects into Geometry and Distance objects.
     TODO: Laziness.
     """
     if SpatialBackend.oracle:
         # Running through Oracle's first.
         value = super(GeoQuery, self).convert_values(value, field)
     if isinstance(field, DistanceField):
         # Using the field's distance attribute, can instantiate
         # `Distance` with the right context.
         value = Distance(**{field.distance_att: value})
     elif isinstance(field, AreaField):
         value = Area(**{field.area_att: value})
     elif isinstance(field, GeomField):
         value = SpatialBackend.Geometry(value)
     return value
Esempio n. 26
0
 def get_distance(self, f, value, lookup_type):
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             raise ValueError(
                 'SAP HANA does not support distance queries on '
                 'geometry fields with a geodetic coordinate system. '
                 'Distance objects; use a numeric value of your '
                 'distance in degrees instead.')
         else:
             dist_param = getattr(
                 value,
                 Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
    def get_distance(self, f, dist_val, lookup_type, handle_spheroid=True):
        """
        Retrieve the distance parameters for the given geometry field,
        distance lookup value, and the distance lookup type.

        This is the most complex implementation of the spatial backends due to
        what is supported on geodetic geometry columns vs. what's available on
        projected geometry columns.  In addition, it has to take into account
        the geography column type.
        """
        # Getting the distance parameter
        value = dist_val[0]

        # Shorthand boolean flags.
        geodetic = f.geodetic(self.connection)
        geography = f.geography

        if isinstance(value, Distance):
            if geography:
                dist_param = value.m
            elif geodetic:
                if lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are '
                                     'allowed on geographic DWithin queries.')
                dist_param = value.m
            else:
                dist_param = getattr(
                    value,
                    Distance.unit_attname(f.units_name(self.connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = value

        params = [dist_param]
        # handle_spheroid *might* be dropped in Django 2.0 as PostGISDistanceOperator
        # also handles it (#25524).
        if handle_spheroid and len(dist_val) > 1:
            option = dist_val[1]
            if (not geography and geodetic and lookup_type != 'dwithin'
                    and option == 'spheroid'):
                # using distance_spheroid requires the spheroid of the field as
                # a parameter.
                params.insert(0, f._spheroid)
        return params
Esempio n. 28
0
def ride_search(request: HttpRequest) -> JsonResponse:
    try:
        post = json.loads(request.body)
    except json.JSONDecodeError:
        return JsonResponse('', status=status.HTTP_400_BAD_REQUEST, safe=False)
    query = Q()
    if 'latitude' not in post or 'longitude' not in post:
        return JsonResponse('', status=status.HTTP_400_BAD_REQUEST, safe=False)
    initial_point = Point(post['longitude'], post['latitude'])
    if 'title' in post:
        query |= Q(title__contains=post['title'])
    if 'start_loc_name' in post:
        query |= Q(start_loc__contains=post['start_loc_name'])
    if 'end_loc_name' in post:
        query |= Q(end_loc__contains=post['end_loc_name'])
    if 'max_start_dist' in post:
        max_dist = float(re.sub(r'\D', '', post['max_start_dist']))
        if post['max_start_dist'][-1] == 'm':
            query &= Q(start_loc__distance_lt=(initial_point, Distance(m=max_dist)))
        elif post['max_start_dist'][-2:] == 'km':
            query &= Q(start_loc__distance_lt=(initial_point, Distance(km=max_dist)))
        elif post['max_start_dist'][-2:] == 'yd':
            query &= Q(start_loc__distance_lt=(initial_point, Distance(yd=max_dist)))
        elif post['max_start_dist'][-2:] == 'mi':
            query &= Q(start_loc__distance_lt=(initial_point, Distance(mi=max_dist)))
        else:
            print('invalid units in distance {}'.format(post['max_start_dist']))
    if 'max_end_dist' in post:
        max_dist = float(re.sub(r'\D', '', post['max_end_dist']))
        if post['max_end_dist'][-1] == 'm':
            query &= Q(end_loc__distance_lt=(initial_point, Distance(m=max_dist)))
        elif post['max_end_dist'][-2:] == 'km':
            query &= Q(end_loc__distance_lt=(initial_point, Distance(km=max_dist)))
        elif post['max_end_dist'][-2:] == 'yd':
            query &= Q(end_loc__distance_lt=(initial_point, Distance(yd=max_dist)))
        elif post['max_end_dist'][-2:] == 'mi':
            query &= Q(end_loc__distance_lt=(initial_point, Distance(mi=max_dist)))
        else:
            print('invalid units in distance {}'.format(post['max_end_dist']))
    rides = Ride.objects.filter(query).all()
    return JsonResponse(serialize_public_rides(rides), safe=False)
Esempio n. 29
0
 def test_distance_search_api_result(self):
     c = Consumer.objects.all()[0]
     r = Report(product=Product.objects.all()[2],
                price=100,
                pnt='POINT(-200.1000 44.0489)',
                consumer=c)
     r.save()
     search = {
         "product_query": "product",
         'pnt': 'POINT(-200.1000 44.0000)',
         'distance': 100
     }
     response = self.client.post('/reports/search', data=search).json()
     pnt = GEOSGeometry('POINT(-200.1000 44.0000)', srid=SRID)
     self.assertEqual(
         len(response['results']['features']),
         len(
             Report.objects.filter(pnt__distance_lte=(pnt,
                                                      Distance(km=100)))))
Esempio n. 30
0
 def get(self, request):
     request_user = request.user
     profile = request_user.profile
     distance = profile.search_distance
     post = Post.objects.select_related('user').filter(
         ~Q(user=request_user)
         & Q(user__profile__location__distance_lt=(profile.location,
                                                   Distance(km=distance)))
         &  # TODO distance based on subscription
         ~Q(user__profile__in=profile.viewed.all())).first()
     if not post:
         return Response(
             data={
                 'message': 'found no one around',
                 'tip': f"You can try to clear viewed users in your profile"
             })
     profile.viewed.add(post.user.profile)
     serializer = PostSerializer(post, context={'request': request})
     return Response(serializer.data)
Esempio n. 31
0
def recommendations(request, n):
    radius = 5
    current_user = User.objects.get(name=n)
    recommendations_list = User.objects.filter(
        location__dwithin=(current_user.location, Distance(km=radius)))
    latitude = []
    longitude = []
    names = []
    for u in recommendations_list:
        if (u.name != n):
            latitude.append(u.location.y)
            longitude.append(u.location.x)
            names.append(u.name)
    context = {'latitude': latitude, 'longitude': longitude, 'names': names}
    return render(request, 'lex/recommendations.html',
                  {"recommendations": json.dumps(context)})


# Create your views here.
Esempio n. 32
0
    def get_distance(self, f, dist_val, lookup_type):
        """
        Retrieve the distance parameters for the given geometry field,
        distance lookup value, and the distance lookup type.

        This is the most complex implementation of the spatial backends due to
        what is supported on geodetic geometry columns vs. what's available on
        projected geometry columns.  In addition, it has to take into account
        the newly introduced geography column type introudced in PostGIS 1.5.
        """
        # Getting the distance parameter and any options.
        if len(dist_val) == 1:
            value, option = dist_val[0], None
        else:
            value, option = dist_val

        # Shorthand boolean flags.
        geodetic = f.geodetic(self.connection)
        geography = f.geography and self.geography

        if isinstance(value, Distance):
            if geography:
                dist_param = value.m
            elif geodetic:
                if lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are '
                                     'allowed on geographic DWithin queries.')
                dist_param = value.m
            else:
                dist_param = getattr(
                    value,
                    Distance.unit_attname(f.units_name(self.connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = value

        if (not geography and geodetic and lookup_type != 'dwithin'
                and option == 'spheroid'):
            # using distance_spheroid requires the spheroid of the field as
            # a parameter.
            return [f._spheroid, dist_param]
        else:
            return [dist_param]
Esempio n. 33
0
    def get_distance(self, f, dist_val, lookup_type, handle_spheroid=True):
        """
        Retrieve the distance parameters for the given geometry field,
        distance lookup value, and the distance lookup type.

        This is the most complex implementation of the spatial backends due to
        what is supported on geodetic geometry columns vs. what's available on
        projected geometry columns.  In addition, it has to take into account
        the geography column type.
        """
        # Getting the distance parameter
        value = dist_val[0]

        # Shorthand boolean flags.
        geodetic = f.geodetic(self.connection)
        geography = f.geography

        if isinstance(value, Distance):
            if geography:
                dist_param = value.m
            elif geodetic:
                if lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are '
                                     'allowed on geographic DWithin queries.')
                dist_param = value.m
            else:
                dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = value

        params = [dist_param]
        # handle_spheroid *might* be dropped in Django 2.0 as PostGISDistanceOperator
        # also handles it (#25524).
        if handle_spheroid and len(dist_val) > 1:
            option = dist_val[1]
            if (not geography and geodetic and lookup_type != 'dwithin'
                    and option == 'spheroid'):
                # using distance_spheroid requires the spheroid of the field as
                # a parameter.
                params.insert(0, f._spheroid)
        return params
Esempio n. 34
0
    def filter_queryset(self, request, queryset, view):
        filter_field = getattr(view, 'distance_filter_field', None)
        radius = request.query_params.get(self.radius_param, None)
        point = self.get_filter_point(request)

        if not all((filter_field, radius, point)):
            return queryset

        # distance in meters
        try:
            dist = Distance(m=radius)
        except TypeError:
            raise ParseError(
                'Invalid distance string supplied for parameter {0}'.format(
                    self.radius_param))

        return queryset.filter(
            Q(**{'{}__distance_lt'.format(filter_field): (
                     point, dist)})).annotate(distance=DistanceFunc(
                         'coordinates', Point(point.x, point.y, srid=4326)))
Esempio n. 35
0
 def _process_preexisting(self, location):
     erp = (Erp.objects.exclude(source=Erp.SOURCE_NESTENN).filter(
         activite=self.activite,
         geom__distance_lte=(location, Distance(m=2000)),
     ).first())
     if erp:
         # unpublish already imported duplicate
         old_erp = Erp.objects.find_by_source_id(
             Erp.SOURCE_NESTENN,
             self.record["id"],
             published=True,
         ).first()
         if old_erp:
             old_erp.published = False
             old_erp.save()
             logger.info(f"Unpublished obsolete duplicate: {str(old_erp)}")
         # update preexisting erp with new import information
         erp.source = Erp.SOURCE_NESTENN
         erp.source_id = self.record["id"]
     return erp
Esempio n. 36
0
    def convert_values(self, value, field, connection):
        """        Using the same routines that Oracle does we can convert our
        extra selection objects into Geometry and Distance objects.
        TODO: Make converted objects 'lazy' for less overhead.
        """
        if connection.ops.oracle:
            # Running through Oracle's first.
            value = super(GeoQuery,
                          self).convert_values(value, field or GeomField(),
                                               connection)

        if isinstance(field, DistanceField):
            # Using the field's distance attribute, can instantiate
            # `Distance` with the right context.
            value = Distance(**{field.distance_att: value})
        elif isinstance(field, AreaField):
            value = Area(**{field.area_att: value})
        elif isinstance(field, (GeomField, GeometryField)) and value:
            value = Geometry(value)
        return value
Esempio n. 37
0
    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)
Esempio n. 38
0
    def get_queryset(self):
        query_params = Q()
        categories_params = Q()
        exclude_dates_params = Q()

        categories = self.request.query_params.getlist('categories[]')
        latitude = (self.request.query_params.get('lat'))
        longitude = (self.request.query_params.get('lng'))
        distance = (self.request.query_params.get('miles'))
        min_price = (self.request.query_params.get('minPrice'))
        max_price = (self.request.query_params.get('maxPrice'))
        start_date = (self.request.query_params.get('startDate'))
        end_date = (self.request.query_params.get('endDate'))
        gear = (self.request.query_params.get('gear'))
        user = (self.request.query_params.get('user'))

        if latitude and longitude and distance:
            center = fromstr("POINT({} {})".format(latitude, longitude))
            distance_from_point = {'mi': distance}
            query_params.add(Q(point__distance_lte=(center, Distance(**distance_from_point))), query_params.connector)
        if min_price:
            query_params.add(Q(gear__price__gte=min_price), query_params.connector)
        if max_price:
            query_params.add(Q(gear__price__lte=max_price), query_params.connector)
        if gear:
            query_params.add(Q(gear__id=gear), query_params.connector)
        if user:
            query_params.add(Q(gear__user__id=user), query_params.connector)

        if start_date:
            start = datetime.strptime(start_date, "%Y-%m-%d")
            exclude_dates_params.add(Q(gear__gearavailability__not_available_date__gte=start), query_params.connector)
        if end_date:
            end = datetime.strptime(end_date, "%Y-%m-%d")
            exclude_dates_params.add(Q(gear__gearavailability__not_available_date__lte=end), query_params.connector)

        for i in categories:
            categories_params.add(Q(gear__category__id=i), categories_params.OR)

        queryset = self.queryset.filter(query_params).filter(categories_params).exclude(exclude_dates_params)#.distance(center).order_by('distance')
        return queryset
Esempio n. 39
0
    def get_distance(self, f, dist_val, lookup_type):
        """
        Retrieve the distance parameters for the given geometry field,
        distance lookup value, and the distance lookup type.

        This is the most complex implementation of the spatial backends due to
        what is supported on geodetic geometry columns vs. what's available on
        projected geometry columns.  In addition, it has to take into account
        the newly introduced geography column type introudced in PostGIS 1.5.
        """
        # Getting the distance parameter and any options.
        if len(dist_val) == 1:
            value, option = dist_val[0], None
        else:
            value, option = dist_val

        # Shorthand boolean flags.
        geodetic = f.geodetic(self.connection)
        geography = f.geography and self.geography

        if isinstance(value, Distance):
            if geography:
                dist_param = value.m
            elif geodetic:
                if lookup_type == 'dwithin':
                    raise ValueError('Only numeric values of degree units are '
                                     'allowed on geographic DWithin queries.')
                dist_param = value.m
            else:
                dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
        else:
            # Assuming the distance is in the units of the field.
            dist_param = value

        if (not geography and geodetic and lookup_type != 'dwithin'
            and option == 'spheroid'):
            # using distance_spheroid requires the spheroid of the field as
            # a parameter.
            return [f._spheroid, dist_param]
        else:
            return [dist_param]
Esempio n. 40
0
 def get_distance(self, f, value, lookup_type):
     """
     Returns the distance parameters for the given geometry field,
     lookup value, and lookup type.  This is based on the Spatialite
     backend, since we don't currently support geography operations.
     """
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             raise ValueError('The SQL Server backend does not support '
                              'distance queries on geometry fields with '
                              'a geodetic coordinate system. Distance '
                              'objects; use a numeric value of your '
                              'distance in degrees instead.')
         else:
             dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 41
0
 def get_distance(self, f, value, lookup_type):
     """
     Returns the distance parameters for the given geometry field,
     lookup value, and lookup type.  SpatiaLite only supports regular
     cartesian-based queries (no spheroid/sphere calculations for point
     geometries like PostGIS).
     """
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             raise ValueError('SpatiaLite does not support distance queries on '
                              'geometry fields with a geodetic coordinate system. '
                              'Distance objects; use a numeric value of your '
                              'distance in degrees instead.')
         else:
             dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 42
0
 def get_distance(self, f, value, lookup_type, **kwargs):
     """
     Return the distance parameters for the given geometry field,
     lookup value, and lookup type.
     """
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             if lookup_type == 'dwithin':
                 raise ValueError(
                     'Only numeric values of degree units are allowed on '
                     'geographic DWithin queries.'
                 )
             dist_param = value.m
         else:
             dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 43
0
 def get_distance(self, f, value, lookup_type):
     """
     Return the distance parameters for the given geometry field,
     lookup value, and lookup type.
     """
     if not value:
         return []
     value = value[0]
     if isinstance(value, Distance):
         if f.geodetic(self.connection):
             if lookup_type == 'dwithin':
                 raise ValueError(
                     'Only numeric values of degree units are allowed on '
                     'geographic DWithin queries.'
                 )
             dist_param = value.m
         else:
             dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
     else:
         dist_param = value
     return [dist_param]
Esempio n. 44
0
    def get_distance(self, f, value, lookup_type):
        """
        Returns the distance parameters given the value and the lookup type.
        On Oracle, geometry columns with a geodetic coordinate system behave
        implicitly like a geography column, and thus meters will be used as
        the distance parameter on them.
        """
        if not value:
            return []
        value = value[0]
        if isinstance(value, Distance):
            if f.geodetic(self.connection):
                dist_param = value.m
            else:
                dist_param = getattr(value, Distance.unit_attname(f.units_name(self.connection)))
        else:
            dist_param = value

        # dwithin lookups on oracle require a special string parameter
        # that starts with "distance=".
        if lookup_type == 'dwithin':
            dist_param = 'distance=%s' % dist_param

        return [dist_param]
Esempio n. 45
0
"""
Esempio n. 46
0
import re
Esempio n. 47
0
from decimal import Decimal
Esempio n. 48
0
    def _distance_attribute(self, func, geom=None, tolerance=0.05, spheroid=False, **kwargs):
        """
        DRY routine for GeoQuerySet distance attribute routines.
        """
        # Setting up the distance procedure arguments.
        procedure_args, geo_field = self._spatial_setup(func, field_name=kwargs.get('field_name', None))

        # If geodetic defaulting distance attribute to meters (Oracle and
        # PostGIS spherical distances return meters).  Otherwise, use the
        # units of the geometry field.
        if geo_field.geodetic:
            dist_att = 'm'
        else:
            dist_att = Distance.unit_attname(geo_field._unit_name)

        # Shortcut booleans for what distance function we're using.
        distance = func == 'distance'
        length = func == 'length'
        perimeter = func == 'perimeter'
        if not (distance or length or perimeter):
            raise ValueError('Unknown distance function: %s' % func)

        # The field's get_db_prep_lookup() is used to get any
        # extra distance parameters.  Here we set up the
        # parameters that will be passed in to field's function.
        lookup_params = [geom or 'POINT (0 0)', 0]

        # If the spheroid calculation is desired, either by the `spheroid`
        # keyword or wehn calculating the length of geodetic field, make
        # sure the 'spheroid' distance setting string is passed in so we
        # get the correct spatial stored procedure.
        if spheroid or (SpatialBackend.postgis and geo_field.geodetic and length):
            lookup_params.append('spheroid')
        where, params = geo_field.get_db_prep_lookup('distance_lte', lookup_params)

        # The `geom_args` flag is set to true if a geometry parameter was
        # passed in.
        geom_args = bool(geom)

        if SpatialBackend.oracle:
            if distance:
                procedure_fmt = '%(geo_col)s,%(geom)s,%(tolerance)s'
            elif length or perimeter:
                procedure_fmt = '%(geo_col)s,%(tolerance)s'
            procedure_args['tolerance'] = tolerance
        else:
            # Getting whether this field is in units of degrees since the field may have
            # been transformed via the `transform` GeoQuerySet method.
            if self.query.transformed_srid:
                u, unit_name, s = get_srid_info(self.query.transformed_srid)
                geodetic = unit_name in geo_field.geodetic_units
            else:
                geodetic = geo_field.geodetic

            if distance:
                if self.query.transformed_srid:
                    # Setting the `geom_args` flag to false because we want to handle
                    # transformation SQL here, rather than the way done by default
                    # (which will transform to the original SRID of the field rather
                    #  than to what was transformed to).
                    geom_args = False
                    procedure_fmt = '%s(%%(geo_col)s, %s)' % (SpatialBackend.transform, self.query.transformed_srid)
                    if geom.srid is None or geom.srid == self.query.transformed_srid:
                        # If the geom parameter srid is None, it is assumed the coordinates
                        # are in the transformed units.  A placeholder is used for the
                        # geometry parameter.
                        procedure_fmt += ', %%s'
                    else:
                        # We need to transform the geom to the srid specified in `transform()`,
                        # so wrapping the geometry placeholder in transformation SQL.
                        procedure_fmt += ', %s(%%%%s, %s)' % (SpatialBackend.transform, self.query.transformed_srid)
                else:
                    # `transform()` was not used on this GeoQuerySet.
                    procedure_fmt  = '%(geo_col)s,%(geom)s'

                if geodetic:
                    # Spherical distance calculation is needed (because the geographic
                    # field is geodetic). However, the PostGIS ST_distance_sphere/spheroid()
                    # procedures may only do queries from point columns to point geometries
                    # some error checking is required.
                    if not isinstance(geo_field, PointField):
                        raise TypeError('Spherical distance calculation only supported on PointFields.')
                    if not str(SpatialBackend.Geometry(buffer(params[0].wkb)).geom_type) == 'Point':
                        raise TypeError('Spherical distance calculation only supported with Point Geometry parameters')
                    # The `function` procedure argument needs to be set differently for
                    # geodetic distance calculations.
                    if spheroid:
                        # Call to distance_spheroid() requires spheroid param as well.
                        procedure_fmt += ',%(spheroid)s'
                        procedure_args.update({'function' : SpatialBackend.distance_spheroid, 'spheroid' : where[1]})
                    else:
                        procedure_args.update({'function' : SpatialBackend.distance_sphere})
            elif length or perimeter:
                procedure_fmt = '%(geo_col)s'
                if geodetic and length:
                    # There's no `length_sphere`
                    procedure_fmt += ',%(spheroid)s'
                    procedure_args.update({'function' : SpatialBackend.length_spheroid, 'spheroid' : where[1]})

        # Setting up the settings for `_spatial_attribute`.
        s = {'select_field' : DistanceField(dist_att),
             'setup' : False,
             'geo_field' : geo_field,
             'procedure_args' : procedure_args,
             'procedure_fmt' : procedure_fmt,
             }
        if geom_args:
            s['geom_args'] = ('geom',)
            s['procedure_args']['geom'] = geom
        elif geom:
            # The geometry is passed in as a parameter because we handled
            # transformation conditions in this routine.
            s['select_params'] = [SpatialBackend.Adaptor(geom)]
        return self._spatial_attribute(func, s, **kwargs)
Esempio n. 49
0
    def _distance_attribute(self, func, geom=None, tolerance=0.05, spheroid=False, **kwargs):
        """
        DRY routine for GeoQuerySet distance attribute routines.
        """
        # Setting up the distance procedure arguments.
        procedure_args, geo_field = self._spatial_setup(func, field_name=kwargs.get('field_name'))

        # If geodetic defaulting distance attribute to meters (Oracle and
        # PostGIS spherical distances return meters).  Otherwise, use the
        # units of the geometry field.
        connection = connections[self.db]
        geodetic = geo_field.geodetic(connection)
        geography = geo_field.geography

        if geodetic:
            dist_att = 'm'
        else:
            dist_att = Distance.unit_attname(geo_field.units_name(connection))

        # Shortcut booleans for what distance function we're using and
        # whether the geometry field is 3D.
        distance = func == 'distance'
        length = func == 'length'
        perimeter = func == 'perimeter'
        if not (distance or length or perimeter):
            raise ValueError('Unknown distance function: %s' % func)
        geom_3d = geo_field.dim == 3

        # The field's get_db_prep_lookup() is used to get any
        # extra distance parameters.  Here we set up the
        # parameters that will be passed in to field's function.
        lookup_params = [geom or 'POINT (0 0)', 0]

        # Getting the spatial backend operations.
        backend = connection.ops

        # If the spheroid calculation is desired, either by the `spheroid`
        # keyword or when calculating the length of geodetic field, make
        # sure the 'spheroid' distance setting string is passed in so we
        # get the correct spatial stored procedure.
        if spheroid or (backend.postgis and geodetic and
                        (not geography) and length):
            lookup_params.append('spheroid')
        lookup_params = geo_field.get_prep_value(lookup_params)
        params = geo_field.get_db_prep_lookup('distance_lte', lookup_params, connection=connection)

        # The `geom_args` flag is set to true if a geometry parameter was
        # passed in.
        geom_args = bool(geom)

        if backend.oracle:
            if distance:
                procedure_fmt = '%(geo_col)s,%(geom)s,%(tolerance)s'
            elif length or perimeter:
                procedure_fmt = '%(geo_col)s,%(tolerance)s'
            procedure_args['tolerance'] = tolerance
        else:
            # Getting whether this field is in units of degrees since the field may have
            # been transformed via the `transform` GeoQuerySet method.
            srid = self.query.get_context('transformed_srid')
            if srid:
                u, unit_name, s = get_srid_info(srid, connection)
                geodetic = unit_name.lower() in geo_field.geodetic_units

            if geodetic and not connection.features.supports_distance_geodetic:
                raise ValueError(
                    'This database does not support linear distance '
                    'calculations on geodetic coordinate systems.'
                )

            if distance:
                if srid:
                    # Setting the `geom_args` flag to false because we want to handle
                    # transformation SQL here, rather than the way done by default
                    # (which will transform to the original SRID of the field rather
                    #  than to what was transformed to).
                    geom_args = False
                    procedure_fmt = '%s(%%(geo_col)s, %s)' % (backend.transform, srid)
                    if geom.srid is None or geom.srid == srid:
                        # If the geom parameter srid is None, it is assumed the coordinates
                        # are in the transformed units.  A placeholder is used for the
                        # geometry parameter.  `GeomFromText` constructor is also needed
                        # to wrap geom placeholder for SpatiaLite.
                        if backend.spatialite:
                            procedure_fmt += ', %s(%%%%s, %s)' % (backend.from_text, srid)
                        else:
                            procedure_fmt += ', %%s'
                    else:
                        # We need to transform the geom to the srid specified in `transform()`,
                        # so wrapping the geometry placeholder in transformation SQL.
                        # SpatiaLite also needs geometry placeholder wrapped in `GeomFromText`
                        # constructor.
                        if backend.spatialite:
                            procedure_fmt += (', %s(%s(%%%%s, %s), %s)' % (
                                backend.transform, backend.from_text,
                                geom.srid, srid))
                        else:
                            procedure_fmt += ', %s(%%%%s, %s)' % (backend.transform, srid)
                else:
                    # `transform()` was not used on this GeoQuerySet.
                    procedure_fmt = '%(geo_col)s,%(geom)s'

                if not geography and geodetic:
                    # Spherical distance calculation is needed (because the geographic
                    # field is geodetic). However, the PostGIS ST_distance_sphere/spheroid()
                    # procedures may only do queries from point columns to point geometries
                    # some error checking is required.
                    if not backend.geography:
                        if not isinstance(geo_field, PointField):
                            raise ValueError('Spherical distance calculation only supported on PointFields.')
                        if not str(Geometry(six.memoryview(params[0].ewkb)).geom_type) == 'Point':
                            raise ValueError(
                                'Spherical distance calculation only supported with '
                                'Point Geometry parameters'
                            )
                    # The `function` procedure argument needs to be set differently for
                    # geodetic distance calculations.
                    if spheroid:
                        # Call to distance_spheroid() requires spheroid param as well.
                        procedure_fmt += ",'%(spheroid)s'"
                        procedure_args.update({'function': backend.distance_spheroid, 'spheroid': params[1]})
                    else:
                        procedure_args.update({'function': backend.distance_sphere})
            elif length or perimeter:
                procedure_fmt = '%(geo_col)s'
                if not geography and geodetic and length:
                    # There's no `length_sphere`, and `length_spheroid` also
                    # works on 3D geometries.
                    procedure_fmt += ",'%(spheroid)s'"
                    procedure_args.update({'function': backend.length_spheroid, 'spheroid': params[1]})
                elif geom_3d and connection.features.supports_3d_functions:
                    # Use 3D variants of perimeter and length routines on supported backends.
                    if perimeter:
                        procedure_args.update({'function': backend.perimeter3d})
                    elif length:
                        procedure_args.update({'function': backend.length3d})

        # Setting up the settings for `_spatial_attribute`.
        s = {'select_field': DistanceField(dist_att),
             'setup': False,
             'geo_field': geo_field,
             'procedure_args': procedure_args,
             'procedure_fmt': procedure_fmt,
             }
        if geom_args:
            s['geom_args'] = ('geom',)
            s['procedure_args']['geom'] = geom
        elif geom:
            # The geometry is passed in as a parameter because we handled
            # transformation conditions in this routine.
            s['select_params'] = [backend.Adapter(geom)]
        return self._spatial_attribute(func, s, **kwargs)
Esempio n. 50
0
import warnings
Esempio n. 51
0
"""