Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added `reverse` and `force_rhr` methods to `GeoQuerySet`. Refs #12416.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12349 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 5b21033847848608359836d56349db5060b26d84 1 parent 1733518
Justin Bronn authored January 29, 2010
1  django/contrib/gis/db/backends/base.py
@@ -50,6 +50,7 @@ class BaseSpatialOperations(object):
50 50
     perimeter3d = False
51 51
     point_on_surface = False
52 52
     polygonize = False
  53
+    reverse = False
53 54
     scale = False
54 55
     snap_to_grid = False
55 56
     sym_difference = False
1  django/contrib/gis/db/backends/oracle/operations.py
@@ -88,6 +88,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
88 88
     num_points = 'SDO_UTIL.GETNUMVERTICES'
89 89
     perimeter = length
90 90
     point_on_surface = 'SDO_GEOM.SDO_POINTONSURFACE'
  91
+    reverse = 'SDO_UTIL.REVERSE_LINESTRING'
91 92
     sym_difference = 'SDO_GEOM.SDO_XOR'
92 93
     transform = 'SDO_CS.TRANSFORM'
93 94
     union = 'SDO_GEOM.SDO_UNION'
2  django/contrib/gis/db/backends/postgis/operations.py
@@ -252,6 +252,7 @@ def get_dist_ops(operator):
252 252
         self.envelope = prefix + 'Envelope'
253 253
         self.extent = prefix + 'Extent'
254 254
         self.extent3d = prefix + 'Extent3D'
  255
+        self.force_rhr = prefix + 'ForceRHR'
255 256
         self.geohash = GEOHASH
256 257
         self.geojson = GEOJSON
257 258
         self.gml = prefix + 'AsGML'
@@ -268,6 +269,7 @@ def get_dist_ops(operator):
268 269
         self.perimeter3d = prefix + 'Perimeter3D'
269 270
         self.point_on_surface = prefix + 'PointOnSurface'
270 271
         self.polygonize = prefix + 'Polygonize'
  272
+        self.reverse = prefix + 'Reverse'
271 273
         self.scale = prefix + 'Scale'
272 274
         self.snap_to_grid = prefix + 'SnapToGrid'
273 275
         self.svg = prefix + 'AsSVG'
6  django/contrib/gis/db/models/manager.py
@@ -36,6 +36,9 @@ def extent(self, *args, **kwargs):
36 36
     def extent3d(self, *args, **kwargs):
37 37
         return self.get_query_set().extent3d(*args, **kwargs)
38 38
 
  39
+    def force_rhr(self, *args, **kwargs):
  40
+        return self.get_query_set().force_rhr(*args, **kwargs)
  41
+
39 42
     def geojson(self, *args, **kwargs):
40 43
         return self.get_query_set().geojson(*args, **kwargs)
41 44
 
@@ -69,6 +72,9 @@ def perimeter(self, *args, **kwargs):
69 72
     def point_on_surface(self, *args, **kwargs):
70 73
         return self.get_query_set().point_on_surface(*args, **kwargs)
71 74
 
  75
+    def reverse(self, *args, **kwargs):
  76
+        return self.get_query_set().reverse(*args, **kwargs)
  77
+
72 78
     def scale(self, *args, **kwargs):
73 79
         return self.get_query_set().scale(*args, **kwargs)
74 80
 
24  django/contrib/gis/db/models/query.py
@@ -2,7 +2,7 @@
2 2
 from django.db.models.query import QuerySet, Q, ValuesQuerySet, ValuesListQuerySet
3 3
 
4 4
 from django.contrib.gis.db.models import aggregates
5  
-from django.contrib.gis.db.models.fields import get_srid_info, GeometryField, PointField
  5
+from django.contrib.gis.db.models.fields import get_srid_info, GeometryField, PointField, LineStringField
6 6
 from django.contrib.gis.db.models.sql import AreaField, DistanceField, GeomField, GeoQuery, GeoWhereNode
7 7
 from django.contrib.gis.geometry.backend import Geometry
8 8
 from django.contrib.gis.measure import Area, Distance
@@ -119,6 +119,15 @@ def extent3d(self, **kwargs):
119 119
         """
120 120
         return self._spatial_aggregate(aggregates.Extent3D, **kwargs)
121 121
 
  122
+    def force_rhr(self, **kwargs):
  123
+        """
  124
+        Returns a modified version of the Polygon/MultiPolygon in which
  125
+        all of the vertices follow the Right-Hand-Rule.  By default,
  126
+        this is attached as the `force_rhr` attribute on each element
  127
+        of the GeoQuerySet.
  128
+        """
  129
+        return self._geom_attribute('force_rhr', **kwargs)
  130
+
122 131
     def geojson(self, precision=8, crs=False, bbox=False, **kwargs):
123 132
         """
124 133
         Returns a GeoJSON representation of the geomtry field in a `geojson`
