Skip to content

Commit

Permalink
Merge pull request #39 from kbevers/v1.1improvements
Browse files Browse the repository at this point in the history
Add SRID, area of use and bounding box info to CRS entrypoints
  • Loading branch information
kbevers authored Mar 29, 2022
2 parents 196d236 + bc5419c commit 9f0e83c
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 8 deletions.
81 changes: 75 additions & 6 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import sys
import json
import pprint

import pytest

Expand All @@ -20,7 +21,11 @@ def _assert_result(entry, expected_json_output):
"""
Check that a given API resource return the expected result.
"""
print(entry)
decoded_response = _get_and_decode_response(entry)
pprint.pprint(decoded_response)
print("-----")
pprint.pprint(expected_json_output)
assert decoded_response == expected_json_output


Expand Down Expand Up @@ -95,7 +100,9 @@ def test_crs_that_doesnt_exist(api_all):
"""

errmsg = f"'unknowncrs' not available. You have requested this URI "
errmsg += f"[/{api_all}/crs/unknowncrs] but did you mean /{api_all}/crs/<string:crs>"
errmsg += (
f"[/{api_all}/crs/unknowncrs] but did you mean /{api_all}/crs/<string:crs>"
)

response = _get_and_decode_response(f"/{api_all}/crs/unknowncrs")
assert response["message"].startswith(errmsg)
Expand Down Expand Up @@ -148,9 +155,7 @@ def test_sys34(api_all):
Test that system 34 is handled correctly. In this case
we transform from S34J to EPSG:25832 and vice versa.
"""
api_entry_fwd = (
f"/{api_all}/trans/DK:S34J/EPSG:25832/295799.3977,175252.0903"
)
api_entry_fwd = f"/{api_all}/trans/DK:S34J/EPSG:25832/295799.3977,175252.0903"
exp_fwd = {
"v1": 499999.99999808666,
"v2": 6206079.587029327,
Expand All @@ -168,7 +173,9 @@ def test_sys34(api_all):
}
_assert_coordinate(api_entry_inv, exp_inv)

api_entry_js = f"/{api_all}/trans/DK:S34J/DK:S34S/138040.74248674404,63621.728972878314"
api_entry_js = (
f"/{api_all}/trans/DK:S34J/DK:S34S/138040.74248674404,63621.728972878314"
)
exp_js = {
"v1": 138010.86611871765,
"v2": 63644.234364821285,
Expand Down Expand Up @@ -212,7 +219,9 @@ def test_transformation_between_global_and_regional_crs(api_all):
CRS's are compatible.
"""
# first test the case from a global CRS to a regional CRS
api_entry = f"/{api_all}/trans/EPSG:4326/EPSG:25832/55.68950140789923,12.58696909994519"
api_entry = (
f"/{api_all}/trans/EPSG:4326/EPSG:25832/55.68950140789923,12.58696909994519"
)
expected = {"v1": 725448.0, "v2": 6177354.999999999, "v3": None, "v4": None}
_assert_coordinate(api_entry, expected)

Expand Down Expand Up @@ -289,3 +298,63 @@ def test_combined_epsg_codes(api_all):
"v4": None,
}
_assert_coordinate(api_entry, expected, tolerance=0.01)


def test_crs_return_srid(api_from_v1_1):
"""
Test that CRS routes return the calling srid
"""
testdata = {
"EPSG:25832": {
"country": "DK",
"title": "ETRS89 / UTM Zone 32 Nord",
"title_short": "ETRS89/UTM32N",
"v1": "Easting",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": "Ellipsoidehøjde",
"v3_short": "h",
"v4": None,
"v4_short": None,
"srid": "EPSG:25832",
"area_of_use": "Europe between 6°E and 12°E: Austria; Belgium; Denmark - onshore and offshore; Germany - onshore and offshore; Norway including - onshore and offshore; Spain - offshore.",
"bounding_box": [6.0, 38.76, 12.0, 84.33],
},
"EPSG:23032+5733": {
"country": "DK",
"title": "ED50 / UTM Zone 32 Nord + Dansk Normal Nul",
"title_short": "ED50/UTM32N + DNN",
"v1": "Easting",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": "Ellipsoidehøjde",
"v3_short": "h",
"v4": None,
"v4_short": None,
"srid": "EPSG:23032+5733",
"area_of_use": "Denmark - onshore.",
"bounding_box": [8.0, 54.51, 15.24, 57.8],
},
"DK:S34S": {
"country": "DK",
"title": "System 34 Sjælland",
"title_short": "S34S",
"v1": "Westing",
"v1_short": "x",
"v2": "Northing",
"v2_short": "y",
"v3": None,
"v3_short": None,
"v4": None,
"v4_short": None,
"srid": "DK:S34S",
"area_of_use": "Denmark - Sealand onshore",
"bounding_box": [11.0, 54.5, 12.8, 56.5],
},
}

for srid, crsinfo in testdata.items():
api_entry = f"/{api_from_v1_1}/crs/{srid}"
_assert_result(api_entry, crsinfo)
48 changes: 46 additions & 2 deletions webproj/api.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from cmath import inf
import os
import json
from pathlib import Path

from flask import Flask
from flask_cors import CORS
from flask_restx import Api, Resource, fields, abort
from flask_restx import Api, Resource, abort
import pyproj
from pyproj.transformer import Transformer, AreaOfInterest

Expand Down Expand Up @@ -190,7 +191,6 @@ def get(self):


@api.route("/v1.0/crs/<string:crs>")
@api.route("/v1.1/crs/<string:crs>")
class CRS(Resource):
def get(self, crs):
"""
Expand All @@ -202,6 +202,50 @@ def get(self, crs):
abort(404, message=f"'{crs}' not available")


@api.route("/v1.1/crs/<string:crs>")
class CRSv1_1(CRS):
def get(self, crs):
"""
Retrieve information about a given coordinate reference system
Version 1.1 includes the SRID, area of use and bounding box in
the CRS info.
"""

output = super().get(crs)
output["srid"] = crs

# determine area of use and bounding box
try:
crs_from_db = pyproj.CRS.from_user_input(crs.upper())
if crs_from_db.is_compound:
area = inf
for subcrs in crs_from_db.sub_crs_list:
aou = subcrs.area_of_use
bbox_area = aou.east - aou.west * aou.north - aou.south
if bbox_area < area:
output["area_of_use"] = subcrs.area_of_use.name
output["bounding_box"] = list(subcrs.area_of_use.bounds)
else:
output["area_of_use"] = crs_from_db.area_of_use.name
output["bounding_box"] = list(crs_from_db.area_of_use.bounds)
except pyproj.exceptions.CRSError:
# special cases not in proj.db
if crs == "DK:S34J":
output["area_of_use"] = "Denmark - Jutland onshore"
output["bounding_box"] = [8.0, 54.5, 11.0, 57.75]
elif crs == "DK:S34S":
output["area_of_use"] = "Denmark - Sealand onshore"
output["bounding_box"] = [11.0, 54.5, 12.8, 56.5]
elif crs == "DK:S45B":
output["area_of_use"] = "Denmark - Bornholm onshore"
output["bounding_box"] = [14.6, 54.9, 15.2, 55.3]
else:
abort(404, message=f"'{crs}' not available")

return output


@api.route("/v1.0/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>")
@api.route("/v1.1/trans/<string:src>/<string:dst>/<number:v1>,<number:v2>")
class Transformation2D(Resource):
Expand Down

0 comments on commit 9f0e83c

Please sign in to comment.