/django/contrib/gis/geos/coordseq.py
Python | 156 lines | 114 code | 23 blank | 19 comment | 20 complexity | 96bd6157c51f2800c4c81f4772dbe3e5 MD5 | raw file
Possible License(s): BSD-3-Clause
- """
- This module houses the GEOSCoordSeq object, which is used internally
- by GEOSGeometry to house the actual coordinates of the Point,
- LineString, and LinearRing geometries.
- """
- from ctypes import c_double, c_uint, byref
- from django.contrib.gis.geos.base import GEOSBase, numpy
- from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
- from django.contrib.gis.geos.libgeos import CS_PTR
- from django.contrib.gis.geos import prototypes as capi
- class GEOSCoordSeq(GEOSBase):
- "The internal representation of a list of coordinates inside a Geometry."
- ptr_type = CS_PTR
- #### Python 'magic' routines ####
- def __init__(self, ptr, z=False):
- "Initializes from a GEOS pointer."
- if not isinstance(ptr, CS_PTR):
- raise TypeError('Coordinate sequence should initialize with a CS_PTR.')
- self._ptr = ptr
- self._z = z
- def __iter__(self):
- "Iterates over each point in the coordinate sequence."
- for i in xrange(self.size):
- yield self[i]
- def __len__(self):
- "Returns the number of points in the coordinate sequence."
- return int(self.size)
- def __str__(self):
- "Returns the string representation of the coordinate sequence."
- return str(self.tuple)
- def __getitem__(self, index):
- "Returns the coordinate sequence value at the given index."
- coords = [self.getX(index), self.getY(index)]
- if self.dims == 3 and self._z:
- coords.append(self.getZ(index))
- return tuple(coords)
- def __setitem__(self, index, value):
- "Sets the coordinate sequence value at the given index."
- # Checking the input value
- if isinstance(value, (list, tuple)):
- pass
- elif numpy and isinstance(value, numpy.ndarray):
- pass
- else:
- raise TypeError('Must set coordinate with a sequence (list, tuple, or numpy array).')
- # Checking the dims of the input
- if self.dims == 3 and self._z:
- n_args = 3
- set_3d = True
- else:
- n_args = 2
- set_3d = False
- if len(value) != n_args:
- raise TypeError('Dimension of value does not match.')
- # Setting the X, Y, Z
- self.setX(index, value[0])
- self.setY(index, value[1])
- if set_3d: self.setZ(index, value[2])
- #### Internal Routines ####
- def _checkindex(self, index):
- "Checks the given index."
- sz = self.size
- if (sz < 1) or (index < 0) or (index >= sz):
- raise GEOSIndexError('invalid GEOS Geometry index: %s' % str(index))
- def _checkdim(self, dim):
- "Checks the given dimension."
- if dim < 0 or dim > 2:
- raise GEOSException('invalid ordinate dimension "%d"' % dim)
- #### Ordinate getting and setting routines ####
- def getOrdinate(self, dimension, index):
- "Returns the value for the given dimension and index."
- self._checkindex(index)
- self._checkdim(dimension)
- return capi.cs_getordinate(self.ptr, index, dimension, byref(c_double()))
- def setOrdinate(self, dimension, index, value):
- "Sets the value for the given dimension and index."
- self._checkindex(index)
- self._checkdim(dimension)
- capi.cs_setordinate(self.ptr, index, dimension, value)
- def getX(self, index):
- "Get the X value at the index."
- return self.getOrdinate(0, index)
- def setX(self, index, value):
- "Set X with the value at the given index."
- self.setOrdinate(0, index, value)
- def getY(self, index):
- "Get the Y value at the given index."
- return self.getOrdinate(1, index)
- def setY(self, index, value):
- "Set Y with the value at the given index."
- self.setOrdinate(1, index, value)
- def getZ(self, index):
- "Get Z with the value at the given index."
- return self.getOrdinate(2, index)
- def setZ(self, index, value):
- "Set Z with the value at the given index."
- self.setOrdinate(2, index, value)
- ### Dimensions ###
- @property
- def size(self):
- "Returns the size of this coordinate sequence."
- return capi.cs_getsize(self.ptr, byref(c_uint()))
- @property
- def dims(self):
- "Returns the dimensions of this coordinate sequence."
- return capi.cs_getdims(self.ptr, byref(c_uint()))
- @property
- def hasz(self):
- """
- Returns whether this coordinate sequence is 3D. This property value is
- inherited from the parent Geometry.
- """
- return self._z
- ### Other Methods ###
- def clone(self):
- "Clones this coordinate sequence."
- return GEOSCoordSeq(capi.cs_clone(self.ptr), self.hasz)
- @property
- def kml(self):
- "Returns the KML representation for the coordinates."
- # Getting the substitution string depending on whether the coordinates have
- # a Z dimension.
- if self.hasz: substr = '%s,%s,%s '
- else: substr = '%s,%s,0 '
- return '<coordinates>%s</coordinates>' % \
- ''.join([substr % self[i] for i in xrange(len(self))]).strip()
- @property
- def tuple(self):
- "Returns a tuple version of this coordinate sequence."
- n = self.size
- if n == 1: return self[0]
- else: return tuple([self[i] for i in xrange(n)])