Пример #1
0
def test_equals_exact_tolerance():
    # specifying tolerance
    p1 = pygeos.points(50, 4)
    p2 = pygeos.points(50.1, 4.1)
    actual = pygeos.equals_exact([p1, p2, None], p1, tolerance=0.05)
    np.testing.assert_allclose(actual, [True, False, False])
    assert actual.dtype == np.bool
    actual = pygeos.equals_exact([p1, p2, None], p1, tolerance=0.2)
    np.testing.assert_allclose(actual, [True, True, False])
    assert actual.dtype == np.bool

    # default value for tolerance
    assert pygeos.equals_exact(p1, p1).item() is True
    assert pygeos.equals_exact(p1, p2).item() is False
Пример #2
0
def test_from_wkt():
    expected = pygeos.points(1, 1)
    actual = pygeos.from_wkt("POINT (1 1)")
    assert pygeos.equals(actual, expected)
    # also accept bytes
    actual = pygeos.from_wkt(b"POINT (1 1)")
    assert pygeos.equals(actual, expected)
Пример #3
0
def boundary_distance(polygon, points):
    """
    Find the distance between a polygon's boundary and an
    array of points.

    Uses either `shapely` or `pygeos` (5-10x faster) as a backend.

    Parameters
    -------------
    polygon : shapely.geometry.Polygon
      Polygon to query
    points : (n, 2) float
      2D points

    Returns
    ------------
    distance : (n,) float
      Minimum distance from each point to polygon boundary
    """

    try:
        import pygeos
        # the pygeos way is 5-10x faster
        pg_points = pygeos.points(*points.T)
        pg_boundary = pygeos.boundary(pygeos.Geometry(polygon.wkt))
        distance = pygeos.distance(pg_boundary, pg_points)
    except BaseException:
        # in pure shapely we have to loop
        inverse = polygon.boundary
        distance = np.array([
            inverse.distance(i) for i in MultiPoint(points)])

    return distance
