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
This commit is contained in:
parent
1733518095
commit
5b21033847
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -252,6 +252,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
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 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
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'
|
||||
|
|
|
@ -36,6 +36,9 @@ class GeoManager(Manager):
|
|||
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 @@ class GeoManager(Manager):
|
|||
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)
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ from django.db import connections
|
|||
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 @@ class GeoQuerySet(QuerySet):
|
|||
"""
|
||||
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 @@ class GeoQuerySet(QuerySet):
|
|||
"""
|
||||
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 @@ class GeoQuerySet(QuerySet):
|
|||
|
||||
# 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']
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -8,7 +8,7 @@ from django.contrib.gis.tests.utils import \
|
|||
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 @@ class GeoModelTest(TestCase):
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue