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

https://code.google.com/p/mango-py/ · Python · 123 lines · 79 code · 22 blank · 22 comment · 12 complexity · bb5076b9c18bcfbe3f3d379a8295571d MD5 · raw file

  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 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
  13. class GeometryCollection(GEOSGeometry):
  14. _typeid = 7
  15. def __init__(self, *args, **kwargs):
  16. "Initializes a Geometry Collection from a sequence of Geometry objects."
  17. # Checking the arguments
  18. if not args:
  19. raise TypeError('Must provide at least one Geometry to initialize %s.' % self.__class__.__name__)
  20. if len(args) == 1:
  21. # If only one geometry provided or a list of geometries is provided
  22. # in the first argument.
  23. if isinstance(args[0], (tuple, list)):
  24. init_geoms = args[0]
  25. else:
  26. init_geoms = args
  27. else:
  28. init_geoms = args
  29. # Ensuring that only the permitted geometries are allowed in this collection
  30. # this is moved to list mixin super class
  31. self._check_allowed(init_geoms)
  32. # Creating the geometry pointer array.
  33. collection = self._create_collection(len(init_geoms), iter(init_geoms))
  34. super(GeometryCollection, self).__init__(collection, **kwargs)
  35. def __iter__(self):
  36. "Iterates over each Geometry in the Collection."
  37. for i in xrange(len(self)):
  38. yield self[i]
  39. def __len__(self):
  40. "Returns the number of geometries in this Collection."
  41. return self.num_geom
  42. ### Methods for compatibility with ListMixin ###
  43. def _create_collection(self, length, items):
  44. # Creating the geometry pointer array.
  45. geoms = get_pointer_arr(length)
  46. for i, g in enumerate(items):
  47. # this is a little sloppy, but makes life easier
  48. # allow GEOSGeometry types (python wrappers) or pointer types
  49. geoms[i] = capi.geom_clone(getattr(g, 'ptr', g))
  50. return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length))
  51. def _get_single_internal(self, index):
  52. return capi.get_geomn(self.ptr, index)
  53. def _get_single_external(self, index):
  54. "Returns the Geometry from this Collection at the given index (0-based)."
  55. # Checking the index and returning the corresponding GEOS geometry.
  56. return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid)
  57. def _set_list(self, length, items):
  58. "Create a new collection, and destroy the contents of the previous pointer."
  59. prev_ptr = self.ptr
  60. srid = self.srid
  61. self.ptr = self._create_collection(length, items)
  62. if srid: self.srid = srid
  63. capi.destroy_geom(prev_ptr)
  64. _set_single = GEOSGeometry._set_single_rebuild
  65. _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild
  66. @property
  67. def kml(self):
  68. "Returns the KML for this Geometry Collection."
  69. return '<MultiGeometry>%s</MultiGeometry>' % ''.join([g.kml for g in self])
  70. @property
  71. def tuple(self):
  72. "Returns a tuple of all the coordinates in this Geometry Collection"
  73. return tuple([g.tuple for g in self])
  74. coords = tuple
  75. # MultiPoint, MultiLineString, and MultiPolygon class definitions.
  76. class MultiPoint(GeometryCollection):
  77. _allowed = Point
  78. _typeid = 4
  79. class MultiLineString(GeometryCollection):
  80. _allowed = (LineString, LinearRing)
  81. _typeid = 5
  82. @property
  83. def merged(self):
  84. """
  85. Returns a LineString representing the line merge of this
  86. MultiLineString.
  87. """
  88. return self._topology(capi.geos_linemerge(self.ptr))
  89. class MultiPolygon(GeometryCollection):
  90. _allowed = Polygon
  91. _typeid = 6
  92. @property
  93. def cascaded_union(self):
  94. "Returns a cascaded union of this MultiPolygon."
  95. if GEOS_PREPARE:
  96. return GEOSGeometry(capi.geos_cascaded_union(self.ptr), self.srid)
  97. else:
  98. raise GEOSException('The cascaded union operation requires GEOS 3.1+.')
  99. # Setting the allowed types here since GeometryCollection is defined before
  100. # its subclasses.
  101. GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)