Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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)
Beispiel #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
Beispiel #5
0
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
Beispiel #6
0
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)
Beispiel #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
Beispiel #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