maplibre/martin

Add small geometry filtering for PG table sources

Open

#756 opened on Jul 9, 2023

 (3 comments) (3 reactions) (1 assignee)Rust (377 forks)auto 404
help wantedpg

Repository metrics

Stars
 (3,761 stars)
PR merge metrics
 (PR metrics pending)

Description

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>

Contributor guide