@@ -11,25 +11,30 @@ tables.pois = osm2pgsql.define_node_table('pois', {
1111 { column = ' tags' , type = ' jsonb' },
1212 -- Create a geometry column for point geometries. The geometry will be
1313 -- in web mercator, EPSG 3857.
14- { column = ' geom' , type = ' point' },
14+ --
15+ -- Usually we want to declare all geometry columns as "NOT NULL". If
16+ -- osm2pgsql encounters an invalid geometry (for whatever reason) it will
17+ -- generate a null geometry which will not be written to the database if
18+ -- "not_null" is set. The result is that broken geometries will just be
19+ -- silently ignored.
20+ { column = ' geom' , type = ' point' , not_null = true },
1521})
1622
1723tables .ways = osm2pgsql .define_way_table (' ways' , {
1824 { column = ' tags' , type = ' jsonb' },
1925 -- Create a geometry column for linestring geometries. The geometry will
2026 -- be in latlong (WGS84), EPSG 4326.
21- { column = ' geom' , type = ' linestring' , projection = 4326 },
27+ { column = ' geom' , type = ' linestring' , projection = 4326 , not_null = true },
2228})
2329
2430tables .polygons = osm2pgsql .define_area_table (' polygons' , {
2531 { column = ' tags' , type = ' jsonb' },
26- { column = ' geom' , type = ' geometry' },
27- -- The 'area' type is used to store the calculated area of a polygon
28- -- feature. This can be used in style sheets to only render larger polygons
29- -- in small zoom levels. This will use the area in web mercator projection,
30- -- you can set 'projection = 4326' to calculate the area in WGS84. Other
31- -- projections are currently not supported.
32- { column = ' area' , type = ' area' },
32+ -- If we don't set "not_null = true", we'll get NULL columns for invalid
33+ -- geometries. This can be useful if we want to detect those cases or
34+ -- if we have multiple geometry columns and some of them can be valid
35+ -- and others not.
36+ { column = ' geom' , type = ' geometry' , projection = 4326 },
37+ { column = ' area' , type = ' real' },
3338})
3439
3540tables .boundaries = osm2pgsql .define_relation_table (' boundaries' , {
@@ -38,7 +43,7 @@ tables.boundaries = osm2pgsql.define_relation_table('boundaries', {
3843 -- Boundaries will be stitched together from relation members into long
3944 -- linestrings. This is a multilinestring column because sometimes the
4045 -- boundaries are not contiguous.
41- { column = ' geom' , type = ' multilinestring' },
46+ { column = ' geom' , type = ' multilinestring' , not_null = true },
4247})
4348
4449-- Tables don't have to have a geometry column. This one will only collect
@@ -101,15 +106,15 @@ function osm2pgsql.process_node(object)
101106 return
102107 end
103108
104- -- The ' geom' column is not mentioned here. So the default geometry
105- -- transformation for a column of type 'point' will be used and the
106- -- node location will be written as Point geometry into the database.
107- tables . pois : add_row ({
108- tags = object . tags
109+ local geom = object : as_point ()
110+
111+ tables . pois : insert ({
112+ tags = object . tags ,
113+ geom = geom -- the point will be automatically be projected to 3857
109114 })
110115
111116 if object .tags .amenity == ' pub' then
112- tables .pubs :add_row ({
117+ tables .pubs :insert ({
113118 name = object .tags .name
114119 })
115120 end
@@ -122,33 +127,36 @@ function osm2pgsql.process_way(object)
122127
123128 -- A closed way that also has the right tags for an area is a polygon.
124129 if object .is_closed and has_area_tags (object .tags ) then
125- tables .polygons :add_row ({
130+ -- Creating the polygon geometry takes time, so we do it once here
131+ -- and later store it in the table and use it to calculate the area.
132+ local geom = object :as_polygon ()
133+ tables .polygons :insert ({
126134 tags = object .tags ,
127- -- The 'geom' column of the 'polygons' table is of type 'geometry'.
128- -- There are several ways a way geometry could be converted to
129- -- a geometry so you have to specify the geometry transformation.
130- -- In this case we want to convert the way data to an area.
131- geom = { create = ' area' }
135+ geom = geom ,
136+ -- Calculate the area in Mercator projection and store in the
137+ -- area column
138+ area = geom :transform (3857 ):area ()
132139 })
133140 else
134- -- The 'geom' column of the 'ways' table is of type 'linestring'.
135- -- Osm2pgsql knows how to create a linestring from a way, but
136- -- if you want to specify extra parameters to this conversion,
137- -- you have to do this explicitly. In this case we want to split
138- -- long linestrings.
139- --
140- -- Set "split_at" to the maximum length the pieces should have. This
141- -- length is in map units, so it depends on the projection used.
141+ -- We want to split long lines into smaller segments. We can use
142+ -- the "segmentize" function for that. The parameter specifies the
143+ -- maximum length the pieces should have. This length is in map units,
144+ -- so it depends on the projection used.
142145 -- "Traditional" osm2pgsql sets this to 1 for 4326 geometries and
143- -- 100000 for 3857 (web mercator) geometries. The default is 0.0, which
144- -- means no splitting.
146+ -- 100000 for 3857 (web mercator) geometries.
145147 --
146- -- Note that if a way is split this will automatically create
147- -- multiple rows that are identical except for the geometry.
148- tables .ways :add_row ({
149- tags = object .tags ,
150- geom = { create = ' line' , split_at = 1 }
151- })
148+ -- Because the result of the segmentation is a multigeometry, we'll
149+ -- have to iterate over all the member geometries to be able to insert
150+ -- the data into a the 'geom' column of the 'ways' table which is of
151+ -- type 'linestring'. (We could have used a multilinestring geometry
152+ -- in our table instead.)
153+ local multi_geom = object :as_multilinestring ():segmentize (1 )
154+ for g in multi_geom :geometries () do
155+ tables .ways :insert ({
156+ tags = object .tags ,
157+ geom = g
158+ })
159+ end
152160 end
153161end
154162
@@ -161,25 +169,30 @@ function osm2pgsql.process_relation(object)
161169
162170 -- Store boundary relations as multilinestrings
163171 if relation_type == ' boundary' then
164- tables .boundaries :add_row ({
172+ tables .boundaries :insert ({
165173 type = object :grab_tag (' boundary' ),
166174 tags = object .tags ,
167175 -- For relations there is no clear definition what their geometry
168- -- is, so you have to declare the geometry transformation
169- -- explicitly.
170- geom = { create = ' line' }
176+ -- is, so you have to decide on the geometry transformation you
177+ -- want. In this case we want the boundary as multilinestring
178+ -- and we want lines merged as much as possible.
179+ geom = object :as_multilinestring ():line_merge ()
171180 })
172181 return
173182 end
174183
175184 -- Store multipolygon relations as polygons
176185 if relation_type == ' multipolygon' then
177- tables .polygons :add_row ({
186+ local geom = object :as_multipolygon ()
187+ tables .polygons :insert ({
178188 tags = object .tags ,
179189 -- For relations there is no clear definition what their geometry
180- -- is, so you have to declare the geometry transformation
181- -- explicitly.
182- geom = { create = ' area' }
190+ -- is, so you have to decide on the geometry transformation.
191+ -- In this case we know from the type tag its a (multi)polygon.
192+ geom = geom ,
193+ -- Calculate the area in Mercator projection and store in the
194+ -- area column
195+ area = geom :transform (3857 ):area ()
183196 })
184197 end
185198end
0 commit comments