Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

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 jbronn authored
1  django/contrib/gis/db/backends/base.py
View
@@ -50,6 +50,7 @@ class BaseSpatialOperations(object):
perimeter3d = False
point_on_surface = False
polygonize = False
+ reverse = False
scale = False
snap_to_grid = False
sym_difference = False
1  django/contrib/gis/db/backends/oracle/operations.py
View
@@ -88,6 +88,7 @@ class OracleOperations(DatabaseOperations, BaseSpatialOperations):
num_points = 'SDO_UTIL.GETNUMVERTICES'
perimeter = length
point_on_surface = 'SDO_GEOM.SDO_POINTONSURFACE'
+ reverse = 'SDO_UTIL.REVERSE_LINESTRING'
sym_difference = 'SDO_GEOM.SDO_XOR'
transform = 'SDO_CS.TRANSFORM'
union = 'SDO_GEOM.SDO_UNION'
2  django/contrib/gis/db/backends/postgis/operations.py
View
@@ -252,6 +252,7 @@ def get_dist_ops(operator):
self.envelope = prefix + 'Envelope'
self.extent = prefix + 'Extent'
self.extent3d = prefix + 'Extent3D'
+ self.force_rhr = prefix + 'ForceRHR'
self.geohash = GEOHASH
self.geojson = GEOJSON
self.gml = prefix + 'AsGML'
@@ -268,6 +269,7 @@ def get_dist_ops(operator):
self.perimeter3d = prefix + 'Perimeter3D'
self.point_on_surface = prefix + 'PointOnSurface'
self.polygonize = prefix + 'Polygonize'
+ self.reverse = prefix + 'Reverse'
self.scale = prefix + 'Scale'
self.snap_to_grid = prefix + 'SnapToGrid'
self.svg = prefix + 'AsSVG'
6 django/contrib/gis/db/models/manager.py
View
@@ -36,6 +36,9 @@ def extent(self, *args, **kwargs):
def extent3d(self, *args, **kwargs):
return self.get_query_set().extent3d(*args, **kwargs)
+ def force_rhr(self, *args, **kwargs):
+ return self.get_query_set().force_rhr(*args, **kwargs)
+
def geojson(self, *args, **kwargs):
return self.get_query_set().geojson(*args, **kwargs)
@@ -69,6 +72,9 @@ def perimeter(self, *args, **kwargs):
def point_on_surface(self, *args, **kwargs):
return self.get_query_set().point_on_surface(*args, **kwargs)
+ def reverse(self, *args, **kwargs):
+ return self.get_query_set().reverse(*args, **kwargs)
+
def scale(self, *args, **kwargs):
return self.get_query_set().scale(*args, **kwargs)
24 django/contrib/gis/db/models/query.py
View
@@ -2,7 +2,7 @@
from django.db.models.query import QuerySet, Q, ValuesQuerySet, ValuesListQuerySet
from django.contrib.gis.db.models import aggregates
-from django.contrib.gis.db.models.fields import get_srid_info, GeometryField, PointField
+from django.contrib.gis.db.models.fields import get_srid_info, GeometryField, PointField, LineStringField
from django.contrib.gis.db.models.sql import AreaField, DistanceField, GeomField, GeoQuery, GeoWhereNode
from django.contrib.gis.geometry.backend import Geometry
from django.contrib.gis.measure import Area, Distance
@@ -119,6 +119,15 @@ def extent3d(self, **kwargs):
"""
return self._spatial_aggregate(aggregates.Extent3D, **kwargs)
+ def force_rhr(self, **kwargs):
+ """
+ Returns a modified version of the Polygon/MultiPolygon in which
+ all of the vertices follow the Right-Hand-Rule. By default,
+ this is attached as the `force_rhr` attribute on each element
+ of the GeoQuerySet.
+ """
+ return self._geom_attribute('force_rhr', **kwargs)
+
def geojson(self, precision=8, crs=False, bbox=False, **kwargs):
"""
Returns a GeoJSON representation of the geomtry field in a `geojson`
@@ -244,6 +253,16 @@ def point_on_surface(self, **kwargs):
"""
return self._geom_attribute('point_on_surface', **kwargs)
+ def reverse(self, **kwargs):
+ """
+ Reverses the coordinate order of the geometry, and attaches as a
+ `reverse` attribute on each element of this GeoQuerySet.
+ """
+ s = {'select_field' : GeomField(),}
+ if connections[self.db].ops.oracle:
+ s['geo_field_type'] = LineStringField
+ return self._spatial_attribute('reverse', s, **kwargs)
+
def scale(self, x, y, z=0.0, **kwargs):
"""
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):
# Performing setup for the spatial column, unless told not to.
if settings.get('setup', True):
- default_args, geo_field = self._spatial_setup(att, desc=settings['desc'], field_name=field_name)
+ default_args, geo_field = self._spatial_setup(att, desc=settings['desc'], field_name=field_name,
+ geo_field_type=settings.get('geo_field_type', None))
for k, v in default_args.iteritems(): settings['procedure_args'].setdefault(k, v)
else:
geo_field = settings['geo_field']
6 django/contrib/gis/tests/geoapp/models.py
View
@@ -27,6 +27,12 @@ class State(models.Model):
objects = models.GeoManager()
def __unicode__(self): return self.name
+class Track(models.Model):
+ name = models.CharField(max_length=30)
+ line = models.LineStringField()
+ objects = models.GeoManager()
+ def __unicode__(self): return self.name
+
if not spatialite:
class Feature(models.Model):
name = models.CharField(max_length=20)
29 django/contrib/gis/tests/geoapp/tests.py
View
@@ -8,7 +8,7 @@
mysql, oracle, postgis, spatialite
from django.test import TestCase
-from models import Country, City, PennsylvaniaCity, State
+from models import Country, City, PennsylvaniaCity, State, Track
if not spatialite:
from models import Feature, MinusOneSRID
@@ -687,6 +687,33 @@ def test27_snap_to_grid(self):
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)))')
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))
+ @no_mysql
+ @no_spatialite
+ def test28_reverse(self):
+ "Testing GeoQuerySet.reverse()."
+ coords = [ (-95.363151, 29.763374), (-95.448601, 29.713803) ]
+ Track.objects.create(name='Foo', line=LineString(coords))
+ t = Track.objects.reverse().get(name='Foo')
+ coords.reverse()
+ self.assertEqual(tuple(coords), t.reverse.coords)
+ if oracle:
+ self.assertRaises(TypeError, State.objects.reverse)
+
+ @no_mysql
+ @no_oracle
+ @no_spatialite
+ def test29_force_rhr(self):
+ "Testing GeoQuerySet.force_rhr()."
+ rings = ( ( (0, 0), (5, 0), (0, 5), (0, 0) ),
+ ( (1, 1), (1, 3), (3, 1), (1, 1) ),
+ )
+ rhr_rings = ( ( (0, 0), (0, 5), (5, 0), (0, 0) ),
+ ( (1, 1), (3, 1), (1, 3), (1, 1) ),
+ )
+ State.objects.create(name='Foo', poly=Polygon(*rings))
+ s = State.objects.force_rhr().get(name='Foo')
+ self.assertEqual(rhr_rings, s.force_rhr.coords)
+
from test_feeds import GeoFeedTest
from test_regress import GeoRegressionTests
from test_sitemaps import GeoSitemapTest
Please sign in to comment.
Something went wrong with that request. Please try again.