martin icon indicating copy to clipboard operation
martin copied to clipboard

Add small geometry filtering for PG table sources

Open nyurik opened this issue 2 years ago • 3 comments

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-small or --filter-small or --visible-only or ...? (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 image image
1:100000 image image

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>

nyurik avatar Jul 09 '23 02:07 nyurik

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

sharkAndshark avatar Jul 11 '23 02:07 sharkAndshark

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?

nyurik avatar Jul 11 '23 02:07 nyurik

I think so. Let's give it a try.

sharkAndshark avatar Jul 11 '23 13:07 sharkAndshark