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
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
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
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)