PageRenderTime 21ms CodeModel.GetById 14ms app.highlight 5ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://code.google.com/p/mango-py/
Python | 123 lines | 93 code | 15 blank | 15 comment | 9 complexity | bb5076b9c18bcfbe3f3d379a8295571d MD5 | raw file
  1"""
  2 This module houses the Geometry Collection objects:
  3 GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
  4"""
  5from ctypes import c_int, c_uint, byref
  6from django.contrib.gis.geos.error import GEOSException, GEOSIndexError
  7from django.contrib.gis.geos.geometry import GEOSGeometry
  8from django.contrib.gis.geos.libgeos import get_pointer_arr, GEOM_PTR, GEOS_PREPARE
  9from django.contrib.gis.geos.linestring import LineString, LinearRing
 10from django.contrib.gis.geos.point import Point
 11from django.contrib.gis.geos.polygon import Polygon
 12from django.contrib.gis.geos import prototypes as capi
 13
 14class GeometryCollection(GEOSGeometry):
 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], (tuple, list)):
 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        # this is moved to list mixin super class
 36        self._check_allowed(init_geoms)
 37
 38        # Creating the geometry pointer array.
 39        collection = self._create_collection(len(init_geoms), iter(init_geoms))
 40        super(GeometryCollection, self).__init__(collection, **kwargs)
 41
 42    def __iter__(self):
 43        "Iterates over each Geometry in the Collection."
 44        for i in xrange(len(self)):
 45            yield self[i]
 46
 47    def __len__(self):
 48        "Returns the number of geometries in this Collection."
 49        return self.num_geom
 50
 51    ### Methods for compatibility with ListMixin ###
 52    def _create_collection(self, length, items):
 53        # Creating the geometry pointer array.
 54        geoms = get_pointer_arr(length)
 55        for i, g in enumerate(items):
 56            # this is a little sloppy, but makes life easier
 57            # allow GEOSGeometry types (python wrappers) or pointer types
 58            geoms[i] = capi.geom_clone(getattr(g, 'ptr', g))
 59
 60        return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length))
 61
 62    def _get_single_internal(self, index):
 63        return capi.get_geomn(self.ptr, index)
 64
 65    def _get_single_external(self, index):
 66        "Returns the Geometry from this Collection at the given index (0-based)."
 67        # Checking the index and returning the corresponding GEOS geometry.
 68        return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid)
 69
 70    def _set_list(self, length, items):
 71        "Create a new collection, and destroy the contents of the previous pointer."
 72        prev_ptr = self.ptr
 73        srid = self.srid
 74        self.ptr = self._create_collection(length, items)
 75        if srid: self.srid = srid
 76        capi.destroy_geom(prev_ptr)
 77
 78    _set_single = GEOSGeometry._set_single_rebuild
 79    _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild
 80
 81    @property
 82    def kml(self):
 83        "Returns the KML for this Geometry Collection."
 84        return '<MultiGeometry>%s</MultiGeometry>' % ''.join([g.kml for g in self])
 85
 86    @property
 87    def tuple(self):
 88        "Returns a tuple of all the coordinates in this Geometry Collection"
 89        return tuple([g.tuple for g in self])
 90    coords = tuple
 91
 92# MultiPoint, MultiLineString, and MultiPolygon class definitions.
 93class MultiPoint(GeometryCollection):
 94    _allowed = Point
 95    _typeid = 4
 96
 97class MultiLineString(GeometryCollection):
 98    _allowed = (LineString, LinearRing)
 99    _typeid = 5
100
101    @property
102    def merged(self):
103        """ 
104        Returns a LineString representing the line merge of this 
105        MultiLineString.
106        """ 
107        return self._topology(capi.geos_linemerge(self.ptr))         
108
109class MultiPolygon(GeometryCollection):
110    _allowed = Polygon
111    _typeid = 6
112
113    @property
114    def cascaded_union(self):
115        "Returns a cascaded union of this MultiPolygon."
116        if GEOS_PREPARE:
117            return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid)
118        else:
119            raise GEOSException('The cascaded union operation requires GEOS 3.1+.')
120
121# Setting the allowed types here since GeometryCollection is defined before
122# its subclasses.
123GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)