Esempio n. 1
0
def _get_intersect_tiles(target: GeoDataFrame, tiles: GeoDataFrame, limit=0.001):
    """
    Find all tiles that intersects given region with area >= limit km2 using R-tree indexing
        Parameters
        ----------
        target: GeoDataFrame
            Input Polygon
        tiles: GeoDataFrame
            Tiles (Sentinel2)
        limit: float
            min considered tile area in km2
        Returns
        -------
        GeoDataFrame
            Precised intersect tiles for given Polygon
    """

    # Get the indices of the tiles that are likely to be inside the bounding box of the given Polygon
    geometry = target.geometry[0]
    tiles_indexes = list(tiles.sindex.intersection(geometry.bounds))
    tiles = tiles.loc[tiles_indexes]
    # Make the precise tiles in Polygon query
    tiles = tiles.loc[tiles.intersects(geometry)]
    # change geometry and calculate intersection area
    code = _get_epsg_code(geometry.centroid.x, geometry.centroid.y)
    epsg = f"epsg:{code}"
    target['geometry'] = target.geometry.to_crs({'init': epsg})
    tiles['geometry'] = tiles.geometry.to_crs({'init': epsg})
    tiles['area'] = tiles.geometry.apply(lambda g: g.intersection(target.geometry[0]).area / 1e6)
    tiles = tiles.loc[tiles['area'] > limit]
    tiles = tiles.sort_values(by=['area', 'Name'], ascending=[False, True])
    return tiles, epsg
Esempio n. 2
0
def intersect_grid_orbit_single_utm_zone(
        group_gdf: gpd.GeoDataFrame,
        orbit_gdf: gpd.GeoDataFrame,
        utm_zone: int,
        utm_north: bool,
        filter_orbits_df: Optional[pd.DataFrame] = None) -> gpd.GeoDataFrame:

    # Use bounds of gdf instead of a naive UTM bbox because there are some
    # exceptions to the 6 deg width rule, especially around Norway and Svalbard.
    # The MGRS grid follows these exceptions.
    bbox = box(*group_gdf.total_bounds)

    # Keep orbits that intersect this bbox
    local_utm_orbits = orbit_gdf[orbit_gdf.intersects(bbox)]

    # Intersect with bbox. Since this is a global bbox, it's ok for this to be
    # in WGS84.
    local_utm_orbits = local_utm_orbits.set_geometry(
        local_utm_orbits.geometry.intersection(bbox))

    # Reproject to UTM zone
    epsg_code = get_utm_epsg(utm_zone, utm_north)
    local_grid = group_gdf.to_crs(epsg=epsg_code)
    local_utm_orbits = local_utm_orbits.to_crs(epsg=epsg_code)

    # Get swath for each orbit. The swath is 290km, or 145km on each side.
    # cap_style=3 makes a square cap instead of the default round cap.
    local_utm_swaths = local_utm_orbits.set_geometry(
        local_utm_orbits.buffer(145_000, cap_style=3))
def find_child_land_tiles(tile: mercantile.Tile, gdf: gpd.GeoDataFrame,
                          maxzoom: int) -> List[mercantile.Tile]:
    """Recursively find tiles at desired zoom that intersect land areas

    Args:
        - tile: tile to recursively search within
        - gdf: GeoDataFrame with geometries of land masses
        - maxzoom: zoom at which to stop recursing

    Returns:
        List of tiles intersecting land
    """
    land_tiles = []

    for child in mercantile.children(tile):
        tile_geom = shape(mercantile.feature(tile)['geometry'])

        intersects_land = gdf.intersects(tile_geom).any()

        if not intersects_land:
            continue

        if child.z == maxzoom:
            land_tiles.append(child)
            continue

        land_tiles.extend(find_child_land_tiles(child, gdf, maxzoom))

    return land_tiles
