`GeoQuerySet.distance` now allows calculations to/from non-point geodetic geometry fields as allowed on PostGIS 1.5.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12312 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
a6a176013a
commit
ff6b44980a
|
@ -632,10 +632,11 @@ class GeoQuerySet(QuerySet):
|
||||||
# field is geodetic). However, the PostGIS ST_distance_sphere/spheroid()
|
# field is geodetic). However, the PostGIS ST_distance_sphere/spheroid()
|
||||||
# procedures may only do queries from point columns to point geometries
|
# procedures may only do queries from point columns to point geometries
|
||||||
# some error checking is required.
|
# some error checking is required.
|
||||||
if not isinstance(geo_field, PointField):
|
if not backend.geography:
|
||||||
raise ValueError('Spherical distance calculation only supported on PointFields.')
|
if not isinstance(geo_field, PointField):
|
||||||
if not str(Geometry(buffer(params[0].ewkb)).geom_type) == 'Point':
|
raise ValueError('Spherical distance calculation only supported on PointFields.')
|
||||||
raise ValueError('Spherical distance calculation only supported with Point Geometry parameters')
|
if not str(Geometry(buffer(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
|
# The `function` procedure argument needs to be set differently for
|
||||||
# geodetic distance calculations.
|
# geodetic distance calculations.
|
||||||
if spheroid:
|
if spheroid:
|
||||||
|
|
|
@ -148,13 +148,24 @@ class DistanceTest(unittest.TestCase):
|
||||||
if oracle: tol = 2
|
if oracle: tol = 2
|
||||||
else: tol = 5
|
else: tol = 5
|
||||||
|
|
||||||
# Now testing geodetic distance aggregation.
|
# Testing geodetic distance calculation with a non-point geometry
|
||||||
hillsdale = AustraliaCity.objects.get(name='Hillsdale')
|
# (a LineString of Wollongong and Shellharbour coords).
|
||||||
if not oracle:
|
ls = LineString( ( (150.902, -34.4245), (150.87, -34.5789) ) )
|
||||||
# PostGIS is limited to disance queries only to/from point geometries,
|
if oracle or connection.ops.geography:
|
||||||
# ensuring a TypeError is raised if something else is put in.
|
# Reference query:
|
||||||
self.assertRaises(ValueError, AustraliaCity.objects.distance, 'LINESTRING(0 0, 1 1)')
|
# SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326)) FROM distapp_australiacity ORDER BY name;
|
||||||
self.assertRaises(ValueError, AustraliaCity.objects.distance, LineString((0, 0), (1, 1)))
|
distances = [1120954.92533513, 140575.720018241, 640396.662906304,
|
||||||
|
60580.9693849269, 972807.955955075, 568451.8357838,
|
||||||
|
40435.4335201384, 0, 68272.3896586844, 12375.0643697706, 0]
|
||||||
|
qs = AustraliaCity.objects.distance(ls).order_by('name')
|
||||||
|
for city, distance in zip(qs, distances):
|
||||||
|
# Testing equivalence to within a meter.
|
||||||
|
self.assertAlmostEqual(distance, city.distance.m, 0)
|
||||||
|
else:
|
||||||
|
# PostGIS 1.4 and below is limited to disance queries only
|
||||||
|
# to/from point geometries, check for raising of ValueError.
|
||||||
|
self.assertRaises(ValueError, AustraliaCity.objects.distance, ls)
|
||||||
|
self.assertRaises(ValueError, AustraliaCity.objects.distance, ls.wkt)
|
||||||
|
|
||||||
# Got the reference distances using the raw SQL statements:
|
# Got the reference distances using the raw SQL statements:
|
||||||
# SELECT ST_distance_spheroid(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326), 'SPHEROID["WGS 84",6378137.0,298.257223563]') FROM distapp_australiacity WHERE (NOT (id = 11));
|
# SELECT ST_distance_spheroid(point, ST_GeomFromText('POINT(151.231341 -33.952685)', 4326), 'SPHEROID["WGS 84",6378137.0,298.257223563]') FROM distapp_australiacity WHERE (NOT (id = 11));
|
||||||
|
@ -182,6 +193,7 @@ class DistanceTest(unittest.TestCase):
|
||||||
1162619.7297006]
|
1162619.7297006]
|
||||||
|
|
||||||
# Testing with spheroid distances first.
|
# Testing with spheroid distances first.
|
||||||
|
hillsdale = AustraliaCity.objects.get(name='Hillsdale')
|
||||||
qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point, spheroid=True)
|
qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point, spheroid=True)
|
||||||
for i, c in enumerate(qs):
|
for i, c in enumerate(qs):
|
||||||
self.assertAlmostEqual(spheroid_distances[i], c.distance.m, tol)
|
self.assertAlmostEqual(spheroid_distances[i], c.distance.m, tol)
|
||||||
|
@ -195,8 +207,9 @@ class DistanceTest(unittest.TestCase):
|
||||||
def test03c_distance_method(self):
|
def test03c_distance_method(self):
|
||||||
"Testing the `distance` GeoQuerySet method used with `transform` on a geographic field."
|
"Testing the `distance` GeoQuerySet method used with `transform` on a geographic field."
|
||||||
# Normally you can't compute distances from a geometry field
|
# Normally you can't compute distances from a geometry field
|
||||||
# that is not a PointField (on PostGIS).
|
# that is not a PointField (on PostGIS 1.4 and below).
|
||||||
self.assertRaises(ValueError, CensusZipcode.objects.distance, self.stx_pnt)
|
if not connection.ops.geography:
|
||||||
|
self.assertRaises(ValueError, CensusZipcode.objects.distance, self.stx_pnt)
|
||||||
|
|
||||||
# We'll be using a Polygon (created by buffering the centroid
|
# We'll be using a Polygon (created by buffering the centroid
|
||||||
# of 77005 to 100m) -- which aren't allowed in geographic distance
|
# of 77005 to 100m) -- which aren't allowed in geographic distance
|
||||||
|
|
Loading…
Reference in New Issue