Author: jbronn Date: 2010-01-27 17:09:46 -0600 (Wed, 27 Jan 2010) New Revision: 12312
Modified: django/trunk/django/contrib/gis/db/models/query.py django/trunk/django/contrib/gis/tests/distapp/tests.py Log: `GeoQuerySet.distance` now allows calculations to/from non-point geodetic geometry fields as allowed on PostGIS 1.5. Modified: django/trunk/django/contrib/gis/db/models/query.py =================================================================== --- django/trunk/django/contrib/gis/db/models/query.py 2010-01-27 19:42:03 UTC (rev 12311) +++ django/trunk/django/contrib/gis/db/models/query.py 2010-01-27 23:09:46 UTC (rev 12312) @@ -632,10 +632,11 @@ # 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 ValueError('Spherical distance calculation only supported on PointFields.') - if not str(Geometry(buffer(params[0].ewkb)).geom_type) == 'Point': - raise ValueError('Spherical distance calculation only supported with Point Geometry parameters') + if not backend.geography: + if not isinstance(geo_field, PointField): + raise ValueError('Spherical distance calculation only supported on PointFields.') + 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 # geodetic distance calculations. if spheroid: Modified: django/trunk/django/contrib/gis/tests/distapp/tests.py =================================================================== --- django/trunk/django/contrib/gis/tests/distapp/tests.py 2010-01-27 19:42:03 UTC (rev 12311) +++ django/trunk/django/contrib/gis/tests/distapp/tests.py 2010-01-27 23:09:46 UTC (rev 12312) @@ -148,13 +148,24 @@ if oracle: tol = 2 else: tol = 5 - # Now testing geodetic distance aggregation. - hillsdale = AustraliaCity.objects.get(name='Hillsdale') - if not oracle: - # PostGIS is limited to disance queries only to/from point geometries, - # ensuring a TypeError is raised if something else is put in. - self.assertRaises(ValueError, AustraliaCity.objects.distance, 'LINESTRING(0 0, 1 1)') - self.assertRaises(ValueError, AustraliaCity.objects.distance, LineString((0, 0), (1, 1))) + # Testing geodetic distance calculation with a non-point geometry + # (a LineString of Wollongong and Shellharbour coords). + ls = LineString( ( (150.902, -34.4245), (150.87, -34.5789) ) ) + if oracle or connection.ops.geography: + # Reference query: + # SELECT ST_distance_sphere(point, ST_GeomFromText('LINESTRING(150.9020 -34.4245,150.8700 -34.5789)', 4326)) FROM distapp_australiacity ORDER BY name; + 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: # 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 @@ 1162619.7297006] # Testing with spheroid distances first. + hillsdale = AustraliaCity.objects.get(name='Hillsdale') qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point, spheroid=True) for i, c in enumerate(qs): self.assertAlmostEqual(spheroid_distances[i], c.distance.m, tol) @@ -195,8 +207,9 @@ def test03c_distance_method(self): "Testing the `distance` GeoQuerySet method used with `transform` on a geographic field." # Normally you can't compute distances from a geometry field - # that is not a PointField (on PostGIS). - self.assertRaises(ValueError, CensusZipcode.objects.distance, self.stx_pnt) + # that is not a PointField (on PostGIS 1.4 and below). + 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 # of 77005 to 100m) -- which aren't allowed in geographic distance -- You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-upda...@googlegroups.com. To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/django-updates?hl=en.