Changeset 5786
- Timestamp:
- 08/02/07 00:31:10 (1 year ago)
- Files:
-
- django/branches/gis/django/contrib/gis/geos/base.py (modified) (9 diffs)
- django/branches/gis/django/contrib/gis/geos/collections.py (modified) (7 diffs)
- django/branches/gis/django/contrib/gis/geos/geometries.py (modified) (9 diffs)
- django/branches/gis/django/contrib/gis/geos/libgeos.py (modified) (7 diffs)
- django/branches/gis/django/contrib/gis/tests/geometries.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/__init__.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/tests/test_geos.py (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/geos/base.py
r5760 r5786 13 13 import re 14 14 from warnings import warn 15 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, HAS_NUMPY, ISQLQuote 15 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, HAS_NUMPY, ISQLQuote, GEOM_FUNC_PREFIX 16 16 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 17 17 from django.contrib.gis.geos.coordseq import GEOSCoordSeq, create_cs … … 88 88 def __del__(self): 89 89 "Destroys this geometry -- only if the pointer is valid and whether or not it belongs to a parent." 90 #print ' Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid)90 #print 'base: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid) 91 91 # Only calling destroy on valid pointers not spawned from a parent 92 92 if self._ptr.valid and not self._parent: lgeos.GEOSGeom_destroy(self._ptr()) … … 102 102 def __eq__(self, other): 103 103 "Equivalence testing." 104 return self.equals (other)104 return self.equals_exact(other) 105 105 106 106 def __ne__(self, other): 107 107 "The not equals operator." 108 return not self.equals (other)108 return not self.equals_exact(other) 109 109 110 110 ### Geometry set-like operations ### … … 116 116 return self.union(other) 117 117 118 # g1 |= g2 119 def __ior__(self, other): 120 "Reassigns this Geometry to the union of this Geometry and the other." 121 return self.union(other) 122 118 123 # g = g1 & g2 119 124 def __and__(self, other): … … 121 126 return self.intersection(other) 122 127 128 # g1 &= g2 129 def __iand__(self, other): 130 "Reassigns this Geometry to the intersection of this Geometry and the other." 131 return self.intersection(other) 132 123 133 # g = g1 - g2 124 134 def __sub__(self, other): … … 126 136 return self.difference(other) 127 137 138 # g1 -= g2 139 def __isub__(self, other): 140 "Reassigns this Geometry to the difference of this Geometry and the other." 141 return self.difference(other) 142 128 143 # g = g1 ^ g2 129 144 def __xor__(self, other): 130 145 "Return the symmetric difference of this Geometry and the other." 131 146 return self.sym_difference(other) 147 148 # g1 ^= g2 149 def __ixor__(self, other): 150 "Reassigns this Geometry to the symmetric difference of this Geometry and the other." 151 return self.sym_difference(other) 152 153 def _nullify(self): 154 """During initialization of geometries from other geometries, this routine is 155 used to nullify any parent geometries (since they will now be missing memory 156 components) and to nullify the geometry itself to prevent future access. 157 Only the address (an integer) of the current geometry is returned for use in 158 initializing the new geometry.""" 159 # First getting the memory address of the geometry. 160 address = self._ptr() 161 162 # If the geometry is a child geometry, then the parent geometry pointer is 163 # nullified. 164 if self._parent: self._parent.nullify() 165 166 # Nullifying the geometry pointer 167 self._ptr.nullify() 168 169 return address 170 171 def _reassign(self, new_geom): 172 "Internal routine for reassigning internal pointer to a new geometry." 173 # Only can re-assign when given a pointer or a geometry. 174 if not isinstance(new_geom, (GEOSPointer, GEOSGeometry)): 175 raise TypeError, 'cannot reassign geometry on given type: %s' % type(new_geom) 176 gtype = new_geom.geom_type 177 178 # Re-assigning the internal GEOSPointer to the new geometry, nullifying 179 # the new Geometry in the process. 180 if isinstance(new_geom, GEOSGeometry): self._ptr.set(new_geom._nullify()) 181 else: self._ptr = new_geom 182 183 # The new geometry class may be different from the original, so setting 184 # the __class__ and populating the internal geometry or ring dictionary. 185 self.__class__ = GEOS_CLASSES[gtype] 186 if isinstance(self, (Polygon, GeometryCollection)): self._populate() 132 187 133 188 #### Psycopg2 database adaptor routines #### … … 141 196 def getquoted(self): 142 197 "Returns a properly quoted string for use in PostgresSQL/PostGIS." 143 return "GeometryFromText('%s', %s)" % (self.wkt, self.srid or -1) 198 # GeometryFromText() is ST_GeometryFromText() in PostGIS >= 1.2.2 199 return "%sGeometryFromText('%s', %s)" % (GEOM_FUNC_PREFIX, self.wkt, self.srid or -1) 144 200 145 201 #### Coordinate Sequence Routines #### … … 300 356 "Gets the SRID for the geometry, returns None if no SRID is set." 301 357 s = lgeos.GEOSGetSRID(self._ptr()) 302 if s == 0: 303 return None 304 else: 305 return s 358 if s == 0: return None 359 else: return s 306 360 307 361 def set_srid(self, srid): … … 405 459 def clone(self): 406 460 "Clones this Geometry." 407 return GEOSGeometry(lgeos.GEOSGeom_clone(self._ptr()) )461 return GEOSGeometry(lgeos.GEOSGeom_clone(self._ptr()), srid=self.srid) 408 462 409 463 # Class mapping dictionary django/branches/gis/django/contrib/gis/geos/collections.py
r5760 r5786 5 5 from ctypes import c_int, c_uint, byref, cast 6 6 from types import TupleType, ListType 7 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, init_from_geom,get_pointer_arr, GEOM_PTR7 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, get_pointer_arr, GEOM_PTR 8 8 from django.contrib.gis.geos.base import GEOSGeometry 9 9 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 10 10 from django.contrib.gis.geos.geometries import Point, LineString, LinearRing, Polygon 11 12 def init_from_poly(poly):13 "Internal routine used for initializing Geometry Collections from Polygons."14 # Constructing a new Polygon to take control of the rings.15 p = Polygon(*tuple(ring for ring in poly))16 17 # If this Polygon came from a GeometryCollection, it is a child18 # and the parent geometry pointer is nullified.19 if poly._parent: poly._parent.nullify()20 21 # Nullifying the polygon pointer22 poly._ptr.nullify()23 24 # Returning the address of the new Polygon.25 return p._ptr()26 11 27 12 class GeometryCollection(GEOSGeometry): … … 30 15 31 16 def __init__(self, *args, **kwargs): 17 "Initializes a Geometry Collection from a sequence of Geometry objects." 18 # Setting up the collection for creation 32 19 self._ptr = GEOSPointer(0) # Initially NULL 33 20 self._geoms = {} 34 self._parent = False21 self._parent = None 35 22 23 # Checking the arguments 36 24 if not args: 37 raise TypeError, 'Must provide at least one LinearRing to initialize Polygon.'25 raise TypeError, 'Must provide at least one Geometry to initialize %s.' % self.__class__.__name__ 38 26 39 27 if len(args) == 1: # If only one geometry provided or a list of geometries is provided … … 55 43 # Incrementing through each input geometry. 56 44 for i in xrange(ngeom): 57 if isinstance(init_geoms[i], Polygon): 58 # Special care is taken when importing from Polygons 59 geoms[i] = cast(init_from_poly(init_geoms[i]), GEOM_PTR) 60 else: 61 geoms[i] = cast(init_from_geom(init_geoms[i]), GEOM_PTR) 62 45 geoms[i] = cast(init_geoms[i]._nullify(), GEOM_PTR) 46 63 47 # Calling the parent class, using the pointer returned from GEOS createCollection() 64 48 super(GeometryCollection, self).__init__(lgeos.GEOSGeom_createCollection(c_int(self._typeid), byref(geoms), c_uint(ngeom)), **kwargs) … … 66 50 def __del__(self): 67 51 "Overloaded deletion method for Geometry Collections." 68 #print ' Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid)52 #print 'collection: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid) 69 53 # If this geometry is still valid, it hasn't been modified by others. 70 54 if self._ptr.valid: 71 55 # Nullifying pointers to internal geometries, preventing any attempted future access. 72 56 for k in self._geoms: self._geoms[k].nullify() 73 super(GeometryCollection, self).__del__()74 57 else: 75 58 # Internal memory has become part of other Geometry objects, must delete the … … 81 64 lgeos.GEOSGeom_destroy(self._geoms[k].address) 82 65 self._geoms[k].nullify() 66 super(GeometryCollection, self).__del__() 83 67 84 68 def __getitem__(self, index): 85 " For indexing on the multiple geometries."69 "Returns the Geometry from this Collection at the given index (0-based)." 86 70 # Checking the index and returning the corresponding GEOS geometry. 87 71 self._checkindex(index) 88 72 return GEOSGeometry(self._geoms[index], parent=self._ptr, srid=self.srid) 89 73 74 def __setitem__(self, index, geom): 75 "Sets the Geometry at the specified index." 76 self._checkindex(index) 77 if not isinstance(geom, self._allowed): 78 raise TypeError, 'Incompatible Geometry for collection.' 79 80 # Constructing the list of geometries that will go in the collection. 81 new_geoms = [] 82 for i in xrange(len(self)): 83 if i == index: new_geoms.append(geom) 84 else: new_geoms.append(self[i]) 85 86 # Creating a new geometry collection from the list, and 87 # re-assigning the pointers. 88 new_collection = self.__class__(*new_geoms) 89 self._reassign(new_collection) 90 90 91 def __iter__(self): 91 " For iteration on the multiple geometries."92 "Iterates over each Geometry in the Collection." 92 93 for i in xrange(len(self)): 93 94 yield self.__getitem__(i) 94 95 95 96 def __len__(self): 96 "Returns the number of geometries in this collection."97 "Returns the number of geometries in this Collection." 97 98 return self.num_geom 98 99 … … 102 103 raise GEOSGeometryIndexError, 'invalid GEOS Geometry index: %s' % str(index) 103 104 105 def _nullify(self): 106 "Overloaded from base method to nullify geometry references in this Collection." 107 # Nullifying the references to the internal Geometry objects from this Collection. 108 for k in self._geoms: self._geoms[k].nullify() 109 return super(GeometryCollection, self)._nullify() 110 104 111 def _populate(self): 105 112 "Populates the internal child geometry dictionary." … … 107 114 for i in xrange(self.num_geom): 108 115 self._geoms[i] = GEOSPointer(lgeos.GEOSGetGeometryN(self._ptr(), c_int(i))) 109 110 116 111 117 # MultiPoint, MultiLineString, and MultiPolygon class definitions. django/branches/gis/django/contrib/gis/geos/geometries.py
r5760 r5786 8 8 from types import FloatType, IntType, ListType, TupleType 9 9 from django.contrib.gis.geos.coordseq import GEOSCoordSeq, create_cs 10 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, get_pointer_arr, init_from_geom,GEOM_PTR, HAS_NUMPY10 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, get_pointer_arr, GEOM_PTR, HAS_NUMPY 11 11 from django.contrib.gis.geos.base import GEOSGeometry 12 12 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError … … 22 22 """ 23 23 24 # Setting-up for Point Creation 24 25 self._ptr = GEOSPointer(0) # Initially NULL 26 self._parent = None 25 27 26 28 if isinstance(x, (TupleType, ListType)): … … 133 135 ls = LineString(Point(1, 1), Point(2, 2)) 134 136 """ 137 # Setting up for LineString creation 135 138 self._ptr = GEOSPointer(0) # Initially NULL 139 self._parent = None 136 140 137 141 # If only one argument was provided, then set the coords array appropriately … … 255 259 """ 256 260 self._ptr = GEOSPointer(0) # Initially NULL 261 self._parent = None 257 262 self._rings = {} 258 263 if not args: … … 278 283 for i in xrange(nholes): 279 284 # Casting to the Geometry Pointer type 280 holes[i] = cast(init_ from_geom(init_holes[i]), GEOM_PTR)285 holes[i] = cast(init_holes[i]._nullify(), GEOM_PTR) 281 286 282 287 # Getting the shell pointer address, 283 shell = init_from_geom(ext_ring)288 shell = ext_ring._nullify() 284 289 285 290 # Calling with the GEOS createPolygon factory. … … 288 293 def __del__(self): 289 294 "Overloaded deletion method for Polygons." 290 #print ' Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid)295 #print 'polygon: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid) 291 296 # If this geometry is still valid, it hasn't been modified by others. 292 297 if self._ptr.valid: 293 298 # Nulling the pointers to internal rings, preventing any attempted future access 294 299 for k in self._rings: self._rings[k].nullify() 295 super(Polygon, self).__del__() 296 else: 300 elif not self._parent: 297 301 # Internal memory has become part of other objects; must delete the 298 302 # internal objects which are still valid individually, since calling 299 303 # destructor on entire geometry will result in an attempted deletion 300 # of NULL pointers for the missing components. 304 # of NULL pointers for the missing components. Not performed on 305 # children Polygons from MultiPolygon or GeometryCollection objects. 301 306 for k in self._rings: 302 307 if self._rings[k].valid: 303 308 lgeos.GEOSGeom_destroy(self._rings[k].address) 304 309 self._rings[k].nullify() 310 super(Polygon, self).__del__() 305 311 306 312 def __getitem__(self, index): 307 313 """Returns the ring at the specified index. The first index, 0, will always 308 314 return the exterior ring. Indices > 0 will return the interior ring.""" 309 if index < 0 or index > self.num_interior_rings: 310 raise GEOSGeometryIndexError, 'invalid GEOS Geometry index: %s' % str(index) 311 else: 312 if index == 0: 313 return self.exterior_ring 314 else: 315 # Getting the interior ring, have to subtract 1 from the index. 316 return self.get_interior_ring(index-1) 315 if index == 0: 316 return self.exterior_ring 317 else: 318 # Getting the interior ring, have to subtract 1 from the index. 319 return self.get_interior_ring(index-1) 320 321 def __setitem__(self, index, ring): 322 "Sets the ring at the specified index with the given ring." 323 # Checking the index and ring parameters. 324 self._checkindex(index) 325 if not isinstance(ring, LinearRing): 326 raise TypeError, 'must set Polygon index with a LinearRing object' 327 328 # Constructing the ring parameters 329 new_rings = [] 330 for i in xrange(len(self)): 331 if index == i: new_rings.append(ring) 332 else: new_rings.append(self[i]) 333 334 # Constructing the new Polygon with the ring parameters, and reassigning the internals. 335 new_poly = Polygon(*new_rings) 336 self._reassign(new_poly) 317 337 318 338 def __iter__(self): … … 325 345 return self.num_interior_rings + 1 326 346 347 def _checkindex(self, index): 348 "Internal routine for checking the given ring index." 349 if index < 0 or index >= len(self): 350 raise GEOSGeometryIndexError, 'invalid Polygon ring index: %s' % index 351 352 def _nullify(self): 353 "Overloaded from base method to nullify ring references as well." 354 # Nullifying the references to the internal rings of this Polygon. 355 for k in self._rings: self._rings[k].nullify() 356 return super(Polygon, self)._nullify() 357 327 358 def _populate(self): 328 359 "Populates the internal rings dictionary." … … 337 368 """Gets the interior ring at the specified index, 338 369 0 is for the first interior ring, not the exterior ring.""" 339 340 # Making sure the ring index is within range 341 if ring_i < 0 or ring_i >= self.num_interior_rings: 342 raise IndexError, 'ring index out of range' 343 344 # Returning the ring from the internal ring dictionary (have to 345 # add one to the index) 370 # Returning the ring from the internal ring dictionary (have to add one 371 # to index since all internal rings come after the exterior ring) 372 self._checkindex(ring_i+1) 346 373 return GEOSGeometry(self._rings[ring_i+1], parent=self._ptr, srid=self.srid) 347 374 … … 362 389 return GEOSGeometry(self._rings[0], parent=self._ptr, srid=self.srid) 363 390 364 def set_ext_ring(self ):391 def set_ext_ring(self, ring): 365 392 "Sets the exterior ring of the Polygon." 366 # Sets the exterior ring 367 raise NotImplementedError 393 self[0] = ring 368 394 369 395 # properties for the exterior ring/shell 370 exterior_ring = property(get_ext_ring )371 shell = property(get_ext_ring )396 exterior_ring = property(get_ext_ring, set_ext_ring) 397 shell = property(get_ext_ring, set_ext_ring) 372 398 373 399 @property django/branches/gis/django/contrib/gis/geos/libgeos.py
r5760 r5786 19 19 HAS_NUMPY = False 20 20 21 # Psycopg2 supported?21 # Are psycopg2 and GeoDjango models being used? 22 22 try: 23 23 from psycopg2.extensions import ISQLQuote 24 except ImportError: 24 from django.contrib.gis.db.backend.postgis import GEOM_FUNC_PREFIX 25 except (ImportError, EnvironmentError): 25 26 ISQLQuote = None 27 GEOM_FUNC_PREFIX = None 26 28 27 29 # Setting the appropriate name for the GEOS-C library, depending on which … … 72 74 lgeos.initGEOS(notice_h, error_h) 73 75 74 #### GEOS Geometry Pointer utilities. ####76 #### GEOS Geometry Pointer object, related C data structures, and functions. #### 75 77 76 78 # Opaque GEOS geometry structure … … 78 80 "Opaque structure used when arrays of geometries are needed as parameters." 79 81 pass 82 80 83 # Pointer to opaque geometry structure 81 84 GEOM_PTR = POINTER(GEOSGeom_t) 85 82 86 # Used specifically by the GEOSGeom_createPolygon and GEOSGeom_createCollection GEOS routines 83 87 def get_pointer_arr(n): … … 86 90 return GeomArr() 87 91 88 #### GEOS Pointer object and routines ####89 92 class GEOSPointer(object): 90 93 """The GEOSPointer provides a layer of abstraction in accessing the values returned by … … 109 112 else: raise GEOSException, 'GEOS pointer no longer valid (was this geometry or the parent geometry deleted or modified?)' 110 113 111 def __ bool__(self):114 def __nonzero__(self): 112 115 "Returns True when the GEOSPointer is valid." 113 116 return self.valid … … 115 118 def __str__(self): 116 119 return str(self.address) 120 121 def __repr__(self): 122 return 'GEOSPointer(%s)' % self.address 117 123 118 124 ### GEOSPointer Properties ### … … 162 168 self.set(0) 163 169 self.set(0, coordseq=True) 164 165 def init_from_geom(geom):166 """During initialization of geometries from other geometries, this routine is167 used to nullify any parent geometries (since they will now be missing memory168 components) and to nullify the geometry itself to prevent future access.169 Only the address (an integer) of the current geometry is returned for use in170 initializing the new geometry."""171 # First getting the memory address of the geometry.172 address = geom._ptr()173 174 # If the geometry is a child geometry, then the parent geometry pointer is175 # nullified.176 if geom._parent: geom._parent.nullify()177 178 # Nullifying the geometry pointer179 geom._ptr.nullify()180 181 return addressdjango/branches/gis/django/contrib/gis/tests/geometries.py
r5742 r5786 116 116 117 117 intersect_geoms = ( TestGeom('POLYGON ((5 5,5 0,0 0,0 5,5 5))'), 118 TestGeom('POLYGON ((10 1, 11 3, 13 4, 15 6, 16 8, 16 10, 15 12, 13 13, 11 12, 10 10, 9 12, 7 13, 5 12, 4 10, 4 8, 5 6, 7 4, 9 3, 10 1))')118 TestGeom('POLYGON ((10 1, 9 3, 7 4, 5 6, 4 8, 4 10, 5 12, 7 13, 9 12, 10 10, 11 12, 13 13, 15 12, 16 10, 16 8, 15 6, 13 4, 11 3, 10 1))'), 119 119 ) 120 120 121 121 union_geoms = ( TestGeom('POLYGON ((-5 0,-5 10,5 10,5 5,10 5,10 -5,0 -5,0 0,-5 0))'), 122 TestGeom('POLYGON ((2 0, 18 0, 18 15, 2 15, 2 0))'),122 TestGeom('POLYGON ((2 0, 2 15, 18 15, 18 0, 2 0))'), 123 123 ) 124 124 125 125 diff_geoms = ( TestGeom('POLYGON ((-5 0,-5 10,5 10,5 5,0 5,0 0,-5 0))'), 126 TestGeom('POLYGON ((2 0, 18 0, 18 15, 2 15, 2 0), (10 1, 11 3, 13 4, 15 6, 16 8, 16 10, 15 12, 13 13, 11 12, 10 10, 9 12, 7 13, 5 12, 4 10, 4 8, 5 6, 7 4, 9 3, 10 1))'),126 TestGeom('POLYGON ((2 0, 2 15, 18 15, 18 0, 2 0), (10 1, 11 3, 13 4, 15 6, 16 8, 16 10, 15 12, 13 13, 11 12, 10 10, 9 12, 7 13, 5 12, 4 10, 4 8, 5 6, 7 4, 9 3, 10 1))'), 127 127 ) 128 128 129 129 sdiff_geoms = ( TestGeom('MULTIPOLYGON (((-5 0,-5 10,5 10,5 5,0 5,0 0,-5 0)),((0 0,5 0,5 5,10 5,10 -5,0 -5,0 0)))'), 130 TestGeom('POLYGON ((2 0, 18 0, 18 15, 2 15, 2 0), (10 1, 11 3, 13 4, 15 6, 16 8, 16 10, 15 12, 13 13, 11 12, 10 10, 9 12, 7 13, 5 12, 4 10, 4 8, 5 6, 7 4, 9 3, 10 1))'),130 TestGeom('POLYGON ((2 0, 2 15, 18 15, 18 0, 2 0), (10 1, 11 3, 13 4, 15 6, 16 8, 16 10, 15 12, 13 13, 11 12, 10 10, 9 12, 7 13, 5 12, 4 10, 4 8, 5 6, 7 4, 9 3, 10 1))'), 131 131 ) 132 132 django/branches/gis/django/contrib/gis/tests/__init__.py
r5776 r5786 57 57 58 58 # Getting initial values. 59 old_debug = settings.DEBUG 59 60 old_name = copy(settings.DATABASE_NAME) 60 61 old_installed = copy(settings.INSTALLED_APPS) 62 63 # Want DEBUG to be set to False. 64 settings.DEBUG = False 61 65 62 66 # Creating the test suite, adding the test models to INSTALLED_APPS, and … … 83 87 # Cleaning up, destroying the test spatial database and resetting the INSTALLED_APPS. 84 88 destroy_test_db(old_name, verbosity) 89 settings.DEBUG = old_debug 85 90 settings.INSTALLED_APPS = old_installed 86 91 django/branches/gis/django/contrib/gis/tests/test_geos.py
r5742 r5786 1 import unittest1 import random, unittest 2 2 from django.contrib.gis.geos import \ 3 3 GEOSException, GEOSGeometryIndexError, \ … … 167 167 self.assertEqual(lr, LinearRing(*lr.tuple)) 168 168 self.assertEqual(lr, LinearRing([list(tup) for tup in lr.tuple])) 169 if HAS_NUMPY: self.assertEqual(lr, Line String(array(lr.tuple)))169 if HAS_NUMPY: self.assertEqual(lr, LinearRing(array(lr.tuple))) 170 170 171 171 def test05a_polygons(self): … … 201 201 self.assertEqual(p.ext_ring_cs, poly[0].tuple) # Testing __getitem__ 202 202 203 # Testing __iter__ 203 # Testing __getitem__ and __setitem__ on invalid indices 204 self.assertRaises(GEOSGeometryIndexError, poly.__getitem__, len(poly)) 205 self.assertRaises(GEOSGeometryIndexError, poly.__setitem__, len(poly), False) 206 self.assertRaises(GEOSGeometryIndexError, poly.__getitem__, -1) 207 208 # Testing __iter__ 204 209 for r in poly: 205 self.assertEqual(r ing.geom_type, 'LinearRing')206 self.assertEqual(r ing.geom_typeid, 2)210 self.assertEqual(r.geom_type, 'LinearRing') 211 self.assertEqual(r.geom_typeid, 2) 207 212 208 213 # Testing polygon construction. … … 225 230 pass 226 231 poly[0][1] = newval # setting the second point in the polygon with the newvalue (based on the old) 227 self.assertEqual(newval, poly[0][1]) # The point in the polygon should be the 228 self.assertEqual(False, poly == prev) # Evendifferent from the clone we just made232 self.assertEqual(newval, poly[0][1]) # The point in the polygon should be the new value 233 self.assertEqual(False, poly == prev) # Should be different from the clone we just made 229 234 230 235 def test05b_multipolygons(self): … … 427 432 b = GEOSGeometry(g_tup[1].wkt) 428 433 i1 = GEOSGeometry(intersect_geoms[i].wkt) 429 430 434 self.assertEqual(True, a.intersects(b)) 431 435 i2 = a.intersection(b) 432 436 self.assertEqual(i1, i2) 433 self.assertEqual(i1, a & b) 437 self.assertEqual(i1, a & b) # __and__ is intersection operator 438 a &= b # testing __iand__ 439 self.assertEqual(i1, a) 434 440 435 441 def test11_union(self): … … 442 448 u2 = a.union(b) 443 449 self.assertEqual(u1, u2) 444 self.assertEqual(u1, a | b) # Union ('|') operator 450 self.assertEqual(u1, a | b) # __or__ is union operator 451 a |= b # testing __ior__ 452 self.assertEqual(u1, a) 445 453 446 454 def test12_difference(self): … … 453 461 d2 = a.difference(b) 454 462 self.assertEqual(d1, d2) 455 self.assertEqual(d1, a - b) # Difference ('-') operator 463 self.assertEqual(d1, a - b) # __sub__ is difference operator 464 a -= b # testing __isub__ 465 self.assertEqual(d1, a) 456 466 457 467 def test13_symdifference(self): … … 464 474 d2 = a.sym_difference(b) 465 475 self.assertEqual(d1, d2) 466 self.assertEqual(d1, a ^ b) # Symmetric difference ('^') operator 476 self.assertEqual(d1, a ^ b) # __xor__ is symmetric difference operator 477 a ^= b # testing __ixor__ 478 self.assertEqual(d1, a) 467 479 468 480 def test14_buffer(self): … … 493 505 self.assertAlmostEqual(exp_ring[k][1], buf_ring[k][1], 9) 494 506 507 def test15_srid(self): 508 "Testing the SRID property and keyword." 509 # Testing SRID keyword on Point 510 pnt = Point(5, 23, srid=4326) 511 self.assertEqual(4326, pnt.srid) 512 pnt.srid = 3084 513 self.assertEqual(3084, pnt.srid) 514 self.assertRaises(TypeError, pnt.set_srid, '4326') 515 516 # Testing SRID keyword on fromstr(), and on Polygon rings. 517 poly = fromstr(polygons[1].wkt, srid=4269) 518 self.assertEqual(4269, poly.srid) 519 for ring in poly: self.assertEqual(4269, ring.srid) 520 poly.srid = 4326 521 self.assertEqual(4326, poly.shell.srid) 522 523 # Testing SRID keyword on GeometryCollection 524 gc = GeometryCollection(Point(5, 23), LineString((0, 0), (1.5, 1.5), (3, 3)), srid=32021) 525 self.assertEqual(32021, gc.srid) 526 for i in range(len(gc)): self.assertEqual(32021, gc[i].srid) 527 528 def test16_mutable_geometries(self): 529 "Testing the mutability of Polygons and Geometry Collections." 530 ### Testing the mutability of Polygons ### 531 for p in polygons: 532 poly = fromstr(p.wkt) 533 534 # Should only be able to use __setitem__ with LinearRing geometries. 535 self.assertRaises(TypeError, poly.__setitem__, 0, LineString((1, 1), (2, 2))) 536 537 # Constructing the new shell by adding 500 to every point in the old shell. 538 shell_tup = poly.shell.tuple 539 new_coords = [] 540 for point in shell_tup: new_coords.append((point[0] + 500., point[1] + 500.)) 541 shell1 = LinearRing(*tuple(new_coords)) 542 shell2 = shell1.clone() 543 544 # Assigning polygon's exterior ring w/the new shell 545 poly.exterior_ring = shell1 546 self.assertRaises(GEOSException, str, shell1) # shell1 should no longer be accessible 547 self.assertEqual(poly.exterior_ring, shell2) 548 self.assertEqual(poly[0], shell2) 549 del poly, shell1, shell_tup # cleaning up 550 551 ### Testing the mutability of Geometry Collections 552 for tg in multipoints: 553 mp = fromstr(tg.wkt) 554 for i in range(len(mp)): 555 # Creating a random point. 556 pnt = mp[i].clone() 557 new = Point(random.randint(1, 100), random.randint(1, 100)) 558 tmp = new.clone() 559 # Testing the assignmen 560 mp[i] = tmp 561 self.assertRaises(GEOSException, len, tmp) 562 self.assertEqual(mp[i], new) 563 self.assertEqual(mp[i].wkt, new.wkt) 564 self.assertNotEqual(pnt, mp[i]) 565 del mp 566 567 # Multipolygons involve much more memory management because each 568 # polygon w/in the collection has its own rings. 569 for tg in multipolygons: 570 mpoly = fromstr(tg.wkt) 571 for i in xrange(len(mpoly)): 572 poly = mpoly[i].clone() 573 # Offsetting the each ring in the polygon by 500. 574 tmp = poly.clone() 575 for r in tmp: 576 for j in xrange(len(r)): r[j] = (r[j][0] + 500., r[j][1] + 500.) 577 self.assertNotEqual(poly, tmp) 578 new = tmp.clone() # a 'reference' copy of the geometry used in assignment 579 # Testing the assignment 580 mpoly[i] = tmp 581 self.assertRaises(GEOSException, str, tmp) 582 self.assertEqual(mpoly[i], new) 583 self.assertNotEqual(poly, mpoly[i]) 584 del mpoly 585 495 586 def suite(): 496 587 s = unittest.TestSuite()
