Django

Code

root/django/branches/gis/django/contrib/gis/geos/collections.py

Revision 7114, 4.1 kB (checked in by jbronn, 10 months ago)

gis: geos: Added GeoJSON input/output support for GEOSGeometry (requires GDAL 1.5+); Polygons may now be instantiated with tuples of coordinates instead of only LinearRing instances; added extent property; added coords property alias for tuple (and added tuple for GeometryCollection); made small optimizations to KML and coordinate array generators. Small GDAL protochange that didn't make last commit: get_envelope is now generated w/the previously unused env_func.

Line 
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
Note: See TracBrowser for help on using the browser.