Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 4 additions & 13 deletions tests/routes/test_items.py
Original file line number Diff line number Diff line change
Expand Up @@ -688,6 +688,9 @@ def test_items_geometry_return_options(app):
}
Items.model_validate(body)

response = app.get("/collections/public.landsat_wrs/items?ids=1")
geom = response.json()["features"][0]["geometry"]

response = app.get("/collections/public.landsat_wrs/items?ids=1&simplify=.001")
assert response.status_code == 200
assert response.headers["content-type"] == "application/geo+json"
Expand All @@ -697,19 +700,7 @@ def test_items_geometry_return_options(app):
assert body["numberReturned"] == 1
assert body["features"][0]["id"] == 1
assert body["features"][0]["properties"]["ogc_fid"] == 1
assert body["features"][0]["geometry"] == {
"coordinates": [
[
[-10.803, 80.989],
[-8.974, 80.342],
[-16.985, 79.689],
[-22.215, 81.092],
[-13.255, 81.856],
[-10.803, 80.989],
]
],
"type": "Polygon",
}
assert body["features"][0]["geometry"] != geom
Items.model_validate(body)


Expand Down
28 changes: 28 additions & 0 deletions tests/routes/test_tiles.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,3 +247,31 @@ def test_stylejson(app):
"/collections/public.landsat/tiles/WebMercatorQuad/style.json?geom-column=centroid"
)
assert response.status_code == 200


def test_tile_simplify(app):
"""Test tile simplification."""
name = "landsat_wrs"
response = app.get(
f"/collections/public.{name}/tiles/WebMercatorQuad/0/0/0?limit=1"
)
assert response.status_code == 200
decoded = mapbox_vector_tile.decode(response.content)
assert len(decoded["default"]["features"]) == 1
geom = decoded["default"]["features"][0]["geometry"]

response = app.get(
f"/collections/public.{name}/tiles/WebMercatorQuad/0/0/0?limit=1&simplify=0.01"
)
assert response.status_code == 200
decoded = mapbox_vector_tile.decode(response.content)
assert len(decoded["default"]["features"]) == 1
assert decoded["default"]["features"][0]["properties"] == {
"id": "1286",
"ogc_fid": 796,
"path": 182,
"pr": "182047",
"row": 47,
}
assert decoded["default"]["features"][0]["id"] == 0
assert decoded["default"]["features"][0]["geometry"] != geom
8 changes: 7 additions & 1 deletion tipg/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -673,7 +673,7 @@ def _geom_expr(
g = f"ST_Envelope({g})"
elif simplify:
s = float(simplify)
g = f"ST_SnapToGrid(ST_Simplify({g}, {s}), {s})"
g = f"ST_SnapToGrid(ST_SimplifyPreserveTopology({g}, {s}), {s})"

return g

Expand Down Expand Up @@ -711,12 +711,16 @@ def _select_mvt(
geometry_column: Column,
tms: TileMatrixSet,
tile: Tile,
simplify: float | None = None,
) -> str:
"""Build the SELECT clause that emits an MVT geometry per row."""
cols = self._select_property_columns(properties)

geom = f"CAST({_quote_ident(geometry_column.name)} AS geometry)"

if simplify:
geom = f"ST_SnapToGrid(ST_SimplifyPreserveTopology({geom}, {simplify}), {simplify})"

# For tiles that fall outside the TMS's natural domain (e.g. an
# over-zoomed corner tile), clip the source geometry to the TMS's
# geographic bbox before reprojecting — otherwise ST_AsMVTGeom can
Expand Down Expand Up @@ -968,6 +972,7 @@ async def get_tile(
geom: Optional[str] = None,
dt: Optional[str] = None,
limit: Optional[int] = None,
simplify: float | None = None,
):
"""Build query to get Vector Tile."""
limit = limit or mvt_settings.max_features_per_tile
Expand Down Expand Up @@ -1001,6 +1006,7 @@ async def get_tile(
geometry_column=geometry_column,
tms=tms,
tile=tile,
simplify=simplify,
),
self._from(function_parameters, params),
self._where_clause(where_filter),
Expand Down
7 changes: 7 additions & 0 deletions tipg/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -1668,6 +1668,12 @@ async def collection_get_tile(
description="Limits the number of features in the response. Defaults to 10000 or TIPG_MAX_FEATURES_PER_TILE environment variable."
),
] = None,
simplify: Annotated[
float | None,
Query(
description="Simplify the output geometry to given threshold in the units of the output CRS.",
),
] = None,
):
"""Return Vector Tile."""
tms = self.supported_tms.get(tileMatrixSetId)
Expand All @@ -1688,6 +1694,7 @@ async def collection_get_tile(
limit=limit,
geom=geom_column,
dt=datetime_column,
simplify=simplify,
)

return Response(tile, media_type=MediaType.mvt.value)
Expand Down
Loading