#25498 closed Cleanup/optimization (fixed)
PostGIS Distance lookups use ST_Distance_Sphere() and not ST_Distance()
Reported by: | Bibhas C Debnath | Owned by: | nobody |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Currently the doc says that PostGIS uses ST_Distance()
for distance lookups like distance_gte
etc. But actually ST_Distance_Sphere()
is used. We need to fix that on the doc.
The doc also says in the beginning -
... an optional third element, 'spheroid', may be included to tell GeoDjango to use the more accurate spheroid distance calculation functions on fields with a geodetic coordinate system (e.g.,
ST_Distance_Spheroid
would be used instead ofST_Distance_Sphere
).
But then ST_Distance_Sphere
is not mentioned anywhere else.
Here is what currently is happening -
current_localities = Locality.objects.filter(centroid__distance_lte=(pnt, 1000))
results in -
(0.005) SELECT "map_locality"."id", "map_locality"."name", "map_locality"."slug", "map_locality"."centroid", "map_locality"."radius" FROM "map_locality" WHERE ST_Distance_Sphere("map_locality"."centroid", ST_GeomFromEWKB('\x0101000020e6100000865ad3bce3685340e9b7af03e7ec2940'::bytea)) <= 1000 LIMIT 21; args=(<django.contrib.gis.db.backends.postgis.adapter.PostGISAdapter object at 0x7fdcc9d320d0>, 1000)
Attaching a patch with the issue. I can send a PR.
Attachments (1)
Change History (11)
by , 9 years ago
Attachment: | doc_gis_distance.patch added |
---|
comment:1 by , 9 years ago
Has patch: | set |
---|
comment:2 by , 9 years ago
Description: | modified (diff) |
---|
follow-up: 4 comment:3 by , 9 years ago
Patch needs improvement: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
You are right in that the documentation is not up-to-date. However, it's a bit more complicated than that. The real function used depends on the type of the geometry field in the database. You can see the logic here: https://github.com/django/django/blob/master/django/contrib/gis/db/backends/postgis/operations.py#L39
If the field is geodetic (latitude/longitude), ST_Distance_Sphere
is used by default (with spheroid as an option). If the field has projected coordinates, ST_Distance
is used by default.
comment:4 by , 9 years ago
Replying to claudep:
If the field is geodetic (latitude/longitude),
ST_Distance_Sphere
is used by default (with spheroid as an option). If the field has projected coordinates,ST_Distance
is used by default.
By geodetic
do you mean a Point type geometry field using SRID 4326? In my example above, centroid
is of type geometry(Point,4326)
.
Just trying to get a clear idea about it.
comment:5 by , 9 years ago
Yes, 4326 is geodetic in the sense that coordinates (latitude/longitude) are measured in angles based on an ellispoid representation of the earth. On the other hand, projected systems are measured in meters or miles based on a projected plane of the earth (generally only accurate on limited areas).
comment:6 by , 9 years ago
So maybe we can say something like -
PostGIS:
ST_Distance_Sphere(poly, geom) <= 5
when SRID 4326 is used
PostGIS:ST_Distance(poly, geom) <= 5
when any other projected projected coordinates are used
in 2 different rows. Or use a single row to say both of them.
comment:8 by , 9 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Type: | Bug → Cleanup/optimization |
patch to rename st_distance to st_distance_sphere