Add small geometry filtering for PG table sources
It would be great to limit low-zoom tiles from including invisible geometries -- the ones that are too small at the low zoom.
Implementation ideas
- Add a CLI flag, something like
--pg-filter-smallor--filter-smallor--visible-onlyor ...? (naming is hard) - Add a table config file setting, e.g.
hide_small_geometries(we may want naming consistent with CLI though)- this could be a boolean for now, but eventually could even introduce some percentage "per pixel", where the size of the pixel is computed from zoom and extent settings
- Should we offer any kind of "clustering" support, e.g. if there is an area with lots of buildings, each building is too small to be seen, but if they are close enough, they would still be visible as a cluster. OMT did something similar here
[!NOTE] ST_AsMVTGeom does already drop geometries smaller than the resolution as discussed here. This would thus not be nessesary.
Discussed in https://github.com/maplibre/martin/discussions/731
Originally posted by sharkAndshark June 27, 2023 Hi. It's just some random ideas. For automatically discovered data sources, Martin will fetch a large amount of data when the zoom level is low, such as 0 to 4. At these zoom levels, the tiles are large and contain an overload of information on the map.Is it possible to remove polygons or linestrings whose area / length is not bigger than a single pixel in size at the current zoom level?
| scale | Marin table source | Martin function source with filtering |
|---|---|---|
| 1:250000 | ||
| 1:100000 |
The function source
CREATE
OR REPLACE FUNCTION test_filtering ( z INTEGER, x INTEGER, y INTEGER ) RETURNS bytea AS $$ DECLARE
mvt bytea;
BEGIN
SELECT INTO
mvt ST_AsMVT ( tile, 'function_zxy_query', 4096, 'geom' )
FROM
(
SELECT
ST_AsMVTGeom ( ST_Transform ( ST_CurveToLine ( geom ), 3857 ), ST_TileEnvelope ( z, x, y ), 4096, 64, TRUE ) AS geom
FROM
"SHANGHAI_BUILDINGS"
WHERE
geom && ST_Transform ( ST_TileEnvelope ( z, x, y ), 4326 )
AND ( st_area ( st_transform ( geom, 3857 ) ) >= ( ( 40075016.68 / ( 2 ^ z * 512 ) ) ^ 2 ) )
-- when the tile size is 512 * 512 pixels, the actual area covered by one pixel would be: (40075016.68 / (2^zoom * 512))^2
) AS tile
WHERE
geom IS NOT NULL;
RETURN mvt;
END $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE;
```</div>
Just another reference about the clustering stuffs, they call it polygon dust here: How We Make Your Data Look Great At Every Scale with Tippecanoe
Thx @sharkAndshark, it would be awesome to implement as well. I wonder if we should dig through Tippecanoe code to see if we can adapt it somehow, or if PostGIS could do it all for us?
I think so. Let's give it a try.