Skip to content

Commit 7c69937

Browse files
justb4MTachon
andauthored
add CRS Support for OGC API Feature pygeoapi Provider (geopython#1174)
* OGC API - Features Part 2 (groundwork+CRS-BBOX) from PR geopython#1155 - contributes to issue geopython#1128 * geopython#1128 provide conformance class for OAPIF Part 2 in /conformance page * geopython#1128 bitten by flake8... * geopython#1128 configurability CRS Feature Providers with syntax, defaults and tests * geopython#1128 configurability CRS Feature Providers refine for default values * geopython#1128 display supported CRSs in HTML Collection template * geopython#1128 config, mmetadata and tests for storageCRS and storageCrsCoordinateEpoch * geopython#1128 WIP for bbox-crs parameter support * geopython#1128 utility function and tests for default/mandatory supprted CRS list * geopython#1128 default supported CRS adaptation to OAPIF Part 2 standard * geopython#1128 grr flake8 whitespace * geopython#1128 start adding full API tests OGR for bbox-crs and crs parms * geopython#1128 fix flake8 * geopython#1128 fix flake8 - install GDAL in workflow main for OGR tests * geopython#1128 fix flake8 - install GDAL in workflow main for OGR tests - need pip package? * geopython#1128 fix flake8 - install GDAL in workflow main for OGR tests - using libgdal-dev gdal-bin * geopython#1128 fix SensorThings test for main.yml Workflow * geopython#1128 fix SensorThings test for main.yml Workflow nr 2 * geopython#1128 make all OGR tests working again * geopython#1128 make all OGR tests working again - flake8 * geopython#1128 make all OGR tests working again - GeoSolutions WFS bbox * geopython#1128 geopython#1155 add documentation for OGC OAPIF Part 2 CRS CRS BBOX support * geopython#1128 geopython#1155 refine documentation for OGC OAPIF Part 2 CRS CRS BBOX support * geopython#1128 geopython#1155 refine documentation to align with geopython#1149 * geopython#1128 geopython#1155 rework from review OAS and pygeoapi config schema * geopython#1128 geopython#1155 minor: compile Re for CRS URI only once as global var * geopython#1128 merge in changes from PR geopython#1173 - fix missing import * WIP Ogcapi features part 2 - Support for crs query parameter (geopython#1149) * feat(ogcapi_features_crs): start implementing crs support from ogcapi features part2 * Pass input and output CRSs WKT instead of crs transformation object * fix longs lines and blank lines * fix typo * fix import for type annotation not supported by python version * fix variable visibility in local scope * fix tabs/spaces indentations * Add support for the crs parameter to OGRProvider * make flake8 happy * Make crs transformation mechanism more consistent between PostgreSQL and OGR providers * test(util): add two test functions in util.py New functions: test_get_crs_from_uri and test_get_transform_from_crs * fix too long lines... * Update get_crs_from_uri and corresponding test function * fix(get_crs_from_uri): make the error more explicit in if wrong crs uri format * flake8 again... * Keep support for source_srs/target_srs in config for OGRProvider * revert changes made to pygeoapi-config-0.x.yml, overlap with PR 1155 * test: add test data and update test config file * Extract 'crs' and 'storage_crs' and provider level instead of collection level * feat(crs): new decorator to support coordinates transformation of feature collections * feat(crs): 'crs' query parameter for CSVProvider * test(crs): add tests for 'crs' query parameter * test: update number of collections in test_describe_collections * test: update number of collections in test_filter_dict_by_key_value * fix(crs_transform): change the crs transformation decorator Change the logic of the decorator so that it works for both functions that return FeatureCollections and for functions tha return single Features. * test: add tests for get_collection_item end-point with 'crs' parameter * fix(test_get_collection_item_crs): id as path parameter, not query parameter * test: unpack coordinates to create point geometry * feat(crs): add suuport for crs query parameter for all providers of type 'feature' * docs(crs): add documentation to illustrate use of 'crs' query parameters * docs(crs): more data access examples * fix typo and add new line * refactor: specify None as default value for crs_transform_out parameter in _sqlalchemy_to_feature method * changes for PR 1149, test_api and style formatting * CRS84 as default crs also for test_get_collection_items_crs * test(crs): test coordinates transformation implementation of PostgreSQLProvider * test(crs): move tests to test_postgresql_provider * fix test function calls * change test to ensure returned features are the same * add json format to request object * test(crs): test coordinates transformation implementation of OGRProvider * refactor(crs): make more compact get_collection_item and get_collection_items Define two new static methods in API class, to create crs_transform_wkt and setting content-crs header. These methods can be re-used in both get_collection_item and get_collection_items methods and removes code duplication. --------- Co-authored-by: Just van den Broecke <just@justobjects.nl> * geopython#1178 fix flake8 error * geopython#1178 use EPSG:28992 i.s.o. 32631 - fix unit test OGR Shapefile * geopython#1174 use CRS-compliant Axis ordering for crs support * geopython#1174 fix and honour CRS 4258disable native CRS Transform in OGR Provider - Axis ordering not honoured... * geopython#1174 remove ADR tests rom test_util.py * geopython#1174 enable native CRS transform again in OGR Provider * geopython#1174 enable native CRS transform again in OGR Provider - fix config * geopython#1174 remove support for source/target_srs in OGRProvider - enforce transforms always based on storageCRS * geopython#1174 fix tests Postgresql Provider for Transforms * geopython#1174 fix tests Postgresql Provider for Transforms * geopython#1174 add tests for OGR Transformation and Axis Order * geopython#1174 Suppress potential axis-swapping in OGR ExportToJSON * geopython#1174 minor fix test - unassign spatialref before setgeom infeat * geopython#1174 minor fix test - unassign spatialref before setgeom infeat - flake8 * geopython#1174 solve CI WFS test failures with GDAL HTTP config options * geopython#1174 bbox and bbox-crs defs local in openapi.py for CITE validators * geopython#1174 merge master - geopython#1152 geopython#1203 etc * geopython#1174 small doc changes * geopython#1174 move GeomObject typedef to beginning of util.py * geopython#1174 added debug logging in transform Decorator func --------- Co-authored-by: Mathieu Tachon <92298764+MTachon@users.noreply.github.com>
1 parent d594653 commit 7c69937

40 files changed

+2516
-698
lines changed

.github/workflows/main.yml

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,11 @@ jobs:
8080
with:
8181
packages: libsqlite3-mod-spatialite
8282
version: 4.3.0a-6build1
83+
- name: Install GDAL with Python bindings
84+
uses: awalsh128/cache-apt-pkgs-action@latest
85+
with:
86+
packages: gdal-bin libgdal-dev
87+
version: 3.0.4
8388
- name: Install requirements 📦
8489
run: |
8590
pip3 install -r requirements.txt
@@ -89,6 +94,7 @@ jobs:
8994
python3 setup.py install
9095
pip3 install --upgrade numpy elasticsearch
9196
pip3 install --upgrade numpy "sqlalchemy<2"
97+
pip3 install --global-option=build_ext --global-option="-I/usr/include/gdal" GDAL==`gdal-config --version`
9298
#pip3 install --upgrade rasterio==1.1.8
9399
- name: setup test data ⚙️
94100
run: |
@@ -102,6 +108,7 @@ jobs:
102108
POSTGRESQL_PASSWORD: ${{ secrets.DatabasePassword || 'postgres' }}
103109
run: |
104110
pytest tests/test_api.py
111+
pytest tests/test_api_ogr_provider.py
105112
pytest tests/test_config.py
106113
pytest tests/test_csv__formatter.py
107114
pytest tests/test_csv__provider.py
@@ -110,12 +117,12 @@ jobs:
110117
pytest tests/test_filesystem_provider.py
111118
pytest tests/test_geojson_provider.py
112119
pytest tests/test_mongo_provider.py
113-
#pytest tests/test_ogr_csv_provider.py
114-
#pytest tests/test_ogr_esrijson_provider.py
115-
#pytest tests/test_ogr_gpkg_provider.py
116-
#pytest tests/test_ogr_shapefile_provider.py
117-
#pytest tests/test_ogr_sqlite_provider.py
118-
#pytest tests/test_ogr_wfs_provider.py
120+
pytest tests/test_ogr_csv_provider.py
121+
pytest tests/test_ogr_esrijson_provider.py
122+
pytest tests/test_ogr_gpkg_provider.py
123+
pytest tests/test_ogr_shapefile_provider.py
124+
pytest tests/test_ogr_sqlite_provider.py
125+
pytest tests/test_ogr_wfs_provider.py
119126
pytest tests/test_openapi.py
120127
pytest tests/test_postgresql_provider.py
121128
pytest tests/test_rasterio_provider.py

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,3 +115,9 @@ ENV/
115115

116116
.DS_Store
117117
examples/django/sample_project/db.sqlite3
118+
119+
# Backup files
120+
*~
121+
122+
# Pre-commit hooks config file
123+
.pre-commit-config.yaml

aws-lambda/function/pygeoapi-config.yml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,8 @@ resources:
296296
data:
297297
source_type: WFS
298298
source: WFS:https://service.pdok.nl/kadaster/rdinfo/wfs/v1_0?
299-
source_srs: EPSG:28992
300-
target_srs: EPSG:4326
299+
# source_srs: EPSG:28992
300+
# target_srs: EPSG:4326
301301
source_capabilities:
302302
paging: True
303303

@@ -312,6 +312,12 @@ resources:
312312
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
313313
CPL_DEBUG: NO
314314

315+
crs:
316+
- http://www.opengis.net/def/crs/OGC/1.3/CRS84
317+
- http://www.opengis.net/def/crs/EPSG/0/4326
318+
- http://www.opengis.net/def/crs/EPSG/0/4258
319+
- http://www.opengis.net/def/crs/EPSG/0/28992
320+
storage_crs: http://www.opengis.net/def/crs/EPSG/0/28992
315321
id_field: gml_id
316322
layer: rdinfo:stations
317323

docker/default.config.yml

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -211,8 +211,8 @@ resources:
211211
data:
212212
source_type: WFS
213213
source: WFS:https://service.pdok.nl/kadaster/rdinfo/wfs/v1_0?
214-
source_srs: EPSG:28992
215-
target_srs: EPSG:4326
214+
# source_srs: EPSG:28992
215+
# target_srs: EPSG:4326
216216
source_capabilities:
217217
paging: True
218218

@@ -227,6 +227,10 @@ resources:
227227
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
228228
CPL_DEBUG: NO
229229

230+
crs:
231+
- http://www.opengis.net/def/crs/EPSG/0/4258
232+
- http://www.opengis.net/def/crs/EPSG/0/28992
233+
storage_crs: http://www.opengis.net/def/crs/EPSG/0/28992
230234
id_field: gml_id
231235
layer: rdinfo:stations
232236

@@ -258,8 +262,8 @@ resources:
258262
data:
259263
source_type: WFS
260264
source: WFS:http://demo.deegree.org/utah-workspace/services/wfs?TYPENAME=app:SGID93_LOCATION_UDOTMap_CityLocations
261-
source_srs: EPSG:26912
262-
target_srs: EPSG:4326
265+
# source_srs: EPSG:26912
266+
# target_srs: EPSG:4326
263267
source_capabilities:
264268
paging: True
265269

@@ -274,6 +278,10 @@ resources:
274278
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
275279
CPL_DEBUG: NO
276280

281+
crs:
282+
- http://www.opengis.net/def/crs/EPSG/0/4258
283+
- http://www.opengis.net/def/crs/EPSG/0/26912
284+
storage_crs: http://www.opengis.net/def/crs/EPSG/0/26912
277285
id_field: NAME
278286
layer: app:SGID93_LOCATION_UDOTMap_CityLocations
279287

@@ -304,8 +312,8 @@ resources:
304312
data:
305313
source_type: WFS
306314
source: WFS:https://gs-stable.geosolutionsgroup.com/geoserver/wfs
307-
source_srs: EPSG:32632
308-
target_srs: EPSG:4326
315+
# source_srs: EPSG:32632
316+
# target_srs: EPSG:4326
309317
source_capabilities:
310318
paging: True
311319

@@ -320,6 +328,10 @@ resources:
320328
# GDAL_PROXY_AUTH: (optional auth for remote WFS)
321329
CPL_DEBUG: NO
322330

331+
crs:
332+
- http://www.opengis.net/def/crs/EPSG/0/4258
333+
- http://www.opengis.net/def/crs/EPSG/0/32632
334+
storage_crs: http://www.opengis.net/def/crs/EPSG/0/32632
323335
id_field: gml_id
324336
layer: unesco:Unesco_point
325337

@@ -355,8 +367,8 @@ resources:
355367
data:
356368
source_type: GPKG
357369
source: tests/data/poi_portugal.gpkg
358-
source_srs: EPSG:4326
359-
target_srs: EPSG:4326
370+
# source_srs: EPSG:4326
371+
# target_srs: EPSG:4326
360372
source_capabilities:
361373
paging: True
362374

@@ -395,8 +407,8 @@ resources:
395407
data:
396408
source_type: GeoJSON
397409
source: tests/data/ne_110m_lakes.geojson
398-
source_srs: EPSG:4326
399-
target_srs: EPSG:4326
410+
# source_srs: EPSG:4326
411+
# target_srs: EPSG:4326
400412
source_capabilities:
401413
paging: True
402414

@@ -438,8 +450,8 @@ resources:
438450
source_type: SQLite
439451
# source: tests/data/ne_110m_admin_0_countries.sqlite
440452
source: tests/data/dutch_addresses_4326.sqlite
441-
source_srs: EPSG:4326
442-
target_srs: EPSG:4326
453+
# source_srs: EPSG:4326
454+
# target_srs: EPSG:4326
443455
source_capabilities:
444456
paging: True
445457

@@ -480,8 +492,8 @@ resources:
480492
data:
481493
source_type: GPKG
482494
source: tests/data/dutch_addresses_4326.gpkg
483-
source_srs: EPSG:4326
484-
target_srs: EPSG:4326
495+
# source_srs: EPSG:4326
496+
# target_srs: EPSG:4326
485497
source_capabilities:
486498
paging: True
487499

docs/source/configuration.rst

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,8 +161,8 @@ default.
161161
- observations
162162
- monitoring
163163
linked-data: # linked data configuration (see Linked Data section)
164-
item_template: tests/data/base.jsonld
165-
context:
164+
item_template: tests/data/base.jsonld
165+
context:
166166
- datetime: https://schema.org/DateTime
167167
- vocab: https://example.com/vocab#
168168
stn_id: "vocab:stn_id"
@@ -195,6 +195,13 @@ default.
195195
uri_field: uri # optional field corresponding to the Uniform Resource Identifier (see Linked Data section)
196196
time_field: datetimestamp # optional field corresponding to the temporal property of the dataset
197197
title_field: foo # optional field of which property to display as title/label on HTML pages
198+
crs: # optional: supported CRSs for parameters 'crs' and 'bbox-crs' (OGC OAPIF Part 2)
199+
# default: http://www.opengis.net/def/crs/OGC/1.3/CRS84
200+
- http://www.opengis.net/def/crs/EPSG/0/4326
201+
- http://www.opengis.net/def/crs/EPSG/0/3857
202+
- http://www.opengis.net/def/crs/EPSG/0/28992
203+
storage_crs: http://www.opengis.net/def/crs/OGC/1.3/CRS84 # optional CRS in which data is stored, default: as 'crs' field
204+
storage_crs_coordinate_epoch: : 2017.23 # optional, if storage_crs is a dynamic coordinate reference system
198205
format: # optional default format
199206
name: GeoJSON # required: format name
200207
mimetype: application/json # required: format mimetype
@@ -203,6 +210,14 @@ default.
203210
properties: # optional: only return the following properties, in order
204211
- stn_id
205212
- value
213+
# coordinate reference systems (CRS) section is optional
214+
# default CRSs are http://www.opengis.net/def/crs/OGC/1.3/CRS84 (coordinates without height)
215+
# and http://www.opengis.net/def/crs/OGC/1.3/CRS84h (coordinates with ellipsoidal height)
216+
storage_crs: http://www.opengis.net/def/crs/EPSG/0/28992 # CRS of the dataset to publish
217+
crs: # supported coordinate reference systems (CRS) for 'crs' query parameter
218+
- http://www.opengis.net/def/crs/EPSG/0/28992
219+
- http://www.opengis.net/def/crs/OGC/1.3/CRS84
220+
- http://www.opengis.net/def/crs/EPSG/0/4326
206221
207222
hello-world: # name of process
208223
type: collection # REQUIRED (collection, process, or stac-collection)
@@ -570,12 +585,12 @@ deployment flexibility, the path can be specified with string interpolation of e
570585
.. code-block:: yaml
571586
572587
linked-data:
573-
item_template: tests/data/base.jsonld
588+
item_template: tests/data/base.jsonld
574589
context:
575590
- datetime: https://schema.org/DateTime
576591
577592
.. note::
578-
The template ``tests/data/base.jsonld`` renders the unmodified JSON-LD. For more information on the capacities
593+
The template ``tests/data/base.jsonld`` renders the unmodified JSON-LD. For more information on the capacities
579594
of Jinja2 templates, see :ref:`html-templating`.
580595

581596
Summary

0 commit comments

Comments
 (0)