Пример #1
0
def test_polygons_not_enough_points_in_shell(shape):
    coords = np.ones(shape)
    with pytest.raises(pygeos.GEOSException):
        pygeos.polygons(coords)

    # make sure the first coordinate != second coordinate
    coords[..., 1] += 1
    with pytest.raises(pygeos.GEOSException):
        pygeos.polygons(coords)
Пример #2
0
def test_polygons_not_enough_points_in_holes(shape):
    coords = np.ones(shape)
    with pytest.raises(ValueError):
        pygeos.polygons(np.ones((1, 4, 2)), coords)

    # make sure the first coordinate != second coordinate
    coords[..., 1] += 1
    with pytest.raises(ValueError):
        pygeos.polygons(np.ones((1, 4, 2)), coords)
Пример #3
0
def default_filter(
    tile: mercantile.Tile,
    dataset: Sequence[Dict],
    geoms: Sequence[polygons],
    minimum_tile_cover=None,
    tile_cover_sort=False,
    maximum_items_per_tile: Optional[int] = None,
) -> List:
    """Filter and/or sort dataset per intersection coverage."""
    indices = list(range(len(dataset)))

    if minimum_tile_cover or tile_cover_sort:
        tile_geom = polygons(
            mercantile.feature(tile)["geometry"]["coordinates"][0])
        int_pcts = _intersect_percent(tile_geom, geoms)

        if minimum_tile_cover:
            indices = [
                ind for ind in indices if int_pcts[ind] > minimum_tile_cover
            ]

        if tile_cover_sort:
            # https://stackoverflow.com/a/9764364
            indices, _ = zip(*sorted(zip(indices, int_pcts), reverse=True))

    if maximum_items_per_tile:
        indices = indices[:maximum_items_per_tile]

    return [dataset[ind] for ind in indices]
Пример #4
0
    def __init__(self, tessellation, edges, buildings, id_name, unique_id,
                 **kwargs):
        self.tessellation = tessellation
        self.edges = edges
        self.buildings = buildings
        self.id_name = id_name
        self.unique_id = unique_id

        if id_name in buildings.columns:
            raise ValueError(
                "'{}' column cannot be in the buildings GeoDataFrame".format(
                    id_name))

        cut = gpd.overlay(
            tessellation,
            gpd.GeoDataFrame(geometry=edges.buffer(0.001)),
            how="difference",
        ).explode()

        W = libpysal.weights.Queen.from_dataframe(cut, silence_warnings=True)
        cut["component"] = W.component_labels
        buildings_c = buildings.copy()
        buildings_c.geometry = buildings_c.representative_point(
        )  # make points
        centroids_tempID = gpd.sjoin(
            buildings_c,
            cut[[cut.geometry.name, "component"]],
            how="left",
            op="intersects",
        )
        cells_copy = tessellation[[
            unique_id, tessellation.geometry.name
        ]].merge(centroids_tempID[[unique_id, "component"]],
                 on=unique_id,
                 how="left")
        blocks = cells_copy.dissolve(by="component").explode().reset_index(
            drop=True)
        blocks[id_name] = range(len(blocks))
        blocks[blocks.geometry.name] = gpd.GeoSeries(pygeos.polygons(
            blocks.exterior.values.data),
                                                     crs=blocks.crs)
        blocks = blocks[[id_name, blocks.geometry.name]]

        centroids_w_bl_ID2 = gpd.sjoin(buildings_c,
                                       blocks,
                                       how="left",
                                       op="intersects")
        bl_ID_to_uID = centroids_w_bl_ID2[[unique_id, id_name]]

        buildings_m = buildings[[unique_id]].merge(bl_ID_to_uID,
                                                   on=unique_id,
                                                   how="left")
        self.buildings_id = buildings_m[id_name]

        cells_m = tessellation[[unique_id]].merge(bl_ID_to_uID,
                                                  on=unique_id,
                                                  how="left")
        self.tessellation_id = cells_m[id_name]

        self.blocks = blocks
