From a2d9e75c731a1c63f57bf4da1acc651d07ddb66f Mon Sep 17 00:00:00 2001 From: Wouter Date: Thu, 15 Feb 2024 15:07:40 +0100 Subject: [PATCH 1/3] Descriptions openapi spec (#135) * update description openapi spec * updated example by removing weird rounding digit length * Small update regarding description and example in the OAS spec --- .../assets/openapi.yaml | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/src/coordinate_transformation_api/assets/openapi.yaml b/src/coordinate_transformation_api/assets/openapi.yaml index 6458987..e94dca8 100644 --- a/src/coordinate_transformation_api/assets/openapi.yaml +++ b/src/coordinate_transformation_api/assets/openapi.yaml @@ -150,7 +150,7 @@ paths: on geodesic (ellipsoidal great-circle) distance on the ellipsoid of the (base) CRS description: | - Check density of polygon and linestring geometries. Returns a `DensityCheckReport` containing a FeatureCollection containing all line segments exceeding the `maxSegmentLength/Deviation` (if any). + Check density of polygon and linestring geometries. Returns a `DensityCheckReport` containing a FeatureCollection containing all line segments exceeding the maximum segment length 'maxSegmentLength' or maximum segment deviation `maxSegmentDeviation`. parameters: - $ref: "#/components/parameters/sourceCrs" - $ref: "#/components/parameters/contentCrs" @@ -192,10 +192,10 @@ paths: geometry: type: LineString coordinates: - - - 156264.906359842570964 - - 601302.588919493253343 - - - 165681.964475793502061 - - 605544.313164469087496 + - - 156264.9063 + - 601302.5889 + - - 165681.9644 + - 605544.3131 responses: "200": description: OK @@ -208,7 +208,8 @@ paths: api-version: $ref: "#/components/headers/api-version" content-crs: - description: FOOBAR + description: + Coordinate reference system (CRS) of the input coordinates $ref: "#/components/headers/content-crs" "400": $ref: "#/components/responses/400" @@ -226,11 +227,13 @@ paths: (base) CRS description: > A POST endpoint that accepts a GeoJSON object and densifies the - geometries using the `max-segment-length` threshold. + geometries using the maximum segment length 'maxSegmentLength' or + maximum segment deviation `maxSegmentDeviation` threshold. parameters: - $ref: "#/components/parameters/sourceCrs" - $ref: "#/components/parameters/contentCrs" - $ref: "#/components/parameters/maxSegmentLength" + - $ref: "#/components/parameters/maxSegmentDeviation" requestBody: required: true @@ -261,10 +264,10 @@ paths: geometry: type: LineString coordinates: - - - 156264.90635984257 - - 601302.5889194933 - - - 165681.9644757935 - - 605544.3131644691 + - - 156264.9063 + - 601302.5889 + - - 165681.9644 + - 605544.3131 responses: "200": description: OK @@ -272,7 +275,6 @@ paths: application/json: schema: $ref: https://geojson.org/schema/FeatureCollection.json - description: FOOBAR example: type: FeatureCollection name: lijnen @@ -286,10 +288,10 @@ paths: geometry: type: LineString coordinates: - - - 156264.906359842570964 - - 601302.588919493253343 - - - 165681.964475793502061 - - 605544.313164469087496 + - - 156264.9063 + - 601302.5889 + - - 165681.9644 + - 605544.3131 headers: api-version: $ref: "#/components/headers/api-version" @@ -752,7 +754,7 @@ components: - - 165681.9645 - 605544.3131 properties: - segment_length: 10327.966539495786 + segment_length: 10327.9665 id: null crs: properties: @@ -839,7 +841,8 @@ components: schema: $ref: "#/components/schemas/Epoch" maxSegmentDeviation: - description: Maximum segment deviation for densify and density-check + description: + Maximum segment deviation in metres for densify and density-check in: query name: max-segment-deviation required: false @@ -847,7 +850,8 @@ components: type: number minimum: 0.001 maxSegmentLength: - description: Maximum segment length for densify and density-check + description: + Maximum segment length in metres for densify and density-check in: query name: max-segment-length required: false @@ -857,7 +861,7 @@ components: minimum: 200 sourceCrs: description: | - Source Coordinate Reference System (CRS) + Source coordinate reference system (CRS) in: query name: source-crs example: EPSG:7415 @@ -865,7 +869,7 @@ components: schema: $ref: "#/components/schemas/CrsEnum" targetCrs: - description: Target Coordinate Reference System (CRS) + description: Target coordinate reference system (CRS) in: query name: target-crs required: false @@ -900,7 +904,7 @@ components: api-version: $ref: "#/components/headers/api-version" "404Crs": - description: CRS Not Found. + description: Coordinate reference system (CRS) Not Found. content: application/problem+json: schema: @@ -1056,7 +1060,7 @@ components: - 605544.3131 type: LineString properties: - segment_length: 10327.966539495786 + segment_length: 10327.9665 type: Feature name: failed-line-segments type: FeatureCollection @@ -1135,14 +1139,14 @@ components: properties: description: example: | - Landing page of the Coordinatetransformation API + Landing page of the Coordinate Transformation API type: string links: items: $ref: "#/components/schemas/Link" type: array title: - example: Coordinatetransformation API + example: Coordinate Transformation API type: string required: - links From 796953c83457b69a828e2b3568286b6e194d16c9 Mon Sep 17 00:00:00 2001 From: Wouter Date: Thu, 15 Feb 2024 15:16:15 +0100 Subject: [PATCH 2/3] Correct transformation inputs (#136) * remove stripping of input values before the transformation, so all the original values are used * added specific test case for EPSG:7415 -> EPSG:32631 with or without epoch --- .../crs_transform.py | 2 +- tests/data/test_wgs_epoch.json | 8 +++ tests/test_geojson_transformation.py | 57 +++++++++++++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 tests/data/test_wgs_epoch.json diff --git a/src/coordinate_transformation_api/crs_transform.py b/src/coordinate_transformation_api/crs_transform.py index 74d2403..b532f0e 100644 --- a/src/coordinate_transformation_api/crs_transform.py +++ b/src/coordinate_transformation_api/crs_transform.py @@ -406,7 +406,7 @@ def transform_crs(val: CoordinatesType) -> tuple[float, ...]: ): # check so we can safely cast to tuple[float, float], tuple[float, float, float] raise ValueError(f"dimension of target-crs should be 2 or 3, is {dim}") - val = cast(tuple[float, float] | tuple[float, float, float], val[0:dim]) + val = cast(tuple[float, float] | tuple[float, float, float], val) # TODO: fix epoch handling, should only be added in certain cases # when one of the src or tgt crs has a dynamic time component diff --git a/tests/data/test_wgs_epoch.json b/tests/data/test_wgs_epoch.json new file mode 100644 index 0000000..a8c0121 --- /dev/null +++ b/tests/data/test_wgs_epoch.json @@ -0,0 +1,8 @@ +{ + "type": "Feature", + "properties": {}, + "geometry": { + "type": "Point", + "coordinates": [155000, 463000, 0] + } +} diff --git a/tests/test_geojson_transformation.py b/tests/test_geojson_transformation.py index 43351c6..a279a04 100644 --- a/tests/test_geojson_transformation.py +++ b/tests/test_geojson_transformation.py @@ -1,4 +1,5 @@ import json +import math from contextlib import nullcontext as does_not_raise import pytest @@ -159,3 +160,59 @@ def test_validate_crs_transformed_geojson(feature): crs_transform(feature_no_exc, "EPSG:28992", "EPSG:4326") with does_not_raise(): validate_crs_transformed_geojson(feature_no_exc) + + +def test_wgs_epoch(): + with open("tests/data/test_wgs_epoch.json") as f: + data = json.load(f) + feature_2024 = Feature(**data) + feature_2010 = Feature(**data) + feature_epoch_none = Feature(**data) + + crs_transform(feature_2024, "EPSG:28992", "EPSG:32631", 2024) + crs_transform(feature_2010, "EPSG:28992", "EPSG:32631", 2010) + crs_transform(feature_epoch_none, "EPSG:28992", "EPSG:32631") + + assert feature_2024 != feature_2010 + assert feature_2010 != feature_epoch_none + assert feature_epoch_none != feature_2024 + + coords_2024 = feature_2024.geometry.coordinates + coords_2010 = feature_2010.geometry.coordinates + coords_epoch_none = feature_epoch_none.geometry.coordinates + + dif_2024_2010 = 0.34 + dif_2024_epoch_none = 0.86 + + assert ( + round( + math.sqrt( + ( + (coords_2024[0] - coords_2010[0]) + * (coords_2024[0] - coords_2010[0]) + ) + + ( + (coords_2024[1] - coords_2010[1]) + * (coords_2024[1] - coords_2010[1]) + ) + ), + 2, + ) + == dif_2024_2010 + ) + assert ( + round( + math.sqrt( + ( + (coords_2024[0] - coords_epoch_none[0]) + * (coords_2024[0] - coords_epoch_none[0]) + ) + + ( + (coords_2024[1] - coords_epoch_none[1]) + * (coords_2024[1] - coords_epoch_none[1]) + ) + ), + 2, + ) + == dif_2024_epoch_none + ) From 8f670ed90608bed214c2c100b27307606616df67 Mon Sep 17 00:00:00 2001 From: Wouter Date: Thu, 15 Feb 2024 15:21:29 +0100 Subject: [PATCH 3/3] (re)reverted alway_xy, for output (#134) --- src/coordinate_transformation_api/crs_transform.py | 4 +++- tests/test_transform_endpoint.py | 14 +++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/coordinate_transformation_api/crs_transform.py b/src/coordinate_transformation_api/crs_transform.py index b532f0e..f78af26 100644 --- a/src/coordinate_transformation_api/crs_transform.py +++ b/src/coordinate_transformation_api/crs_transform.py @@ -294,7 +294,9 @@ def get_transformer( # Get available transformer through TransformerGroup # TODO check/validate if always_xy=True is correct - tfg = transformer.TransformerGroup(s_crs, t_crs, allow_ballpark=False) + tfg = transformer.TransformerGroup( + s_crs, t_crs, allow_ballpark=False, always_xy=True + ) # If everything is 'right' we should always have a transformer # based on our configured proj.db. Therefor this error. diff --git a/tests/test_transform_endpoint.py b/tests/test_transform_endpoint.py index e28f757..61c238a 100644 --- a/tests/test_transform_endpoint.py +++ b/tests/test_transform_endpoint.py @@ -12,14 +12,14 @@ "128410.0958,445806.4960", { "type": "Point", - "coordinates": [52.0, 5.0], + "coordinates": [5.0, 52.0], }, "EPSG:28992", "EPSG:4326", None, ), ( - "52.0,5.0", + "5.0,52.0", { "type": "Point", "coordinates": [128410.0958, 445806.4960], @@ -29,7 +29,7 @@ None, ), ( - "52.0,5.0,43", + "5.0,52.0,43", { "type": "Point", "coordinates": [128410.0958, 445806.4960, -0.4754], @@ -72,7 +72,7 @@ "78835.84,457831.732,9.724", { "type": "Point", - "coordinates": [52.103482881, 4.275510253, 53.122], + "coordinates": [4.275510253, 52.103482881, 53.122], }, "EPSG:7415", "EPSG:9754", @@ -108,7 +108,7 @@ def test_transform_get(input, expectation, source_crs, target_crs, epoch): }, { "type": "Point", - "coordinates": [47.974858137, 3.313687707], + "coordinates": [3.313687707, 47.974858137], }, "EPSG:28992", "EPSG:4326", @@ -116,7 +116,7 @@ def test_transform_get(input, expectation, source_crs, target_crs, epoch): ( { "type": "Point", - "coordinates": [47.974858137, 3.313687707], + "coordinates": [3.313687707, 47.974858137], }, { "type": "Point", @@ -138,7 +138,7 @@ def test_transform_get(input, expectation, source_crs, target_crs, epoch): "features": [ { "type": "Feature", - "geometry": {"type": "Point", "coordinates": [52, 5, 43]}, + "geometry": {"type": "Point", "coordinates": [5, 52, 43]}, "properties": {"prop0": "value0"}, }, {