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