Added `merged` property to LineString & MultiLineString, which returns the output of the GEOS line merging operation.
2 This module houses the Geometry Collection objects:
3 GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
5 from ctypes import c_int, c_uint, byref
6 from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
7 from django.contrib.gis.geos.geometry import GEOSGeometry
8 from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOM_PTR, GEOS_PREPARE
9 from django.contrib.gis.geos.linestring import LineString, LinearRing
10 from django.contrib.gis.geos.point import Point
11 from django.contrib.gis.geos.polygon import Polygon
12 from django.contrib.gis.geos import prototypes as capi
14 class GeometryCollection(GEOSGeometry):
18 def __init__(self, *args, **kwargs):
19 "Initializes a Geometry Collection from a sequence of Geometry objects."
21 # Checking the arguments
23 raise TypeError, 'Must provide at least one Geometry to initialize %s.' % self.__class__.__name__
26 # If only one geometry provided or a list of geometries is provided
27 # in the first argument.
28 if isinstance(args[0], (tuple, list)):
35 # Ensuring that only the permitted geometries are allowed in this collection
36 # this is moved to list mixin super class
37 self._check_allowed(init_geoms)
39 # Creating the geometry pointer array.
40 collection = self._create_collection(len(init_geoms), iter(init_geoms))
41 super(GeometryCollection, self).__init__(collection, **kwargs)
44 "Iterates over each Geometry in the Collection."
45 for i in xrange(len(self)):
49 "Returns the number of geometries in this Collection."
52 ### Methods for compatibility with ListMixin ###
54 def _create_collection(cls, length, items):
55 # Creating the geometry pointer array.
56 geoms = get_pointer_arr(length)
57 for i, g in enumerate(items):
58 # this is a little sloppy, but makes life easier
59 # allow GEOSGeometry types (python wrappers) or pointer types
60 geoms[i] = capi.geom_clone(getattr(g, 'ptr', g))
62 return capi.create_collection(c_int(cls._typeid), byref(geoms), c_uint(length))
64 def _getitem_internal(self, index):
65 return capi.get_geomn(self.ptr, index)
67 def _getitem_external(self, index):
68 "Returns the Geometry from this Collection at the given index (0-based)."
69 # Checking the index and returning the corresponding GEOS geometry.
70 return GEOSGeometry(capi.geom_clone(self._getitem_internal(index)), srid=self.srid)
72 def _set_collection(self, length, items):
73 "Create a new collection, and destroy the contents of the previous pointer."
76 self.ptr = self._create_collection(length, items)
77 if srid: self.srid = srid
78 capi.destroy_geom(prev_ptr)
80 # Because GeometryCollections need to be rebuilt upon the changing of a
81 # component geometry, these routines are set to their counterparts that
82 # rebuild the entire geometry.
83 _set_single = GEOSGeometry._set_single_rebuild
84 _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild
88 "Returns the KML for this Geometry Collection."
89 return '<MultiGeometry>%s</MultiGeometry>' % ''.join([g.kml for g in self])
93 "Returns a tuple of all the coordinates in this Geometry Collection"
94 return tuple([g.tuple for g in self])
97 # MultiPoint, MultiLineString, and MultiPolygon class definitions.
98 class MultiPoint(GeometryCollection):
102 class MultiLineString(GeometryCollection):
103 _allowed = (LineString, LinearRing)
109 Returns a LineString representing the line merge of this
112 return self._topology(capi.geos_linemerge(self.ptr))
114 class MultiPolygon(GeometryCollection):
119 def cascaded_union(self):
120 "Returns a cascaded union of this MultiPolygon."
122 return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid)
124 raise GEOSException('The cascaded union operation requires GEOS 3.1+.')
126 # Setting the allowed types here since GeometryCollection is defined before
128 GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)