From 837de4c956465b78207994fb71339dd50d85c0a4 Mon Sep 17 00:00:00 2001 From: Joachim Ungar Date: Mon, 4 Nov 2024 09:20:21 +0100 Subject: [PATCH] make check for known CRSes to determine their bounds more solid; fix code smells --- mapchete/geometry/reproject.py | 78 +++++++++++++++++---------------- mapchete/geometry/segmentize.py | 2 +- 2 files changed, 42 insertions(+), 38 deletions(-) diff --git a/mapchete/geometry/reproject.py b/mapchete/geometry/reproject.py index cb830e18..6665564f 100644 --- a/mapchete/geometry/reproject.py +++ b/mapchete/geometry/reproject.py @@ -8,12 +8,19 @@ from shapely.geometry import mapping, shape from mapchete.bounds import Bounds -from mapchete.errors import GeometryTypeError, ReprojectionFailed +from mapchete.errors import ReprojectionFailed from mapchete.geometry.latlon import LATLON_CRS from mapchete.geometry.repair import repair from mapchete.geometry.segmentize import get_segmentize_value, segmentize_geometry from mapchete.geometry.shape import to_shape -from mapchete.types import Geometry, GeometryLike +from mapchete.types import ( + Geometry, + GeometryLike, + Polygon, + LinearRing, + LineString, + MultiPolygon, +) from mapchete.types import CRSLike from mapchete.validate import validate_crs @@ -22,24 +29,23 @@ CRS_BOUNDS = { # http://spatialreference.org/ref/epsg/wgs-84/ - "epsg:4326": Bounds(-180.0, -90.0, 180.0, 90.0), + CRS.from_epsg(4326): Bounds(-180.0, -90.0, 180.0, 90.0), # unknown source - "epsg:3857": Bounds(-180.0, -85.0511, 180.0, 85.0511), + CRS.from_epsg(3857): Bounds(-180.0, -85.0511, 180.0, 85.0511), # http://spatialreference.org/ref/epsg/3035/ - "epsg:3035": Bounds(-10.6700, 34.5000, 31.5500, 71.0500), + CRS.from_epsg(3035): Bounds(-10.6700, 34.5000, 31.5500, 71.0500), } def get_crs_bounds(crs: CRS) -> Bounds: - if crs.is_epsg_code: - try: - # get bounds from known CRSes - return CRS_BOUNDS[crs.get("init")] - except KeyError: - # try to get bounds using pyproj - area_of_use = pyproj.CRS(crs.to_epsg()).area_of_use - if area_of_use: - return Bounds.from_inp(area_of_use.bounds) + try: + # get bounds from known CRSes + return CRS_BOUNDS[crs] + except KeyError: + # try to get bounds using pyproj + area_of_use = pyproj.CRS(crs.to_epsg()).area_of_use + if area_of_use: + return Bounds.from_inp(area_of_use.bounds) raise ValueError(f"bounds of CRS {crs} could not be determined") @@ -127,14 +133,13 @@ def reproject_geometry( # segmentize clipped geometry using one 100th of with or height depending on # which is shorter - if segmentize_on_clip or segmentize: - try: - clipped_latlon = segmentize_geometry( - clipped_latlon, - get_segmentize_value(clipped_latlon, segmentize_fraction), - ) - except GeometryTypeError: - pass + if (segmentize_on_clip or segmentize) and isinstance( + clipped_latlon, (Polygon, LinearRing, LineString, MultiPolygon) + ): + clipped_latlon = segmentize_geometry( + clipped_latlon, + get_segmentize_value(clipped_latlon, segmentize_fraction), + ) # clip geometry dst_crs boundaries and return return _reproject_geom( @@ -148,21 +153,20 @@ def reproject_geometry( # return without clipping if destination CRS does not have defined bounds try: - if segmentize: - try: - return _reproject_geom( - segmentize_geometry( - geometry, - get_segmentize_value(geometry, segmentize_fraction), - ), - src_crs, - dst_crs, - validity_check, - antimeridian_cutting, - fiona_env, - ) - except GeometryTypeError: - pass + if segmentize and isinstance( + geometry, (Polygon, LinearRing, LineString, MultiPolygon) + ): + return _reproject_geom( + segmentize_geometry( + geometry, + get_segmentize_value(geometry, segmentize_fraction), + ), + src_crs, + dst_crs, + validity_check, + antimeridian_cutting, + fiona_env, + ) return _reproject_geom( geometry, src_crs, diff --git a/mapchete/geometry/segmentize.py b/mapchete/geometry/segmentize.py index 334c303d..13ae7c0d 100644 --- a/mapchete/geometry/segmentize.py +++ b/mapchete/geometry/segmentize.py @@ -61,5 +61,5 @@ def coords_segmentize(coords: CoordArrays, segmentize_value: float) -> CoordArra def get_segmentize_value(geometry: Geometry, segmentize_fraction: float) -> float: """Divide the smaller one of geometry height or width by segmentize fraction.""" - bounds = Bounds.from_inp(geometry, strict=False) + bounds = Bounds.from_inp(geometry.bounds, strict=False) return min([bounds.height, bounds.width]) / segmentize_fraction