Skip to content

Commit 384739d

Browse files
authored
Merge pull request #1736 from joto/wip-geom-flex
Add geometry functions in Lua / new insert syntax
2 parents f9cdadd + 6642d04 commit 384739d

19 files changed

Lines changed: 1248 additions & 14 deletions

flex-config/new-insert-syntax.lua

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
-- This config example file is released into the Public Domain.
2+
3+
-- This is Lua config showing the handling of custom geometries.
4+
--
5+
-- This is "work in progress", changes are possible.
6+
--
7+
-- Note that the insert() function is used instead of the old add_row()!
8+
9+
-- The following magic can be used to wrap the internal "insert" function
10+
local orig_insert = osm2pgsql.Table.insert
11+
local function my_insert(table, data)
12+
local json = require 'json'
13+
inserted, message, column, object = orig_insert(table, data)
14+
if not inserted then
15+
for key, value in pairs(data) do
16+
if type(value) == 'userdata' then
17+
data[key] = tostring(value)
18+
end
19+
end
20+
print("insert() failed: " .. message .. " column='" .. column .. "' object='" .. json.encode(object) .. "' data='" .. json.encode(data) .. "'")
21+
end
22+
end
23+
osm2pgsql.Table.insert = my_insert
24+
25+
26+
local tables = {}
27+
28+
-- This table will get all nodes and areas with an "addr:street" tag, for
29+
-- areas we'll calculate the centroid.
30+
tables.addr = osm2pgsql.define_table({
31+
name = 'addr',
32+
ids = { type = 'any', id_column = 'osm_id', type_column = 'osm_type' },
33+
columns = {
34+
{ column = 'tags', type = 'jsonb' },
35+
{ column = 'geom', type = 'point', projection = 4326 },
36+
}
37+
})
38+
39+
tables.ways = osm2pgsql.define_way_table('ways', {
40+
{ column = 'tags', type = 'jsonb' },
41+
{ column = 'geom', type = 'linestring', projection = 4326 },
42+
{ column = 'poly', type = 'polygon', projection = 4326 },
43+
{ column = 'geom3857', type = 'linestring', projection = 3857 },
44+
{ column = 'geomautoproj', type = 'linestring', projection = 3857 },
45+
})
46+
47+
tables.major_roads = osm2pgsql.define_way_table('major_roads', {
48+
{ column = 'tags', type = 'jsonb' },
49+
{ column = 'geom', type = 'linestring' },
50+
{ column = 'sgeom', type = 'linestring' }
51+
})
52+
53+
tables.polygons = osm2pgsql.define_area_table('polygons', {
54+
{ column = 'tags', type = 'jsonb' },
55+
{ column = 'geom', type = 'geometry', not_null = true },
56+
{ column = 'area4326', type = 'real' },
57+
{ column = 'area3857', type = 'real' }
58+
})
59+
60+
tables.routes = osm2pgsql.define_relation_table('routes', {
61+
{ column = 'tags', type = 'jsonb' },
62+
{ column = 'geom', type = 'multilinestring', projection = 4326 },
63+
})
64+
65+
tables.route_parts = osm2pgsql.define_relation_table('route_parts', {
66+
{ column = 'tags', type = 'jsonb' },
67+
{ column = 'geom', type = 'linestring', projection = 4326 },
68+
})
69+
70+
-- Helper function to remove some of the tags we usually are not interested in.
71+
-- Returns true if there are no tags left.
72+
function clean_tags(tags)
73+
tags.odbl = nil
74+
tags.created_by = nil
75+
tags.source = nil
76+
tags['source:ref'] = nil
77+
78+
return next(tags) == nil
79+
end
80+
81+
-- Helper function that looks at the tags and decides if this is possibly
82+
-- an area.
83+
function has_area_tags(tags)
84+
if tags.area == 'yes' then
85+
return true
86+
end
87+
if tags.area == 'no' then
88+
return false
89+
end
90+
91+
return tags.aeroway
92+
or tags.amenity
93+
or tags.building
94+
or tags.harbour
95+
or tags.historic
96+
or tags.landuse
97+
or tags.leisure
98+
or tags.man_made
99+
or tags.military
100+
or tags.natural
101+
or tags.office
102+
or tags.place
103+
or tags.power
104+
or tags.public_transport
105+
or tags.shop
106+
or tags.sport
107+
or tags.tourism
108+
or tags.water
109+
or tags.waterway
110+
or tags.wetland
111+
or tags['abandoned:aeroway']
112+
or tags['abandoned:amenity']
113+
or tags['abandoned:building']
114+
or tags['abandoned:landuse']
115+
or tags['abandoned:power']
116+
or tags['area:highway']
117+
end
118+
119+
function osm2pgsql.process_node(object)
120+
if clean_tags(object.tags) then
121+
return
122+
end
123+
124+
if object.tags['addr:street'] then
125+
tables.addr:insert({
126+
tags = object.tags,
127+
geom = object:as_point()
128+
})
129+
end
130+
end
131+
132+
function osm2pgsql.process_way(object)
133+
if clean_tags(object.tags) then
134+
return
135+
end
136+
137+
if object.is_closed and object.tags['addr:street'] then
138+
tables.addr:insert({
139+
tags = object.tags,
140+
geom = object:as_polygon():centroid()
141+
})
142+
end
143+
144+
if object.tags.highway == 'motorway' or
145+
object.tags.highway == 'trunk' or
146+
object.tags.highway == 'primary' then
147+
tables.major_roads:insert({
148+
tags = object.tags,
149+
geom = object:as_linestring(),
150+
sgeom = object:as_linestring():simplify(100),
151+
})
152+
end
153+
154+
-- A closed way that also has the right tags for an area is a polygon.
155+
if object.is_closed and has_area_tags(object.tags) then
156+
local g = object:as_polygon()
157+
local a = g:area()
158+
if a < 0.0000001 then
159+
tables.polygons:insert({
160+
tags = object.tags,
161+
geom = g,
162+
area4326 = a,
163+
area3857 = g:transform(3857):area()
164+
})
165+
end
166+
else
167+
tables.ways:insert({
168+
tags = object.tags,
169+
geom = object:as_linestring(),
170+
poly = object:as_polygon(),
171+
geom3857 = object:as_linestring():transform(3857), -- project geometry into target srid 3857
172+
geomautoproj = object:as_linestring() -- automatically projected into projection of target column
173+
})
174+
end
175+
end
176+
177+
function osm2pgsql.process_relation(object)
178+
if clean_tags(object.tags) then
179+
return
180+
end
181+
182+
local relation_type = object:grab_tag('type')
183+
184+
if relation_type == 'multipolygon' then
185+
local g = object:as_multipolygon()
186+
local a = g:area()
187+
if a < 0.0000001 then
188+
tables.polygons:insert({
189+
tags = object.tags,
190+
geom = g,
191+
area4326 = a,
192+
area3857 = g:transform(3857):area()
193+
})
194+
end
195+
return
196+
end
197+
198+
if relation_type == 'route' then
199+
local route_geom = object:as_multilinestring()
200+
if not route_geom:is_null() then
201+
tables.routes:insert({
202+
tags = object.tags,
203+
geom = route_geom
204+
})
205+
for line in route_geom:geometries() do
206+
tables.route_parts:insert({
207+
tags = object.tags,
208+
geom = line
209+
})
210+
end
211+
end
212+
end
213+
end
214+

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ if (WITH_LUA)
4848
target_sources(osm2pgsql_lib PRIVATE
4949
flex-table.cpp
5050
flex-table-column.cpp
51+
flex-lua-geom.cpp
5152
geom-transform.cpp
5253
lua-utils.cpp
5354
output-flex.cpp

0 commit comments

Comments
 (0)