diff --git a/SearchAPI/CMR/Translate/translate_params.py b/SearchAPI/CMR/Translate/translate_params.py index 660d59e7..2e1906b3 100644 --- a/SearchAPI/CMR/Translate/translate_params.py +++ b/SearchAPI/CMR/Translate/translate_params.py @@ -6,6 +6,9 @@ import requests from SearchAPI.asf_env import get_config +from shapely import wkt +from shapely.geometry import Polygon +from shapely.geometry.base import BaseGeometry def translate_params(p): """ Translate supported params into CMR params @@ -28,6 +31,14 @@ def translate_params(p): if 'errors' in response: raise ValueError(f'Could not repair WKT: {val}') val = response['wkt']['wrapped'] + shape = wkt.loads(response['wkt']['unwrapped']) + if _should_use_bbox(shape): + bbox = _get_bbox(shape) + try: + params['bbox'] = input_map()['bbox'][2](bbox) + continue + except ValueError as exc: + raise ValueError(f'{key}: {exc}') from exc try: params[key] = input_map()[key][2](val) except ValueError as exc: @@ -52,3 +63,35 @@ def translate_params(p): del params['maxresults'] return params, output, max_results + +def _get_bbox(aoi: BaseGeometry): + # If a wide rectangle is provided, make sure to use the bounding box + # instead of the wkt for better responses from CMR + # This will provide better results with AOI's near poles + bounds = aoi.boundary.bounds + if bounds[0] > 180 or bounds[2] > 180: + bounds = [(x + 180) % 360 - 180 if idx % 2 == 0 and abs(x) > 180 else x for idx, x in enumerate(bounds)] + + bottom_left = [str(coord) for coord in bounds[:2]] + top_right = [str(coord) for coord in bounds[2:]] + + bbox = ','.join([*bottom_left, *top_right]) + return bbox + + +def _should_use_bbox(shape: BaseGeometry): + """ + If the passed shape is a polygon, and if that polygon + is equivalent to it's bounding box (if it's a rectangle), + we should use the bounding box to search instead + """ + if isinstance(shape, Polygon): + coords = [ + [shape.bounds[0], shape.bounds[1]], + [shape.bounds[2], shape.bounds[1]], + [shape.bounds[2], shape.bounds[3]], + [shape.bounds[0], shape.bounds[3]], + ] + return shape.equals(Polygon(shell=coords)) + + return False \ No newline at end of file