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.

Reply via email to