|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196 |
- """
- 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 byref, c_double, c_uint
-
- from django.contrib.gis.geos import prototypes as capi
- from django.contrib.gis.geos.base import GEOSBase
- from django.contrib.gis.geos.error import GEOSException
- from django.contrib.gis.geos.libgeos import CS_PTR
- from django.contrib.gis.shortcuts import numpy
-
-
- class GEOSCoordSeq(GEOSBase):
- "The internal representation of a list of coordinates inside a Geometry."
-
- ptr_type = CS_PTR
-
- def __init__(self, ptr, z=False):
- "Initialize 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):
- "Iterate over each point in the coordinate sequence."
- for i in range(self.size):
- yield self[i]
-
- def __len__(self):
- "Return the number of points in the coordinate sequence."
- return int(self.size)
-
- def __str__(self):
- "Return the string representation of the coordinate sequence."
- return str(self.tuple)
-
- def __getitem__(self, index):
- "Return the coordinate sequence value at the given index."
- self._checkindex(index)
- return self._point_getter(index)
-
- def __setitem__(self, index, value):
- "Set 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
- point_setter = self._set_point_3d
- else:
- n_args = 2
- point_setter = self._set_point_2d
- if len(value) != n_args:
- raise TypeError('Dimension of value does not match.')
- self._checkindex(index)
- point_setter(index, value)
-
- # #### Internal Routines ####
- def _checkindex(self, index):
- "Check the given index."
- if not (0 <= index < self.size):
- raise IndexError('invalid GEOS Geometry index: %s' % index)
-
- def _checkdim(self, dim):
- "Check the given dimension."
- if dim < 0 or dim > 2:
- raise GEOSException('invalid ordinate dimension "%d"' % dim)
-
- def _get_x(self, index):
- return capi.cs_getx(self.ptr, index, byref(c_double()))
-
- def _get_y(self, index):
- return capi.cs_gety(self.ptr, index, byref(c_double()))
-
- def _get_z(self, index):
- return capi.cs_getz(self.ptr, index, byref(c_double()))
-
- def _set_x(self, index, value):
- capi.cs_setx(self.ptr, index, value)
-
- def _set_y(self, index, value):
- capi.cs_sety(self.ptr, index, value)
-
- def _set_z(self, index, value):
- capi.cs_setz(self.ptr, index, value)
-
- @property
- def _point_getter(self):
- return self._get_point_3d if self.dims == 3 and self._z else self._get_point_2d
-
- def _get_point_2d(self, index):
- return (self._get_x(index), self._get_y(index))
-
- def _get_point_3d(self, index):
- return (self._get_x(index), self._get_y(index), self._get_z(index))
-
- def _set_point_2d(self, index, value):
- x, y = value
- self._set_x(index, x)
- self._set_y(index, y)
-
- def _set_point_3d(self, index, value):
- x, y, z = value
- self._set_x(index, x)
- self._set_y(index, y)
- self._set_z(index, z)
-
- # #### Ordinate getting and setting routines ####
- def getOrdinate(self, dimension, index):
- "Return 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):
- "Set 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):
- "Return the size of this coordinate sequence."
- return capi.cs_getsize(self.ptr, byref(c_uint()))
-
- @property
- def dims(self):
- "Return the dimensions of this coordinate sequence."
- return capi.cs_getdims(self.ptr, byref(c_uint()))
-
- @property
- def hasz(self):
- """
- Return whether this coordinate sequence is 3D. This property value is
- inherited from the parent Geometry.
- """
- return self._z
-
- # ### Other Methods ###
- def clone(self):
- "Clone this coordinate sequence."
- return GEOSCoordSeq(capi.cs_clone(self.ptr), self.hasz)
-
- @property
- def kml(self):
- "Return 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 range(len(self))).strip()
-
- @property
- def tuple(self):
- "Return a tuple version of this coordinate sequence."
- n = self.size
- get_point = self._point_getter
- if n == 1:
- return get_point(0)
- return tuple(get_point(i) for i in range(n))
|