def find_plots_intersect_boundingbox(bounding_box: ogr.Geometry, all_plots: dict) -> dict: """Take a list of plots and return only those overlapping bounding box. Arguments: bounding_box: the geometry of the bounding box all_plots: the dictionary of all available plots Return: A dictionary of all intersecting plots """ bb_sr = bounding_box.GetSpatialReference() intersecting_plots = {} logging.debug("[find_plots_intersect_boundingbox] Bounding box %s %s", str(bb_sr), str(bounding_box)) for plot_name in all_plots: current_poly = all_plots[plot_name] # Check for a need to convert coordinate systems check_poly = current_poly if bb_sr: poly_sr = current_poly.GetSpatialReference() if poly_sr and not bb_sr.IsSame(poly_sr): # We need to convert to the same coordinate system before an intersection check_poly = geometries.convert_geometry(current_poly, bb_sr) logging.debug("[find_plots_intersect_boundingbox] Intersection with %s", str(check_poly)) intersection_with_bounding_box = bounding_box.Intersection(check_poly) if intersection_with_bounding_box is not None: intersection = json.loads(intersection_with_bounding_box.ExportToJson()) if 'coordinates' in intersection and len(intersection['coordinates']) > 0: intersecting_plots[str(plot_name)] = current_poly return intersecting_plots
def clip_raster_intersection(file_path: str, file_bounds: ogr.Geometry, plot_bounds: ogr.Geometry, out_file: str) ->\ Optional[int]: """Clips the raster to the intersection of the file bounds and plot bounds Arguments: file_path: the path to the source file file_bounds: the geometric boundary of the source file plot_bounds: the geometric boundary of the plot to clip to out_file: the path to store the clipped image Return: The number of pixels in the new image, or None if no pixels were saved Notes: Assumes the boundaries are in the same coordinate system Exceptions: Raises RuntimeError if the polygons are invalid """ logging.debug("Clip to intersect of plot boundary: File: '%s' '%s' Plot: '%s'", file_path, str(file_bounds), str(plot_bounds)) try: if not file_bounds or not plot_bounds: logging.error("Invalid polygon specified for clip_raster_intersection: File: '%s' plot: '%s'", str(file_bounds), str(plot_bounds)) raise RuntimeError("One or more invalid polygons specified when clipping raster") intersection = file_bounds.Intersection(plot_bounds) if not intersection or not intersection.Area(): logging.info("File does not intersect plot boundary: %s", file_path) return None # Make sure we pass a multipolygon down to the tuple converter if intersection.GetGeometryName().startswith('MULTI'): multi_polygon = intersection else: multi_polygon = ogr.Geometry(ogr.wkbMultiPolygon) multi_polygon.AddGeometry(intersection) # Proceed to clip to the intersection tuples = geometries.geometry_to_tuples(multi_polygon) return clip_raster(file_path, tuples, out_path=out_file, compress=True) except Exception as ex: logging.exception("Exception caught while clipping image to plot intersection") raise ex
def calculate_overlap_percent(check_bounds: ogr.Geometry, other_bounds: ogr.Geometry) -> float: """Calculates and returns the percentage overlap between the two boundaries. The calculation determines the overlap shape between the two parameters and then calculates the percentage by dividing the overlap area by the checking bounds area, and returns that value. Args: check_bounds: geometry of boundary to check other_bounds: geometry of boundary to check against Return: The calculated overlap percent (0.0 - 1.0) or 0.0 if there is no overlap. If an exception is detected, a warning message is logged and 0.0 is returned. """ try: if check_bounds and other_bounds: intersection = other_bounds.Intersection(check_bounds) if intersection: return intersection.Area() / check_bounds.Area() except Exception as ex: logging.warning("Exception caught while calculating shape overlap: %s", str(ex)) return 0.0