예제 #1
0
 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)
예제 #2
0
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
예제 #3
0
 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
예제 #4
0
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
예제 #5
0
 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)
예제 #6
0
 def _update(self):
     self._ndim = self.__p__._ndim
     self._cseq = lgeos.GEOSGeom_getCoordSeq(self.__p__._geom)
예제 #7
0
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
예제 #8
0
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