Пример #5
0
def pg_polygons_wgs84():
    size = 1000
    x1, y1 = generate_lon_lat(size)
    x2, y2 = generate_lon_lat(size)

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

    df = DataFrame(
        data={
            "x1": x1,
            "y1": y1,
            "x2": x2,
            "y2": y2,
            "f": f,
            "i": i,
            "ui": ui,
            "labels": i.astype("str"),
        })

    # Generate random triangles
    df["geometry"] = df[["x1", "y1", "x2", "y2"]].apply(
        lambda row: pg.polygons([[row.x1, row.y1], [row.x2, row.y1],
                                 [row.x2, row.y2], [row.x1, row.y1]]),
        axis=1,
    )

    return df
Пример #6
0
    def transform_geometry(self, geom, rs, max_points=5):
        """Transforms a geometry embedding new points.

        In case geom is (multi)line or (multi)polygon, it adds points collinear to their neighbours, so that an equivalent geometry is generated. The number of extra points depends on the number of vertices in the geometry.

        Arguments:
            geom (pygeos.Geometry): Geometry
            rs (numpy.RandomState): Random State
            max_points (int): Maximum value of extra points.

        Returns:
            (pygeos.Geometry)

        Raises:
            ValueError: When geometry type is not supported.
        """
        type_ = pg.get_type_id(geom)
        if type_ == 1 or type_ == 3:
            # LINESTRING or POLYGON
            vertices = pg.get_coordinates(geom)
            size = min(max_points, math.ceil(len(vertices) / 6))
            vert_ids = rs.randint(1, len(vertices), size)
            vert_ids.sort()
            new = []
            for idx in vert_ids:
                xa, ya = vertices[idx - 1]
                xb, yb = vertices[idx]
                if xa == xb:
                    x = xa
                    y = self._random_float(rs, ya, yb)
                else:
                    x = self._random_float(rs, xa, xb)
                    y = (yb - ya) * (x - xa) / (xb - xa) + ya
                x = _round(x, [xa, xb])
                y = _round(y, [ya, yb])
                new.append((idx, [x, y]))
            offset = 0
            extended = []
            for idx, entry in new:
                extended.extend(vertices[offset:idx])
                extended.append(entry)
                offset = idx
            extended.extend(vertices[offset:])
            extended = np.array(extended)
            result = pg.linestrings(extended) if type_ == 1 else pg.polygons(
                extended)
        elif type_ == 5 or type_ == 6:
            # MULTILINESTRING or MULTIPOLYGON
            parts = pg.get_parts(geom)
            part_idx = rs.randint(0, len(parts))
            parts[part_idx] = self.transform_geometry(parts[part_idx], rs)
            result = pg.multilinestrings(
                parts) if type_ == 5 else pg.multipolygons(parts)
        else:
            raise ValueError(
                'geom should be linestring, polygon, multilinestring, or multipolygon.'
            )

        return result
Пример #7
0
 def setup(self):
     self.multipolygons = np.array(
         [
             pygeos.multipolygons(pygeos.polygons(np.random.random((2, 100, 2))))
             for i in range(10000)
         ],
         dtype=object,
     )
Пример #8
0
def test_polygon_with_none_hole():
    actual = pygeos.polygons(
        pygeos.linearrings(box_tpl(0, 0, 10, 10)),
        [
            pygeos.linearrings(box_tpl(1, 1, 2, 2)),
            None,
            pygeos.linearrings(box_tpl(3, 3, 4, 4)),
        ],
    )
    assert pygeos.area(actual) == 98.0
Пример #9
0
 def assets_for_tile(self, x: int, y: int, z: int) -> List[str]:
     """Retrieve assets for tile."""
     bbox = self.tms.bounds(x, y, z)
     geom = polygons(
         [
             [bbox[0], bbox[3]],
             [bbox[0], bbox[1]],
             [bbox[2], bbox[1]],
             [bbox[2], bbox[3]],
             [bbox[0], bbox[3]],
         ]
     )
     return self.get_assets(geom)
Пример #10
0
 def __init__(self, bdy):
     """
     Construct rich "Boundary" type. Input "bdy" can either be:
         (1) GlobalSmoothBoundary type (from pybie2d)
         (2) complex form of (x, y) points of boundary
     """
     if type(bdy) == GSB:
         self.GSB = bdy
     else:
         self.GSB = GSB(c=bdy)
     self.c = self.GSB.c
     self.x = self.GSB.x
     self.y = self.GSB.y
     self.SH = pygeos.polygons([*zip(self.x, self.y)])
     pygeos.prepare(self.SH)
