flex.lua

changeset 1
959dc869b765
parent 0
b0eb3af2f9ee
child 2
8d4148a8ded4
equal deleted inserted replaced
0:b0eb3af2f9ee 1:959dc869b765
37 local enable_legacy_route_processing = false 37 local enable_legacy_route_processing = false
38 38
39 -- --------------------------------------------------------------------------- 39 -- ---------------------------------------------------------------------------
40 40
41 if hstore and hstore_all then 41 if hstore and hstore_all then
42 error("hstore and hstore_all can't be both true") 42 error("hstore and hstore_all can't be both true")
43 end 43 end
44 44
45 -- Used for splitting up long linestrings 45 -- Used for splitting up long linestrings
46 if osm2pgsql.srid == 4326 then 46 if osm2pgsql.srid == 4326 then
47 max_length = 1 47 max_length = 1
48 else 48 else
49 max_length = 100000 49 max_length = 100000
50 end 50 end
51 51
52 -- Ways with any of the following keys will be treated as polygon 52 -- Ways with any of the following keys will be treated as polygon
53 local polygon_keys = { 53 local polygon_keys = {
54 'aeroway', 54 'aeroway',
55 'amenity', 55 'amenity',
56 'building', 56 'building',
57 'harbour', 57 'harbour',
58 'historic', 58 'historic',
59 'landuse', 59 'landuse',
60 'leisure', 60 'leisure',
61 'man_made', 61 'man_made',
62 'military', 62 'military',
63 'natural', 63 'natural',
64 'office', 64 'office',
65 'place', 65 'place',
66 'power', 66 'power',
67 'public_transport', 67 'public_transport',
68 'shop', 68 'shop',
69 'sport', 69 'sport',
70 'tourism', 70 'tourism',
71 'water', 71 'water',
72 'waterway', 72 'waterway',
73 'wetland', 73 'wetland',
74 'abandoned:aeroway', 74 'abandoned:aeroway',
75 'abandoned:amenity', 75 'abandoned:amenity',
76 'abandoned:building', 76 'abandoned:building',
77 'abandoned:landuse', 77 'abandoned:landuse',
78 'abandoned:power', 78 'abandoned:power',
79 'area:highway' 79 'area:highway'
80 } 80 }
81 81
82 -- Objects without any of the following keys will be deleted 82 -- Objects without any of the following keys will be deleted
83 local generic_keys = { 83 local generic_keys = {
84 'access', 84 'access',
85 'addr:housename', 85 'addr:housename',
86 'addr:housenumber', 86 'addr:housenumber',
87 'addr:interpolation', 87 'addr:interpolation',
88 'admin_level', 88 'admin_level',
89 'aerialway', 89 'aerialway',
90 'aeroway', 90 'aeroway',
91 'amenity', 91 'amenity',
92 'area', 92 'area',
93 'barrier', 93 'barrier',
94 'bicycle', 94 'bicycle',
95 'boundary', 95 'boundary',
96 'brand', 96 'brand',
97 'bridge', 97 'bridge',
98 'building', 98 'building',
99 'capital', 99 'capital',
100 'construction', 100 'construction',
101 'covered', 101 'covered',
102 'culvert', 102 'culvert',
103 'cutting', 103 'cutting',
104 'denomination', 104 'denomination',
105 'disused', 105 'disused',
106 'ele', 106 'ele',
107 'embankment', 107 'embankment',
108 'foot', 108 'foot',
109 'generation:source', 109 'generation:source',
110 'harbour', 110 'harbour',
111 'healthcare', 111 'healthcare',
112 'highway', 112 'highway',
113 'historic', 113 'historic',
114 'hours', 114 'hours',
115 'intermittent', 115 'intermittent',
116 'junction', 116 'junction',
117 'landuse', 117 'landuse',
118 'layer', 118 'layer',
119 'leisure', 119 'leisure',
120 'lock', 120 'lock',
121 'man_made', 121 'man_made',
122 'military', 122 'military',
123 'motorcar', 123 'motorcar',
124 'name', 124 'name',
125 'natural', 125 'natural',
126 'office', 126 'office',
127 'oneway', 127 'oneway',
128 'operator', 128 'operator',
129 'place', 129 'place',
130 'population', 130 'population',
131 'power', 131 'power',
132 'power_source', 132 'power_source',
133 'public_transport', 133 'public_transport',
134 'railway', 134 'railway',
135 'ref', 135 'ref',
136 'religion', 136 'religion',
137 'route', 137 'route',
138 'service', 138 'service',
139 'shop', 139 'shop',
140 'sport', 140 'sport',
141 'surface', 141 'surface',
142 'toll', 142 'toll',
143 'tourism', 143 'tourism',
144 'tower:type', 144 'tower:type',
145 'tracktype', 145 'tracktype',
146 'tunnel', 146 'tunnel',
147 'water', 147 'water',
148 'waterway', 148 'waterway',
149 'wetland', 149 'wetland',
150 'width', 150 'width',
151 'wood', 151 'wood',
152 'abandoned:aeroway', 152 'abandoned:aeroway',
153 'abandoned:amenity', 153 'abandoned:amenity',
154 'abandoned:building', 154 'abandoned:building',
155 'abandoned:landuse', 155 'abandoned:landuse',
156 'abandoned:power', 156 'abandoned:power',
157 'area:highway' 157 'area:highway'
158 } 158 }
159 159
160 -- The following keys will be deleted 160 -- The following keys will be deleted
161 local delete_keys = { 161 local delete_keys = {
162 'attribution', 162 'attribution',
163 'comment', 163 'comment',
164 'created_by', 164 'created_by',
165 'fixme', 165 'fixme',
166 'note', 166 'note',
167 'note:*', 167 'note:*',
168 'odbl', 168 'odbl',
169 'odbl:note', 169 'odbl:note',
170 'source', 170 'source',
171 'source:*', 171 'source:*',
172 'source_ref', 172 'source_ref',
173 'way', 173 'way',
174 'way_area', 174 'way_area',
175 'z_order', 175 'z_order',
176 } 176 }
177 177
178 local point_columns = { 178 local point_columns = {
179 'access', 179 'access',
180 'addr:housename', 180 'addr:housename',
181 'addr:housenumber', 181 'addr:housenumber',
182 'addr:interpolation', 182 'addr:interpolation',
183 'admin_level', 183 'admin_level',
184 'aerialway', 184 'aerialway',
185 'aeroway', 185 'aeroway',
186 'amenity', 186 'amenity',
187 'area', 187 'area',
188 'barrier', 188 'barrier',
189 'bicycle', 189 'bicycle',
190 'brand', 190 'brand',
191 'bridge', 191 'bridge',
192 'boundary', 192 'boundary',
193 'building', 193 'building',
194 'capital', 194 'capital',
195 'construction', 195 'construction',
196 'covered', 196 'covered',
197 'culvert', 197 'culvert',
198 'cutting', 198 'cutting',
199 'denomination', 199 'denomination',
200 'disused', 200 'disused',
201 'ele', 201 'ele',
202 'embankment', 202 'embankment',
203 'foot', 203 'foot',
204 'generator:source', 204 'generator:source',
205 'harbour', 205 'harbour',
206 'highway', 206 'highway',
207 'historic', 207 'historic',
208 'horse', 208 'horse',
209 'intermittent', 209 'intermittent',
210 'junction', 210 'junction',
211 'landuse', 211 'landuse',
212 'layer', 212 'layer',
213 'leisure', 213 'leisure',
214 'lock', 214 'lock',
215 'man_made', 215 'man_made',
216 'military', 216 'military',
217 'motorcar', 217 'motorcar',
218 'name', 218 'name',
219 'name:fi', 219 'name:fi',
220 'name:sv', 220 'name:sv',
221 'minority_name', 221 'minority_name',
222 'majority_name', 222 'majority_name',
223 'bilingual_name', 223 'bilingual_name',
224 'natural', 224 'natural',
225 'office', 225 'office',
226 'oneway', 226 'oneway',
227 'operator', 227 'operator',
228 'place', 228 'place',
229 'population', 229 'population',
230 'power', 230 'power',
231 'power_source', 231 'power_source',
232 'public_transport', 232 'public_transport',
233 'railway', 233 'railway',
234 'ref', 234 'ref',
235 'religion', 235 'religion',
236 'route', 236 'route',
237 'service', 237 'service',
238 'shop', 238 'shop',
239 'sport', 239 'sport',
240 'surface', 240 'surface',
241 'toll', 241 'toll',
242 'tourism', 242 'tourism',
243 'tower:type', 243 'tower:type',
244 'tunnel', 244 'tunnel',
245 'water', 245 'water',
246 'waterway', 246 'waterway',
247 'wetland', 247 'wetland',
248 'width', 248 'width',
249 'wood', 249 'wood',
250 } 250 }
251 251
252 local non_point_columns = { 252 local non_point_columns = {
253 'access', 253 'access',
254 'addr:housename', 254 'addr:housename',
255 'addr:housenumber', 255 'addr:housenumber',
256 'addr:interpolation', 256 'addr:interpolation',
257 'admin_level', 257 'admin_level',
258 'aerialway', 258 'aerialway',
259 'aeroway', 259 'aeroway',
260 'amenity', 260 'amenity',
261 'area', 261 'area',
262 'barrier', 262 'barrier',
263 'bicycle', 263 'bicycle',
264 'brand', 264 'brand',
265 'bridge', 265 'bridge',
266 'boundary', 266 'boundary',
267 'building', 267 'building',
268 'construction', 268 'construction',
269 'covered', 269 'covered',
270 'culvert', 270 'culvert',
271 'cutting', 271 'cutting',
272 'denomination', 272 'denomination',
273 'disused', 273 'disused',
274 'embankment', 274 'embankment',
275 'foot', 275 'foot',
276 'generator:source', 276 'generator:source',
277 'harbour', 277 'harbour',
278 'highway', 278 'highway',
279 'historic', 279 'historic',
280 'horse', 280 'horse',
281 'intermittent', 281 'intermittent',
282 'junction', 282 'junction',
283 'landuse', 283 'landuse',
284 'layer', 284 'layer',
285 'leisure', 285 'leisure',
286 'lock', 286 'lock',
287 'man_made', 287 'man_made',
288 'military', 288 'military',
289 'motorcar', 289 'motorcar',
290 'name', 290 'name',
291 'name:fi', 291 'name:fi',
292 'name:sv', 292 'name:sv',
293 'minority_name', 293 'minority_name',
294 'majority_name', 294 'majority_name',
295 'bilingual_name', 295 'bilingual_name',
296 'natural', 296 'natural',
297 'office', 297 'office',
298 'oneway', 298 'oneway',
299 'operator', 299 'operator',
300 'place', 300 'place',
301 'population', 301 'population',
302 'power', 302 'power',
303 'power_source', 303 'power_source',
304 'public_transport', 304 'public_transport',
305 'railway', 305 'railway',
306 'ref', 306 'ref',
307 'ref_class', 307 'ref_class',
308 'ref_width', 308 'ref_width',
309 'religion', 309 'religion',
310 'route', 310 'route',
311 'service', 311 'service',
312 'shop', 312 'shop',
313 'sport', 313 'sport',
314 'surface', 314 'surface',
315 'toll', 315 'toll',
316 'tourism', 316 'tourism',
317 'tower:type', 317 'tower:type',
318 'tracktype', 318 'tracktype',
319 'tunnel', 319 'tunnel',
320 'water', 320 'water',
321 'waterway', 321 'waterway',
322 'wetland', 322 'wetland',
323 'width', 323 'width',
324 'wood', 324 'wood',
325 } 325 }
326 326
327 -- highlight some suburbs in the capital region 327 -- highlight some suburbs in the capital region
328 boroughs = { 328 boroughs = {
329 -- Helsinki 329 -- Helsinki
330 ["Q2116584"] = 1, -- Vuosaari / Nordsjö 330 ["Q2116584"] = 1, -- Vuosaari / Nordsjö
331 ["Q2510635"] = 1, -- Oulunkylä / Åggelby 331 ["Q2510635"] = 1, -- Oulunkylä / Åggelby
332 ["Q3130945"] = 1, -- Viikki / Vik 332 ["Q3130945"] = 1, -- Viikki / Vik
333 ["Q1614778"] = 1, -- Herttoniemi / Hertonäs 333 ["Q1614778"] = 1, -- Herttoniemi / Hertonäs
334 -- Espoo 334 -- Espoo
335 ["Q166942"] = 1, -- Leppävaara / Alberga 335 ["Q166942"] = 1, -- Leppävaara / Alberga
336 ["Q3107346"] = 1, -- Matinkylä / Mattby 336 ["Q3107346"] = 1, -- Matinkylä / Mattby
337 ["Q211491"] = 1, -- Espoonlahti / Esboviken 337 ["Q211491"] = 1, -- Espoonlahti / Esboviken
338 ["Q211489"] = 1, -- Espoon keskus / Esbo centrum 338 ["Q211489"] = 1, -- Espoon keskus / Esbo centrum
339 ["Q219044"] = 1, -- Kauklahti / Köklax 339 ["Q219044"] = 1, -- Kauklahti / Köklax
340 ["Q1668730"] = 1, -- Tapiola / Hagalund 340 ["Q1668730"] = 1, -- Tapiola / Hagalund
341 -- Vantaa 341 -- Vantaa
342 ["Q2640455"] = 1, -- Tikkurila / Dickursby 342 ["Q2640455"] = 1, -- Tikkurila / Dickursby
343 ["Q4412122"] = 1, -- Aviapolis 343 ["Q4412122"] = 1, -- Aviapolis
344 ["Q3736737"] = 1, -- Myyrmäki / Myrbacka 344 ["Q3736737"] = 1, -- Myyrmäki / Myrbacka
345 ["Q4557316"] = 1, -- Kivistö 345 ["Q4557316"] = 1, -- Kivistö
346 ["Q4556551"] = 1, -- Koivukylä / Björkby 346 ["Q4556551"] = 1, -- Koivukylä / Björkby
347 ["Q3742144"] = 1, -- Korso 347 ["Q3742144"] = 1, -- Korso
348 ["Q4556262"] = 1, -- Hakunila / Håkansböle 348 ["Q4556262"] = 1, -- Hakunila / Håkansböle
349 } 349 }
350 350
351 -- 351 --
352 -- Name in majority language for object. This is name unless both name:fi and 352 -- Name in majority language for object. This is name unless both name:fi and
353 -- name:sv disagree with name. 353 -- name:sv disagree with name.
354 -- @param tags Raw OSM tags 354 -- @param tags Raw OSM tags
355 -- @return Bilingual name 355 -- @return Bilingual name
356 -- 356 --
357 function majority_name(tags) 357 function majority_name(tags)
358 if tags.name ~= nil and tags['name:sv'] ~= nil and tags['name:fi'] and tags.name ~= tags['name:fi'] and tags.name ~= tags['name:sv'] 358 if tags.name ~= nil and tags['name:sv'] ~= nil and tags['name:fi'] and tags.name ~= tags['name:fi'] and tags.name ~= tags['name:sv']
359 then 359 then
360 return tags['name:fi'] 360 return tags['name:fi']
361 else 361 else
362 return tags.name 362 return tags.name
363 end 363 end
364 end 364 end
365 -- 365 --
366 -- Name in minority language for object. This is the Swedish name if name is in 366 -- Name in minority language for object. This is the Swedish name if name is in
367 -- Finnish, and the Finnish name if name is in Swedish. 367 -- Finnish, and the Finnish name if name is in Swedish.
368 -- @param tags Raw OSM tags 368 -- @param tags Raw OSM tags
369 -- @return Bilingual name 369 -- @return Bilingual name
370 -- 370 --
371 function minority_name(tags) 371 function minority_name(tags)
372 if tags['name:sv'] ~= nil and tags['name'] ~= tags['name:sv'] 372 if tags['name:sv'] ~= nil and tags['name'] ~= tags['name:sv']
373 then 373 then
374 return tags['name:sv'] 374 return tags['name:sv']
375 elseif tags['name:fi'] ~= nil and tags['name'] ~= tags['name:fi'] 375 elseif tags['name:fi'] ~= nil and tags['name'] ~= tags['name:fi']
376 then 376 then
377 return tags['name:fi'] 377 return tags['name:fi']
378 else 378 else
379 return nil 379 return nil
380 end 380 end
381 end 381 end
382 382
383 function bilingual_name(tags) 383 function bilingual_name(tags)
384 if tags.majority_name ~= nil and tags.minority_name ~= nil 384 if tags.majority_name ~= nil and tags.minority_name ~= nil
385 then 385 then
386 return tags.majority_name .. '\n' .. tags.minority_name 386 return tags.majority_name .. '\n' .. tags.minority_name
387 else 387 else
388 return tags.majority_name 388 return tags.majority_name
389 end 389 end
390 end 390 end
391 391
392 -- Makes highway classes more sensible 392 -- Makes highway classes more sensible
393 function highway_class(tags) 393 function highway_class(tags)
394 if string.match(tags.highway, '_link$') 394 if string.match(tags.highway, '_link$')
395 then 395 then
396 if tags.tags.functional_class == 'service' or tags.tags.functional_class == 'unclassified' 396 if tags.tags.functional_class == 'service' or tags.tags.functional_class == 'unclassified'
397 then 397 then
398 return tags.tags.functional_class 398 return tags.tags.functional_class
399 elseif tags.tags.functional_class ~= nil 399 elseif tags.tags.functional_class ~= nil
400 then 400 then
401 return tags.tags.functional_class..'_link' 401 return tags.tags.functional_class..'_link'
402 elseif tags.highway == 'motorway_link' 402 elseif tags.highway == 'motorway_link'
403 then 403 then
404 return 'trunk_link' 404 return 'trunk_link'
405 else 405 else
406 return tags.highway 406 return tags.highway
407 end 407 end
408 elseif tags.highway == 'motorway' 408 elseif tags.highway == 'motorway'
409 then 409 then
410 if tags.tags.functional_class == 'primary' or tags.tags.functional_class == 'secondary' or tags.tags.functional_class == 'tertiary' 410 if tags.tags.functional_class == 'primary' or tags.tags.functional_class == 'secondary' or tags.tags.functional_class == 'tertiary'
411 then 411 then
412 return tags.tags.functional_class 412 return tags.tags.functional_class
413 elseif tags.tags.functional_class == 'service' 413 elseif tags.tags.functional_class == 'service'
414 then 414 then
415 return 'service' 415 return 'service'
416 else 416 else
417 return 'trunk' 417 return 'trunk'
418 end 418 end
419 else 419 else
420 if tags.highway ~= nil and tags.tags.functional_class ~= nil 420 if tags.highway ~= nil and tags.tags.functional_class ~= nil
421 then 421 then
422 return tags.tags.functional_class 422 return tags.tags.functional_class
423 else 423 else
424 return tags.highway 424 return tags.highway
425 end 425 end
426 end 426 end
427 end 427 end
428 428
429 function has_shields(tags) 429 function has_shields(tags)
430 return (tags.highway == 'trunk' or tags.highway == 'primary' or tags.highway == 'secondary' or tags.highway == 'tertiary') 430 return (tags.highway == 'trunk' or tags.highway == 'primary' or tags.highway == 'secondary' or tags.highway == 'tertiary')
431 end 431 end
432 432
433 -- https://stackoverflow.com/a/7615129 433 -- https://stackoverflow.com/a/7615129
434 function mysplit(inputstr, sep) 434 function mysplit(inputstr, sep)
435 if sep == nil then 435 if sep == nil then
436 sep = "%s" 436 sep = "%s"
437 end 437 end
438 local t={} 438 local t={}
439 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do 439 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
440 table.insert(t, str) 440 table.insert(t, str)
441 end 441 end
442 return t 442 return t
443 end 443 end
444 444
445 function combine_stringlists(a, b) 445 function combine_stringlists(a, b)
446 if a ~= nil and a ~= '' 446 if a ~= nil and a ~= ''
447 then 447 then
448 if b ~= nil and b ~= '' 448 if b ~= nil and b ~= ''
449 then 449 then
450 return a..';'..b 450 return a..';'..b
451 else 451 else
452 return a 452 return a
453 end 453 end
454 else 454 else
455 return b 455 return b
456 end 456 end
457 end 457 end
458 458
459 function combine_refs(a, b) 459 function combine_refs(a, b)
460 return combine_stringlists(a, b) 460 return combine_stringlists(a, b)
461 end 461 end
462 462
463 -- Widths of ref characters in Liikenne font, used to calculate shield sizes 463 -- Widths of ref characters in Liikenne font, used to calculate shield sizes
464 character_widths = { 464 character_widths = {
465 ['0'] = 616, 465 ['0'] = 616,
466 ['1'] = 337, 466 ['1'] = 337,
467 ['2'] = 600, 467 ['2'] = 600,
468 ['3'] = 621, 468 ['3'] = 621,
469 ['4'] = 689, 469 ['4'] = 689,
470 ['5'] = 623, 470 ['5'] = 623,
471 ['6'] = 566, 471 ['6'] = 566,
472 ['7'] = 499, 472 ['7'] = 499,
473 ['8'] = 616, 473 ['8'] = 616,
474 ['9'] = 566, 474 ['9'] = 566,
475 [' '] = 260, 475 [' '] = 260,
476 ['E'] = 613, 476 ['E'] = 613,
477 } 477 }
478 478
479 function ref_width(ref) 479 function ref_width(ref)
480 local result = 0 480 local result = 0
481 for i = 1, #ref 481 for i = 1, #ref
482 do 482 do
483 result = result + (character_widths[ref:sub(i, i)] or 0) 483 result = result + (character_widths[ref:sub(i, i)] or 0)
484 end 484 end
485 return math.max(math.ceil((result - 1000) / 77), 1) 485 return math.max(math.ceil((result - 1000) / 77), 1)
486 end 486 end
487 487
488 function ref_widths(refs) 488 function ref_widths(refs)
489 local result = '' 489 local result = ''
490 for _, ref in ipairs(mysplit(refs, ';')) 490 for _, ref in ipairs(mysplit(refs, ';'))
491 do 491 do
492 result = combine_stringlists(result, ref_width(ref)) 492 result = combine_stringlists(result, ref_width(ref))
493 end 493 end
494 return result 494 return result
495 end 495 end
496 496
497 -- Makes refs more sensible. 497 -- Makes refs more sensible.
498 -- 5-digit refs are not found on the ground so they are omitted. 498 -- 5-digit refs are not found on the ground so they are omitted.
499 -- int_ref is added to refs. 499 -- int_ref is added to refs.
500 function highway_refs(tags) 500 function highway_refs(tags)
501 if has_shields(tags) and (tags.ref ~= nil or tags.tags.int_ref ~= nil) 501 if has_shields(tags) and (tags.ref ~= nil or tags.tags.int_ref ~= nil)
502 then 502 then
503 if tags.junction == 'roundabout' 503 if tags.junction == 'roundabout'
504 then 504 then
505 return nil 505 return nil
506 else 506 else
507 local result = '' 507 local result = ''
508 local all_refs = combine_refs(tags.ref, tags.tags.int_ref) 508 local all_refs = combine_refs(tags.ref, tags.tags.int_ref)
509 for _, ref in ipairs(mysplit(all_refs, ';')) 509 for _, ref in ipairs(mysplit(all_refs, ';'))
510 do 510 do
511 if tonumber(ref) == nil or tonumber(ref) < 10000 511 if tonumber(ref) == nil or tonumber(ref) < 10000
512 then 512 then
513 ref = string.gsub(ref, '^E 0', 'E ') 513 ref = string.gsub(ref, '^E 0', 'E ')
514 result = combine_refs(result, ref) 514 result = combine_refs(result, ref)
515 end 515 end
516 end 516 end
517 return result 517 return result
518 end 518 end
519 else 519 else
520 return tags.ref 520 return tags.ref
521 end 521 end
522 end 522 end
523 523
524 -- classify road type by number 524 -- classify road type by number
525 function road_class_by_ref(ref) 525 function road_class_by_ref(ref)
526 local n = tonumber(ref) 526 local n = tonumber(ref)
527 if n ~= nil and n > 0 527 if n ~= nil and n > 0
528 then 528 then
529 if n < 40 529 if n < 40
530 then 530 then
531 return 'valtatie' 531 return 'valtatie'
532 elseif n < 100 532 elseif n < 100
533 then 533 then
534 return 'kantatie' 534 return 'kantatie'
535 elseif n < 1000 535 elseif n < 1000
536 then 536 then
537 return 'seututie' 537 return 'seututie'
538 else 538 else
539 return 'yhdystie' 539 return 'yhdystie'
540 end 540 end
541 elseif string.match(ref, '^E ?%d+$') 541 elseif string.match(ref, '^E ?%d+$')
542 then 542 then
543 return 'eurooppatie' 543 return 'eurooppatie'
544 else 544 else
545 return 'unknown' 545 return 'unknown'
546 end 546 end
547 end 547 end
548 548
549 function classify_road_numbers(refs) 549 function classify_road_numbers(refs)
550 local result = '' 550 local result = ''
551 for _, ref in ipairs(mysplit(refs, ';')) 551 for _, ref in ipairs(mysplit(refs, ';'))
552 do 552 do
553 result = combine_stringlists(result, road_class_by_ref(ref)) 553 result = combine_stringlists(result, road_class_by_ref(ref))
554 end 554 end
555 return result 555 return result
556 end 556 end
557 557
558 function gen_columns(text_columns, with_hstore, area, geometry_type) 558 function gen_columns(text_columns, with_hstore, area, geometry_type)
559 columns = {} 559 columns = {}
560 560
561 local add_column = function (name, type) 561 local add_column = function (name, type)
562 columns[#columns + 1] = { column = name, type = type } 562 columns[#columns + 1] = { column = name, type = type }
563 end 563 end
564 564
565 for _, c in ipairs(text_columns) do 565 for _, c in ipairs(text_columns) do
566 add_column(c, 'text') 566 add_column(c, 'text')
567 end 567 end
568 568
569 add_column('z_order', 'int') 569 add_column('z_order', 'int')
570 570
571 if area ~= nil then 571 if area ~= nil then
572 if area then 572 if area then
573 add_column('way_area', 'area') 573 add_column('way_area', 'area')
574 else 574 else
575 add_column('way_area', 'real') 575 add_column('way_area', 'real')
576 end 576 end
577 end 577 end
578 578
579 if hstore_column then 579 if hstore_column then
580 add_column(hstore_column, 'hstore') 580 add_column(hstore_column, 'hstore')
581 end 581 end
582 582
583 if with_hstore then 583 if with_hstore then
584 add_column('tags', 'hstore') 584 add_column('tags', 'hstore')
585 end 585 end
586 586
587 add_column('way', geometry_type) 587 add_column('way', geometry_type)
588 588
589 return columns 589 return columns
590 end 590 end
591 591
592 local tables = {} 592 local tables = {}
593 593
594 tables.point = osm2pgsql.define_table{ 594 tables.point = osm2pgsql.define_table{
595 name = prefix .. '_point', 595 name = prefix .. '_point',
596 ids = { type = 'node', id_column = 'osm_id' }, 596 ids = { type = 'node', id_column = 'osm_id' },
597 columns = gen_columns(point_columns, hstore or hstore_all, nil, 'point') 597 columns = gen_columns(point_columns, hstore or hstore_all, nil, 'point')
598 } 598 }
599 599
600 tables.line = osm2pgsql.define_table{ 600 tables.line = osm2pgsql.define_table{
601 name = prefix .. '_line', 601 name = prefix .. '_line',
602 ids = { type = 'way', id_column = 'osm_id' }, 602 ids = { type = 'way', id_column = 'osm_id' },
603 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring') 603 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring')
604 } 604 }
605 605
606 tables.polygon = osm2pgsql.define_table{ 606 tables.polygon = osm2pgsql.define_table{
607 name = prefix .. '_polygon', 607 name = prefix .. '_polygon',
608 ids = { type = 'area', id_column = 'osm_id' }, 608 ids = { type = 'area', id_column = 'osm_id' },
609 columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'geometry') 609 columns = gen_columns(non_point_columns, hstore or hstore_all, true, 'geometry')
610 } 610 }
611 611
612 tables.roads = osm2pgsql.define_table{ 612 tables.roads = osm2pgsql.define_table{
613 name = prefix .. '_roads', 613 name = prefix .. '_roads',
614 ids = { type = 'way', id_column = 'osm_id' }, 614 ids = { type = 'way', id_column = 'osm_id' },
615 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring') 615 columns = gen_columns(non_point_columns, hstore or hstore_all, false, 'linestring')
616 } 616 }
617 617
618 local z_order_lookup = { 618 local z_order_lookup = {
619 proposed = {1, false}, 619 proposed = {1, false},
620 construction = {2, false}, 620 construction = {2, false},
621 steps = {10, false}, 621 steps = {10, false},
622 cycleway = {10, false}, 622 cycleway = {10, false},
623 bridleway = {10, false}, 623 bridleway = {10, false},
624 footway = {10, false}, 624 footway = {10, false},
625 path = {10, false}, 625 path = {10, false},
626 track = {11, false}, 626 track = {11, false},
627 service = {15, false}, 627 service = {15, false},
628 628
629 tertiary_link = {24, false}, 629 tertiary_link = {24, false},
630 secondary_link = {25, true}, 630 secondary_link = {25, true},
631 primary_link = {27, true}, 631 primary_link = {27, true},
632 trunk_link = {28, true}, 632 trunk_link = {28, true},
633 motorway_link = {29, true}, 633 motorway_link = {29, true},
634 634
635 raceway = {30, false}, 635 raceway = {30, false},
636 pedestrian = {31, false}, 636 pedestrian = {31, false},
637 living_street = {32, false}, 637 living_street = {32, false},
638 road = {33, false}, 638 road = {33, false},
639 unclassified = {33, false}, 639 unclassified = {33, false},
640 residential = {33, false}, 640 residential = {33, false},
641 tertiary = {34, false}, 641 tertiary = {34, false},
642 secondary = {36, true}, 642 secondary = {36, true},
643 primary = {37, true}, 643 primary = {37, true},
644 trunk = {38, true}, 644 trunk = {38, true},
645 motorway = {39, true} 645 motorway = {39, true}
646 } 646 }
647 647
648 function as_bool(value) 648 function as_bool(value)
649 return value == 'yes' or value == 'true' or value == '1' 649 return value == 'yes' or value == 'true' or value == '1'
650 end 650 end
651 651
652 function get_z_order(tags) 652 function get_z_order(tags)
653 local z_order = 100 * math.floor(tonumber(tags.layer or '0') or 0) 653 local z_order = 100 * math.floor(tonumber(tags.layer or '0') or 0)
654 local roads = false 654 local roads = false
655 655
656 local highway = tags['highway'] 656 local highway = tags['highway']
657 if highway then 657 if highway then
658 local r = z_order_lookup[highway] or {0, false} 658 local r = z_order_lookup[highway] or {0, false}
659 z_order = z_order + r[1] 659 z_order = z_order + r[1]
660 roads = r[2] 660 roads = r[2]
661 end 661 end
662 662
663 if tags.railway then 663 if tags.railway then
664 z_order = z_order + 35 664 z_order = z_order + 35
665 roads = true 665 roads = true
666 end 666 end
667 667
668 if tags.boundary and tags.boundary == 'administrative' then 668 if tags.boundary and tags.boundary == 'administrative' then
669 roads = true 669 roads = true
670 end 670 end
671 671
672 if as_bool(tags.bridge) then 672 if as_bool(tags.bridge) then
673 z_order = z_order + 100 673 z_order = z_order + 100
674 end 674 end
675 675
676 if as_bool(tags.tunnel) then 676 if as_bool(tags.tunnel) then
677 z_order = z_order - 100 677 z_order = z_order - 100
678 end 678 end
679 679
680 return z_order, roads 680 return z_order, roads
681 end 681 end
682 682
683 function make_check_in_list_func(list) 683 function make_check_in_list_func(list)
684 local h = {} 684 local h = {}
685 for _, k in ipairs(list) do 685 for _, k in ipairs(list) do
686 h[k] = true 686 h[k] = true
687 end 687 end
688 return function(tags) 688 return function(tags)
689 for k, _ in pairs(tags) do 689 for k, _ in pairs(tags) do
690 if h[k] then 690 if h[k] then
691 return true 691 return true
692 end 692 end
693 end 693 end
694 return false 694 return false
695 end 695 end
696 end 696 end
697 697
698 local is_polygon = make_check_in_list_func(polygon_keys) 698 local is_polygon = make_check_in_list_func(polygon_keys)
699 local clean_tags = osm2pgsql.make_clean_tags_func(delete_keys) 699 local clean_tags = osm2pgsql.make_clean_tags_func(delete_keys)
700 700
701 function make_column_hash(columns) 701 function make_column_hash(columns)
702 local h = {} 702 local h = {}
703 703
704 for _, k in ipairs(columns) do 704 for _, k in ipairs(columns) do
705 h[k] = true 705 h[k] = true
706 end 706 end
707 707
708 return h 708 return h
709 end 709 end
710 710
711 function make_get_output(columns, hstore_all) 711 function make_get_output(columns, hstore_all)
712 local h = make_column_hash(columns) 712 local h = make_column_hash(columns)
713 if hstore_all then 713 if hstore_all then
714 return function(tags) 714 return function(tags)
715 local output = {} 715 local output = {}
716 local hstore_entries = {} 716 local hstore_entries = {}
717 717
718 for k, _ in pairs(tags) do 718 for k, _ in pairs(tags) do
719 if h[k] then 719 if h[k] then
720 output[k] = tags[k] 720 output[k] = tags[k]
721 end 721 end
722 hstore_entries[k] = tags[k] 722 hstore_entries[k] = tags[k]
723 end 723 end
724 724
725 return output, hstore_entries 725 return output, hstore_entries
726 end 726 end
727 else 727 else
728 return function(tags) 728 return function(tags)
729 local output = {} 729 local output = {}
730 local hstore_entries = {} 730 local hstore_entries = {}
731 731
732 for k, _ in pairs(tags) do 732 for k, _ in pairs(tags) do
733 if h[k] then 733 if h[k] then
734 output[k] = tags[k] 734 output[k] = tags[k]
735 else 735 else
736 hstore_entries[k] = tags[k] 736 hstore_entries[k] = tags[k]
737 end 737 end
738 end 738 end
739 739
740 return output, hstore_entries 740 return output, hstore_entries
741 end 741 end
742 end 742 end
743 end 743 end
744 744
745 local has_generic_tag = make_check_in_list_func(generic_keys) 745 local has_generic_tag = make_check_in_list_func(generic_keys)
746 746
747 local get_point_output = make_get_output(point_columns, hstore_all) 747 local get_point_output = make_get_output(point_columns, hstore_all)
748 local get_non_point_output = make_get_output(non_point_columns, hstore_all) 748 local get_non_point_output = make_get_output(non_point_columns, hstore_all)
749 749
750 function get_hstore_column(tags) 750 function get_hstore_column(tags)
751 local len = #hstore_column 751 local len = #hstore_column
752 local h = {} 752 local h = {}
753 for k, v in pairs(tags) do 753 for k, v in pairs(tags) do
754 if k:sub(1, len) == hstore_column then 754 if k:sub(1, len) == hstore_column then
755 h[k:sub(len + 1)] = v 755 h[k:sub(len + 1)] = v
756 end 756 end
757 end 757 end
758 758
759 if next(h) then 759 if next(h) then
760 return h 760 return h
761 end 761 end
762 return nil 762 return nil
763 end 763 end
764 764
765 function add_generic_tags(object, output) 765 function add_generic_tags(object, output)
766 output.majority_name = majority_name(output) 766 output.majority_name = majority_name(output)
767 output.minority_name = minority_name(output) 767 output.minority_name = minority_name(output)
768 output.bilingual_name = bilingual_name(output) 768 output.bilingual_name = bilingual_name(output)
769 return output 769 return output
770 end 770 end
771 771
772 function osm2pgsql.process_node(object) 772 function osm2pgsql.process_node(object)
773 if clean_tags(object.tags) then 773 if clean_tags(object.tags) then
774 return 774 return
775 end 775 end
776 776
777 if object.tags.layer then 777 if object.tags.layer then
778 object.tags.layer = tonumber(object.tags.layer) 778 object.tags.layer = tonumber(object.tags.layer)
779 end 779 end
780 780
781 local output 781 local output
782 local output_hstore = {} 782 local output_hstore = {}
783 if hstore or hstore_all then 783 if hstore or hstore_all then
784 output, output_hstore = get_point_output(object.tags) 784 output, output_hstore = get_point_output(object.tags)
785 if not next(output) and not next(output_hstore) then 785 if not next(output) and not next(output_hstore) then
786 return 786 return
787 end 787 end
788 if hstore_match_only and not has_generic_tag(object.tags) then 788 if hstore_match_only and not has_generic_tag(object.tags) then
789 return 789 return
790 end 790 end
791 else 791 else
792 output = object.tags 792 output = object.tags
793 if not has_generic_tag(object.tags) then 793 if not has_generic_tag(object.tags) then
794 return 794 return
795 end 795 end
796 end 796 end
797 797
798 output = add_generic_tags(object, output) 798 output = add_generic_tags(object, output)
799 output.tags = output_hstore 799 output.tags = output_hstore
800 800
801 if hstore_column then 801 if hstore_column then
802 output[hstore_column] = get_hstore_column(object.tags) 802 output[hstore_column] = get_hstore_column(object.tags)
803 end 803 end
804 804
805 tables.point:add_row(output) 805 tables.point:add_row(output)
806 end 806 end
807 807
808 function osm2pgsql.process_way(object) 808 function osm2pgsql.process_way(object)
809 if clean_tags(object.tags) then 809 if clean_tags(object.tags) then
810 return 810 return
811 end 811 end
812 812
813 if object.tags.layer then 813 if object.tags.layer then
814 object.tags.layer = tonumber(object.tags.layer) 814 object.tags.layer = tonumber(object.tags.layer)
815 end 815 end
816 816
817 817
818 local add_area = false 818 local add_area = false
819 if object.tags.natural == 'coastline' then 819 if object.tags.natural == 'coastline' then
820 add_area = true 820 add_area = true
821 if not keep_coastlines then 821 if not keep_coastlines then
822 object.tags.natural = nil 822 object.tags.natural = nil
823 end 823 end
824 end 824 end
825 825
826 local output 826 local output
827 local output_hstore = {} 827 local output_hstore = {}
828 if hstore or hstore_all then 828 if hstore or hstore_all then
829 output, output_hstore = get_non_point_output(object.tags) 829 output, output_hstore = get_non_point_output(object.tags)
830 if not next(output) and not next(output_hstore) then 830 if not next(output) and not next(output_hstore) then
831 return 831 return
832 end 832 end
833 if hstore_match_only and not has_generic_tag(object.tags) then 833 if hstore_match_only and not has_generic_tag(object.tags) then
834 return 834 return
835 end 835 end
836 if add_area and hstore_all then 836 if add_area and hstore_all then
837 output_hstore.area = 'yes' 837 output_hstore.area = 'yes'
838 end 838 end
839 else 839 else
840 output = object.tags 840 output = object.tags
841 if not has_generic_tag(object.tags) then 841 if not has_generic_tag(object.tags) then
842 return 842 return
843 end 843 end
844 end 844 end
845 845
846 local polygon 846 local polygon
847 local area_tag = object.tags.area 847 local area_tag = object.tags.area
848 if area_tag == 'yes' or area_tag == '1' or area_tag == 'true' then 848 if area_tag == 'yes' or area_tag == '1' or area_tag == 'true' then
849 polygon = true 849 polygon = true
850 elseif area_tag == 'no' or area_tag == '0' or area_tag == 'false' then 850 elseif area_tag == 'no' or area_tag == '0' or area_tag == 'false' then
851 polygon = false 851 polygon = false
852 else 852 else
853 polygon = is_polygon(object.tags) 853 polygon = is_polygon(object.tags)
854 end 854 end
855 855
856 if add_area then 856 if add_area then
857 output.area = 'yes' 857 output.area = 'yes'
858 polygon = true 858 polygon = true
859 end 859 end
860 860
861 local z_order, roads = get_z_order(object.tags) 861 local z_order, roads = get_z_order(object.tags)
862 output.z_order = z_order 862 output.z_order = z_order
863 output = add_generic_tags(object, output) 863 output = add_generic_tags(object, output)
864 864
865 output.tags = output_hstore 865 output.tags = output_hstore
866 866
867 if output.highway ~= nil 867 if output.highway ~= nil
868 then 868 then
869 if output.highway == 'construction' 869 if output.highway == 'construction'
870 then 870 then
871 return 871 return
872 end 872 end
873 output.highway = highway_class(output) 873 output.highway = highway_class(output)
874 output.ref = highway_refs(output) 874 output.ref = highway_refs(output)
875 if output.highway == 'construction' and output.construction == 'motorway' 875 if output.highway == 'construction' and output.construction == 'motorway'
876 then 876 then
877 output.construction = 'trunk' 877 output.construction = 'trunk'
878 elseif output.highway == 'construction' and output.construction == 'motorway_link' 878 elseif output.highway == 'construction' and output.construction == 'motorway_link'
879 then 879 then
880 output.construction = 'trunk_link' 880 output.construction = 'trunk_link'
881 end 881 end
882 882
883 -- classify references for for Finland shield rendering 883 -- classify references for for Finland shield rendering
884 if output.ref ~= nil 884 if output.ref ~= nil
885 then 885 then
886 output.ref_class = classify_road_numbers(output.ref) 886 output.ref_class = classify_road_numbers(output.ref)
887 output.ref_width = ref_widths(output.ref) 887 output.ref_width = ref_widths(output.ref)
888 end 888 end
889 end 889 end
890 890
891 if hstore_column then 891 if hstore_column then
892 output[hstore_column] = get_hstore_column(object.tags) 892 output[hstore_column] = get_hstore_column(object.tags)
893 end 893 end
894 894
895 if polygon and object.is_closed then 895 if polygon and object.is_closed then
896 output.way = { create = 'area' } 896 output.way = { create = 'area' }
897 tables.polygon:add_row(output) 897 tables.polygon:add_row(output)
898 else 898 else
899 output.way = { create = 'line', split_at = max_length } 899 output.way = { create = 'line', split_at = max_length }
900 tables.line:add_row(output) 900 tables.line:add_row(output)
901 if roads then 901 if roads then
902 tables.roads:add_row(output) 902 tables.roads:add_row(output)
903 end 903 end
904 end 904 end
905 end 905 end
906 906
907 function osm2pgsql.process_relation(object) 907 function osm2pgsql.process_relation(object)
908 if clean_tags(object.tags) then 908 if clean_tags(object.tags) then
909 return 909 return
910 end 910 end
911 911
912 local type = object.tags.type 912 local type = object.tags.type
913 if (type ~= 'route') and (type ~= 'multipolygon') and (type ~= 'boundary') then 913 if (type ~= 'route') and (type ~= 'multipolygon') and (type ~= 'boundary') then
914 return 914 return
915 end 915 end
916 object.tags.type = nil 916 object.tags.type = nil
917 917
918 local output 918 local output
919 local output_hstore = {} 919 local output_hstore = {}
920 if hstore or hstore_all then 920 if hstore or hstore_all then
921 output, output_hstore = get_non_point_output(object.tags) 921 output, output_hstore = get_non_point_output(object.tags)
922 if not next(output) and not next(output_hstore) then 922 if not next(output) and not next(output_hstore) then
923 return 923 return
924 end 924 end
925 if hstore_match_only and not has_generic_tag(object.tags) then 925 if hstore_match_only and not has_generic_tag(object.tags) then
926 return 926 return
927 end 927 end
928 else 928 else
929 output = object.tags 929 output = object.tags
930 if not has_generic_tag(object.tags) then 930 if not has_generic_tag(object.tags) then
931 return 931 return
932 end 932 end
933 end 933 end
934 934
935 if not next(output) and not next(output_hstore) then 935 if not next(output) and not next(output_hstore) then
936 return 936 return
937 end 937 end
938 938
939 if enable_legacy_route_processing and (hstore or hstore_all) and type == 'route' then 939 if enable_legacy_route_processing and (hstore or hstore_all) and type == 'route' then
940 if not object.tags.route_name then 940 if not object.tags.route_name then
941 output_hstore.route_name = object.tags.name 941 output_hstore.route_name = object.tags.name
942 end 942 end
943 943
944 local state = object.tags.state 944 local state = object.tags.state
945 if state ~= 'alternate' and state ~= 'connection' then 945 if state ~= 'alternate' and state ~= 'connection' then
946 state = 'yes' 946 state = 'yes'
947 end 947 end
948 948
949 local network = object.tags.network 949 local network = object.tags.network
950 if network == 'lcn' then 950 if network == 'lcn' then
951 output_hstore.lcn = output_hstore.lcn or state 951 output_hstore.lcn = output_hstore.lcn or state
952 output_hstore.lcn_ref = output_hstore.lcn_ref or object.tags.ref 952 output_hstore.lcn_ref = output_hstore.lcn_ref or object.tags.ref
953 elseif network == 'rcn' then 953 elseif network == 'rcn' then
954 output_hstore.rcn = output_hstore.rcn or state 954 output_hstore.rcn = output_hstore.rcn or state
955 output_hstore.rcn_ref = output_hstore.rcn_ref or object.tags.ref 955 output_hstore.rcn_ref = output_hstore.rcn_ref or object.tags.ref
956 elseif network == 'ncn' then 956 elseif network == 'ncn' then
957 output_hstore.ncn = output_hstore.ncn or state 957 output_hstore.ncn = output_hstore.ncn or state
958 output_hstore.ncn_ref = output_hstore.ncn_ref or object.tags.ref 958 output_hstore.ncn_ref = output_hstore.ncn_ref or object.tags.ref
959 elseif network == 'lwn' then 959 elseif network == 'lwn' then
960 output_hstore.lwn = output_hstore.lwn or state 960 output_hstore.lwn = output_hstore.lwn or state
961 output_hstore.lwn_ref = output_hstore.lwn_ref or object.tags.ref 961 output_hstore.lwn_ref = output_hstore.lwn_ref or object.tags.ref
962 elseif network == 'rwn' then 962 elseif network == 'rwn' then
963 output_hstore.rwn = output_hstore.rwn or state 963 output_hstore.rwn = output_hstore.rwn or state
964 output_hstore.rwn_ref = output_hstore.rwn_ref or object.tags.ref 964 output_hstore.rwn_ref = output_hstore.rwn_ref or object.tags.ref
965 elseif network == 'nwn' then 965 elseif network == 'nwn' then
966 output_hstore.nwn = output_hstore.nwn or state 966 output_hstore.nwn = output_hstore.nwn or state
967 output_hstore.nwn_ref = output_hstore.nwn_ref or object.tags.ref 967 output_hstore.nwn_ref = output_hstore.nwn_ref or object.tags.ref
968 end 968 end
969 969
970 local pc = object.tags.preferred_color 970 local pc = object.tags.preferred_color
971 if pc == '0' or pc == '1' or pc == '2' or pc == '3' or pc == '4' then 971 if pc == '0' or pc == '1' or pc == '2' or pc == '3' or pc == '4' then
972 output_hstore.route_pref_color = pc 972 output_hstore.route_pref_color = pc
973 else 973 else
974 output_hstore.route_pref_color = '0' 974 output_hstore.route_pref_color = '0'
975 end 975 end
976 end 976 end
977 977
978 local make_boundary = false 978 local make_boundary = false
979 local make_polygon = false 979 local make_polygon = false
980 if type == 'boundary' then 980 if type == 'boundary' then
981 make_boundary = true 981 make_boundary = true
982 elseif type == 'multipolygon' and object.tags.boundary then 982 elseif type == 'multipolygon' and object.tags.boundary then
983 make_boundary = true 983 make_boundary = true
984 elseif type == 'multipolygon' then 984 elseif type == 'multipolygon' then
985 make_polygon = true 985 make_polygon = true
986 end 986 end
987 987
988 local z_order, roads = get_z_order(object.tags) 988 local z_order, roads = get_z_order(object.tags)
989 output.z_order = z_order 989 output.z_order = z_order
990 output = add_generic_tags(object, output) 990 output = add_generic_tags(object, output)
991 991
992 output.tags = output_hstore 992 output.tags = output_hstore
993 993
994 if hstore_column then 994 if hstore_column then
995 output[hstore_column] = get_hstore_column(object.tags) 995 output[hstore_column] = get_hstore_column(object.tags)
996 end 996 end
997 997
998 if not make_polygon then 998 if not make_polygon then
999 output.way = { create = 'line', split_at = max_length } 999 output.way = { create = 'line', split_at = max_length }
1000 tables.line:add_row(output) 1000 tables.line:add_row(output)
1001 if roads then 1001 if roads then
1002 tables.roads:add_row(output) 1002 tables.roads:add_row(output)
1003 end 1003 end
1004 end 1004 end
1005 1005
1006 if make_boundary or make_polygon then 1006 if make_boundary or make_polygon then
1007 output.way = { create = 'area', multi = multi_geometry } 1007 output.way = { create = 'area', multi = multi_geometry }
1008 tables.polygon:add_row(output) 1008 tables.polygon:add_row(output)
1009 end 1009 end
1010 end 1010 end
1011 1011

mercurial