diff -r 000000000000 -r 0d40e90630ef web/lib/django/contrib/gis/geos/collections.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/lib/django/contrib/gis/geos/collections.py Wed Jan 20 00:34:04 2010 +0100 @@ -0,0 +1,123 @@ +""" + This module houses the Geometry Collection objects: + GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon +""" +from ctypes import c_int, c_uint, byref +from django.contrib.gis.geos.error import GEOSException, GEOSIndexError +from django.contrib.gis.geos.geometry import GEOSGeometry +from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOM_PTR, GEOS_PREPARE +from django.contrib.gis.geos.linestring import LineString, LinearRing +from django.contrib.gis.geos.point import Point +from django.contrib.gis.geos.polygon import Polygon +from django.contrib.gis.geos import prototypes as capi + +class GeometryCollection(GEOSGeometry): + _typeid = 7 + + def __init__(self, *args, **kwargs): + "Initializes a Geometry Collection from a sequence of Geometry objects." + + # Checking the arguments + if not args: + raise TypeError, 'Must provide at least one Geometry to initialize %s.' % self.__class__.__name__ + + if len(args) == 1: + # If only one geometry provided or a list of geometries is provided + # in the first argument. + if isinstance(args[0], (tuple, list)): + init_geoms = args[0] + else: + init_geoms = args + else: + init_geoms = args + + # Ensuring that only the permitted geometries are allowed in this collection + # this is moved to list mixin super class + self._check_allowed(init_geoms) + + # Creating the geometry pointer array. + collection = self._create_collection(len(init_geoms), iter(init_geoms)) + super(GeometryCollection, self).__init__(collection, **kwargs) + + def __iter__(self): + "Iterates over each Geometry in the Collection." + for i in xrange(len(self)): + yield self[i] + + def __len__(self): + "Returns the number of geometries in this Collection." + return self.num_geom + + ### Methods for compatibility with ListMixin ### + def _create_collection(self, length, items): + # Creating the geometry pointer array. + geoms = get_pointer_arr(length) + for i, g in enumerate(items): + # this is a little sloppy, but makes life easier + # allow GEOSGeometry types (python wrappers) or pointer types + geoms[i] = capi.geom_clone(getattr(g, 'ptr', g)) + + return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length)) + + def _get_single_internal(self, index): + return capi.get_geomn(self.ptr, index) + + def _get_single_external(self, index): + "Returns the Geometry from this Collection at the given index (0-based)." + # Checking the index and returning the corresponding GEOS geometry. + return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid) + + def _set_list(self, length, items): + "Create a new collection, and destroy the contents of the previous pointer." + prev_ptr = self.ptr + srid = self.srid + self.ptr = self._create_collection(length, items) + if srid: self.srid = srid + capi.destroy_geom(prev_ptr) + + _set_single = GEOSGeometry._set_single_rebuild + _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild + + @property + def kml(self): + "Returns the KML for this Geometry Collection." + return '%s' % ''.join([g.kml for g in self]) + + @property + def tuple(self): + "Returns a tuple of all the coordinates in this Geometry Collection" + return tuple([g.tuple for g in self]) + coords = tuple + +# MultiPoint, MultiLineString, and MultiPolygon class definitions. +class MultiPoint(GeometryCollection): + _allowed = Point + _typeid = 4 + +class MultiLineString(GeometryCollection): + _allowed = (LineString, LinearRing) + _typeid = 5 + + @property + def merged(self): + """ + Returns a LineString representing the line merge of this + MultiLineString. + """ + return self._topology(capi.geos_linemerge(self.ptr)) + +class MultiPolygon(GeometryCollection): + _allowed = Polygon + _typeid = 6 + + @property + def cascaded_union(self): + "Returns a cascaded union of this MultiPolygon." + if GEOS_PREPARE: + return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid) + else: + raise GEOSException('The cascaded union operation requires GEOS 3.1+.') + +# Setting the allowed types here since GeometryCollection is defined before +# its subclasses. +GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)