Changeset 6024
- Timestamp:
- 08/29/07 20:38:44 (1 year ago)
- Files:
-
- django/branches/gis/django/contrib/gis/geos/base.py (modified) (27 diffs)
- django/branches/gis/django/contrib/gis/geos/collections.py (modified) (6 diffs)
- django/branches/gis/django/contrib/gis/geos/coordseq.py (modified) (6 diffs)
- django/branches/gis/django/contrib/gis/geos/error.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/geos/geometries.py (modified) (14 diffs)
- django/branches/gis/django/contrib/gis/geos/__init__.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/geos/libgeos.py (modified) (5 diffs)
- django/branches/gis/django/contrib/gis/geos/pointer.py (added)
- django/branches/gis/django/contrib/gis/tests/test_geos.py (modified) (32 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis/django/contrib/gis/geos/base.py
r5991 r6024 1 1 """ 2 2 This module contains the 'base' GEOSGeometry object -- all GEOS geometries 3 inherit from this object.3 inherit from this object. 4 4 """ 5 6 5 # ctypes and types dependencies. 7 6 from ctypes import \ … … 12 11 # Python and GEOS-related dependencies. 13 12 import re 14 from warnings import warn 15 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, HAS_NUMPY, ISQLQuote 13 from django.contrib.gis.geos.coordseq import GEOSCoordSeq, create_cs 16 14 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 17 from django.contrib.gis.geos. coordseq import GEOSCoordSeq, create_cs18 if HAS_NUMPY: from numpy import ndarray, array 15 from django.contrib.gis.geos.libgeos import lgeos, HAS_NUMPY, ISQLQuote 16 from django.contrib.gis.geos.pointer import GEOSPointer, NULL_GEOM 19 17 20 18 # Regular expression for recognizing HEXEWKB and WKT. A prophylactic measure … … 27 25 "A class that, generally, encapsulates a GEOS geometry." 28 26 27 # Initially, all geometries use a NULL pointer. 28 _ptr = NULL_GEOM 29 29 30 #### Python 'magic' routines #### 30 def __init__(self, geo_input, input_type=False, parent=None, srid=None): 31 """The constructor for GEOS geometry objects. May take the following 32 strings as inputs, WKT ("wkt"), HEXEWKB ("hex", PostGIS-specific canonical form). 33 34 The `input_type` keyword has been deprecated -- geometry type is now auto-detected. 35 36 The `parent` keyword is for internal use only, and indicates to the garbage collector 37 not to delete this geometry because it was spawned from a parent (e.g., the exterior 38 ring from a polygon). Its value is the GEOSPointer of the parent geometry. 39 """ 40 41 # Initially, setting the pointer to NULL 42 self._ptr = GEOSPointer(0) 31 def __init__(self, geo_input, srid=None): 32 """ 33 The base constructor for GEOS geometry objects, and may take the following 34 string inputs: WKT and HEXEWKB (a PostGIS-specific canonical form). 35 36 The `srid` keyword is used to specify the Source Reference Identifier 37 (SRID) number for this Geometry. If not set, the SRID will be None. 38 """ 43 39 44 40 if isinstance(geo_input, UnicodeType): 45 41 # Encoding to ASCII, WKT or HEXEWKB doesn't need any more. 46 42 geo_input = geo_input.encode('ascii') 47 48 43 if isinstance(geo_input, StringType): 49 if input_type: warn('input_type keyword is deprecated')50 51 44 if hex_regex.match(geo_input): 52 45 # If the regex matches, the geometry is in HEX form. … … 59 52 else: 60 53 raise GEOSException, 'given string input "%s" unrecognized as WKT or HEXEWKB.' % geo_input 61 62 54 elif isinstance(geo_input, (IntType, GEOSPointer)): 63 # When the input is either a raw pointer value (an integer), or a GEOSPointer object. 55 # When the input is either a memory address (an integer), or a 56 # GEOSPointer object. 64 57 g = geo_input 65 58 else: … … 68 61 69 62 if bool(g): 70 # If we have a GEOSPointer object, just set the '_ptr' attribute with input 71 if isinstance(g, GEOSPointer): self._ptr = g 72 else: self._ptr.set(g) # Otherwise, set with the address 63 # Setting the pointer object with a valid pointer. 64 self._ptr = GEOSPointer(g) 73 65 else: 74 66 raise GEOSException, 'Could not initialize GEOS Geometry with given input.' 75 67 76 # Setting the 'parent' flag -- when the object is labeled with this flag77 # it will not be destroyed by __del__(). This is used for child geometries spawned from78 # parent geometries (e.g., LinearRings from a Polygon, Points from a MultiPoint, etc.).79 if isinstance(parent, GEOSPointer):80 self._parent = parent81 else:82 self._parent = GEOSPointer(0)83 84 68 # Setting the SRID, if given. 85 69 if srid and isinstance(srid, int): self.srid = srid … … 88 72 self.__class__ = GEOS_CLASSES[self.geom_type] 89 73 90 # Getting the coordinate sequence for the geometry (will be None on geometries that91 # do not have coordinate sequences)92 self._ get_cs()93 94 # Extra setup needed for Geometries that may be parents.74 # Setting the coordinate sequence for the geometry (will be None on 75 # geometries that do not have coordinate sequences) 76 self._set_cs() 77 78 # _populate() needs to be called for parent Geometries. 95 79 if isinstance(self, (Polygon, GeometryCollection)): self._populate() 96 80 97 81 def __del__(self): 98 "Destroys this geometry -- only if the pointer is valid and whether or not it belongs to a parent." 99 #print 'base: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._parent, self._ptr.valid) 100 # Only calling destroy on valid pointers not spawned from a parent 101 if self._ptr.valid and not self._parent: lgeos.GEOSGeom_destroy(self._ptr()) 82 """ 83 Destroys this Geometry; in other words, frees the memory used by the 84 GEOS C++ object -- but only if the pointer is not a child Geometry 85 (e.g., don't delete the LinearRings spawned from a Polygon). 86 """ 87 #print 'base: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._ptr.parent, self._ptr.valid) 88 if not self._ptr.child: self._ptr.destroy() 102 89 103 90 def __str__(self): … … 157 144 # g1 ^= g2 158 145 def __ixor__(self, other): 159 "Reassigns this Geometry to the symmetric difference of this Geometry and the other." 146 """ 147 Reassigns this Geometry to the symmetric difference of this Geometry 148 and the other. 149 """ 160 150 return self.sym_difference(other) 161 151 152 #### Internal GEOSPointer-related routines. #### 162 153 def _nullify(self): 163 """ During initialization of geometries from other geometries, this routine is164 used to nullify any parent geometries (since they will now be missing memory165 components) and to nullify the geometry itself to prevent future access.166 Only the address (an integer) of the current geometry is returned for use in167 initializing the new geometry."""154 """ 155 Returns the address of this Geometry, and nullifies any related pointers. 156 This function is called if this Geometry is used in the initialization 157 of another Geometry. 158 """ 168 159 # First getting the memory address of the geometry. 169 160 address = self._ptr() … … 171 162 # If the geometry is a child geometry, then the parent geometry pointer is 172 163 # nullified. 173 if self._parent: self._parent.nullify() 174 164 if self._ptr.child: 165 p = self._ptr.parent 166 # If we have a grandchild (a LinearRing from a MultiPolygon or 167 # GeometryCollection), then nullify the collection as well. 168 if p.child: p.parent.nullify() 169 p.nullify() 170 175 171 # Nullifying the geometry pointer 176 172 self._ptr.nullify() … … 179 175 180 176 def _reassign(self, new_geom): 181 " Internal routine for reassigning internal pointer to a new geometry."177 "Reassigns the internal pointer to that of the new Geometry." 182 178 # Only can re-assign when given a pointer or a geometry. 183 179 if not isinstance(new_geom, (GEOSPointer, GEOSGeometry)): … … 187 183 # Re-assigning the internal GEOSPointer to the new geometry, nullifying 188 184 # the new Geometry in the process. 189 if isinstance(new_geom, GEOS Geometry): self._ptr.set(new_geom._nullify())190 else: self._ptr = new_geom185 if isinstance(new_geom, GEOSPointer): self._ptr = new_geom 186 else: self._ptr = GEOSPointer(new_geom._nullify()) 191 187 192 188 # The new geometry class may be different from the original, so setting … … 201 197 return self 202 198 else: 203 raise GEOSException, 'Error implementing psycopg2 protocol. Is psycopg2 installed?'199 raise GEOSException, 'Error implementing psycopg2 protocol. Is psycopg2 installed?' 204 200 205 201 def getquoted(self): 206 "Returns a properly quoted string for use in Postgre sSQL/PostGIS."202 "Returns a properly quoted string for use in PostgreSQL/PostGIS." 207 203 # Using ST_GeomFromText(), corresponds to SQL/MM ISO standard. 208 204 return "ST_GeomFromText('%s', %s)" % (self.wkt, self.srid or -1) … … 218 214 return False 219 215 220 def _ get_cs(self):221 " Gets the coordinate sequence for this Geometry."216 def _set_cs(self): 217 "Sets the coordinate sequence for this Geometry." 222 218 if self.has_cs: 223 self._ptr.set(lgeos.GEOSGeom_getCoordSeq(self._ptr()), coordseq=True) 219 if not self._ptr.coordseq_valid: 220 self._ptr.set_coordseq(lgeos.GEOSGeom_getCoordSeq(self._ptr())) 224 221 self._cs = GEOSCoordSeq(self._ptr, self.hasz) 225 222 else: … … 273 270 ## Internal for GEOS unary & binary predicate functions ## 274 271 def _unary_predicate(self, func): 275 """Returns the result, or raises an exception for the given unary 276 predicate function.""" 272 """ 273 Returns the result, or raises an exception for the given unary predicate 274 function. 275 """ 277 276 val = func(self._ptr()) 278 277 if val == 0: return False … … 281 280 282 281 def _binary_predicate(self, func, other, *args): 283 """Returns the result, or raises an exception for the given binary 284 predicate function.""" 282 """ 283 Returns the result, or raises an exception for the given binary 284 predicate function. 285 """ 285 286 if not isinstance(other, GEOSGeometry): 286 287 raise TypeError, 'Binary predicate operation ("%s") requires another GEOSGeometry instance.' % func.__name__ … … 293 294 @property 294 295 def empty(self): 295 "Returns a boolean indicating whether the set of points in this Geometry are empty." 296 """ 297 Returns a boolean indicating whether the set of points in this Geometry 298 are empty. 299 """ 296 300 return self._unary_predicate(lgeos.GEOSisEmpty) 297 301 … … 318 322 #### Binary predicates. #### 319 323 def relate_pattern(self, other, pattern): 320 """Returns true if the elements in the DE-9IM intersection matrix for 321 the two Geometries match the elements in pattern.""" 324 """ 325 Returns true if the elements in the DE-9IM intersection matrix for the 326 two Geometries match the elements in pattern. 327 """ 322 328 if len(pattern) > 9: 323 329 raise GEOSException, 'invalid intersection matrix pattern' … … 325 331 326 332 def disjoint(self, other): 327 """Returns true if the DE-9IM intersection matrix for the two Geometries 328 is FF*FF****.""" 333 """ 334 Returns true if the DE-9IM intersection matrix for the two Geometries 335 is FF*FF****. 336 """ 329 337 return self._binary_predicate(lgeos.GEOSDisjoint, other) 330 338 331 339 def touches(self, other): 332 """Returns true if the DE-9IM intersection matrix for the two Geometries 333 is FT*******, F**T***** or F***T****.""" 340 """ 341 Returns true if the DE-9IM intersection matrix for the two Geometries 342 is FT*******, F**T***** or F***T****. 343 """ 334 344 return self._binary_predicate(lgeos.GEOSTouches, other) 335 345 … … 339 349 340 350 def crosses(self, other): 341 """Returns true if the DE-9IM intersection matrix for the two Geometries 342 is T*T****** (for a point and a curve,a point and an area or a line and 343 an area) 0******** (for two curves).""" 351 """ 352 Returns true if the DE-9IM intersection matrix for the two Geometries 353 is T*T****** (for a point and a curve,a point and an area or a line and 354 an area) 0******** (for two curves). 355 """ 344 356 return self._binary_predicate(lgeos.GEOSCrosses, other) 345 357 346 358 def within(self, other): 347 """Returns true if the DE-9IM intersection matrix for the two Geometries 348 is T*F**F***.""" 359 """ 360 Returns true if the DE-9IM intersection matrix for the two Geometries 361 is T*F**F***. 362 """ 349 363 return self._binary_predicate(lgeos.GEOSWithin, other) 350 364 … … 354 368 355 369 def overlaps(self, other): 356 """Returns true if the DE-9IM intersection matrix for the two Geometries 357 is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves).""" 370 """ 371 Returns true if the DE-9IM intersection matrix for the two Geometries 372 is T*T***T** (for two points or two surfaces) 1*T***T** (for two curves). 373 """ 358 374 return self._binary_predicate(lgeos.GEOSOverlaps, other) 359 375 360 376 def equals(self, other): 361 """Returns true if the DE-9IM intersection matrix for the two Geometries 362 is T*F**FFF*.""" 377 """ 378 Returns true if the DE-9IM intersection matrix for the two Geometries 379 is T*F**FFF*. 380 """ 363 381 return self._binary_predicate(lgeos.GEOSEquals, other) 364 382 365 383 def equals_exact(self, other, tolerance=0): 366 """Returns true if the two Geometries are exactly equal, up to a 367 specified tolerance.""" 384 """ 385 Returns true if the two Geometries are exactly equal, up to a 386 specified tolerance. 387 """ 368 388 return self._binary_predicate(lgeos.GEOSEqualsExact, other, 369 389 c_double(tolerance)) … … 384 404 @property 385 405 def wkt(self): 386 "Returns the WKT of the Geometry."406 "Returns the WKT (Well-Known Text) of the Geometry." 387 407 return string_at(lgeos.GEOSGeomToWKT(self._ptr())) 388 408 389 409 @property 390 410 def hex(self): 391 "Returns the WKBHEXof the Geometry."411 "Returns the HEXEWKB of the Geometry." 392 412 sz = c_size_t() 393 413 h = lgeos.GEOSGeomToHEX_buf(self._ptr(), byref(sz)) … … 402 422 #### Topology Routines #### 403 423 def _unary_topology(self, func, *args): 404 """Returns a GEOSGeometry for the given unary (takes only one Geomtery 405 as a paramter) topological operation.""" 424 """ 425 Returns a GEOSGeometry for the given unary (takes only one Geomtery 426 as a paramter) topological operation. 427 """ 406 428 return GEOSGeometry(func(self._ptr(), *args), srid=self.srid) 407 429 408 430 def _binary_topology(self, func, other, *args): 409 """Returns a GEOSGeometry for the given binary (takes two Geometries 410 as parameters) topological operation.""" 431 """ 432 Returns a GEOSGeometry for the given binary (takes two Geometries 433 as parameters) topological operation. 434 """ 411 435 return GEOSGeometry(func(self._ptr(), other._ptr(), *args), srid=self.srid) 412 436 413 437 def buffer(self, width, quadsegs=8): 414 """Returns a geometry that represents all points whose distance from this 415 Geometry is less than or equal to distance. Calculations are in the 416 Spatial Reference System of this Geometry. The optional third parameter sets 417 the number of segment used to approximate a quarter circle (defaults to 8). 418 (Text from PostGIS documentation at ch. 6.1.3) 438 """ 439 Returns a geometry that represents all points whose distance from this 440 Geometry is less than or equal to distance. Calculations are in the 441 Spatial Reference System of this Geometry. The optional third parameter sets 442 the number of segment used to approximate a quarter circle (defaults to 8). 443 (Text from PostGIS documentation at ch. 6.1.3) 419 444 """ 420 445 if not isinstance(width, (FloatType, IntType)): … … 431 456 @property 432 457 def centroid(self): 433 """The centroid is equal to the centroid of the set of component Geometries 434 of highest dimension (since the lower-dimension geometries contribute zero 435 "weight" to the centroid).""" 458 """ 459 The centroid is equal to the centroid of the set of component Geometries 460 of highest dimension (since the lower-dimension geometries contribute zero 461 "weight" to the centroid). 462 """ 436 463 return self._unary_topology(lgeos.GEOSGetCentroid) 437 464 … … 443 470 @property 444 471 def convex_hull(self): 445 """Returns the smallest convex Polygon that contains all the points 446 in the Geometry.""" 472 """ 473 Returns the smallest convex Polygon that contains all the points 474 in the Geometry. 475 """ 447 476 return self._unary_topology(lgeos.GEOSConvexHull) 448 477 … … 452 481 return self._unary_topology(lgeos.GEOSPointOnSurface) 453 482 483 def simplify(self, tolerance=0.0): 484 """ 485 Returns the Geometry, simplified using the Douglas-Peucker algorithm 486 to the specified tolerance (higher tolerance => less points). If no 487 tolerance provided, defaults to 0. 488 """ 489 return self._unary_topology(lgeos.GEOSSimplify, c_double(tolerance)) 490 454 491 def relate(self, other): 455 "Returns the DE-9IM intersection matrix for this geometry and the other."492 "Returns the DE-9IM intersection matrix for this Geometry and the other." 456 493 return string_at(lgeos.GEOSRelate(self._ptr(), other._ptr())) 457 494 … … 462 499 463 500 def sym_difference(self, other): 464 """Returns a set combining the points in this Geometry not in other, 465 and the points in other not in this Geometry.""" 501 """ 502 Returns a set combining the points in this Geometry not in other, 503 and the points in other not in this Geometry. 504 """ 466 505 return self._binary_topology(lgeos.GEOSSymDifference, other) 467 506 … … 484 523 485 524 def distance(self, other): 486 """Returns the distance between the closest points on this Geometry 487 and the other. Units will be in those of the coordinate system. of 488 the Geometry.""" 525 """ 526 Returns the distance between the closest points on this Geometry 527 and the other. Units will be in those of the coordinate system of 528 the Geometry. 529 """ 489 530 if not isinstance(other, GEOSGeometry): 490 531 raise TypeError, 'distance() works only on other GEOS Geometries.' … … 496 537 @property 497 538 def length(self): 498 """Returns the length of this Geometry (e.g., 0 for point, or the 499 circumfrence of a Polygon).""" 539 """ 540 Returns the length of this Geometry (e.g., 0 for point, or the 541 circumfrence of a Polygon). 542 """ 500 543 l = c_double() 501 544 status = lgeos.GEOSLength(self._ptr(), byref(l)) django/branches/gis/django/contrib/gis/geos/collections.py
r5805 r6024 1 1 """ 2 This module houses the Geometry Collection objects:3 GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon2 This module houses the Geometry Collection objects: 3 GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon 4 4 """ 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, get_pointer_arr, GEOM_PTR8 7 from django.contrib.gis.geos.base import GEOSGeometry 9 8 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 10 9 from django.contrib.gis.geos.geometries import Point, LineString, LinearRing, Polygon 10 from django.contrib.gis.geos.libgeos import lgeos, get_pointer_arr, GEOM_PTR 11 from django.contrib.gis.geos.pointer import GEOSPointer 11 12 12 13 class GeometryCollection(GEOSGeometry): … … 16 17 def __init__(self, *args, **kwargs): 17 18 "Initializes a Geometry Collection from a sequence of Geometry objects." 18 # Setting up the collection for creation19 self._ptr = GEOSPointer(0) # Initially NULL20 self._geoms = {}21 self._parent = None22 19 23 20 # Checking the arguments … … 25 22 raise TypeError, 'Must provide at least one Geometry to initialize %s.' % self.__class__.__name__ 26 23 27 if len(args) == 1: # If only one geometry provided or a list of geometries is provided 24 if len(args) == 1: 25 # If only one geometry provided or a list of geometries is provided 26 # in the first argument. 28 27 if isinstance(args[0], (TupleType, ListType)): 29 28 init_geoms = args[0] … … 37 36 raise TypeError, 'Invalid Geometry type encountered in the arguments.' 38 37 39 # Creating the geometry pointer array 38 # Creating the geometry pointer array, and populating each element in 39 # the array with the address of the Geometry returned by _nullify(). 40 40 ngeom = len(init_geoms) 41 41 geoms = get_pointer_arr(ngeom) 42 43 # Incrementing through each input geometry.44 42 for i in xrange(ngeom): 45 43 geoms[i] = cast(init_geoms[i]._nullify(), GEOM_PTR) 46 44 47 # Calling the parent class, using the pointer returned from GEOS createCollection() 48 super(GeometryCollection, self).__init__(lgeos.GEOSGeom_createCollection(c_int(self._typeid), byref(geoms), c_uint(ngeom)), **kwargs) 45 # Calling the parent class, using the pointer returned from the 46 # GEOS createCollection() factory. 47 addr = lgeos.GEOSGeom_createCollection(c_int(self._typeid), 48 byref(geoms), c_uint(ngeom)) 49 super(GeometryCollection, self).__init__(addr, **kwargs) 49 50 50 51 def __del__(self): 51 52 "Overloaded deletion method for Geometry Collections." 52 #print 'collection: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._p arent, self._ptr.valid)53 #print 'collection: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._ptr.parent, self._ptr.valid) 53 54 # If this geometry is still valid, it hasn't been modified by others. 54 55 if self._ptr.valid: 55 # Nullifying pointers to internal geometries, preventing any attempted future access. 56 for k in self._geoms: self._geoms[k].nullify() 56 # Nullifying pointers to internal Geometries, preventing any 57 # attempted future access. 58 for g in self._ptr: g.nullify() 57 59 else: 58 # Internal memory has become part of other Geometry objects, must delete the 59 # internal objects which are still valid individually, since calling destructor 60 # on entire geometry will result in an attempted deletion of NULL pointers for 61 # the missing components. 62 for k in self._geoms: 63 if self._geoms[k].valid: 64 lgeos.GEOSGeom_destroy(self._geoms[k].address) 65 self._geoms[k].nullify() 60 # Internal memory has become part of other Geometry objects; must 61 # delete the internal objects which are still valid individually, 62 # because calling the destructor on the entire geometry will result 63 # in an attempted deletion of NULL pointers for the missing 64 # components (which may crash Python). 65 for g in self._ptr: 66 if len(g) > 0: 67 # The collection geometry is a Polygon, destroy any leftover 68 # LinearRings. 69 for r in g: r.destroy() 70 g.destroy() 71 66 72 super(GeometryCollection, self).__del__() 67 73 … … 70 76 # Checking the index and returning the corresponding GEOS geometry. 71 77 self._checkindex(index) 72 return GEOSGeometry(self._ geoms[index], parent=self._ptr, srid=self.srid)78 return GEOSGeometry(self._ptr[index], srid=self.srid) 73 79 74 80 def __setitem__(self, index, geom): … … 106 112 "Overloaded from base method to nullify geometry references in this Collection." 107 113 # Nullifying the references to the internal Geometry objects from this Collection. 108 for k in self._geoms: self._geoms[k].nullify()114 for g in self._ptr: g.nullify() 109 115 return super(GeometryCollection, self)._nullify() 110 116 111 117 def _populate(self): 112 "Populates the internal child geometry dictionary." 113 self._geoms = {} 114 for i in xrange(self.num_geom): 115 self._geoms[i] = GEOSPointer(lgeos.GEOSGetGeometryN(self._ptr(), c_int(i))) 118 "Internal routine that populates the internal children geometries list." 119 ptr_list = [] 120 for i in xrange(len(self)): 121 # Getting the geometry pointer for the geometry at the index. 122 geom_ptr = lgeos.GEOSGetGeometryN(self._ptr(), c_int(i)) 123 124 # Adding the coordinate sequence to the list, or using None if the 125 # collection Geometry doesn't support coordinate sequences. 126 if lgeos.GEOSGeomTypeId(geom_ptr) in (0, 1, 2): 127 ptr_list.append((geom_ptr, lgeos.GEOSGeom_getCoordSeq(geom_ptr))) 128 else: 129 ptr_list.append((geom_ptr, None)) 130 self._ptr.set_children(ptr_list) 116 131 117 132 @property django/branches/gis/django/contrib/gis/geos/coordseq.py
r5805 r6024 1 from django.contrib.gis.geos.libgeos import lgeos, GEOSPointer, HAS_NUMPY 1 """ 2 This module houses the GEOSCoordSeq object, and is used internally 3 by GEOSGeometry to house the actual coordinates of the Point, 4 LineString, and LinearRing geometries. 5 """ 2 6 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 7 from django.contrib.gis.geos.libgeos import lgeos, HAS_NUMPY 8 from django.contrib.gis.geos.pointer import GEOSPointer 3 9 from ctypes import c_double, c_int, c_uint, byref 4 10 from types import ListType, TupleType 5 11 if HAS_NUMPY: from numpy import ndarray 6 7 """8 This module houses the GEOSCoordSeq object, and is used internally9 by GEOSGeometry to house the actual coordinates of the Point,10 LineString, and LinearRing geometries.11 """12 12 13 13 class GEOSCoordSeq(object): … … 32 32 33 33 def __str__(self): 34 " The string representation of the coordinate sequence."34 "Returns the string representation of the coordinate sequence." 35 35 return str(self.tuple) 36 36 37 37 def __getitem__(self, index): 38 " Can use the index [] operator to get coordinate sequence at an index."38 "Returns the coordinate sequence value at the given index." 39 39 coords = [self.getX(index), self.getY(index)] 40 40 if self.dims == 3 and self._z: … … 43 43 44 44 def __setitem__(self, index, value): 45 " Can use the index [] operator to set coordinate sequence at an index."45 "Sets the coordinate sequence value at the given index." 46 46 # Checking the input value 47 47 if isinstance(value, (ListType, TupleType)): … … 67 67 #### Internal Routines #### 68 68 def _checkindex(self, index): 69 "Checks the index."69 "Checks the given index." 70 70 sz = self.size 71 71 if (sz < 1) or (index < 0) or (index >= sz): … … 79 79 #### Ordinate getting and setting routines #### 80 80 def getOrdinate(self, dimension, index): 81 " Gets the value for the given dimension and index."81 "Returns the value for the given dimension and index." 82 82 self._checkindex(index) 83 83 self._checkdim(dimension) … … 153 153 @property 154 154 def hasz(self): 155 "Inherits this from the parent geometry." 155 """ 156 Returns whether this coordinate sequence is 3D. This property value is 157 inherited from the parent Geometry. 158 """ 156 159 return self._z 157 160 django/branches/gis/django/contrib/gis/geos/error.py
r5655 r6024 1 """ 2 This module houses the GEOS exceptions, specifically, GEOSException and 3 GEOSGeometryIndexError. 4 """ 1 5 2 6 class GEOSException(Exception): … … 5 9 6 10 class GEOSGeometryIndexError(GEOSException, KeyError): 7 """This exception is raised when an invalid index is encountered, and has 11 """ 12 This exception is raised when an invalid index is encountered, and has 8 13 the 'silent_variable_feature' attribute set to true. This ensures that 9 14 django's templates proceed to use the next lookup type gracefully when … … 11 16 """ 12 17 # "If, during the method lookup, a method raises an exception, the exception 13 # will be propagated, unless the exception has an attribute silent_variable_failure14 # whose value is True." -- django template docs.18 # will be propagated, unless the exception has an attribute 19 # `silent_variable_failure` whose value is True." -- Django template docs. 15 20 silent_variable_failure = True django/branches/gis/django/contrib/gis/geos/geometries.py
r5832 r6024 4 4 GEOSGeometry. 5 5 """ 6 7 6 from ctypes import c_double, c_int, c_uint, byref, cast 8 7 from types import FloatType, IntType, ListType, TupleType 8 from django.contrib.gis.geos.base import GEOSGeometry 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, GEOM_PTR, HAS_NUMPY11 from django.contrib.gis.geos. base import GEOSGeometry10 from django.contrib.gis.geos.libgeos import lgeos, get_pointer_arr, GEOM_PTR, HAS_NUMPY 11 from django.contrib.gis.geos.pointer import GEOSPointer 12 12 from django.contrib.gis.geos.error import GEOSException, GEOSGeometryIndexError 13 13 if HAS_NUMPY: from numpy import ndarray, array … … 16 16 17 17 def __init__(self, x, y=None, z=None, srid=None): 18 """The Point object may be initialized with either a tuple, or individual 19 parameters. For example: 18 """ 19 The Point object may be initialized with either a tuple, or individual 20 parameters. For example: 20 21 >>> p = Point((5, 23)) # 2D point, passed in as a tuple 21 22 >>> p = Point(5, 23, 8) # 3D point, passed in with individual parameters 22 23 """ 23 24 24 # Setting-up for Point Creation25 self._ptr = GEOSPointer(0) # Initially NULL26 self._parent = None27 28 25 if isinstance(x, (TupleType, ListType)): 29 # Here a tuple or list was passed in under the ` `x`` parameter.26 # Here a tuple or list was passed in under the `x` parameter. 30 27 ndim = len(x) 31 28 if ndim < 2 or ndim > 3: … … 33 30 coords = x 34 31 elif isinstance(x, (IntType, FloatType)) and isinstance(y, (IntType, FloatType)): 35 # Here X, Y, and (optionally) Z were passed in individually as parameters.32 # Here X, Y, and (optionally) Z were passed in individually, as parameters. 36 33 if isinstance(z, (IntType, FloatType)): 37 34 ndim = 3 … … 43 40 raise TypeError, 'Invalid parameters given for Point initialization.' 44 41 45 # Creating the coordinate sequence 42 # Creating the coordinate sequence, and setting X, Y, [Z] 46 43 cs = create_cs(c_uint(1), c_uint(ndim)) 47 48 # Setting the X49 44 status = lgeos.GEOSCoordSeq_setX(cs, c_uint(0), c_double(coords[0])) 50 45 if not status: raise GEOSException, 'Could not set X during Point initialization.' 51 52 # Setting the Y53 46 status = lgeos.GEOSCoordSeq_setY(cs, c_uint(0), c_double(coords[1])) 54 47 if not status: raise GEOSException, 'Could not set Y during Point initialization.' 55 56 # Setting the Z57 48 if ndim == 3: 58 49 status = lgeos.GEOSCoordSeq_setZ(cs, c_uint(0), c_double(coords[2])) 59 50 60 # Initializing from the geometry, and getting a Python object 51 # Initializing using the address returned from the GEOS 52 # createPoint factory. 61 53 super(Point, self).__init__(lgeos.GEOSGeom_createPoint(cs), srid=srid) 62 54 … … 126 118 #### Python 'magic' routines #### 127 119 def __init__(self, *args, **kwargs): 128 """Initializes on the given sequence -- may take lists, tuples, NumPy arrays 129 of X,Y pairs, or Point objects. If Point objects are used, ownership is 130 _not_ transferred to the LineString object. 120 """ 121 Initializes on the given sequence -- may take lists, tuples, NumPy arrays 122 of X,Y pairs, or Point objects. If Point objects are used, ownership is 123 _not_ transferred to the LineString object. 131 124 132 125 Examples: … … 136 129 ls = LineString(Point(1, 1), Point(2, 2)) 137 130 """ 138 # Setting up for LineString creation 139 self._ptr = GEOSPointer(0) # Initially NULL 140 self._parent = None 141 142 # If only one argument was provided, then set the coords array appropriately 131 # If only one argument provided, set the coords array appropriately 143 132 if len(args) == 1: coords = args[0] 144 133 else: coords = args … … 167 156 raise TypeError, 'Invalid initialization input for LineStrings.' 168 157 169 # Creating the coordinate sequence 158 # Creating a coordinate sequence object because it is easier to 159 # set the points using GEOSCoordSeq.__setitem__(). 170 160 cs = GEOSCoordSeq(GEOSPointer(0, create_cs(c_uint(ncoords), c_uint(ndim))), z=bool(ndim==3)) 171 172 # Setting each point in the coordinate sequence173 161 for i in xrange(ncoords): 174 162 if numpy_coords: cs[i] = coords[i,:] … … 185 173 srid = kwargs.get('srid', None) 186 174 187 # Calling the base geometry initialization with the returned pointer from the function. 175 # Calling the base geometry initialization with the returned pointer 176 # from the function. 188 177 super(LineString, self).__init__(func(cs._ptr.coordseq()), srid=srid) 189 178 … … 215 204 216 205 def _listarr(self, func): 217 """Internal routine that returns a sequence (list) corresponding with 218 the given function. Will return a numpy array if possible.""" 219 lst = [func(i) for i in xrange(len(self))] # constructing the list, using the function 206 """ 207 Internal routine that returns a sequence (list) corresponding with 208 the given function. Will return a numpy array if possible. 209 """ 210 lst = [func(i) for i in xrange(len(self))] 220 211 if HAS_NUMPY: return array(lst) # ARRRR! 221 212 else: return lst … … 252 243 253 244 def __init__(self, *args, **kwargs): 254 """Initializes on an exterior ring and a sequence of holes (both instances of LinearRings. 255 All LinearRing instances used for creation will become owned by this Polygon. 245 """ 246 Initializes on an exterior ring and a sequence of holes (both 247 instances of LinearRings. All LinearRing instances used for creation 248 will become owned by this Polygon. 256 249 257 Examples, where shell, hole1, and hole2 are valid LinearRing geometries: 258 poly = Polygon(shell, hole1, hole2) 259 poly = Polygon(shell, (hole1, hole2)) 260 """ 261 self._ptr = GEOSPointer(0) # Initially NULL 262 self._parent = None 263 self._rings = {} 250 Below are some examples of initialization, where shell, hole1, and 251 hole2 are valid LinearRing geometries: 252 >>> poly = Polygon(shell, hole1, hole2) 253 >>> poly = Polygon(shell, (hole1, hole2)) 254 """ 264 255 if not args: 265 256 raise TypeError, 'Must provide at list one LinearRing instance to initialize Polygon.' … … 294 285 def __del__(self): 295 286 "Overloaded deletion method for Polygons." 296 #print 'polygon: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._p arent, self._ptr.valid)297 # If this geometry is still valid, it hasn't been modified by others.298 if self._ptr.valid:299 # Nulling the pointers to internal rings, preventing any attempted future access300 for k in self._rings: self._rings[k].nullify()301 elif not self._parent:302 # Internal memory has become part of other objects; must delete the303 # internal objects which are still valid individually, since calling304 # destructor on entire geometry will result in an attempted deletion305 # of NULL pointers for the missing components. Not performed on306 # children Polygons from MultiPolygon or GeometryCollection objects.307 for k in self._rings:308 if self._rings[k].valid:309 lgeos.GEOSGeom_destroy(self._rings[k].address)310 self._rings[k].nullify()287 #print 'polygon: Deleting %s (parent=%s, valid=%s)' % (self.__class__.__name__, self._ptr.parent, self._ptr.valid) 288 # Not performed on children Polygons from MultiPolygon or GeometryCollection objects. 289 if not self._ptr.child: 290 # If this geometry is still valid, it hasn't been modified by others. 291 if self._ptr.valid: 292 # Nulling the pointers to internal rings, preventing any 293 # attempted future access. 294 for r in self._ptr: r.nullify() 295 else: 296 # Internal memory has become part of other Geometry objects; must 297 # delete the internal objects which are still valid individually, 298 # because calling the destructor on entire geometry will result 299 # in an attempted deletion of NULL pointers for th
