collections.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. """
  2. This module houses the Geometry Collection objects:
  3. GeometryCollection, MultiPoint, MultiLineString, and MultiPolygon
  4. """
  5. from ctypes import byref, c_int, c_uint
  6. from django.contrib.gis.geos import prototypes as capi
  7. from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
  8. from django.contrib.gis.geos.libgeos import GEOM_PTR
  9. from django.contrib.gis.geos.linestring import LinearRing, LineString
  10. from django.contrib.gis.geos.point import Point
  11. from django.contrib.gis.geos.polygon import Polygon
  12. class GeometryCollection(GEOSGeometry):
  13. _typeid = 7
  14. def __init__(self, *args, **kwargs):
  15. "Initialize a Geometry Collection from a sequence of Geometry objects."
  16. # Checking the arguments
  17. if len(args) == 1:
  18. # If only one geometry provided or a list of geometries is provided
  19. # in the first argument.
  20. if isinstance(args[0], (tuple, list)):
  21. init_geoms = args[0]
  22. else:
  23. init_geoms = args
  24. else:
  25. init_geoms = args
  26. # Ensuring that only the permitted geometries are allowed in this collection
  27. # this is moved to list mixin super class
  28. self._check_allowed(init_geoms)
  29. # Creating the geometry pointer array.
  30. collection = self._create_collection(len(init_geoms), init_geoms)
  31. super().__init__(collection, **kwargs)
  32. def __iter__(self):
  33. "Iterate over each Geometry in the Collection."
  34. for i in range(len(self)):
  35. yield self[i]
  36. def __len__(self):
  37. "Return the number of geometries in this Collection."
  38. return self.num_geom
  39. # ### Methods for compatibility with ListMixin ###
  40. def _create_collection(self, length, items):
  41. # Creating the geometry pointer array.
  42. geoms = (GEOM_PTR * length)(*[
  43. # this is a little sloppy, but makes life easier
  44. # allow GEOSGeometry types (python wrappers) or pointer types
  45. capi.geom_clone(getattr(g, 'ptr', g)) for g in items
  46. ])
  47. return capi.create_collection(c_int(self._typeid), byref(geoms), c_uint(length))
  48. def _get_single_internal(self, index):
  49. return capi.get_geomn(self.ptr, index)
  50. def _get_single_external(self, index):
  51. "Return the Geometry from this Collection at the given index (0-based)."
  52. # Checking the index and returning the corresponding GEOS geometry.
  53. return GEOSGeometry(capi.geom_clone(self._get_single_internal(index)), srid=self.srid)
  54. def _set_list(self, length, items):
  55. "Create a new collection, and destroy the contents of the previous pointer."
  56. prev_ptr = self.ptr
  57. srid = self.srid
  58. self.ptr = self._create_collection(length, items)
  59. if srid:
  60. self.srid = srid
  61. capi.destroy_geom(prev_ptr)
  62. _set_single = GEOSGeometry._set_single_rebuild
  63. _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild
  64. @property
  65. def kml(self):
  66. "Return the KML for this Geometry Collection."
  67. return '<MultiGeometry>%s</MultiGeometry>' % ''.join(g.kml for g in self)
  68. @property
  69. def tuple(self):
  70. "Return a tuple of all the coordinates in this Geometry Collection"
  71. return tuple(g.tuple for g in self)
  72. coords = tuple
  73. # MultiPoint, MultiLineString, and MultiPolygon class definitions.
  74. class MultiPoint(GeometryCollection):
  75. _allowed = Point
  76. _typeid = 4
  77. class MultiLineString(LinearGeometryMixin, GeometryCollection):
  78. _allowed = (LineString, LinearRing)
  79. _typeid = 5
  80. class MultiPolygon(GeometryCollection):
  81. _allowed = Polygon
  82. _typeid = 6
  83. # Setting the allowed types here since GeometryCollection is defined before
  84. # its subclasses.
  85. GeometryCollection._allowed = (Point, LineString, LinearRing, Polygon, MultiPoint, MultiLineString, MultiPolygon)