def geos_multipolygon_from_polygons(ob): """ ob must be either a MultiPolygon, sequence or array of sequences or arrays. """ if isinstance(ob, MultiPolygon): return geos_geom_from_py(ob) obs = getattr(ob, 'geoms', None) or ob L = len(obs) assert L >= 1 exemplar = obs[0] try: N = len(exemplar[0][0]) except TypeError: N = exemplar._ndim assert N == 2 or N == 3 subs = (c_void_p * L)() for l in range(L): shell = getattr(obs[l], 'exterior', None) if shell is None: shell = obs[l][0] holes = getattr(obs[l], 'interiors', None) if holes is None: holes = obs[l][1] geom, ndims = polygon.geos_polygon_from_py(shell, holes) subs[l] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
def geos_multilinestring_from_py(ob): # ob must be either a MultiLineString, a sequence, or # array of sequences or arrays if isinstance(ob, MultiLineString): return geos_geom_from_py(ob) obs = getattr(ob, 'geoms', ob) L = len(obs) assert L >= 1 exemplar = obs[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim if N not in (2, 3): raise ValueError("Invalid coordinate dimensionality") # Array of pointers to point geometries subs = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndims = linestring.geos_linestring_from_py(obs[l]) subs[l] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
def geos_polygon_from_py(shell, holes=None): if isinstance(shell, Polygon): return geos_geom_from_py(shell) if shell is not None: geos_shell, ndim = geos_linearring_from_py(shell) if holes is not None and len(holes) > 0: ob = holes L = len(ob) exemplar = ob[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim if not L >= 1: raise ValueError("number of holes must be non zero") if not N in (2, 3): raise ValueError("insufficiant coordinate dimension") # Array of pointers to ring geometries geos_holes = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndim = geos_linearring_from_py(ob[l]) geos_holes[l] = cast(geom, c_void_p) else: geos_holes = POINTER(c_void_p)() L = 0 return (lgeos.GEOSGeom_createPolygon(c_void_p(geos_shell), geos_holes, L), ndim)
def geos_multilinestring_from_py(ob): # ob must be either a MultiLineString, a sequence, or # array of sequences or arrays if isinstance(ob, MultiLineString): return geos_geom_from_py(ob) obs = getattr(ob, 'geoms', ob) L = len(obs) assert L >= 1 exemplar = obs[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim if N not in (2, 3): raise ValueError("Invalid coordinate dimensionality") # Array of pointers to point geometries subs = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndims = linestring.geos_linestring_from_py(obs[l]) if lgeos.GEOSisEmpty(geom): raise EmptyPartError( "Can't create MultiLineString with empty component") subs[l] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
def geos_multipoint_from_py(ob): if isinstance(ob, MultiPoint): return geos_geom_from_py(ob) m = len(ob) try: n = len(ob[0]) except TypeError: n = ob[0]._ndim assert n == 2 or n == 3 # Array of pointers to point geometries subs = (c_void_p * m)() # add to coordinate sequence for i in range(m): coords = ob[i] geom, ndims = point.geos_point_from_py(coords) if lgeos.GEOSisEmpty(geom): raise EmptyPartError("Can't create MultiPoint with empty component") subs[i] = cast(geom, c_void_p) return lgeos.GEOSGeom_createCollection(4, subs, m), n
def geos_multipolygon_from_polygons(arg): """Creates a GEOS multipolygon from a sequence of polygon-like objects. Parameters ---------- arg : sequence or MultiPolygon Returns ------- int Pointer to a GEOS multipolygon. """ if isinstance(arg, MultiPolygon): return geos_geom_from_py(arg) obs = getattr(arg, 'geoms', arg) obs = [ ob for ob in obs if ob and not (isinstance(ob, polygon.Polygon) and ob.is_empty) ] L = len(obs) # Bail immediately if we have no input points. if L <= 0: return (lgeos.GEOSGeom_createEmptyCollection(6), 3) # This function does not accept sequences of MultiPolygons: there is # no implicit flattening. if isinstance(obs[0], MultiPolygon): raise ValueError("Sequences of multi-polygons are not valid arguments") exemplar = obs[0] try: N = len(exemplar[0][0]) except TypeError: N = exemplar._ndim assert N == 2 or N == 3 subs = (c_void_p * L)() for i, ob in enumerate(obs): if isinstance(ob, polygon.Polygon): shell = ob.exterior holes = ob.interiors else: shell = ob[0] holes = ob[1] geom, ndims = polygon.geos_polygon_from_py(shell, holes) subs[i] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
def geos_multipolygon_from_polygons(arg): """Creates a GEOS multipolygon from a sequence of polygon-like objects. Parameters ---------- arg : sequence or MultiPolygon Returns ------- int Pointer to a GEOS multipolygon. """ if isinstance(arg, MultiPolygon): return geos_geom_from_py(arg) obs = getattr(arg, 'geoms', arg) obs = [ob for ob in obs if ob and not (isinstance(ob, polygon.Polygon) and ob.is_empty)] L = len(obs) # Bail immediately if we have no input points. if L <= 0: return (lgeos.GEOSGeom_createEmptyCollection(6), 3) # This function does not accept sequences of MultiPolygons: there is # no implicit flattening. if isinstance(obs[0], MultiPolygon): raise ValueError("Sequences of multi-polygons are not valid arguments") exemplar = obs[0] try: N = len(exemplar[0][0]) except TypeError: N = exemplar._ndim assert N == 2 or N == 3 subs = (c_void_p * L)() for i, ob in enumerate(obs): if isinstance(ob, polygon.Polygon): shell = ob.exterior holes = ob.interiors else: shell = ob[0] holes = ob[1] geom, ndims = polygon.geos_polygon_from_py(shell, holes) subs[i] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
def geos_geometrycollection_from_py(ob): """Creates a GEOS GeometryCollection from a list of geometries""" L = len(ob) N = 2 subs = (c_void_p * L)() for l in range(L): assert (isinstance(ob[l], BaseGeometry)) if ob[l].has_z: N = 3 geom, n = geos_geom_from_py(ob[l]) subs[l] = geom return (lgeos.GEOSGeom_createCollection(7, subs, L), N)
def geos_geometrycollection_from_py(ob): """Creates a GEOS GeometryCollection from a list of geometries""" L = len(ob) N = 2 subs = (c_void_p * L)() for l in range(L): assert(isinstance(ob[l], BaseGeometry)) if ob[l].has_z: N = 3 geom, n = geos_geom_from_py(ob[l]) subs[l] = geom return (lgeos.GEOSGeom_createCollection(7, subs, L), N)
def geos_multipoint_from_py(ob): if isinstance(ob, MultiPoint): return geos_geom_from_py(ob) # 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] assert m >= 1 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'] # Array of pointers to sub-geometries subs = (c_void_p * m)() for i in range(m): geom, ndims = point.geos_point_from_py(cp[n*i:n*i+2]) subs[i] = cast(geom, c_void_p) except AttributeError: # Fall back on list m = len(ob) try: n = len(ob[0]) except TypeError: n = ob[0]._ndim assert n == 2 or n == 3 # Array of pointers to point geometries subs = (c_void_p * m)() # add to coordinate sequence for i in range(m): coords = ob[i] geom, ndims = point.geos_point_from_py(coords) subs[i] = cast(geom, c_void_p) return lgeos.GEOSGeom_createCollection(4, subs, m), n
def geos_multipoint_from_py(ob): if isinstance(ob, MultiPoint): return geos_geom_from_py(ob) # 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] assert m >= 1 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'] # Array of pointers to sub-geometries subs = (c_void_p * m)() for i in range(m): geom, ndims = point.geos_point_from_py(cp[n * i:n * i + 2]) subs[i] = cast(geom, c_void_p) except AttributeError: # Fall back on list m = len(ob) try: n = len(ob[0]) except TypeError: n = ob[0]._ndim assert n == 2 or n == 3 # Array of pointers to point geometries subs = (c_void_p * m)() # add to coordinate sequence for i in range(m): coords = ob[i] geom, ndims = point.geos_point_from_py(coords) subs[i] = cast(geom, c_void_p) return lgeos.GEOSGeom_createCollection(4, subs, m), n
def geos_multilinestring_from_py(ob): # ob must be either a MultiLineString, a sequence, or # array of sequences or arrays if isinstance(ob, MultiLineString): return geos_geom_from_py(ob) try: # From array protocol array = ob.__array_interface__ assert len(array['shape']) == 1 L = array['shape'][0] assert L >= 1 # Array of pointers to sub-geometries subs = (c_void_p * L)() for l in range(L): geom, ndims = linestring.geos_linestring_from_py(array['data'][l]) subs[i] = cast(geom, c_void_p) if lgeos.GEOSHasZ(subs[0]): N = 3 else: N = 2 except (NotImplementedError, AttributeError): obs = getattr(ob, 'geoms', ob) L = len(obs) exemplar = obs[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim assert L >= 1 assert N == 2 or N == 3 # Array of pointers to point geometries subs = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndims = linestring.geos_linestring_from_py(obs[l]) subs[l] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
def geos_point_from_py(ob, update_geom=None, update_ndim=0): """Create a GEOS geom from an object that is a Point, a coordinate sequence or that provides the array interface. Returns the GEOS geometry and the number of its dimensions. """ if isinstance(ob, Point): return geos_geom_from_py(ob) # Accept either (x, y) or [(x, y)] if not hasattr(ob, '__getitem__'): # Iterators, e.g. Python 3 zip ob = list(ob) if isinstance(ob[0], tuple): coords = ob[0] else: coords = ob n = len(coords) dx = c_double(coords[0]) dy = c_double(coords[1]) dz = None if n == 3: dz = c_double(coords[2]) if update_geom: 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(1, n) # Because of a bug in the GEOS C API, always set X before Y lgeos.GEOSCoordSeq_setX(cs, 0, dx) lgeos.GEOSCoordSeq_setY(cs, 0, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, 0, dz) if update_geom: return None else: return lgeos.GEOSGeom_createPoint(cs), n
def geos_multipolygon_from_polygons(arg): """ ob must be either a MultiPolygon, sequence or array of sequences or arrays. """ if isinstance(arg, MultiPolygon): return geos_geom_from_py(arg) obs = getattr(arg, 'geoms', arg) obs = [ ob for ob in obs if ob and not (isinstance(ob, polygon.Polygon) and ob.is_empty) ] L = len(obs) # Bail immediately if we have no input points. if L <= 0: return (lgeos.GEOSGeom_createEmptyCollection(6), 3) exemplar = obs[0] try: N = len(exemplar[0][0]) except TypeError: N = exemplar._ndim assert N == 2 or N == 3 subs = (c_void_p * L)() for i, ob in enumerate(obs): if isinstance(ob, polygon.Polygon): shell = ob.exterior holes = ob.interiors else: shell = ob[0] holes = ob[1] geom, ndims = polygon.geos_polygon_from_py(shell, holes) subs[i] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
def geos_polygon_from_py(shell, holes=None): if shell is None: return None if isinstance(shell, Polygon): return geos_geom_from_py(shell) if shell is not None: ret = geos_linearring_from_py(shell) if ret is None: return None geos_shell, ndim = ret if holes is not None and len(holes) > 0: ob = holes L = len(ob) exemplar = ob[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim if not L >= 1: raise ValueError("number of holes must be non zero") if not N in (2, 3): raise ValueError("insufficiant coordinate dimension") # Array of pointers to ring geometries geos_holes = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndim = geos_linearring_from_py(ob[l]) geos_holes[l] = cast(geom, c_void_p) else: geos_holes = POINTER(c_void_p)() L = 0 return ( lgeos.GEOSGeom_createPolygon( c_void_p(geos_shell), geos_holes, L), ndim)
def geos_multilinestring_from_py(ob): # ob must be either a MultiLineString, a sequence, or # array of sequences or arrays if isinstance(ob, MultiLineString): return geos_geom_from_py(ob) try: # From array protocol array = ob.__array_interface__ assert len(array['shape']) == 1 L = array['shape'][0] assert L >= 1 # Array of pointers to sub-geometries subs = (c_void_p * L)() for l in range(L): geom, ndims = linestring.geos_linestring_from_py(array['data'][l]) subs[i] = cast(geom, c_void_p) N = lgeos.GEOSGeom_getCoordinateDimension(subs[0]) except (NotImplementedError, AttributeError): obs = getattr(ob, 'geoms', ob) L = len(obs) exemplar = obs[0] try: N = len(exemplar[0]) except TypeError: N = exemplar._ndim assert L >= 1 assert N == 2 or N == 3 # Array of pointers to point geometries subs = (c_void_p * L)() # add to coordinate sequence for l in range(L): geom, ndims = linestring.geos_linestring_from_py(obs[l]) subs[l] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(5, subs, L), N)
def geos_multipoint_from_py(ob): if isinstance(ob, MultiPoint): return geos_geom_from_py(ob) m = len(ob) try: n = len(ob[0]) except TypeError: n = ob[0]._ndim assert n == 2 or n == 3 # Array of pointers to point geometries subs = (c_void_p * m)() # add to coordinate sequence for i in range(m): coords = ob[i] geom, ndims = point.geos_point_from_py(coords) subs[i] = cast(geom, c_void_p) return lgeos.GEOSGeom_createCollection(4, subs, m), n
def geos_multipolygon_from_polygons(arg): """ ob must be either a MultiPolygon, sequence or array of sequences or arrays. """ if isinstance(arg, MultiPolygon): return geos_geom_from_py(arg) obs = getattr(arg, 'geoms', arg) obs = [ob for ob in obs if ob and not (isinstance(ob, polygon.Polygon) and ob.is_empty)] L = len(obs) # Bail immediately if we have no input points. if L <= 0: return (lgeos.GEOSGeom_createEmptyCollection(6), 3) exemplar = obs[0] try: N = len(exemplar[0][0]) except TypeError: N = exemplar._ndim assert N == 2 or N == 3 subs = (c_void_p * L)() for i, ob in enumerate(obs): if isinstance(ob, polygon.Polygon): shell = ob.exterior holes = ob.interiors else: shell = ob[0] holes = ob[1] geom, ndims = polygon.geos_polygon_from_py(shell, holes) subs[i] = cast(geom, c_void_p) return (lgeos.GEOSGeom_createCollection(6, subs, L), N)
def geos_point_from_py(ob, update_geom=None, update_ndim=0): """Create a GEOS geom from an object that is a Point, a coordinate sequence or that provides the array interface. Returns the GEOS geometry and the number of its dimensions. """ if isinstance(ob, Point): return geos_geom_from_py(ob) # 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']) == 1 n = array['shape'][0] assert n == 2 or n == 3 dz = None da = array['data'] if isinstance(da, tuple): cdata = da[0] # If we had numpy, we would do # from numpy.ctypeslib import as_ctypes # cp = as_ctypes(ob) - check that code? cp = cast(cdata, POINTER(c_double)) dx = c_double(cp[0]) dy = c_double(cp[1]) if n == 3: dz = c_double(cp[2]) else: dx, dy = da[0:2] if n == 3: dz = da[2] except AttributeError: # Fall back on the case of Python sequence data # Accept either (x, y) or [(x, y)] if not hasattr(ob, '__getitem__'): # Iterators, e.g. Python 3 zip ob = list(ob) if isinstance(ob[0], tuple): coords = ob[0] else: coords = ob n = len(coords) dx = c_double(coords[0]) dy = c_double(coords[1]) dz = None if n == 3: dz = c_double(coords[2]) if update_geom: 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(1, n) # Because of a bug in the GEOS C API, always set X before Y lgeos.GEOSCoordSeq_setX(cs, 0, dx) lgeos.GEOSCoordSeq_setY(cs, 0, dy) if n == 3: lgeos.GEOSCoordSeq_setZ(cs, 0, dz) if update_geom: return None else: return lgeos.GEOSGeom_createPoint(cs), n
def geos_linestring_from_py(ob, update_geom=None, update_ndim=0): # If a LineString is passed in, clone it and return # If a LinearRing is passed in, clone the coord seq and return a # LineString. # # NB: access to coordinates using the array protocol has been moved # entirely to the speedups module. if isinstance(ob, LineString): if type(ob) == LineString: return geos_geom_from_py(ob) else: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLineString) try: m = len(ob) except TypeError: # Iterators, e.g. Python 3 zip 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 try: n = len(_coords(ob[0])) except TypeError: raise ValueError( "Input %s is the wrong shape for a LineString" % str(ob)) assert n == 2 or n == 3 # 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 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") if update_geom is not None: return None else: return lgeos.GEOSGeom_createLineString(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 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 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: # Iterators, e.g. Python 3 zip ob = list(ob) m = len(ob) if m == 0: return None 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: 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 = 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 LineString is passed in, clone the coord seq and return a LinearRing if isinstance(ob, LineString): if type(ob) == LinearRing: return geos_geom_from_py(ob) else: if ob.is_closed and len(ob.coords) >= 4: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLinearRing) # 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 range(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 try: m = len(ob) except TypeError: # Iterators, e.g. Python 3 zip ob = list(ob) m = len(ob) if m == 0: return None 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 range(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_linestring_from_py(ob, update_geom=None, update_ndim=0): # If a LineString is passed in, clone it and return # If a LinearRing is passed in, clone the coord seq and return a LineString if isinstance(ob, LineString): if type(ob) == LineString: return geos_geom_from_py(ob) else: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLineString) # 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] if m < 2: raise ValueError( "LineStrings must have at least 2 coordinate tuples") try: n = array['shape'][1] except IndexError: raise ValueError( "Input %s is the wrong shape for a LineString" % str(ob)) 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'] # 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 range(m): dx = c_double(cp[n*i]) dy = c_double(cp[n*i+1]) dz = None if n == 3: try: dz = c_double(cp[n*i+2]) except IndexError: raise ValueError("Inconsistent coordinate dimensionality") # 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) except AttributeError: # Fall back on list try: m = len(ob) except TypeError: # Iterators, e.g. Python 3 zip ob = list(ob) m = len(ob) if m < 2: raise ValueError( "LineStrings must have at least 2 coordinate tuples") def _coords(o): if isinstance(o, Point): return o.coords[0] else: return o try: n = len(_coords(ob[0])) except TypeError: raise ValueError( "Input %s is the wrong shape for a LineString" % str(ob)) assert n == 2 or n == 3 # 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 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") if update_geom is not None: return None else: return lgeos.GEOSGeom_createLineString(cs), n
def geos_linestring_from_py(ob, update_geom=None, update_ndim=0): # If a LineString is passed in, clone it and return # If a LinearRing is passed in, clone the coord seq and return a # LineString. # # NB: access to coordinates using the array protocol has been moved # entirely to the speedups module. if isinstance(ob, LineString): if type(ob) == LineString: return geos_geom_from_py(ob) else: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLineString) try: m = len(ob) except TypeError: # Iterators, e.g. Python 3 zip 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 try: n = len(_coords(ob[0])) except TypeError: raise ValueError("Input %s is the wrong shape for a LineString" % str(ob)) assert n == 2 or n == 3 # 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 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") if update_geom is not None: return None else: return lgeos.GEOSGeom_createLineString(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 LineString is passed in, clone the coord seq and return a LinearRing if isinstance(ob, LineString): if type(ob) == LinearRing: return geos_geom_from_py(ob) else: if ob.is_closed and len(ob.coords) >= 4: return geos_geom_from_py(ob, lgeos.GEOSGeom_createLinearRing) # 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 range(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 try: m = len(ob) except TypeError: # Iterators, e.g. Python 3 zip ob = list(ob) 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 range(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