Пример #11
0
    def __init__(self, gdf, areas=None):
        self.gdf = gdf

        gdf = gdf.copy()
        if areas is None:
            areas = gdf.geometry.area

        if not isinstance(areas, str):
            gdf["mm_a"] = areas
            areas = "mm_a"
        self.areas = gdf[areas]

        exts = pygeos.area(pygeos.polygons(gdf.geometry.exterior.values.data))

        self.series = pd.Series(exts - gdf[areas], index=gdf.index)
Пример #12
0
def create_grid(bbox,height):
    """Create a vector-based grid

    Args:
        bbox ([type]): [description]
        height ([type]): [description]

    Returns:
        [type]: [description]
    """    

    # set xmin,ymin,xmax,and ymax of the grid
    xmin, ymin = pygeos.total_bounds(bbox)[0],pygeos.total_bounds(bbox)[1]
    xmax, ymax = pygeos.total_bounds(bbox)[2],pygeos.total_bounds(bbox)[3]
    
    #estimate total rows and columns
    rows = int(numpy.ceil((ymax-ymin) / height))
    cols = int(numpy.ceil((xmax-xmin) / height))

    # set corner points
    x_left_origin = xmin
    x_right_origin = xmin + height
    y_top_origin = ymax
    y_bottom_origin = ymax - height

    # create actual grid
    res_geoms = []
    for countcols in range(cols):
        y_top = y_top_origin
        y_bottom = y_bottom_origin
        for countrows in range(rows):
            res_geoms.append((
                ((x_left_origin, y_top), (x_right_origin, y_top),
                (x_right_origin, y_bottom), (x_left_origin, y_bottom)
                )))
            y_top = y_top - height
            y_bottom = y_bottom - height
        x_left_origin = x_left_origin + height
        x_right_origin = x_right_origin + height

    return pygeos.polygons(res_geoms)
Пример #13
0
    def _regions(self, voronoi_diagram, unique_id, ids, crs):
        """
        Generate GeoDataFrame of Voronoi regions from scipy.spatial.Voronoi.
        """
        vertices = pd.Series(voronoi_diagram.regions).take(
            voronoi_diagram.point_region)
        polygons = []
        for region in vertices:
            if -1 not in region:
                polygons.append(
                    pygeos.polygons(voronoi_diagram.vertices[region]))
            else:
                polygons.append(None)

        regions_gdf = gpd.GeoDataFrame({
            unique_id: ids
        },
                                       geometry=polygons,
                                       crs=crs).dropna()
        regions_gdf = regions_gdf.loc[regions_gdf[unique_id] !=
                                      -1]  # delete hull-based cells

        return regions_gdf
Пример #14
0
def occult(lines: LineCollection, tolerance: float) -> LineCollection:
    """
    Remove occulted lines.

    The order of the geometries in 'lines' matters, see example below.

    'tolerance' controls the distance tolerance between the first and last points
    of a geometry to consider it closed.

    Examples:
        $ vpype line 0 0 5 5 rect 2 2 1 1 occult show  # line is occulted by rect

        $ vpype rect 2 2 1 1 line 0 0 5 5 occult show  # line is NOT occulted by rect,
        as the line is drawn after the rectangle.
    """

    line_arr = np.array(
        [pygeos.linestrings(list(zip(line.real, line.imag))) for line in lines]
    )

    for i, line in enumerate(line_arr):
        coords = pygeos.get_coordinates(line)

        if math.hypot(coords[-1, 0] - coords[0, 0], coords[-1, 1] - coords[0, 1]) < tolerance:
            tree = pygeos.STRtree(line_arr[:i])
            p = pygeos.polygons(coords)
            geom_idx = tree.query(p, predicate="intersects")
            line_arr[geom_idx] = pygeos.set_operations.difference(line_arr[geom_idx], p)

    new_lines = LineCollection()
    for geom in line_arr:
        for i in range(pygeos.get_num_geometries(geom)):
            coords = pygeos.get_coordinates(pygeos.get_geometry(geom, i))
            new_lines.append(coords[:, 0] + coords[:, 1] * 1j)

    return new_lines
