Filtering objects in specified radius

44 views
Skip to first unread message

MikiSoft

unread,
Dec 2, 2016, 9:53:06 PM12/2/16
to SpatiaLite Users
models.py -> User and Business model contain this field:

location = PointField(geography=True)

I'm retrieving via Google Maps Geocode service latitude and longitude from user-input address and then store it in that field above when saving User and Business object.

Now, what I want is to get all nearby Business objects based on user's location:

Business.objects.filter(location__distance_lt=(User.objects.first().location, D(km=1)))

But it doesn't work, it throws this error:

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.

So, does anyone know how to fix this? Thanks in advance!

MikiSoft

unread,
Dec 2, 2016, 9:55:02 PM12/2/16
to SpatiaLite Users
Oh and forgot to mention (although it's obvious) - I'm using (Geo)Django here.

mj10777

unread,
Dec 2, 2016, 10:24:15 PM12/2/16
to SpatiaLite Users
I have no idea on how to use (Geo)Django, so you would have to see how they deal with such matters.

ST_Buffer(user_point,1000) would get you a circle of a 1000 meters around a point.

ST_Transform(ST_Buffer(user_point,1000),4326) would get you a circle (more like an Ellipse) of that 1000 meters around a point as WSG84.

SELECT
 gcp_point, ST_Buffer(gcp_point,1) AS gcp_point_1km,
 ST_Transform(ST_Buffer(gcp_point,1),4326) ASgcp_point_1km_wsg84,
 ST_MaxX(ST_Transform(ST_Buffer(gcp_point,1),4326))-ST_MinX(ST_Transform(ST_Buffer(gcp_point,1),4326)) AS distance_x_degrees,
 ST_MaxY(ST_Transform(ST_Buffer(gcp_point,1),4326))-ST_MinY(ST_Transform(ST_Buffer(gcp_point,1),4326)) AS distance_y_degrees,
 (((ST_MaxX(ST_Transform(ST_Buffer(gcp_point,1),4326))-ST_MinX(ST_Transform(ST_Buffer(gcp_point,1),4326)))+
  (ST_MaxY(ST_Transform(ST_Buffer(gcp_point,1),4326))-ST_MinY(ST_Transform(ST_Buffer(gcp_point,1),4326))))/2) AS distance_average_degrees
FROM gcp_master
LIMIT 1

distance_x_degrees: 0.000029
distance_y_degrees: 0.000018
distance_average_degrees: 0.000024


mj10777

unread,
Dec 2, 2016, 10:30:43 PM12/2/16
to SpatiaLite Users
(Sorry, that was sent off  while editing)

So distance_average_degrees is what you need.

So you will have to look what (Geo)Django has to offer
or
call spatialite directly to replace the result of '(User.objects.first().location, D(km=1))'

Mark

MikiSoft

unread,
Dec 3, 2016, 9:10:27 AM12/3/16
to SpatiaLite Users
Okay thanks for the answer, I'm still trying to wrap my head around it. I have no idea how to do this in Django and I'm still trying to learn about geographical and geometrical systems, but so far no avail...

a.fu...@lqt.it

unread,
Dec 3, 2016, 11:24:59 AM12/3/16
to spatiali...@googlegroups.com
On Sat, 3 Dec 2016 06:10:27 -0800 (PST), MikiSoft wrote:
> Okay thanks for the answer, I'm still trying to wrap my head around
> it. I have no idea how to do this in Django and I'm still trying to
> learn about geographical and geometrical systems, but so far no
> avail...
>

just a very short summary, hoping this could help you someway.

a. planet Earth is a sphere; more precisely, it's an ellipsoid
slightly flattened at both Poles.
the most natural system allowing to precisely identify any
possible point laying on the surface of an ellipsoid is by
measuring two ANGLES, the latitude and the longitude.
this is a "geographical" system, and the natural unit of
measure for any geographical system are "degrees" as an
obvious consequence of using angular coordinates.

b. if we are not interested in mapping the whole planet
but just a very limited small portion of it (France,
or Argentina or New Zealand etc) we can use some
appropriate geometric projection, so to get a planar
representation of such small area. this is a "cartesian"
or "geometric" or "projected" system.
and in this case we are finally free to adopt more
familiars cartesian coordinates measured in metres
(or inches, or whatever else intending a length
measure).
but such an approach can safely work only if the
region projected on the plane is very narrow; a
commonly adopted requirement is to fix a maximum
extent of 6 longitude degrees, so to avoid introducing
too strong deformations and errors.

note: converting angular distances on a spheroid surface
into more conventional length units (meters, inches etc)
is a complex and hard mathematical problem, because no
fixed ratio exists.
just few practical examples to understand better:

near the Equator:
=================
point A long=11.5 lat=1.5
point B long=12.5 lat=2.5 distance is about 157 Km

somewhere midway between the Equator and the North Pole:
========================================================
point A long=11.5 lat=41.5
point B long=12.5 lat=42.5 distance is about 138 Km

near the North Pole:
====================
point A long=11.5 lat=81.5
point B long=12.5 lat=82.5 distance is about 112 Km

we are always measuring a diagonal on a square of
exactly 1 degree by 1 degree, but as you can easily
notice the metric distances show an impressive
dispersion depending on their actual positions.


short conclusion: if you are mainly interested into
supporting the planet as a whole (as it happens in aerial
or maritime navigation systems) using a geographical
system is the obvious best option.
but in this case you should be prepared to always use
complex and computationally heavy geodetic formulae
every time that you wish to get a precise distance
measure expressed in length units (meters, inches etc).

if instead you are mainly interested in supporting
just a single state or region (as it usually happens
in car or railway navigation systems) using an
appropriate projected-planar system will surely make
your life much easier.

bye Sandro

MikiSoft

unread,
Dec 3, 2016, 12:04:34 PM12/3/16
to SpatiaLite Users
Thank you so much for detailed explanation! I understand now this much better. I'm actually now trying to convert angles and store them into projected system, so I can use them later for calculations about distance and such.
Reply all
Reply to author
Forward
0 new messages