def __setstate__(self, state): """WKB doesn't differentiate between LineString and LinearRing so we need to move the coordinate sequence into the correct geometry type""" super(LinearRing, self).__setstate__(state) cs = lgeos.GEOSGeom_getCoordSeq(self.__geom__) cs_clone = lgeos.GEOSCoordSeq_clone(cs) lgeos.GEOSGeom_destroy(self.__geom__) self.__geom__ = lgeos.GEOSGeom_createLinearRing(cs_clone)
def geos_linearring_from_py(ob, update_geom=None, update_ndim=0): # If numpy is present, we use numpy.require to ensure that we have a # C-continguous array that owns its data. View data will be copied. ob = required(ob) try: # From array protocol array = ob.__array_interface__ assert len(array['shape']) == 2 m = array['shape'][0] n = array['shape'][1] if m < 3: raise ValueError( "A LinearRing must have at least 3 coordinate tuples") assert n == 2 or n == 3 # Make pointer to the coordinate array if isinstance(array['data'], tuple): # numpy tuple (addr, read-only) cp = cast(array['data'][0], POINTER(c_double)) else: cp = array['data'] # Add closing coordinates to sequence? if cp[0] != cp[m * n - n] or cp[1] != cp[m * n - n + 1]: M = m + 1 else: M = m # Create a coordinate sequence if update_geom is not None: cs = lgeos.GEOSGeom_getCoordSeq(update_geom) if n != update_ndim: raise ValueError( "Wrong coordinate dimensions; this geometry has dimensions: %d" \ % update_ndim) else: cs = lgeos.GEOSCoordSeq_create(M, n) # add to coordinate sequence for i in xrange(m): # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, i, cp[n * i]) lgeos.GEOSCoordSeq_setY(cs, i, cp[n * i + 1]) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, i, cp[n * i + 2]) # Add closing coordinates to sequence? if M > m: # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, M - 1, cp[0]) lgeos.GEOSCoordSeq_setY(cs, M - 1, cp[1]) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, M - 1, cp[2]) except AttributeError: # Fall back on list m = len(ob) n = len(ob[0]) if m < 3: raise ValueError( "A LinearRing must have at least 3 coordinate tuples") assert (n == 2 or n == 3) # Add closing coordinates if not provided if m == 3 or ob[0][0] != ob[-1][0] or ob[0][1] != ob[-1][1]: M = m + 1 else: M = m # Create a coordinate sequence if update_geom is not None: cs = lgeos.GEOSGeom_getCoordSeq(update_geom) if n != update_ndim: raise ValueError( "Wrong coordinate dimensions; this geometry has dimensions: %d" \ % update_ndim) else: cs = lgeos.GEOSCoordSeq_create(M, n) # add to coordinate sequence for i in xrange(m): coords = ob[i] # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, i, coords[0]) lgeos.GEOSCoordSeq_setY(cs, i, coords[1]) if n == 3: try: lgeos.GEOSCoordSeq_setZ(cs, i, coords[2]) except IndexError: raise ValueError("Inconsistent coordinate dimensionality") # Add closing coordinates to sequence? if M > m: coords = ob[0] # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, M - 1, coords[0]) lgeos.GEOSCoordSeq_setY(cs, M - 1, coords[1]) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, M - 1, coords[2]) if update_geom is not None: return None else: return lgeos.GEOSGeom_createLinearRing(cs), n
def geos_linearring_from_py(ob, update_geom=None, update_ndim=0): # If a LinearRing is passed in, clone it and return # If a valid LineString is passed in, clone the coord seq and return a # LinearRing. # # NB: access to coordinates using the array protocol has been moved # entirely to the speedups module. if isinstance(ob, LineString): if type(ob) == LinearRing: return geos_geom_from_py(ob) elif not ob.is_valid: raise TopologicalError("An input LineString must be valid.") elif ob.is_closed and len(ob.coords) >= 4: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLinearRing) else: ob = list(ob.coords) try: m = len(ob) except TypeError: # generators ob = list(ob) m = len(ob) if m == 0: return None def _coords(o): if isinstance(o, Point): return o.coords[0] else: return o n = len(_coords(ob[0])) if m < 3: raise ValueError("A LinearRing must have at least 3 coordinate tuples") assert (n == 2 or n == 3) # Add closing coordinates if not provided if (m == 3 or _coords(ob[0])[0] != _coords(ob[-1])[0] or _coords(ob[0])[1] != _coords(ob[-1])[1]): M = m + 1 else: M = m # Create a coordinate sequence if update_geom is not None: if n != update_ndim: raise ValueError( "Coordinate dimensions mismatch: target geom has {} dims, " "update geom has {} dims".format(n, update_ndim)) cs = lgeos.GEOSGeom_getCoordSeq(update_geom) else: cs = lgeos.GEOSCoordSeq_create(M, n) # add to coordinate sequence for i in range(m): coords = _coords(ob[i]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, i, coords[0]) lgeos.GEOSCoordSeq_setY(cs, i, coords[1]) if n == 3: try: lgeos.GEOSCoordSeq_setZ(cs, i, coords[2]) except IndexError: raise ValueError("Inconsistent coordinate dimensionality") # Add closing coordinates to sequence? if M > m: coords = _coords(ob[0]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, M - 1, coords[0]) lgeos.GEOSCoordSeq_setY(cs, M - 1, coords[1]) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, M - 1, coords[2]) if update_geom is not None: return None else: return lgeos.GEOSGeom_createLinearRing(cs), n
def geos_linearring_from_py(ob, update_geom=None, update_ndim=0): try: # From array protocol array = ob.__array_interface__ assert len(array['shape']) == 2 m = array['shape'][0] n = array['shape'][1] if m < 3: raise ValueError( "A LinearRing must have at least 3 coordinate tuples") assert n == 2 or n == 3 # Make pointer to the coordinate array try: cp = cast(array['data'][0], POINTER(c_double)) except ArgumentError: cp = array['data'] # Add closing coordinates to sequence? if cp[0] != cp[m * n - n] or cp[1] != cp[m * n - n + 1]: M = m + 1 else: M = m # Create a coordinate sequence if update_geom is not None: cs = lgeos.GEOSGeom_getCoordSeq(update_geom) if n != update_ndim: raise ValueError( "Wrong coordinate dimensions; this geometry has dimensions: %d" \ % update_ndim) else: cs = lgeos.GEOSCoordSeq_create(M, n) # add to coordinate sequence for i in xrange(m): dx = c_double(cp[n * i]) dy = c_double(cp[n * i + 1]) dz = None if n == 3: dz = c_double(cp[n * i + 2]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, i, dx) lgeos.GEOSCoordSeq_setY(cs, i, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, i, dz) # Add closing coordinates to sequence? if M > m: dx = c_double(cp[0]) dy = c_double(cp[1]) dz = None if n == 3: dz = c_double(cp[2]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, M - 1, dx) lgeos.GEOSCoordSeq_setY(cs, M - 1, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, M - 1, dz) except AttributeError: # Fall back on list m = len(ob) n = len(ob[0]) if m < 3: raise ValueError( "A LinearRing must have at least 3 coordinate tuples") assert (n == 2 or n == 3) # Add closing coordinates if not provided if m == 3 or ob[0][0] != ob[-1][0] or ob[0][1] != ob[-1][1]: M = m + 1 else: M = m # Create a coordinate sequence if update_geom is not None: cs = lgeos.GEOSGeom_getCoordSeq(update_geom) if n != update_ndim: raise ValueError( "Wrong coordinate dimensions; this geometry has dimensions: %d" \ % update_ndim) else: cs = lgeos.GEOSCoordSeq_create(M, n) # add to coordinate sequence for i in xrange(m): coords = ob[i] dx = c_double(coords[0]) dy = c_double(coords[1]) dz = None if n == 3: dz = c_double(coords[2]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, i, dx) lgeos.GEOSCoordSeq_setY(cs, i, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, i, dz) # Add closing coordinates to sequence? if M > m: coords = ob[0] dx = c_double(coords[0]) dy = c_double(coords[1]) dz = None if n == 3: dz = c_double(coords[2]) # Because of a bug in the GEOS C API, # always set X before Y lgeos.GEOSCoordSeq_setX(cs, M - 1, dx) lgeos.GEOSCoordSeq_setY(cs, M - 1, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, M - 1, dz) if update_geom is not None: return None else: return lgeos.GEOSGeom_createLinearRing(cs), n