Пример #15
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]
Пример #16
0
def test_polygon_from_linearring():
    actual = pygeos.polygons(pygeos.linearrings(box_tpl(0, 0, 1, 1)))
    assert str(actual) == "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))"
Пример #17
0
 def setup(self):
     self.points = pygeos.points(np.random.random((100000, 2)))
     self.polygon = pygeos.polygons(np.random.random((3, 2)))
Пример #18
0
 def setup(self):
     self.to_write = pygeos.polygons(np.random.random((10000, 100, 2)))
     self.to_read_wkt = pygeos.to_wkt(self.to_write)
     self.to_read_wkb = pygeos.to_wkb(self.to_write)
Пример #19
0
import numpy as np
import pygeos

point_polygon_testdata = (
    pygeos.points(np.arange(6), np.arange(6)),
    pygeos.box(2, 2, 4, 4),
)
point = pygeos.points(2, 3)
line_string = pygeos.linestrings([(0, 0), (1, 0), (1, 1)])
linear_ring = pygeos.linearrings([(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)])
polygon = pygeos.polygons([(0, 0), (2, 0), (2, 2), (0, 2), (0, 0)])
multi_point = pygeos.multipoints([(0, 0), (1, 2)])
multi_line_string = pygeos.multilinestrings([[(0, 0), (1, 2)]])
multi_polygon = pygeos.multipolygons([
    [(0, 0), (1, 0), (1, 1), (0, 1), (0, 0)],
    [(2.1, 2.1), (2.2, 2.1), (2.2, 2.2), (2.1, 2.2), (2.1, 2.1)],
])
geometry_collection = pygeos.geometrycollections(
    [pygeos.points(51, -1),
     pygeos.linestrings([(52, -1), (49, 2)])])
point_z = pygeos.points(1.0, 1.0, 1.0)
polygon_with_hole = pygeos.Geometry(
    "POLYGON((0 0, 0 10, 10 10, 10 0, 0 0), (2 2, 2 4, 4 4, 4 2, 2 2))")