Esempio n. 4
0
def _generate_point_array_override(
        mp_array: Iterable[Point], route_shape: LineString,
        existing_graph_nodes: gpd.GeoDataFrame,
        stop_distance_distribution: float) -> Iterable[Point]:
    # TODO: Better parameterize the factor used with the distance distribution
    # Figure that we give a 10% "give" - this is, if a stop is within
    # 10% of the target segment distance, then it should be re-assigned
    # to that stop
    reasonable_distance = 0.5 * stop_distance_distribution

    # TODO: Better parameterize the buffer distance setting here
    # Find the nearby stops for the target line from those available
    buffer_distance = 10  # meters
    buffered = route_shape.buffer(buffer_distance)

    try:
        # Use spatial index if available
        egn_sindex = existing_graph_nodes.sindex
        possibles = list(egn_sindex.intersection(route_shape.bounds))
        existing_graph_nodes_sub = existing_graph_nodes.iloc[possibles]
        intersects_mask = existing_graph_nodes_sub.intersects(buffered)
        intersecting_stops_gdf = existing_graph_nodes_sub[intersects_mask]

    except Exception:
        # Otherwise skip the spatial index and just intersect
        # against all geometries in the GeoDataFrame
        intersects_mask = existing_graph_nodes.intersects(buffered)
        intersecting_stops_gdf = existing_graph_nodes[intersects_mask]

    # If we encounter a situation where there are no nearby nodes, bail
    # early and just retyurn the original input array
    if len(intersecting_stops_gdf) == 0:
        return mp_array

    # TODO: Right now we only consider the stops as points (shapes),
    #       but in the future should aim to reuse graph nodes that are
    #       the same location by passing along the node id
    intersecting_stops = intersecting_stops_gdf['geometry'].values

    mp_array_override = []
    for pt in mp_array:
        # TODO: This is can be super slow, is there a potentially
        #       faster path or is the fact that this is only a subset
        #       of all stop nodes mean that the number of points being
        #       evaluated is acceptably small?
        dists = intersecting_stops_gdf.distance(pt).values

        # Skip if the closest existing stop is still too far away
        if dists.min() > reasonable_distance:
            mp_array_override.append(pt)
            continue

        # TODO: This mask operation is slow - is there a faster way?
        dists_mask = dists <= dists.min()
        sub_g_nodes = intersecting_stops[dists_mask]

        # Handle edge cases where matches are not captured
        if len(sub_g_nodes) == 0:
            mp_array_override.append(pt)
            continue

        # Otherwise, we should pass the first nearest stop node
        # as the new stop location
        first_nearest = sub_g_nodes[0]

        # But still make sure that it is on the line because
        # we need to use the points to break up the line and get the
        # segment distances in the next step
        adj_projected = route_shape.project(first_nearest)
        adjusted_nearest = route_shape.interpolate(adj_projected,
                                                   normalized=True)
        mp_array_override.append(adjusted_nearest)

    return mp_array_override
Esempio n. 5
0
    pnp2.load_frames(uvan_frames)

    img_meta.longitude = np.rad2deg(img_meta.longitude)
    img_meta.latitude = np.rad2deg(img_meta.latitude)

    # Get Athens Images
    gjson = fiona.open('/Volumes/Samsung USB/ips/athens_bounds.geojson')
    athens_bounds = sg.box(*gjson.bounds)

    geometry = [
        sp(x, y) for x, y in zip(img_meta.longitude, img_meta.latitude)
    ]
    img_geo_df = GeoDataFrame(img_meta,
                              geometry=geometry,
                              crs=ccrs.PlateCarree())
    athens_imgs = img_geo_df[img_geo_df.intersects(athens_bounds)]
    athens_imgs.reset_index(inplace=True, drop=True)

    pnp_out = []
    opairs = []

    for ii, kp_row in img_meta.iterrows():
        print(ii)
        lon_lat_h = np.array(
            [kp_row.longitude, kp_row.latitude, kp_row.altitude])
        rpy = kp_row[['roll', 'pitch', 'yaw']]
        att = pnputils.rpy_to_cnb(*rpy, units='rad')

        tile = tf.find_tile_from_pose(lon_lat_h, att)
        # tile = mercantile.tile(kp_row.longitude, kp_row.latitude, 15)
        pnp2.set_db_location_from_tiles([tile], N=10000)