コード例 #1
0
def test_set_operation_prec_array(a, func, grid_size):
    actual = func([a, a], point, grid_size=grid_size)
    assert actual.shape == (2, )
    assert isinstance(actual[0], Geometry)

    # results should match the operation when the precision is previously set
    # to same grid_size
    b = pygeos.set_precision(a, grid_size=grid_size)
    point2 = pygeos.set_precision(point, grid_size=grid_size)
    expected = func([b, b], point2)

    assert pygeos.equals(pygeos.normalize(actual),
                         pygeos.normalize(expected)).all()
コード例 #2
0
ファイル: test_geometry.py プロジェクト: brendan-ward/pygeos
def test_set_precision_intersection():
    """Operations should use the most precise presision grid size of the inputs"""

    box1 = pygeos.normalize(pygeos.box(0, 0, 0.9, 0.9))
    box2 = pygeos.normalize(pygeos.box(0.75, 0, 1.75, 0.75))

    assert pygeos.get_precision(pygeos.intersection(box1, box2)) == 0

    # GEOS will use and keep the most precise precision grid size
    box1 = pygeos.set_precision(box1, 0.5)
    box2 = pygeos.set_precision(box2, 1)
    out = pygeos.intersection(box1, box2)
    assert pygeos.get_precision(out) == 0.5
    assert pygeos.equals(out, pygeos.Geometry("LINESTRING (1 1, 1 0)"))
コード例 #3
0
ファイル: _vectorized.py プロジェクト: Imanflow/geopandas
def normalize(data):
    if compat.USE_PYGEOS:
        return pygeos.normalize(data)
    else:
        out = np.empty(len(data), dtype=object)
        with compat.ignore_shapely2_warnings():
            out[:] = [
                _shapely_normalize(geom) if geom is not None else None for geom in data
            ]
        return out
コード例 #4
0
def to_dict(geometry):
    """Convert pygeos Geometry object to a dictionary representation.
    Equivalent to structure of GeoJSON.

    Parameters
    ----------
    geometry : pygeos Geometry object (singular)

    Returns
    -------
    dict
        GeoJSON dict representation of geometry
    """
    geometry = pg.normalize(geometry)

    def get_ring_coords(polygon):
        # outer ring must be reversed to be counterclockwise[::-1]
        coords = [pg.get_coordinates(pg.get_exterior_ring(polygon)).tolist()]
        for i in range(pg.get_num_interior_rings(polygon)):
            # inner rings must be reversed to be clockwise[::-1]
            coords.append(
                pg.get_coordinates(pg.get_interior_ring(polygon, i)).tolist())

        return coords

    geom_type = GEOJSON_TYPE[pg.get_type_id(geometry)]
    coords = []

    if geom_type == "MultiPolygon":
        coords = []
        geoms = pg.get_geometry(geometry,
                                range(pg.get_num_geometries(geometry)))
        for geom in geoms:
            coords.append(get_ring_coords(geom))

    elif geom_type == "Polygon":
        coords = get_ring_coords(geometry)

    else:
        raise NotImplementedError("Not built")

    return {"type": geom_type, "coordinates": coords}
