app/django/contrib/gis/geos/collections.py
changeset 323 ff1a9aa48cfd
equal deleted inserted replaced
322:6641e941ef1e 323:ff1a9aa48cfd
       
     1 """
       
     2  This module houses the Geometry Collection objects:
       
     3  GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
       
     4 """
       
     5 from ctypes import c_int, c_uint, byref
       
     6 from types import TupleType, ListType
       
     7 from django.contrib.gis.geos.base import GEOSGeometry
       
     8 from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
       
     9 from django.contrib.gis.geos.geometries import Point, LineString, LinearRing, Polygon
       
    10 from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOM_PTR
       
    11 from django.contrib.gis.geos.prototypes import create_collection, destroy_geom, geom_clone, geos_typeid, get_cs, get_geomn
       
    12 
       
    13 class GeometryCollection(GEOSGeometry):
       
    14     _allowed = (Point, LineString, LinearRing, Polygon)
       
    15     _typeid = 7
       
    16 
       
    17     def __init__(self, *args, **kwargs):
       
    18         "Initializes a Geometry Collection from a sequence of Geometry objects."
       
    19 
       
    20         # Checking the arguments
       
    21         if not args:
       
    22             raise TypeError, 'Must provide at least one Geometry to initialize %s.' % self.__class__.__name__
       
    23 
       
    24         if len(args) == 1: 
       
    25             # If only one geometry provided or a list of geometries is provided
       
    26             #  in the first argument.
       
    27             if isinstance(args[0], (TupleType, ListType)):
       
    28                 init_geoms = args[0]
       
    29             else:
       
    30                 init_geoms = args
       
    31         else:
       
    32             init_geoms = args
       
    33 
       
    34         # Ensuring that only the permitted geometries are allowed in this collection
       
    35         if False in [isinstance(geom, self._allowed) for geom in init_geoms]:
       
    36             raise TypeError('Invalid Geometry type encountered in the arguments.')
       
    37 
       
    38         # Creating the geometry pointer array.
       
    39         ngeoms = len(init_geoms)
       
    40         geoms = get_pointer_arr(ngeoms)
       
    41         for i in xrange(ngeoms): geoms[i] = geom_clone(init_geoms[i].ptr)
       
    42         super(GeometryCollection, self).__init__(create_collection(c_int(self._typeid), byref(geoms), c_uint(ngeoms)), **kwargs)
       
    43 
       
    44     def __getitem__(self, index):
       
    45         "Returns the Geometry from this Collection at the given index (0-based)."
       
    46         # Checking the index and returning the corresponding GEOS geometry.
       
    47         self._checkindex(index)
       
    48         return GEOSGeometry(geom_clone(get_geomn(self.ptr, index)), srid=self.srid)
       
    49 
       
    50     def __setitem__(self, index, geom):
       
    51         "Sets the Geometry at the specified index."
       
    52         self._checkindex(index)
       
    53         if not isinstance(geom, self._allowed):
       
    54             raise TypeError('Incompatible Geometry for collection.')
       
    55         
       
    56         ngeoms = len(self)
       
    57         geoms = get_pointer_arr(ngeoms)
       
    58         for i in xrange(ngeoms):
       
    59             if i == index:
       
    60                 geoms[i] = geom_clone(geom.ptr)
       
    61             else:
       
    62                 geoms[i] = geom_clone(get_geomn(self.ptr, i))
       
    63         
       
    64         # Creating a new collection, and destroying the contents of the previous poiner.
       
    65         prev_ptr = self.ptr
       
    66         srid = self.srid
       
    67         self._ptr = create_collection(c_int(self._typeid), byref(geoms), c_uint(ngeoms))
       
    68         if srid: self.srid = srid
       
    69         destroy_geom(prev_ptr)
       
    70 
       
    71     def __iter__(self):
       
    72         "Iterates over each Geometry in the Collection."
       
    73         for i in xrange(len(self)):
       
    74             yield self.__getitem__(i)
       
    75 
       
    76     def __len__(self):
       
    77         "Returns the number of geometries in this Collection."
       
    78         return self.num_geom
       
    79 
       
    80     def _checkindex(self, index):
       
    81         "Checks the given geometry index."
       
    82         if index < 0 or index >= self.num_geom:
       
    83             raise GEOSIndexError('invalid GEOS Geometry index: %s' % str(index))
       
    84 
       
    85     @property
       
    86     def kml(self):
       
    87         "Returns the KML for this Geometry Collection."
       
    88         return '<MultiGeometry>%s</MultiGeometry>' % ''.join([g.kml for g in self])
       
    89 
       
    90     @property
       
    91     def tuple(self):
       
    92         "Returns a tuple of all the coordinates in this Geometry Collection"
       
    93         return tuple([g.tuple for g in self])
       
    94     coords = tuple
       
    95 
       
    96 # MultiPoint, MultiLineString, and MultiPolygon class definitions.
       
    97 class MultiPoint(GeometryCollection): 
       
    98     _allowed = Point
       
    99     _typeid = 4
       
   100 class MultiLineString(GeometryCollection): 
       
   101     _allowed = (LineString, LinearRing)
       
   102     _typeid = 5
       
   103 class MultiPolygon(GeometryCollection): 
       
   104     _allowed = Polygon
       
   105     _typeid = 6