Пример #4
0
def close_gaps(df, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    """
    geom = df.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return snapped
Пример #5
0
def test_from_wkb_hex():
    # HEX form
    expected = pygeos.points(1, 1)
    actual = pygeos.from_wkb("0101000000000000000000F03F000000000000F03F")
    assert pygeos.equals(actual, expected)
    actual = pygeos.from_wkb(b"0101000000000000000000F03F000000000000F03F")
    assert pygeos.equals(actual, expected)
Пример #6
0
    def _sample_land_points(self, N_pts):

        pt_df = pd.DataFrame(columns=['lon', 'lat'], index=[])

        ii_p = 0
        while len(pt_df) < N_pts:

            pts = np.random.rand(2 * 2 * (N_pts - len(pt_df))).reshape(
                (N_pts - len(pt_df)) * 2, 2)
            #print ('pts shape',pts.shape)
            pts[:, 0] = pts[:, 0] * 360 - 180  # lon
            pts[:, 1] = pts[:, 1] * (80 + 70) - 70  # lat between -70 and 80

            pts_pygeos = pygeos.points(pts)

            Q = self.tree.query_bulk(pts_pygeos, predicate='within').T[:, 0]
            #print ('Q-shape',Q.shape)

            pt_df = pt_df.append(pd.DataFrame(pts[Q], columns=['lon', 'lat']))
            #print ('len pt_df', len(pt_df), 'iter_toc',time.time()-tic)
            ii_p += 1

        pt_df = pt_df.iloc[0:N_pts]

        # reset the index
        pt_df.index = range(len(pt_df))

        return pt_df
Пример #7
0
def poly_tree():
    # create buffers so that midpoint between two buffers intersects
    # each buffer.  NOTE: add EPS to help mitigate rounding errors at midpoint.
    geoms = pygeos.buffer(pygeos.points(np.arange(10), np.arange(10)),
                          HALF_UNIT_DIAG + EPS,
                          quadsegs=32)
    yield pygeos.STRtree(geoms)
Пример #8
0
 def setup(self):
     # create irregular polygons by merging overlapping point buffers
     self.left = pygeos.union_all(
         pygeos.buffer(pygeos.points(np.random.random((500, 2)) * 500), 15)
     )
     # shift this up and right
     self.right = pygeos.apply(self.left, lambda x: x + 50)
Пример #9
0
        def intersection(self, coordinates):
            # convert bounds to geometry
            # the old API uses tuples of bound, but pygeos uses geometries
            try:
                iter(coordinates)
            except TypeError:
                # likely not an iterable
                # this is a check that rtree does, we mimic it
                # to ensure a useful failure message
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points). "
                    "Got `coordinates` = {}.".format(coordinates))

            # need to convert tuple of bounds to a geometry object
            if len(coordinates) == 4:
                indexes = super().query(pygeos.box(*coordinates))
            elif len(coordinates) == 2:
                indexes = super().query(pygeos.points(*coordinates))
            else:
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points). "
                    "Got `coordinates` = {}.".format(coordinates))

            return indexes
Пример #10
0
def test_flush_geometries(tree):
    arr = pygeos.points(np.arange(10), np.arange(10))
    tree = pygeos.STRtree(arr)
    # Dereference geometries
    arr[:] = None
    # Still it does not lead to a segfault
    tree.query(point)
Пример #11
0
def test_to_wkb_hex():
    point = pygeos.points(1, 1)
    actual = pygeos.to_wkb(point, hex=True, byte_order=1)
    le = "01"
    point_type = "01000000"
    coord = "000000000000F03F"  # 1.0 as double (LE)
    assert actual == le + point_type + 2 * coord
Пример #12
0
def test_to_wkb_3D():
    point_z = pygeos.points(1, 1, 1)
    actual = pygeos.to_wkb(point_z, byte_order=1)
    # fmt: off
    assert actual == b"\x01\x01\x00\x00\x80\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\xf0?\x00\x00\x00\x00\x00\x00\xf0?"  # noqa
    # fmt: on
    actual = pygeos.to_wkb(point_z, output_dimension=2, byte_order=1)
    assert actual == POINT11_WKB
Пример #13
0
def test_to_wkb_byte_order():
    point = pygeos.points(1.0, 1.0)
    be = b"\x00"
    le = b"\x01"
    point_type = b"\x01\x00\x00\x00"  # 1 as 32-bit uint (LE)
    coord = b"\x00\x00\x00\x00\x00\x00\xf0?"  # 1.0 as double (LE)

    assert pygeos.to_wkb(point, byte_order=1) == le + point_type + 2 * coord
    assert pygeos.to_wkb(point, byte_order=0) == be + point_type[::-1] + 2 * coord[::-1]
Пример #14
0
def test_destroy_prepared():
    arr = np.array([pygeos.points(1, 1), None, pygeos.box(0, 0, 1, 1)])
    pygeos.prepare(arr)
    assert arr[0]._ptr_prepared != 0
    assert arr[2]._ptr_prepared != 0
    pygeos.destroy_prepared(arr)
    assert arr[0]._ptr_prepared == 0
    assert arr[1] is None
    assert arr[2]._ptr_prepared == 0
    pygeos.destroy_prepared(arr)  # does not error
Пример #15
0
def test_to_wkt():
    point = pygeos.points(1, 1)
    actual = pygeos.to_wkt(point)
    assert actual == "POINT (1 1)"

    actual = pygeos.to_wkt(point, trim=False)
    assert actual == "POINT (1.000000 1.000000)"

    actual = pygeos.to_wkt(point, rounding_precision=3, trim=False)
    assert actual == "POINT (1.000 1.000)"
Пример #16
0
 def setup(self):
     # create irregular polygons by merging overlapping point buffers
     self.polygon = pygeos.union_all(
         pygeos.buffer(pygeos.points(np.random.random((1000, 2)) * 500),
                       10))
     xmin = np.random.random(100) * 100
     xmax = xmin + 100
     ymin = np.random.random(100) * 100
     ymax = ymin + 100
     self.bounds = np.array([xmin, ymin, xmax, ymax]).T
     self.boxes = pygeos.box(xmin, ymin, xmax, ymax)
Пример #17
0
    def test_nearest_multi(self, geometry, expected, return_all):
        geoms = pygeos.points(np.arange(10), np.arange(10))
        df = geopandas.GeoDataFrame({"geometry": geoms})

        ps = [Point(p) for p in geometry]
        res = df.sindex.nearest(ps, return_all=return_all)
        assert_array_equal(res, expected)

        ps = pygeos.points(geometry)
        res = df.sindex.nearest(ps, return_all=return_all)
        assert_array_equal(res, expected)

        s = geopandas.GeoSeries(ps)
        res = df.sindex.nearest(s, return_all=return_all)
        assert_array_equal(res, expected)

        x, y = zip(*geometry)
        ga = geopandas.points_from_xy(x, y)
        res = df.sindex.nearest(ga, return_all=return_all)
        assert_array_equal(res, expected)
Пример #18
0
        def intersection(self, coordinates, objects=False):
            """Wrapper for pygeos.query that uses the RTree API.

            Parameters
            ----------
            coordinates : sequence or array
                Sequence of the form (min_x, min_y, max_x, max_y)
                to query a rectangle or (x, y) to query a point.
            objects : boolean, default False
                If True, return the label based indexes. If False, integer indexes
                are returned.
            """
            if objects:
                warn(
                    "`objects` is deprecated and will be removed in a future version. "
                    "Instead, use `iloc` to index your GeoSeries/GeoDataFrame using "
                    "integer indexes returned by `intersection`.",
                    FutureWarning,
                )

            # convert bounds to geometry
            # the old API uses tuples of bound, but pygeos uses geometries
            try:
                iter(coordinates)
            except TypeError:
                # likely not an iterable
                # this is a check that rtree does, we mimic it
                # to ensure a useful failure message
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points). "
                    "Got `coordinates` = {}.".format(coordinates))

            # need to convert tuple of bounds to a geometry object
            if len(coordinates) == 4:
                indexes = super().query(pygeos.box(*coordinates))
            elif len(coordinates) == 2:
                indexes = super().query(pygeos.points(*coordinates))
            else:
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points). "
                    "Got `coordinates` = {}.".format(coordinates))

            if objects:
                objs = self.objects[indexes].values
                ids = self.ids[indexes]
                return [
                    self.with_objects(id=id, object=obj)
                    for id, obj in zip(ids, objs)
                ]
            else:
                return indexes
Пример #19
0
def test_prepare():
    arr = np.array([pygeos.points(1, 1), None, pygeos.box(0, 0, 1, 1)])
    assert arr[0]._ptr_prepared == 0
    assert arr[2]._ptr_prepared == 0
    pygeos.prepare(arr)
    assert arr[0]._ptr_prepared != 0
    assert arr[1] is None
    assert arr[2]._ptr_prepared != 0

    # preparing again actually does nothing
    original = arr[0]._ptr_prepared
    pygeos.prepare(arr)
    assert arr[0]._ptr_prepared == original
Пример #20
0
def points_from_xy(x, y, z=None):

    x = np.asarray(x, dtype="float64")
    y = np.asarray(y, dtype="float64")
    if z is not None:
        z = np.asarray(z, dtype="float64")

    if compat.USE_PYGEOS:
        return pygeos.points(x, y, z)
    out = _points_from_xy(x, y, z)
    aout = np.empty(len(x), dtype=object)
    aout[:] = out
    return aout
Пример #21
0
def test_to_wkt_3D():
    # 3D points
    point_z = pygeos.points(1, 1, 1)
    actual = pygeos.to_wkt(point_z)
    assert actual == "POINT Z (1 1 1)"
    actual = pygeos.to_wkt(point_z, output_dimension=3)
    assert actual == "POINT Z (1 1 1)"

    actual = pygeos.to_wkt(point_z, output_dimension=2)
    assert actual == "POINT (1 1)"

    actual = pygeos.to_wkt(point_z, old_3d=True)
    assert actual == "POINT (1 1 1)"
Пример #22
0
def close_gaps(gdf, tolerance):
    """Close gaps in LineString geometry where it should be contiguous.

    Snaps both lines to a centroid of a gap in between.

    Parameters
    ----------
    gdf : GeoDataFrame, GeoSeries
        GeoDataFrame  or GeoSeries containing LineString representation of a network.
    tolerance : float
        nodes within a tolerance will be snapped together

    Returns
    -------
    GeoSeries
    
    See also
    --------
    momepy.extend_lines
    momepy.remove_false_nodes

    """
    geom = gdf.geometry.values.data
    coords = pygeos.get_coordinates(geom)
    indices = pygeos.get_num_coordinates(geom)

    # generate a list of start and end coordinates and create point geometries
    edges = [0]
    i = 0
    for ind in indices:
        ix = i + ind
        edges.append(ix - 1)
        edges.append(ix)
        i = ix
    edges = edges[:-1]
    points = pygeos.points(np.unique(coords[edges], axis=0))

    buffered = pygeos.buffer(points, tolerance / 2)

    dissolved = pygeos.union_all(buffered)

    exploded = [
        pygeos.get_geometry(dissolved, i)
        for i in range(pygeos.get_num_geometries(dissolved))
    ]

    centroids = pygeos.centroid(exploded)

    snapped = pygeos.snap(geom, pygeos.union_all(centroids), tolerance)

    return gpd.GeoSeries(snapped, crs=gdf.crs)
Пример #23
0
def test_to_wkb_srid():
    # hex representation of POINT (0 0) with SRID=4
    ewkb = "01010000200400000000000000000000000000000000000000"
    wkb = "010100000000000000000000000000000000000000"

    actual = pygeos.from_wkb(ewkb)
    assert pygeos.to_wkt(actual, trim=True) == "POINT (0 0)"

    assert pygeos.to_wkb(actual, hex=True, byte_order=1) == wkb
    assert pygeos.to_wkb(actual, hex=True, include_srid=True, byte_order=1) == ewkb

    point = pygeos.points(1, 1)
    point_with_srid = pygeos.set_srid(point, np.int32(4326))
    result = pygeos.to_wkb(point_with_srid, include_srid=True, byte_order=1)
    assert np.frombuffer(result[5:9], "<u4").item() == 4326
Пример #24
0
def points_from_xy(x, y, z=None):

    x = np.asarray(x, dtype="float64")
    y = np.asarray(y, dtype="float64")
    if z is not None:
        z = np.asarray(z, dtype="float64")

    if compat.USE_PYGEOS:
        return pygeos.points(x, y, z)
    else:
        out = _points_from_xy(x, y, z)
        aout = np.empty(len(x), dtype=object)
        with compat.ignore_shapely2_warnings():
            aout[:] = out
        return aout
Пример #25
0
    def test_nearest_max_distance(self, expected, max_distance, return_all,
                                  return_distance):
        geoms = pygeos.points(np.arange(10), np.arange(10))
        df = geopandas.GeoDataFrame({"geometry": geoms})

        ps = [Point(0.5, 0.5), Point(0, 10)]
        res = df.sindex.nearest(
            ps,
            return_all=return_all,
            max_distance=max_distance,
            return_distance=return_distance,
        )
        if return_distance:
            assert_array_equal(res[0], expected[0])
            assert_array_equal(res[1], expected[1])
        else:
            assert_array_equal(res, expected[0])
Пример #26
0
        def intersection(self, coordinates, objects=False):
            """Wrapper for pygeos.query that uses the RTree API.

            Parameters
            ----------
            coordinates : sequence or array
                Sequence of the form (min_x, min_y, max_x, max_y)
                to query a rectangle or (x, y) to query a point.
            objects : True or False
                If True, return the label based indexes. If False, integer indexes
                are returned.
            """
            # convert bounds to geometry
            # the old API uses tuples of bound, but pygeos uses geometries
            try:
                iter(coordinates)
            except TypeError:
                # likely not an iterable
                # this is a check that rtree does, we mimick it
                # to ensure a useful failure message
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points)."
                )

            # need to convert tuple of bounds to a geometry object
            if len(coordinates) == 4:
                indexes = super().query(box(*coordinates))
            elif len(coordinates) == 2:
                indexes = super().query(points(*coordinates))
            else:
                raise TypeError(
                    "Invalid coordinates, must be iterable in format "
                    "(minx, miny, maxx, maxy) (for bounds) or (x, y) (for points)."
                )

            if objects:
                objs = self.objects[indexes].values
                ids = self.ids[indexes]
                return [
                    self.with_objects(id=id, object=obj)
                    for id, obj in zip(ids, objs)
                ]
            else:
                return indexes
Пример #27
0
def pg_points_wgs84():
    size = 1000
    x, y = generate_lon_lat(size)

    # generate some other fields in the data frame
    i = random.randint(-32767, 32767, size=size)
    ui = random.randint(0, 65535, size=size).astype("uint64")

    df = DataFrame(data={
        "x": x,
        "y": y,
        "i": i,
        "ui": ui,
        "labels": i.astype("str")
    })
    df["geometry"] = pg.points(np.array([x, y]).T)

    return df
Пример #28
0
def _geometry_from_latlon(table, lat_field, lon_field, crs):
    """Transforms an arrow to table to spatial arrow table, using lat, lon information.
    Extracts the lat, lon information from an arrow table, creates the Point geometry
    and writes the geometry information to the arrow table.
    Parameters:
        table (object): The arrow table.
        lat_field (string): The latitude field name.
        lon_field (string): The longitude field name.
        crs (string): The lat, lon CRS.
    Returns:
        (object): The arrow spatial table.
    """
    lat = table.column(lat_field)
    lon = table.column(lon_field)
    geometry = pg.to_wkb(pg.points(lon, lat))
    field = pa.field('geometry', 'binary', metadata={'crs': crs})
    table = table.append_column(field, [geometry])
    table = table.drop([lat_field, lon_field])
    return table
Пример #29
0
def convert_to_point(input_array,
                     trim_invalid_geometry=False,
                     autocorrect_invalid_geometry=False):
    r"""Convert an input array to a Point array.

    Args:
        input_array (ndarray, list): A ndarray of Point optionally followed by a confidence value and/or a label
            where each row is: ``[x, y, (confidence), (label)]``
        trim_invalid_geometry (bool): Optional, default to ``False``. If set to ``True`` conversion will ignore invalid
            geometries and leave them out of ``output_array``. This means that the function will return an array where
            ``output_array.shape[0] <= input_array.shape[0]``.  If set to ``False``, an invalid geometry will raise an
            :exc:`~playground_metrics.utils.geometry_utils.InvalidGeometryError`.
        autocorrect_invalid_geometry (Bool): Optional, default to ``False``. Doesn't do anything, introduced to unify
            convert functions interfaces.

    Returns:
        ndarray: A Point ndarray where each row contains a geometry followed by optionally confidence and a label
        e.g.: ``[Point, (confidence), (label)]``

    Raises:
        ValueError: If ``input_array`` have invalid dimensions.

    """
    input_array = np.array(input_array, dtype=np.dtype('O'))
    if input_array.size == 0:
        return 'undefined', input_array
    if len(input_array.shape) == 1 or len(input_array.shape) > 2:
        raise ValueError('Invalid array number of dimensions: '
                         'Expected a 2D array, found {}D.'.format(
                             len(input_array.shape)))

    coordinates_array = input_array[:, :2].astype(np.float64)

    object_array = np.ndarray((input_array.shape[0], input_array.shape[1] - 1),
                              dtype=np.dtype('O'))
    object_array[:, 0] = points(coordinates_array)
    object_array[:, 1:] = input_array[:, 2:]

    if trim_invalid_geometry:
        object_array = object_array[is_valid(object_array[:, 0]), :]

    return object_array
Пример #30
0
class _TestPolygons(_TestSimilarity):
    SIMILAR = [
        box(0, 0, 1, 1),
        polygons([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]),
        polygons([[0.5, 0], [1, 0], [1, 1], [0, 1], [0, 0.5], [0, 0]])
    ]
    DISSIMILAR = [
        box(10, 10, 11, 11),
        polygons([[0, 0], [0, 1], [1, 1], [1, 0], [0, 0]]),
        polygons([[8, 8], [8, 13], [13, 13], [13, 8], [8, 8]],
                 holes=[[[9, 9], [9, 12], [12, 12], [12, 9], [9, 9]]]),
        polygons([[4.5, 4], [5, 4], [5, 5], [4, 5], [4, 4.5], [4, 4]]),
        points([0.5, 0.5])
    ]
    VALUE_GEOMETRIES = [[
        box(0, 0, 2, 2),
        polygons([[8, 8], [8, 13], [13, 13], [13, 8], [8, 8]],
                 holes=[[[9, 9], [9, 12], [12, 12], [12, 9], [9, 9]]])
    ], [box(-1, -1, 1, 1), box(8, 8, 13, 13)]]
    VALUE = [0.14285714285714285, 0.64]