kopia lustrzana https://github.com/openmaptiles/openmaptiles
Building aggregation fix (#1044)
This PR solving the speed and memory issue with buildings aggregation on zoom level 13. The problem was to create ST_ClusterDBScan which failed after try to cluster a larger area. Now it will make cluster only in "small" polygon using 'country_osm_grid` which covers the world's lands. This PR solving #1022 and #974pull/1045/head
rodzic
24b9328a5f
commit
0c6fe2d9ba
|
@ -82,7 +82,7 @@ SELECT geometry,
|
||||||
CASE WHEN hide_3d THEN TRUE END AS hide_3d
|
CASE WHEN hide_3d THEN TRUE END AS hide_3d
|
||||||
FROM (
|
FROM (
|
||||||
SELECT
|
SELECT
|
||||||
-- etldoc: osm_building_block_gen1 -> layer_building:z13
|
-- etldoc: osm_building_block_gen_z13 -> layer_building:z13
|
||||||
osm_id,
|
osm_id,
|
||||||
geometry,
|
geometry,
|
||||||
NULL::int AS render_height,
|
NULL::int AS render_height,
|
||||||
|
@ -90,7 +90,7 @@ FROM (
|
||||||
NULL::text AS material,
|
NULL::text AS material,
|
||||||
NULL::text AS colour,
|
NULL::text AS colour,
|
||||||
FALSE AS hide_3d
|
FALSE AS hide_3d
|
||||||
FROM osm_building_block_gen1
|
FROM osm_building_block_gen_z13
|
||||||
WHERE zoom_level = 13
|
WHERE zoom_level = 13
|
||||||
AND geometry && bbox
|
AND geometry && bbox
|
||||||
UNION ALL
|
UNION ALL
|
||||||
|
|
Plik binarny nie jest wyświetlany.
Przed Szerokość: | Wysokość: | Rozmiar: 34 KiB Po Szerokość: | Wysokość: | Rozmiar: 32 KiB |
|
@ -1,13 +1,13 @@
|
||||||
DROP TRIGGER IF EXISTS trigger_refresh ON buildings.updates;
|
DROP TRIGGER IF EXISTS trigger_refresh ON buildings.updates;
|
||||||
DROP TRIGGER IF EXISTS trigger_flag ON osm_building_polygon;
|
DROP TRIGGER IF EXISTS trigger_flag ON osm_building_polygon;
|
||||||
|
|
||||||
--creating aggregated building blocks with removed small polygons and small
|
-- Creating aggregated building blocks with removed small polygons and small
|
||||||
--holes. Aggregated polygons are simplified.
|
-- holes. Aggregated polygons are simplified by Visvalingam-Whyatt algorithm.
|
||||||
|
-- Aggregating is made block by block using country_osm_grid polygon table.
|
||||||
|
|
||||||
--function returning recordset for matview
|
-- Function returning recordset for matview.
|
||||||
--returning recordset of buildings aggregates by zres 14, with removed small
|
-- Returning recordset of buildings aggregates by zres 14, with removed small
|
||||||
--holes and with removed small buildings/blocks
|
-- holes and with removed small buildings/blocks.
|
||||||
--
|
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION osm_building_block_gen1()
|
CREATE OR REPLACE FUNCTION osm_building_block_gen1()
|
||||||
RETURNS table
|
RETURNS table
|
||||||
|
@ -20,50 +20,68 @@ $$
|
||||||
DECLARE
|
DECLARE
|
||||||
zres14 float := Zres(14);
|
zres14 float := Zres(14);
|
||||||
zres12 float := Zres(12);
|
zres12 float := Zres(12);
|
||||||
|
zres14vw float := Zres(14) * Zres(14);
|
||||||
|
polyg_world record;
|
||||||
|
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR osm_id, geometry IN
|
FOR polyg_world IN
|
||||||
WITH dta AS ( -- CTE is used because of optimization
|
SELECT ST_Transform(country.geometry, 3857) AS geometry
|
||||||
SELECT o.osm_id, o.geometry, ST_ClusterDBSCAN(o.geometry, eps := zres14, minpoints := 1) OVER () cid
|
FROM country_osm_grid country
|
||||||
FROM osm_building_polygon o
|
|
||||||
)
|
|
||||||
SELECT (array_agg(dta.osm_id))[1] osm_id,
|
|
||||||
ST_Buffer(ST_MemUnion(ST_Buffer(dta.geometry, zres14, 'join=mitre')), -zres14, 'join=mitre') geometry
|
|
||||||
FROM dta
|
|
||||||
GROUP BY cid
|
|
||||||
|
|
||||||
LOOP
|
LOOP
|
||||||
-- removing holes smaller than
|
FOR osm_id, geometry IN
|
||||||
IF ST_NumInteriorRings(geometry) > 0 THEN -- only from geometries wih holes
|
WITH dta AS ( -- CTE is used because of optimization
|
||||||
geometry := (
|
SELECT o.osm_id,
|
||||||
-- there are some multi-geometries in this layer
|
o.geometry,
|
||||||
SELECT ST_Collect(gn)
|
ST_ClusterDBSCAN(o.geometry, eps := zres14, minpoints := 1) OVER () cid
|
||||||
FROM (
|
FROM osm_building_polygon o
|
||||||
-- in some cases are "holes" NULL, because all holes are smaller than
|
WHERE ST_Intersects(o.geometry, polyg_world.geometry)
|
||||||
SELECT COALESCE(
|
)
|
||||||
-- exterior ring
|
SELECT (array_agg(dta.osm_id))[1] AS osm_id,
|
||||||
ST_MakePolygon(ST_ExteriorRing(dmp.geom), holes),
|
ST_Buffer(
|
||||||
ST_MakePolygon(ST_ExteriorRing(dmp.geom))
|
ST_Union(
|
||||||
) gn
|
ST_Buffer(
|
||||||
|
ST_SnapToGrid(dta.geometry, 0.000001)
|
||||||
|
, zres14, 'join=mitre')
|
||||||
|
)
|
||||||
|
, -zres14, 'join=mitre') AS geometry
|
||||||
|
FROM dta
|
||||||
|
GROUP BY cid
|
||||||
|
|
||||||
FROM ST_Dump(geometry) dmp, -- 1 dump polygons
|
LOOP
|
||||||
LATERAL (
|
-- removing holes smaller than
|
||||||
SELECT array_agg(ST_Boundary(rg.geom)) holes -- 2 create array
|
IF ST_NumInteriorRings(geometry) > 0 THEN -- only from geometries wih holes
|
||||||
FROM ST_DumpRings(dmp.geom) rg -- 3 from rings
|
geometry := (
|
||||||
WHERE rg.path[1] > 0 -- 5 except inner ring
|
-- there are some multi-geometries in this layer
|
||||||
AND ST_Area(rg.geom) >= power(zres12, 2) -- 4 bigger than
|
SELECT ST_Collect(gn)
|
||||||
) holes
|
FROM (
|
||||||
) new_geom
|
-- in some cases are "holes" NULL, because all holes are smaller than
|
||||||
);
|
SELECT COALESCE(
|
||||||
END IF;
|
-- exterior ring
|
||||||
|
ST_MakePolygon(ST_ExteriorRing(dmp.geom), holes),
|
||||||
|
ST_MakePolygon(ST_ExteriorRing(dmp.geom))
|
||||||
|
) gn
|
||||||
|
|
||||||
IF ST_Area(geometry) < power(zres12, 2) THEN
|
FROM ST_Dump(geometry) dmp, -- 1 dump polygons
|
||||||
CONTINUE;
|
LATERAL (
|
||||||
END IF;
|
SELECT array_agg(ST_Boundary(rg.geom)) holes -- 2 create array
|
||||||
|
FROM ST_DumpRings(dmp.geom) rg -- 3 from rings
|
||||||
|
WHERE rg.path[1] > 0 -- 5 except inner ring
|
||||||
|
AND ST_Area(rg.geom) >= power(zres12, 2) -- 4 bigger than
|
||||||
|
) holes
|
||||||
|
) new_geom
|
||||||
|
);
|
||||||
|
END IF;
|
||||||
|
|
||||||
-- simplify
|
IF ST_Area(geometry) < power(zres12, 2) THEN
|
||||||
geometry := ST_SimplifyPreserveTopology(geometry, zres14::float);
|
CONTINUE;
|
||||||
|
END IF;
|
||||||
|
|
||||||
RETURN NEXT;
|
-- simplify
|
||||||
|
geometry := ST_SimplifyVW(geometry, zres14vw);
|
||||||
|
|
||||||
|
RETURN NEXT;
|
||||||
|
END LOOP;
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END;
|
END;
|
||||||
$$ LANGUAGE plpgsql STABLE
|
$$ LANGUAGE plpgsql STABLE
|
||||||
|
@ -71,15 +89,52 @@ $$ LANGUAGE plpgsql STABLE
|
||||||
PARALLEL SAFE;
|
PARALLEL SAFE;
|
||||||
|
|
||||||
|
|
||||||
DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen1;
|
DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen1_dup CASCADE;
|
||||||
|
|
||||||
CREATE MATERIALIZED VIEW osm_building_block_gen1 AS
|
CREATE MATERIALIZED VIEW osm_building_block_gen1_dup AS
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM osm_building_block_gen1();
|
FROM osm_building_block_gen1();
|
||||||
|
|
||||||
CREATE INDEX ON osm_building_block_gen1 USING gist (geometry);
|
CREATE INDEX ON osm_building_block_gen1_dup USING gist (geometry);
|
||||||
CREATE UNIQUE INDEX ON osm_building_block_gen1 USING btree (osm_id);
|
|
||||||
|
|
||||||
|
-- etldoc: osm_building_polygon -> osm_building_block_gen_z13
|
||||||
|
DROP MATERIALIZED VIEW IF EXISTS osm_building_block_gen_z13;
|
||||||
|
CREATE MATERIALIZED VIEW osm_building_block_gen_z13 AS
|
||||||
|
(
|
||||||
|
WITH
|
||||||
|
counts AS (
|
||||||
|
SELECT count(osm_id) AS counts,
|
||||||
|
osm_id
|
||||||
|
FROM osm_building_block_gen1_dup
|
||||||
|
GROUP BY osm_id
|
||||||
|
),
|
||||||
|
|
||||||
|
duplicates AS (
|
||||||
|
SELECT counts.osm_id
|
||||||
|
FROM counts
|
||||||
|
WHERE counts.counts > 1
|
||||||
|
)
|
||||||
|
|
||||||
|
SELECT osm.osm_id,
|
||||||
|
ST_Union(
|
||||||
|
ST_MakeValid(osm.geometry)) AS geometry
|
||||||
|
FROM osm_building_block_gen1_dup osm,
|
||||||
|
duplicates
|
||||||
|
WHERE osm.osm_id = duplicates.osm_id
|
||||||
|
GROUP BY osm.osm_id
|
||||||
|
|
||||||
|
UNION ALL
|
||||||
|
|
||||||
|
SELECT osm.osm_id,
|
||||||
|
osm.geometry
|
||||||
|
FROM osm_building_block_gen1_dup osm,
|
||||||
|
counts
|
||||||
|
WHERE counts.counts = 1
|
||||||
|
AND osm.osm_id = counts.osm_id
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX ON osm_building_block_gen_z13 USING gist (geometry);
|
||||||
|
CREATE UNIQUE INDEX ON osm_building_block_gen_z13 USING btree (osm_id);
|
||||||
|
|
||||||
-- Handle updates
|
-- Handle updates
|
||||||
|
|
||||||
|
@ -106,7 +161,8 @@ DECLARE
|
||||||
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
|
t TIMESTAMP WITH TIME ZONE := clock_timestamp();
|
||||||
BEGIN
|
BEGIN
|
||||||
RAISE LOG 'Refresh buildings block';
|
RAISE LOG 'Refresh buildings block';
|
||||||
REFRESH MATERIALIZED VIEW osm_building_block_gen1;
|
REFRESH MATERIALIZED VIEW osm_building_block_gen1_dup;
|
||||||
|
REFRESH MATERIALIZED VIEW osm_building_block_gen_z13;
|
||||||
-- noinspection SqlWithoutWhere
|
-- noinspection SqlWithoutWhere
|
||||||
DELETE FROM buildings.updates;
|
DELETE FROM buildings.updates;
|
||||||
|
|
||||||
|
|
Ładowanie…
Reference in New Issue