コード例 #5
0
def constructive(arr, operation, *args, **kwargs):
    if operation == 'boundary':
        geometries = pg.boundary(pg.from_wkb(arr), **kwargs)
    elif operation == 'buffer':
        geometries = pg.buffer(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'build_area':
        geometries = pg.build_area(pg.from_wkb(arr), **kwargs)
    elif operation == 'centroid':
        geometries = pg.centroid(pg.from_wkb(arr), **kwargs)
    elif operation == 'clip_by_rect':
        geometries = pg.clip_by_rect(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'convex_hull':
        geometries = pg.convex_hull(pg.from_wkb(arr), **kwargs)
    elif operation == 'delaunay_triangles':
        geometries = pg.delaunay_triangles(pg.from_wkb(arr), **kwargs)
    elif operation == 'envelope':
        geometries = pg.envelope(pg.from_wkb(arr), **kwargs)
    elif operation == 'extract_unique_points':
        geometries = pg.extract_unique_points(pg.from_wkb(arr), **kwargs)
    elif operation == 'make_valid':
        geometries = pg.make_valid(pg.from_wkb(arr), **kwargs)
    elif operation == 'normalize':
        geometries = pg.normalize(pg.from_wkb(arr), **kwargs)
    elif operation == 'offset_curve':
        geometries = pg.offset_curve(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'point_on_surface':
        geometries = pg.point_on_surface(pg.from_wkb(arr), **kwargs)
    elif operation == 'reverse':
        geometries = pg.reverse(pg.from_wkb(arr), **kwargs)
    elif operation == 'simplify':
        geometries = pg.simplify(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'snap':
        geometries = pg.snap(pg.from_wkb(arr), *args, **kwargs)
    elif operation == 'voronoi_polygons':
        geometries = pg.voronoi_polygons(pg.from_wkb(arr), **kwargs)
    else:
        warnings.warn(f'Operation {operation} not supported.')
        return None
    return pg.to_wkb(geometries)
コード例 #6
0
def find_dam_face_from_waterbody(waterbody, drain_pt):
    total_area = pg.area(waterbody)
    ring = pg.get_exterior_ring(pg.normalize(waterbody))
    total_length = pg.length(ring)
    num_pts = pg.get_num_points(ring) - 1  # drop closing coordinate
    vertices = pg.get_point(ring, range(num_pts))

    ### Extract line segments that are no more than 1/3 coordinates of polygon
    # starting from the vertex nearest the drain
    # note: lower numbers are to the right
    tree = pg.STRtree(vertices)
    ix = tree.nearest(drain_pt)[1][0]
    side_width = min(num_pts // 3, MAX_SIDE_PTS)
    left_ix = ix + side_width
    right_ix = ix - side_width

    # extract these as a left-to-write line;
    pts = vertices[max(right_ix, 0):min(num_pts, left_ix)][::-1]
    if left_ix >= num_pts:
        pts = np.append(vertices[0:left_ix - num_pts][::-1], pts)

    if right_ix < 0:
        pts = np.append(pts, vertices[num_pts + right_ix:num_pts][::-1])

    coords = pg.get_coordinates(pts)

    if len(coords) > 2:
        # first run a simplification process to extract the major shape and bends
        # then run the straight line algorithm
        simp_coords, simp_ix = simplify_vw(
            coords, min(MAX_SIMPLIFY_AREA, total_area / 100))

        if len(simp_coords) > 2:
            keep_coords, ix = extract_straight_segments(
                simp_coords, max_angle=MAX_STRAIGHT_ANGLE, loops=5)
            keep_ix = simp_ix.take(ix)

        else:
            keep_coords = simp_coords
            keep_ix = simp_ix

    else:
        keep_coords = coords
        keep_ix = np.arange(len(coords))

    ### Calculate the length of each run and drop any that are not sufficiently long
    lengths = segment_length(keep_coords)
    ix = (lengths >= MIN_DAM_WIDTH) & (lengths / total_length <
                                       MAX_WIDTH_RATIO)

    pairs = np.dstack([keep_ix[:-1][ix], keep_ix[1:][ix]])[0]

    # since ranges are ragged, we have to do this in a loop instead of vectorized
    segments = []
    for start, end in pairs:
        segments.append(pg.linestrings(coords[start:end + 1]))

    segments = np.array(segments)

    # only keep the segments that are close to the drain
    segments = segments[
        pg.intersects(segments, pg.buffer(drain_pt, MAX_DRAIN_DIST)), ]

    if not len(segments):
        return segments

    # only keep those where the drain is interior to the line
    pos = pg.line_locate_point(segments, drain_pt)
    lengths = pg.length(segments)

    ix = (pos >= MIN_INTERIOR_DIST) & (pos <= (lengths - MIN_INTERIOR_DIST))

    return segments[ix]
コード例 #7
0
def test_normalize(geom, expected):
    actual = pygeos.normalize(geom)
    assert actual == expected
コード例 #8
0
def test_make_valid_1d(geom, expected):
    actual = pygeos.make_valid(geom)
    # normalize needed to handle variation in output across GEOS versions
    assert np.all(pygeos.normalize(actual) == pygeos.normalize(expected))
コード例 #9
0
def test_make_valid(geom, expected):
    actual = pygeos.make_valid(geom)
    assert actual is not expected
    # normalize needed to handle variation in output across GEOS versions
    assert pygeos.normalize(actual) == expected
コード例 #10
0
bnd_df.to_feather(out_dir / "region_boundary.feather")

bnd = bnd_df.geometry.values.data[0]
sarp_bnd = bnd_df.loc[bnd_df.id == "se"].geometry.values.data[0]

bnd_geo = bnd_df.to_crs(GEO_CRS)
bnd_geo["bbox"] = pg.bounds(bnd_geo.geometry.values.data).round(2).tolist()

# used to render maps
with open(ui_dir / "region_bounds.json", "w") as out:
    out.write(bnd_geo[["id", "bbox"]].to_json(orient="records"))

# create mask
world = pg.box(-180, -85, 180, 85)
bnd_mask = bnd_geo.copy()
bnd_mask["geometry"] = pg.normalize(
    pg.difference(world, bnd_mask.geometry.values.data))
write_dataframe(bnd_mask, out_dir / "region_mask.gpkg")

### Extract HUC4 units that intersect boundaries

print("Extracting HUC2...")
# First determine the HUC2s that overlap the region
huc2_df = (read_dataframe(
    wbd_gdb, layer="WBDHU2",
    columns=["huc2"]).to_crs(CRS).rename(columns={"huc2": "HUC2"}))

tree = pg.STRtree(huc2_df.geometry.values.data)

# First extract SARP HUC2
sarp_ix = tree.query(sarp_bnd, predicate="intersects")
sarp_huc2_df = huc2_df.iloc[sarp_ix].reset_index(drop=True)
コード例 #11
0
bnd_df = gp.GeoDataFrame(
    geometry=[pg.union_all(pg.make_valid(bnd_df.geometry.values.data))],
    index=[0],
    crs=bnd_df.crs,
)
bnd_df.to_feather(out_dir / "se_boundary.feather")
write_dataframe(bnd_df, data_dir / "boundaries/se_boundary.fgb")

# create GeoJSON for tiling
bnd_geo = bnd_df.to_crs(GEO_CRS)
write_dataframe(bnd_geo, tile_dir / "se_boundary.geojson", driver="GeoJSONSeq")

### Create mask by cutting SA bounds out of world bounds
print("Creating mask...")
world = pg.box(-180, -85, 180, 85)
mask = pg.normalize(pg.difference(world, bnd_geo.geometry.values.data))

write_dataframe(
    gp.GeoDataFrame({"geometry": mask}, index=[0], crs=GEO_CRS),
    tile_dir / "se_mask.geojson",
    driver="GeoJSONSeq",
)

### Extract counties within SA bounds
print("Extracting states and counties...")
states = (read_dataframe(
    src_dir / "boundaries/tl_2019_us_state.shp",
    read_geometry=False,
    columns=["STATEFP", "NAME"],
).rename(columns={
    "NAME": "state"
コード例 #12
0
data_dir = Path("data")
out_dir = data_dir / "inputs/boundaries"  # used as inputs for other steps
tile_dir = data_dir / "for_tiles"

sa_df = read_dataframe(src_dir / "boundaries/SABlueprint2020_Extent.shp")

### Create mask by cutting SA bounds out of world bounds
print("Creating mask...")
world = pg.box(-180, -85, 180, 85)

# boundary has self-intersections and 4 geometries, need to clean up

bnd = pg.union_all(pg.make_valid(sa_df.geometry.values.data))
bnd_geo = pg.union_all(
    pg.make_valid(sa_df.to_crs(GEO_CRS).geometry.values.data))
mask = pg.normalize(pg.difference(world, bnd_geo))

gp.GeoDataFrame(geometry=[bnd],
                crs=DATA_CRS).to_feather(out_dir / "sa_boundary.feather")

write_dataframe(
    gp.GeoDataFrame({"geometry": bnd_geo}, index=[0], crs=GEO_CRS),
    tile_dir / "sa_boundary.geojson",
    driver="GeoJSONSeq",
)

write_dataframe(
    gp.GeoDataFrame({"geometry": mask}, index=[0], crs=GEO_CRS),
    tile_dir / "sa_mask.geojson",
    driver="GeoJSONSeq",
)