@@ -244,6 +253,16 @@ def point_on_surface(self, **kwargs):
244 253
         """
245 254
         return self._geom_attribute('point_on_surface', **kwargs)
246 255
 
  256
+    def reverse(self, **kwargs):
  257
+        """
  258
+        Reverses the coordinate order of the geometry, and attaches as a
  259
+        `reverse` attribute on each element of this GeoQuerySet.
  260
+        """
  261
+        s = {'select_field' : GeomField(),}
  262
+        if connections[self.db].ops.oracle:
  263
+            s['geo_field_type'] = LineStringField
  264
+        return self._spatial_attribute('reverse', s, **kwargs)
  265
+
247 266
     def scale(self, x, y, z=0.0, **kwargs):
248 267
         """
249 268
         Scales the geometry to a new size by multiplying the ordinates
@@ -489,7 +508,8 @@ def _spatial_attribute(self, att, settings, field_name=None, model_att=None):
489 508
 
490 509
         # Performing setup for the spatial column, unless told not to.
491 510
         if settings.get('setup', True):
492  
-            default_args, geo_field = self._spatial_setup(att, desc=settings['desc'], field_name=field_name)
  511
+            default_args, geo_field = self._spatial_setup(att, desc=settings['desc'], field_name=field_name,
  512
+                                                          geo_field_type=settings.get('geo_field_type', None))
493 513
             for k, v in default_args.iteritems(): settings['procedure_args'].setdefault(k, v)
494 514
         else:
495 515
             geo_field = settings['geo_field']
6  django/contrib/gis/tests/geoapp/models.py
@@ -27,6 +27,12 @@ class State(models.Model):
27 27
     objects = models.GeoManager()
28 28
     def __unicode__(self): return self.name
29 29
 
  30
+class Track(models.Model):
  31
+    name = models.CharField(max_length=30)
  32
+    line = models.LineStringField()
  33
+    objects = models.GeoManager()
  34
+    def __unicode__(self): return self.name
  35
+
30 36
 if not spatialite:
31 37
     class Feature(models.Model):
32 38
         name = models.CharField(max_length=20)
29  django/contrib/gis/tests/geoapp/tests.py
@@ -8,7 +8,7 @@
8 8
     mysql, oracle, postgis, spatialite
9 9
 from django.test import TestCase
10 10
 
11  
-from models import Country, City, PennsylvaniaCity, State
  11
+from models import Country, City, PennsylvaniaCity, State, Track
12 12
 
13 13
 if not spatialite:
14 14
     from models import Feature, MinusOneSRID
@@ -687,6 +687,33 @@ def test27_snap_to_grid(self):
687 687
         ref = fromstr('MULTIPOLYGON(((12.4 43.87,12.45 43.87,12.45 44.1,12.5 44.1,12.5 43.87,12.45 43.87,12.4 43.87)))')
688 688
         self.failUnless(ref.equals_exact(Country.objects.snap_to_grid(0.05, 0.23, 0.5, 0.17).get(name='San Marino').snap_to_grid, tol))
689 689
 
  690
+    @no_mysql
  691
+    @no_spatialite
  692
+    def test28_reverse(self):
  693
+        "Testing GeoQuerySet.reverse()."
  694
+        coords = [ (-95.363151, 29.763374), (-95.448601, 29.713803) ]
  695
+        Track.objects.create(name='Foo', line=LineString(coords))
  696
+        t = Track.objects.reverse().get(name='Foo')
  697
+        coords.reverse()
  698
+        self.assertEqual(tuple(coords), t.reverse.coords)
  699
+        if oracle:
  700
+            self.assertRaises(TypeError, State.objects.reverse)
  701
+        
  702
+    @no_mysql
  703
+    @no_oracle
  704
+    @no_spatialite
  705
+    def test29_force_rhr(self):
  706
+        "Testing GeoQuerySet.force_rhr()."
  707
+        rings = ( ( (0, 0), (5, 0), (0, 5), (0, 0) ),
  708
+                  ( (1, 1), (1, 3), (3, 1), (1, 1) ),
  709
+                  )
  710
+        rhr_rings = ( ( (0, 0), (0, 5), (5, 0), (0, 0) ),
  711
+                      ( (1, 1), (3, 1), (1, 3), (1, 1) ),
  712
+                      )
  713
+        State.objects.create(name='Foo', poly=Polygon(*rings))
  714
+        s = State.objects.force_rhr().get(name='Foo')
  715
+        self.assertEqual(rhr_rings, s.force_rhr.coords)
  716
+
690 717
 from test_feeds import GeoFeedTest
691 718
 from test_regress import GeoRegressionTests
692 719
 from test_sitemaps import GeoSitemapTest

0 notes on commit 5b21033

Please sign in to comment.
Something went wrong with that request. Please try again.