|
| 1 | +-- This config example file is released into the Public Domain. |
| 2 | +-- |
| 3 | +-- This Lua config demonstrates the 'grouped-linemerge' generalization. It |
| 4 | +-- merges connected lines that share the same set of grouping columns into |
| 5 | +-- single (multi-)lines, the equivalent of |
| 6 | +-- |
| 7 | +-- SELECT cols..., (ST_Dump(ST_LineMerge(ST_Collect(geom)))).geom |
| 8 | +-- FROM roads GROUP BY cols... |
| 9 | +-- |
| 10 | +-- but done globally and maintained incrementally on updates. A typical use is |
| 11 | +-- merging road segments that render identically (same name/ref/highway/layer) |
| 12 | +-- so that labels and route shields are placed on the whole road instead of on |
| 13 | +-- each individual OSM way, without the artifacts you get when merging only |
| 14 | +-- within a tile. |
| 15 | +-- |
| 16 | +-- NOTE THAT THE GENERALIZATION SUPPORT IS EXPERIMENTAL AND MIGHT CHANGE |
| 17 | +-- WITHOUT NOTICE! |
| 18 | +-- |
| 19 | +-- Workflow: |
| 20 | +-- * Import as usual: osm2pgsql -O flex -S grouped-linemerge.lua DATA.osm.pbf |
| 21 | +-- * Build the merged table: osm2pgsql-gen -S grouped-linemerge.lua |
| 22 | +-- * Apply an update: osm2pgsql -a -O flex -S grouped-linemerge.lua CHANGES.osc.gz |
| 23 | +-- * Update the merged table: osm2pgsql-gen -a -S grouped-linemerge.lua |
| 24 | + |
| 25 | +-- An expire output records which tiles changed during an update. The |
| 26 | +-- grouped-linemerge generalization uses it only as a seed for "where did line |
| 27 | +-- geometry change" - it then walks each affected connected component out from |
| 28 | +-- there and re-merges it. Use a high maxzoom so the seed regions are small. |
| 29 | +local exp_roads = osm2pgsql.define_expire_output({ |
| 30 | + maxzoom = 18, |
| 31 | + table = 'exp_roads', |
| 32 | +}) |
| 33 | + |
| 34 | +-- The source table with the original road segments (one row per OSM way). |
| 35 | +local roads = osm2pgsql.define_table({ |
| 36 | + name = 'roads', |
| 37 | + ids = { type = 'way', id_column = 'way_id' }, |
| 38 | + columns = { |
| 39 | + { column = 'name', type = 'text' }, |
| 40 | + { column = 'ref', type = 'text' }, |
| 41 | + { column = 'highway', type = 'text' }, |
| 42 | + { column = 'layer', type = 'int' }, |
| 43 | + -- Attach the expire output to the geometry so that any change to a |
| 44 | + -- road's geometry (add/modify/delete) expires the tiles it covers. |
| 45 | + { column = 'geom', type = 'linestring', not_null = true, |
| 46 | + expire = { { output = exp_roads } } }, |
| 47 | + } |
| 48 | +}) |
| 49 | + |
| 50 | +-- The destination table with the merged roads. Its columns are exactly the |
| 51 | +-- grouping columns plus the geometry. It has no OSM id column (it is derived |
| 52 | +-- data maintained by osm2pgsql-gen, not by the normal update process); the |
| 53 | +-- warning osm2pgsql prints about that is expected. |
| 54 | +osm2pgsql.define_table({ |
| 55 | + name = 'roads_merged', |
| 56 | + columns = { |
| 57 | + { column = 'name', type = 'text' }, |
| 58 | + { column = 'ref', type = 'text' }, |
| 59 | + { column = 'highway', type = 'text' }, |
| 60 | + { column = 'layer', type = 'int' }, |
| 61 | + { column = 'geom', type = 'linestring', not_null = true }, |
| 62 | + } |
| 63 | +}) |
| 64 | + |
| 65 | +function osm2pgsql.process_way(object) |
| 66 | + local highway = object.tags.highway |
| 67 | + if not highway then |
| 68 | + return |
| 69 | + end |
| 70 | + roads:insert({ |
| 71 | + name = object.tags.name, |
| 72 | + ref = object.tags.ref, |
| 73 | + highway = highway, |
| 74 | + layer = tonumber(object.tags.layer), |
| 75 | + geom = object:as_linestring(), |
| 76 | + }) |
| 77 | +end |
| 78 | + |
| 79 | +function osm2pgsql.process_gen() |
| 80 | + osm2pgsql.run_gen('grouped-linemerge', { |
| 81 | + name = 'roads', -- name (for logging) |
| 82 | + debug = false, -- set to true for more detailed debug output |
| 83 | + src_table = 'roads', -- input table with the line segments |
| 84 | + dest_table = 'roads_merged', -- output table for the merged lines |
| 85 | + geom_column = 'geom', -- geometry column (same in src and dest) |
| 86 | + |
| 87 | + -- Lines are merged when ALL of these columns are equal (NULLs compare |
| 88 | + -- equal). Pass them as a comma-separated list. |
| 89 | + group_by_columns = 'name, ref, highway, layer', |
| 90 | + |
| 91 | + -- Optional pre-filter (SQL boolean expression on the source columns). |
| 92 | + -- Lines not matching are completely excluded from the generalization. |
| 93 | + -- Here we only merge roads that carry a label or a shield. |
| 94 | + where = 'name IS NOT NULL OR ref IS NOT NULL', |
| 95 | + |
| 96 | + -- In append mode, where to read the expired tiles from, and the zoom |
| 97 | + -- level they were captured at (must match the expire output's maxzoom). |
| 98 | + expire_list = 'exp_roads', |
| 99 | + zoom = 18, |
| 100 | + |
| 101 | + -- Create functional endpoint indexes on the src/dest tables in create |
| 102 | + -- mode. These make the incremental component walk fast. Set to false |
| 103 | + -- if you manage the indexes yourself. |
| 104 | + create_indexes = true, |
| 105 | + }) |
| 106 | +end |
0 commit comments