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_geom_from_py(ob, create_func=None): """Helper function for geos_*_from_py functions in each geom type. If a create_func is specified the coodinate sequence is cloned and a new geometry is created with it, otherwise the geometry is cloned directly. This behaviour is useful for converting between LineString and LinearRing objects. """ if create_func is None: geom = lgeos.GEOSGeom_clone(ob._geom) else: cs = lgeos.GEOSGeom_getCoordSeq(ob._geom) cs = lgeos.GEOSCoordSeq_clone(cs) geom = create_func(cs) N = ob._ndim return geom, N
def ctypes(self): if not self._ctypes_data: temp = c_double() n = self._ndim m = len(self.geoms) array_type = c_double * (m * n) data = array_type() for i in range(m): g = self.geoms[i]._geom cs = lgeos.GEOSGeom_getCoordSeq(g) lgeos.GEOSCoordSeq_getX(cs, 0, byref(temp)) data[n*i] = temp.value lgeos.GEOSCoordSeq_getY(cs, 0, byref(temp)) data[n*i+1] = temp.value if n == 3: # TODO: use hasz lgeos.GEOSCoordSeq_getZ(cs, 0, byref(temp)) data[n*i+2] = temp.value self._ctypes_data = data return self._ctypes_data
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 __call__(self, this): self._validate(this) env = this.envelope if env.geom_type == 'Point': return env.bounds cs = lgeos.GEOSGeom_getCoordSeq(env.exterior._geom) cs_len = c_uint(0) lgeos.GEOSCoordSeq_getSize(cs, byref(cs_len)) minx = 1.e+20 maxx = -1e+20 miny = 1.e+20 maxy = -1e+20 temp = c_double() for i in range(cs_len.value): lgeos.GEOSCoordSeq_getX(cs, i, byref(temp)) x = temp.value if x < minx: minx = x if x > maxx: maxx = x lgeos.GEOSCoordSeq_getY(cs, i, byref(temp)) y = temp.value if y < miny: miny = y if y > maxy: maxy = y return (minx, miny, maxx, maxy)
def _update(self): self._ndim = self.__p__._ndim self._cseq = lgeos.GEOSGeom_getCoordSeq(self.__p__._geom)
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_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 elif m == 1: raise ValueError("LineStrings must have at least 2 coordinate tuples") 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: ptr = lgeos.GEOSGeom_createLineString(cs) if not ptr: raise ValueError( "GEOSGeom_createLineString returned a NULL pointer") return ptr, n