this module houses the geometry collection objects geometrycollection multipoint multilinestring and multipolygon checking the arguments if only one geometry provided or a list of geometries is provided in the first argument ensuring that only the permitted geometries are allowed in this collection this is moved to list mixin super class creating the geometry pointer array methods for compatibility with listmixin creating the geometry pointer array this is a little sloppy but makes life easier allow geosgeometry types python wrappers or pointer types checking the index and returning the corresponding geos geometry multipoint multilinestring and multipolygon class definitions setting the allowed types here since geometrycollection is defined before its subclasses checking the arguments if only one geometry provided or a list of geometries is provided in the first argument ensuring that only the permitted geometries are allowed in this collection this is moved to list mixin super class creating the geometry pointer array methods for compatibility with listmixin creating the geometry pointer array this is a little sloppy but makes life easier allow geosgeometry types python wrappers or pointer types checking the index and returning the corresponding geos geometry multipoint multilinestring and multipolygon class definitions setting the allowed types here since geometrycollection is defined before its subclasses
from django.contrib.gis.geos import prototypes as capi
from django.contrib.gis.geos.geometry import GEOSGeometry, LinearGeometryMixin
from django.contrib.gis.geos.libgeos import GEOM_PTR
from django.contrib.gis.geos.linestring import LinearRing, LineString
from django.contrib.gis.geos.point import Point
from django.contrib.gis.geos.polygon import Polygon


class GeometryCollection(GEOSGeometry):
    _typeid = 7

    def __init__(self, *args, **kwargs):
        "Initialize a Geometry Collection from a sequence of Geometry objects."
        
        if len(args) == 1:
            
            
            if isinstance(args[0], (tuple, list)):
                init_geoms = args[0]
            else:
                init_geoms = args
        else:
            init_geoms = args

        
        
        self._check_allowed(init_geoms)

        
        collection = self._create_collection(len(init_geoms), init_geoms)
        super().__init__(collection, **kwargs)

    def __iter__(self):
        "Iterate over each Geometry in the Collection."
        for i in range(len(self)):
            yield self[i]

    def __len__(self):
        "Return the number of geometries in this Collection."
        return self.num_geom

    
    def _create_collection(self, length, items):
        
        geoms = (GEOM_PTR * length)(
            *[
                
                
                capi.geom_clone(getattr(g, "ptr", g))
                for g in items
            ]
        )
        return capi.create_collection(self._typeid, geoms, length)

    def _get_single_internal(self, index):
        return capi.get_geomn(self.ptr, index)

    def _get_single_external(self, index):
        "Return the Geometry from this Collection at the given index (0-based)."
        
        return GEOSGeometry(
            capi.geom_clone(self._get_single_internal(index)), srid=self.srid
        )

    def _set_list(self, length, items):
        "Create a new collection, and destroy the contents of the previous pointer."
        prev_ptr = self.ptr
        srid = self.srid
        self.ptr = self._create_collection(length, items)
        if srid:
            self.srid = srid
        capi.destroy_geom(prev_ptr)

    _set_single = GEOSGeometry._set_single_rebuild
    _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild

    @property
    def kml(self):
        "Return the KML for this Geometry Collection."
        return "<MultiGeometry>%s</MultiGeometry>" % "".join(g.kml for g in self)

    @property
    def tuple(self):
        "Return a tuple of all the coordinates in this Geometry Collection"
        return tuple(g.tuple for g in self)

    coords = tuple



class MultiPoint(GeometryCollection):
    _allowed = Point
    _typeid = 4


class MultiLineString(LinearGeometryMixin, GeometryCollection):
    _allowed = (LineString, LinearRing)
    _typeid = 5


class MultiPolygon(GeometryCollection):
    _allowed = Polygon
    _typeid = 6




GeometryCollection._allowed = (
    Point,
    LineString,
    LinearRing,
    Polygon,
    MultiPoint,
    MultiLineString,
    MultiPolygon,
)