all_types = (
    point,
    line_string,
    linear_ring,
    polygon,
    multi_point,
    multi_line_string,
Пример #20
0
def test_polygons_invalid_indices(indices):
    with pytest.raises((TypeError, ValueError)):
        pygeos.polygons([linear_ring], [linear_ring], indices=indices)
Пример #21
0
def verify(g, shp, thorough=False):
    #---------------------------------------------------------------------
    logger.info(' Verify grid against coastline\n')
    #---------------------------------------------------------------------

    lon_min = g.Dataset.SCHISM_hgrid_node_x.values.min()
    lon_max = g.Dataset.SCHISM_hgrid_node_x.values.max()
    lat_min = g.Dataset.SCHISM_hgrid_node_y.values.min()
    lat_max = g.Dataset.SCHISM_hgrid_node_y.values.max()

    c = shp.cx[lon_min:lon_max, lat_min:lat_max]

    # ## Test polygons

    d = g.Dataset

    x = d.SCHISM_hgrid_node_x.values
    y = d.SCHISM_hgrid_node_y.values
    tri = d.SCHISM_hgrid_face_nodes.values

    nodes = pd.DataFrame({'lon': x, 'lat': y})

    elems = pd.DataFrame(tri, columns=['a', 'b', 'c'])

    bnodes = g.Dataset[['node', 'id', 'type']].to_dataframe()

    # ### Find the invalid nodes (that cross the coasts)
    cos = pygeos.from_shapely(c.geometry)
    cos_ = pygeos.set_operations.union_all(cos)

    gps = pygeos.points(list(nodes.values))

    gtree = pygeos.STRtree(gps)

    invs = gtree.query(cos_, predicate='contains').tolist()

    #---------------------------------------------------------------------
    logger.info('Number of nodes within the coastlines {}\n'.format(len(invs)))
    #---------------------------------------------------------------------

    nps = len(invs)

    nels = 1

    if thorough:

        # ### Find invalid elements (that cross land)

        # cells to polygons
        ap = nodes.loc[elems.a]
        bp = nodes.loc[elems.b]
        cp = nodes.loc[elems.c]

        elems['ap'] = ap.values.tolist()
        elems['bp'] = bp.values.tolist()
        elems['cp'] = cp.values.tolist()

        n = 2
        al = elems.ap + elems.bp + elems.cp + elems.ap
        coords = [[l[i:i + n] for i in range(0, len(l), n)] for l in al]
        elems['coordinates'] = coords

        jig = pygeos.polygons(coords)

        jtree = pygeos.STRtree(jig)

        jig_ = pygeos.set_operations.union_all(jig)

        cross = pygeos.set_operations.intersection(jig_, cos_)

        # #### convert to dataframe

        fd = pd.DataFrame({'overlap': pygeos.to_wkt(cross)}, index=[0])

        fd['overlap'] = fd['overlap'].apply(shapely.wkt.loads)

        gover = gp.GeoDataFrame(fd, geometry='overlap')

        # #### Reject small injuctions
        ipols = gover.explode().loc[0]

        ipols.columns = ['geometry']

        mask = ipols.area.values == 0.

        ipols = ipols[~mask].reset_index(drop=True)
        ipols = gp.GeoDataFrame(ipols)

        #---------------------------------------------------------------------
        logger.info(
            'Number of elements intersecting the coastlines {}\n'.format(
                ipols.shape[0]))
        #---------------------------------------------------------------------

        nels = ipols.shape[0]

    if nps == 0 and nels == 0:
        #---------------------------------------------------------------------
        logger.info('Grid is verified against the coastline')
        #---------------------------------------------------------------------
        return True
    elif nps == 0:
        #---------------------------------------------------------------------
        logger.info('Grid is node verified against the coastline')
        #---------------------------------------------------------------------
        return True
    else:
        #---------------------------------------------------------------------
        logger.warning('Grid is not verified against the coastline')
        #---------------------------------------------------------------------
        return False
Пример #22
0
def test_2_polygons_with_2_same_holes():
    actual = pygeos.polygons(
        [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)],
        [box_tpl(1, 1, 2, 2), box_tpl(3, 3, 4, 4)],
    )
    assert pygeos.area(actual).tolist() == [98.0, 23.0]
Пример #23
0
def test_2_polygons_with_different_holes():
    actual = pygeos.polygons(
        [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)],
        [[box_tpl(1, 1, 3, 3)], [box_tpl(1, 1, 2, 2)]],
    )
    assert pygeos.area(actual).tolist() == [96.0, 24.0]
Пример #24
0
def test_polygon_with_2_holes():
    actual = pygeos.polygons(
        box_tpl(0, 0, 10, 10), [box_tpl(1, 1, 2, 2), box_tpl(3, 3, 4, 4)]
    )
    assert pygeos.area(actual) == 98.0
Пример #25
0
def test_2_polygons_with_same_hole():
    actual = pygeos.polygons(
        [box_tpl(0, 0, 10, 10), box_tpl(0, 0, 5, 5)], [box_tpl(1, 1, 2, 2)]
    )
    assert pygeos.area(actual).tolist() == [99.0, 24.0]
Пример #26
0
def test_polygon_with_1_hole():
    actual = pygeos.polygons(box_tpl(0, 0, 10, 10), [box_tpl(1, 1, 2, 2)])
    assert pygeos.area(actual) == 99.0
Пример #27
0
def test_polygon_no_hole_list_raises():
    with pytest.raises(ValueError):
        pygeos.polygons(box_tpl(0, 0, 10, 10), box_tpl(1, 1, 2, 2))
Пример #28
0
def test_polygons():
    actual = pygeos.polygons(box_tpl(0, 0, 1, 1))
    assert str(actual) == "POLYGON ((1 0, 1 1, 0 1, 0 0, 1 0))"
Пример #29
0
def test_polygons(holes, indices, expected):
    actual = pygeos.polygons([linear_ring, linear_ring],
                             holes,
                             indices=indices)
    assert_geometries_equal(actual, expected)
Пример #30
0
def test_polygons_missing_shell():
    actual = pygeos.polygons([None, linear_ring], [hole_1, hole_2],
                             indices=[0, 1])
    assert_geometries_equal(actual, [None, poly_hole_2])