Changeset 7138
- Timestamp:
- 02/20/08 15:15:43 (5 months ago)
- Files:
-
- django/branches/gis/django/contrib/gis/db/models/fields/__init__.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/db/models/query.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/models.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/distapp/data.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/distapp/tests.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
r7104 r7138 13 13 try: 14 14 from django.contrib.gis.models import SpatialRefSys 15 except NotImplementedError:15 except ImportError: 16 16 SpatialRefSys = None 17 17 … … 22 22 # The OpenGIS Geometry name. 23 23 _geom = 'GEOMETRY' 24 25 # Geodetic units. 26 geodetic_units = ('Decimal Degree', 'degree') 24 27 25 28 def __init__(self, srid=4326, spatial_index=True, dim=2, **kwargs): … … 83 86 then 1000 would be returned. 84 87 """ 88 85 89 if isinstance(dist, Distance): 86 if self._unit_name in ('Decimal Degree', 'degree'):90 if self._unit_name in self.geodetic_units: 87 91 # Spherical distance calculation parameter should be in meters. 88 92 dist_param = dist.m … … 94 98 95 99 # Sphereical distance query; returning meters. 96 if SpatialBackend.name == 'postgis' and self._unit_name == 'degree':100 if SpatialBackend.name == 'postgis' and self._unit_name in self.geodetic_units: 97 101 return [gqn(self._spheroid), dist_param] 98 102 else: django/branches/gis/django/contrib/gis/db/models/query.py
r7104 r7138 5 5 from django.db.models.fields import FieldDoesNotExist 6 6 from django.utils.datastructures import SortedDict 7 from django.contrib.gis.db.models.fields import GeometryField 7 from django.contrib.gis.db.models.fields import GeometryField, PointField 8 8 # parse_lookup depends on the spatial database backend. 9 9 from django.contrib.gis.db.backend import gqn, parse_lookup, SpatialBackend 10 from django.contrib.gis.geos import GEOSGeometry 10 from django.contrib.gis.geos import GEOSGeometry, Point 11 11 12 12 # Shortcut booleans for determining the backend. … … 280 280 where, params = geo_field.get_db_prep_lookup('distance_lte', (geom, 0)) 281 281 if oracle: 282 # The `tolerance` keyword may be used for Oracle. 282 # The `tolerance` keyword may be used for Oracle; the tolerance is 283 # in meters -- a default of 5 centimeters is used. 283 284 tolerance = kwargs.get('tolerance', 0.05) 284 285 # More legwork here because the OracleSpatialAdaptor doesn't do 286 # quoting of the WKT. 287 tmp_params = [gqn(str(params[0]))] 288 tmp_params.extend(params[1:]) 289 dsql = where[0] % tuple(tmp_params) 290 dist_select = {'distance' : '%s(%s, %s, %s)' % (DISTANCE, geo_col, dsql, tolerance)} 291 else: 292 dsql = where[0] % tuple(params) 285 dist_select = {'distance' : '%s(%s, %s, %s)' % (DISTANCE, geo_col, where[0], tolerance)} 286 else: 293 287 if len(where) == 3: 288 # Spherical distance calculation was requested (b/c spheroid 289 # parameter was attached) However, the PostGIS ST_distance_spheroid() 290 # procedure may only do queries from point columns to point geometries 291 # some error checking is required. 292 if not isinstance(geo_field, PointField): 293 raise TypeError('Spherical distance calculation only supported on PointFields.') 294 if not isinstance(GEOSGeometry(params[0].wkb), Point): 295 raise TypeError('Spherical distance calculation only supported with Point Geometry parameters') 296 294 297 # Call to distance_spheroid() requires the spheroid as well. 295 dist_sql = '%s(%s, %s, %s)' % (SpatialBackend.distance_spheroid, geo_col, dsql, where[1])296 else: 297 dist_sql = '%s(%s, %s)' % (DISTANCE, geo_col, dsql)298 dist_sql = '%s(%s, %s, %s)' % (SpatialBackend.distance_spheroid, geo_col, where[0], where[1]) 299 else: 300 dist_sql = '%s(%s, %s)' % (DISTANCE, geo_col, where[0]) 298 301 dist_select = {'distance' : dist_sql} 299 return self.extra(select=dist_select )302 return self.extra(select=dist_select, params=params) 300 303 301 304 def extent(self, field_name=None): django/branches/gis/django/contrib/gis/models.py
r7104 r7138 215 215 from django.contrib.gis.db.backend.oracle.models import GeometryColumns, SpatialRefSys 216 216 else: 217 raise NotImplementedError('No SpatialRefSys or GeometryColumns models for backend: %s' % settings.DATABASE_ENGINE)217 pass django/branches/gis/django/contrib/gis/tests/distapp/data.py
r7104 r7138 9 9 ('Hobart', 147.33, -42.8827), 10 10 ('Adelaide', 138.6, -34.9258), 11 ('Hillsdale', 151.231341, -33.952685), 11 12 ) 12 13 django/branches/gis/django/contrib/gis/tests/distapp/tests.py
r7104 r7138 3 3 4 4 from django.contrib.gis.gdal import DataSource 5 from django.contrib.gis.geos import GEOSGeometry, Point 5 from django.contrib.gis.geos import GEOSGeometry, Point, LineString 6 6 from django.contrib.gis.measure import D # alias for Distance 7 7 from django.contrib.gis.db.models import GeoQ … … 36 36 37 37 self.assertEqual(10, SouthTexasCity.objects.count()) 38 self.assertEqual(1 0, AustraliaCity.objects.count())38 self.assertEqual(11, AustraliaCity.objects.count()) 39 39 40 40 def test02_dwithin(self): … … 57 57 70870.188967, 165337.758878, 102128.654360, 58 58 139196.085105] 59 60 # Testing when the field name is explicitly set. 59 61 dist1 = SouthTexasCity.objects.distance('point', lagrange) 60 dist2 = SouthTexasCity.objects.distance(lagrange) 62 dist2 = SouthTexasCity.objects.distance(lagrange) # Using GEOSGeometry parameter 63 dist3 = SouthTexasCity.objects.distance(lagrange.ewkt) # Using EWKT string parameter. 61 64 62 65 # Original query done on PostGIS, have to adjust AlmostEqual tolerance 63 66 # for Oracle. 64 if oracle: tol = 367 if oracle: tol = 2 65 68 else: tol = 5 66 69 67 for qs in [dist1, dist2]: 70 # Ensuring expected distances are returned for each distance queryset. 71 for qs in [dist1, dist2, dist3]: 68 72 for i, c in enumerate(qs): 69 73 self.assertAlmostEqual(distances[i], c.distance, tol) 74 75 # Now testing geodetic distance aggregation. 76 hillsdale = AustraliaCity.objects.get(name='Hillsdale') 77 if not oracle: 78 # PostGIS is limited to disance queries only to/from point geometries, 79 # ensuring a TypeError is raised if something else is put in. 80 self.assertRaises(TypeError, AustraliaCity.objects.distance, 'LINESTRING(0 0, 1 1)') 81 self.assertRaises(TypeError, AustraliaCity.objects.distance, LineString((0, 0), (1, 1))) 82 83 # Got these distances using the raw SQL statement: 84 # 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)); 85 geodetic_distances = [60504.0628825298, 77023.948962654, 49154.8867507115, 90847.435881812, 217402.811862568, 709599.234619957, 640011.483583758, 7772.00667666425, 1047861.7859506, 1165126.55237647] 86 87 # Ensuring the expected distances are returned. 88 qs = AustraliaCity.objects.exclude(id=hillsdale.id).distance(hillsdale.point) 89 for i, c in enumerate(qs): 90 self.assertAlmostEqual(geodetic_distances[i], c.distance, tol) 70 91 71 92 def test04_distance_lookups(self):
