Skip to content

Commit

Permalink
Addressing Requirements class 2 (Requirements Class Tileset) of the O…
Browse files Browse the repository at this point in the history
…GC API Tiles Standard (geopython#1497)

* - refactored mvt classes to support all implemented metadata formats, regardless of the provider

* - fixed formatting issues

* Implementing basic tile metadata methods

* Fixing yml models

* Adding additional format

* Fixing schema set on load

* Removing unused field from documentation

* - added support to TileMatrixSets endpoint
- added TileMatrixSet definitions for WorldCRS84Quad and WebMercatorQuad

* - added tiling-schemes link in the json representation of the landing page

* - added html pages for tilematrixset endpoints

* - advertise json and html representations of the tiling schemes in the landing page

* - Use api definition of Well-known TileMatrixSets in the tiling-schemes element of the tiles metadata page

* - added tiling-scheme url on tiles metadata page, for es and tippecanoe providers

* - fixed flak8 formatting errors

* - updated number of links  on the landing page, on the api test

* - Manage tile matrix set id dinamically, on tilematrix set flask endpoint

* - renamed functions to lower case

* - renamed tilematrix set functions on flask

* - Use TtileMatrixSetId parameter in tilematrixset api function

* - added support to TileMatrixSet endpoints on starlette

* - added test for tileMatrixSets api endpoint

* - added test for the tilematrixset endpoint

* - added routes for django

---------

Co-authored-by: Antonio Cerciello <[email protected]>
  • Loading branch information
2 people authored and sjordan29 committed Oct 21, 2024
1 parent 9760aee commit cdccaa6
Show file tree
Hide file tree
Showing 12 changed files with 3,184 additions and 48 deletions.
136 changes: 134 additions & 2 deletions pygeoapi/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,8 @@
from pygeoapi.provider.base import (
ProviderGenericError, ProviderConnectionError, ProviderNotFoundError,
ProviderTypeError)
from pygeoapi.models.provider.base import TilesMetadataFormat
from pygeoapi.models.provider.base import (TilesMetadataFormat,
TileMatrixSetEnum)

from pygeoapi.models.cql import CQLModel
from pygeoapi.util import (dategetter, RequestedProcessExecutionMode,
Expand Down Expand Up @@ -751,6 +752,16 @@ def landing_page(self,
'type': FORMAT_TYPES[F_JSON],
'title': 'Jobs',
'href': f"{self.base_url}/jobs"
}, {
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
'type': FORMAT_TYPES[F_JSON],
'title': 'The list of supported tiling schemes (as JSON)',
'href': f"{self.base_url}/TileMatrixSets?f=json"
}, {
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-schemes',
'type': FORMAT_TYPES[F_HTML],
'title': 'The list of supported tiling schemes (as HTML)',
'href': f"{self.base_url}/TileMatrixSets?f=html"
}]

headers = request.get_response_headers(**self.api_headers)
Expand Down Expand Up @@ -858,6 +869,122 @@ def conformance(self,

return headers, HTTPStatus.OK, to_json(conformance, self.pretty_print)

@gzip
@pre_process
def tilematrixsets(self,
request: Union[APIRequest, Any]) -> Tuple[dict, int,
str]:
"""
Provide tileMatrixSets definition
:param request: A request object
:returns: tuple of headers, status code, content
"""

if not request.is_valid():
return self.get_format_exception(request)

headers = request.get_response_headers(**self.api_headers)

# Retrieve available TileMatrixSets
enums = [e.value for e in TileMatrixSetEnum]

tms = {"tileMatrixSets": []}

for e in enums:
tms['tileMatrixSets'].append({
"title": e.title,
"id": e.tileMatrixSet,
"uri": e.tileMatrixSetURI,
"links": [
{
"rel": "self",
"type": "text/html",
"title": f"The HTML representation of the {e.tileMatrixSet} tile matrix set", # noqa
"href": f"{self.base_url}/TileMatrixSets/{e.tileMatrixSet}?f=html" # noqa
},
{
"rel": "self",
"type": "application/json",
"title": f"The JSON representation of the {e.tileMatrixSet} tile matrix set", # noqa
"href": f"{self.base_url}/TileMatrixSets/{e.tileMatrixSet}?f=json" # noqa
}
]
})

tms['links'] = [{
"rel": "alternate",
"type": "text/html",
"title": "This document as HTML",
"href": f"{self.base_url}/tileMatrixSets?f=html"
}, {
"rel": "self",
"type": "application/json",
"title": "This document",
"href": f"{self.base_url}/tileMatrixSets?f=json"
}]

if request.format == F_HTML: # render
content = render_j2_template(self.tpl_config,
'tilematrixsets/index.html',
tms, request.locale)
return headers, HTTPStatus.OK, content

return headers, HTTPStatus.OK, to_json(tms, self.pretty_print)

@gzip
@pre_process
def tilematrixset(self,
request: Union[APIRequest, Any],
tileMatrixSetId) -> Tuple[dict,
int, str]:
"""
Provide tile matrix definition
:param request: A request object
:returns: tuple of headers, status code, content
"""

if not request.is_valid():
return self.get_format_exception(request)

headers = request.get_response_headers(**self.api_headers)

# Retrieve relevant TileMatrixSet
enums = [e.value for e in TileMatrixSetEnum]
enum = None

try:
for e in enums:
if tileMatrixSetId == e.tileMatrixSet:
enum = e
if not enum:
raise ValueError('could not find this tilematrixset')
except ValueError as err:
return self.get_exception(
HTTPStatus.BAD_REQUEST, headers, request.format,
'InvalidParameterValue', str(err))

tms = {
"title": enum.tileMatrixSet,
"crs": enum.crs,
"id": enum.tileMatrixSet,
"uri": enum.tileMatrixSetURI,
"orderedAxes": enum.orderedAxes,
"wellKnownScaleSet": enum.wellKnownScaleSet,
"tileMatrices": enum.tileMatrices
}

if request.format == F_HTML: # render
content = render_j2_template(self.tpl_config,
'tilematrixsets/tilematrixset.html',
tms, request.locale)
return headers, HTTPStatus.OK, content

return headers, HTTPStatus.OK, to_json(tms, self.pretty_print)

@gzip
@pre_process
@jsonldify
Expand Down Expand Up @@ -2665,7 +2792,12 @@ def get_collection_tiles(self, request: Union[APIRequest, Any],
'dataType': 'vector',
'links': []
}
tile_matrix['links'].append(matrix.tileMatrixSetDefinition)
tile_matrix['links'].append({
'type': FORMAT_TYPES[F_JSON],
'rel': 'http://www.opengis.net/def/rel/ogc/1.0/tiling-scheme',
'title': f'{matrix.tileMatrixSet} TileMatrixSet definition (as {F_JSON})', # noqa
'href': f'{self.base_url}/TileMatrixSets/{matrix.tileMatrixSet}?f={F_JSON}' # noqa
})
tile_matrix['links'].append({
'type': FORMAT_TYPES[F_JSON],
'rel': request.get_linkrel(F_JSON),
Expand Down
10 changes: 10 additions & 0 deletions pygeoapi/django_/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,16 @@ def apply_slash_rule(url: str):
views.conformance,
name='conformance'
),
path(
apply_slash_rule('TileMatrixSets/'),
views.tilematrixsets,
name='tilematrixsets'
),
path(
apply_slash_rule('TileMatrixSets/<str:tilematrixset_id>'),
views.tilematrixsets,
name='tilematrixset'
),
path(
apply_slash_rule('collections/'),
views.collections,
Expand Down
22 changes: 22 additions & 0 deletions pygeoapi/django_/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,28 @@ def conformance(request: HttpRequest) -> HttpResponse:
return response


def tilematrixsets(request: HttpRequest,
tilematrixset_id: Optional[str] = None) -> HttpResponse:
"""
OGC API tilematrixsets endpoint
:request Django HTTP Request
:param tilematrixset_id: tile matrix set identifier
:returns: Django HTTP Response
"""

response = None

if tilematrixset_id is None:
response_ = _feed_response(request, 'tilematrixsets')
else:
response_ = _feed_response(request, 'tilematrixset', tilematrixset_id)
response = _to_django_response(*response_)

return response


def collections(request: HttpRequest,
collection_id: Optional[str] = None) -> HttpResponse:
"""
Expand Down
8 changes: 2 additions & 6 deletions pygeoapi/flask_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,9 @@ def get_tilematrix_set(tileMatrixSetId=None):
OGC API TileMatrixSet endpoint
:param tileMatrixSetId: identifier of tile matrix set
:returns: HTTP response
"""

return execute_from_flask(tiles_api.tilematrixset, request,
tileMatrixSetId)
return get_response(api_.tilematrixset(request, tileMatrixSetId))


@BLUEPRINT.route('/TileMatrixSets')
Expand All @@ -211,8 +208,7 @@ def get_tilematrix_sets():
:returns: HTTP response
"""

return execute_from_flask(tiles_api.tilematrixsets, request)
return get_response(api_.tilematrixsets(request))


@BLUEPRINT.route('/collections')
Expand Down
Loading

0 comments on commit cdccaa6

Please sign in to comment.