Skip to content

Commit 882e065

Browse files
authored
Merge pull request #2224 from joto/area-assembler
Refactor area assembler
2 parents 6e2acda + 83072b0 commit 882e065

11 files changed

+211
-45
lines changed

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ target_sources(osm2pgsql_lib PRIVATE
2525
flex-table-column.cpp
2626
flex-table.cpp
2727
flex-write.cpp
28+
geom-area-assembler.cpp
2829
geom-box.cpp
2930
geom-from-osm.cpp
3031
geom-functions.cpp

src/geom-area-assembler.cpp

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* SPDX-License-Identifier: GPL-2.0-or-later
3+
*
4+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
5+
*
6+
* Copyright (C) 2006-2024 by the osm2pgsql developer community.
7+
* For a full list of authors see the git log.
8+
*/
9+
10+
#include "geom-area-assembler.hpp"
11+
12+
#include <osmium/builder/osm_object_builder.hpp>
13+
14+
namespace geom {
15+
16+
const osmium::area::AssemblerConfig area_config;
17+
18+
area_assembler_t::area_assembler_t(osmium::memory::Buffer *buffer)
19+
: osmium::area::detail::BasicAssembler(area_config), m_buffer(buffer)
20+
{
21+
}
22+
23+
bool area_assembler_t::make_area()
24+
{
25+
if (!create_rings()) {
26+
return false;
27+
}
28+
29+
m_buffer->clear();
30+
{
31+
osmium::builder::AreaBuilder builder{*m_buffer};
32+
add_rings_to_area(builder);
33+
}
34+
m_buffer->commit();
35+
36+
return true;
37+
}
38+
39+
bool area_assembler_t::operator()(const osmium::Way &way)
40+
{
41+
segment_list().extract_segments_from_way(nullptr, stats().duplicate_nodes,
42+
way);
43+
return make_area();
44+
}
45+
46+
// Currently the relation is not needed for assembling the area, because
47+
// the roles on the members are ignored. In the future we might want to use
48+
// the roles, so we leave the function signature as it is.
49+
bool area_assembler_t::operator()(const osmium::Relation & /*relation*/,
50+
const osmium::memory::Buffer &ways_buffer)
51+
{
52+
for (const auto &way : ways_buffer.select<osmium::Way>()) {
53+
segment_list().extract_segments_from_way(nullptr,
54+
stats().duplicate_nodes, way);
55+
}
56+
return make_area();
57+
}
58+
59+
} // namespace geom

src/geom-area-assembler.hpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#ifndef OSM2PGSQL_GEOM_AREA_ASSEMBLER_HPP
2+
#define OSM2PGSQL_GEOM_AREA_ASSEMBLER_HPP
3+
4+
/**
5+
* SPDX-License-Identifier: GPL-2.0-or-later
6+
*
7+
* This file is part of osm2pgsql (https://osm2pgsql.org/).
8+
*
9+
* Copyright (C) 2006-2024 by the osm2pgsql developer community.
10+
* For a full list of authors see the git log.
11+
*/
12+
13+
/**
14+
* \file
15+
*
16+
* Code for assembling areas from ways or relations.
17+
*/
18+
19+
#include <osmium/area/detail/basic_assembler.hpp>
20+
21+
namespace geom {
22+
23+
/**
24+
* The area_assembler_t class is a light wrapper around the libosmium class
25+
* for assembling areas.
26+
*/
27+
class area_assembler_t : public osmium::area::detail::BasicAssembler
28+
{
29+
public:
30+
area_assembler_t(osmium::memory::Buffer *buffer);
31+
32+
/**
33+
* Assemble an area from the given way.
34+
*
35+
* @returns false if there was some kind of error building the
36+
* area, true otherwise.
37+
*/
38+
bool operator()(const osmium::Way &way);
39+
40+
/**
41+
* Assemble an area from the given relation and its member ways
42+
* which are in the ways_buffer.
43+
*
44+
* @returns false if there was some kind of error building the
45+
* area, true otherwise.
46+
*/
47+
bool operator()(const osmium::Relation &relation,
48+
const osmium::memory::Buffer &ways_buffer);
49+
50+
/**
51+
* Access the area that was built last.
52+
*/
53+
osmium::Area const &get_area() const noexcept
54+
{
55+
return m_buffer->get<osmium::Area>(0);
56+
}
57+
58+
private:
59+
bool make_area();
60+
61+
osmium::memory::Buffer* m_buffer;
62+
63+
}; // class area_assembler_t
64+
65+
} // namespace geom
66+
67+
#endif // OSM2PGSQL_GEOM_AREA_ASSEMBLER_HPP

src/geom-from-osm.cpp

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88
*/
99

1010
#include "geom-from-osm.hpp"
11+
12+
#include "geom-area-assembler.hpp"
1113
#include "osmtypes.hpp"
1214

13-
#include <osmium/area/geom_assembler.hpp>
1415
#include <osmium/osm/way.hpp>
1516

1617
#include <cassert>
@@ -90,7 +91,8 @@ geometry_t create_linestring(osmium::Way const &way)
9091
return geom;
9192
}
9293

93-
void create_polygon(geometry_t *geom, osmium::Way const &way)
94+
void create_polygon(geometry_t *geom, osmium::Way const &way,
95+
osmium::memory::Buffer *area_buffer)
9496
{
9597
auto &polygon = geom->set<polygon_t>();
9698

@@ -100,26 +102,24 @@ void create_polygon(geometry_t *geom, osmium::Way const &way)
100102
return;
101103
}
102104

103-
osmium::area::AssemblerConfig area_config;
104-
area_config.ignore_invalid_locations = true;
105-
osmium::area::GeomAssembler assembler{area_config};
106-
osmium::memory::Buffer area_buffer{1024};
105+
geom::area_assembler_t assembler{area_buffer};
107106

108-
if (!assembler(way, area_buffer)) {
107+
if (!assembler(way)) {
109108
geom->reset();
110109
return;
111110
}
112111

113-
auto const &area = area_buffer.get<osmium::Area>(0);
112+
auto const &area = assembler.get_area();
114113
auto const &ring = *area.begin<osmium::OuterRing>();
115114

116115
fill_point_list(&polygon.outer(), ring);
117116
}
118117

119-
geometry_t create_polygon(osmium::Way const &way)
118+
geometry_t create_polygon(osmium::Way const &way,
119+
osmium::memory::Buffer *area_buffer)
120120
{
121121
geometry_t geom{};
122-
create_polygon(&geom, way);
122+
create_polygon(&geom, way, area_buffer);
123123
return geom;
124124
}
125125

@@ -207,19 +207,17 @@ geometry_t create_multilinestring(osmium::memory::Buffer const &buffer,
207207
}
208208

209209
void create_multipolygon(geometry_t *geom, osmium::Relation const &relation,
210-
osmium::memory::Buffer const &buffer)
210+
osmium::memory::Buffer const &buffer,
211+
osmium::memory::Buffer *area_buffer)
211212
{
212-
osmium::area::AssemblerConfig area_config;
213-
area_config.ignore_invalid_locations = true;
214-
osmium::area::GeomAssembler assembler{area_config};
215-
osmium::memory::Buffer area_buffer{1024};
213+
geom::area_assembler_t assembler{area_buffer};
216214

217-
if (!assembler(relation, buffer, area_buffer)) {
215+
if (!assembler(relation, buffer)) {
218216
geom->reset();
219217
return;
220218
}
221219

222-
auto const &area = area_buffer.get<osmium::Area>(0);
220+
auto const &area = assembler.get_area();
223221

224222
if (area.is_multipolygon()) {
225223
auto &multipolygon = geom->set<multipolygon_t>();
@@ -235,10 +233,11 @@ void create_multipolygon(geometry_t *geom, osmium::Relation const &relation,
235233
}
236234

237235
geometry_t create_multipolygon(osmium::Relation const &relation,
238-
osmium::memory::Buffer const &buffer)
236+
osmium::memory::Buffer const &buffer,
237+
osmium::memory::Buffer *area_buffer)
239238
{
240239
geometry_t geom{};
241-
create_multipolygon(&geom, relation, buffer);
240+
create_multipolygon(&geom, relation, buffer, area_buffer);
242241
return geom;
243242
}
244243

src/geom-from-osm.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,18 +76,22 @@ void create_linestring(geometry_t *geom, osmium::Way const &way);
7676
*
7777
* \param geom Pointer to an existing geometry which will be used as output.
7878
* \param way The input way.
79+
* \param area_buffer Temporary buffer used to create area.
7980
*/
80-
void create_polygon(geometry_t *geom, osmium::Way const &way);
81+
void create_polygon(geometry_t *geom, osmium::Way const &way,
82+
osmium::memory::Buffer *area_buffer);
8183

8284
/**
8385
* Create a polygon geometry from a way.
8486
*
8587
* If the resulting polygon would be invalid, a null geometry is returned.
8688
*
8789
* \param way The input way.
90+
* \param area_buffer Temporary buffer used to create area.
8891
* \returns The created geometry.
8992
*/
90-
[[nodiscard]] geometry_t create_polygon(osmium::Way const &way);
93+
[[nodiscard]] geometry_t create_polygon(osmium::Way const &way,
94+
osmium::memory::Buffer *area_buffer);
9195

9296
/**
9397
* Create a multipoint geometry from a bunch of nodes (usually this would be
@@ -163,9 +167,11 @@ create_multilinestring(osmium::memory::Buffer const &buffer,
163167
* \param geom Pointer to an existing geometry which will be used as output.
164168
* \param relation The input relation.
165169
* \param buffer Buffer with OSM objects. Anything but ways are ignored.
170+
* \param area_buffer Temporary buffer used to create area.
166171
*/
167172
void create_multipolygon(geometry_t *geom, osmium::Relation const &relation,
168-
osmium::memory::Buffer const &buffer);
173+
osmium::memory::Buffer const &buffer,
174+
osmium::memory::Buffer *area_buffer);
169175

170176
/**
171177
* Create a (multi)polygon geometry from a relation and member ways.
@@ -175,11 +181,13 @@ void create_multipolygon(geometry_t *geom, osmium::Relation const &relation,
175181
*
176182
* \param relation The input relation.
177183
* \param buffer Buffer with OSM objects. Anything but ways are ignored.
184+
* \param area_buffer Temporary buffer used to create area.
178185
* \returns The created geometry.
179186
*/
180187
[[nodiscard]] geometry_t
181188
create_multipolygon(osmium::Relation const &relation,
182-
osmium::memory::Buffer const &buffer);
189+
osmium::memory::Buffer const &buffer,
190+
osmium::memory::Buffer *area_buffer);
183191

184192
/**
185193
* Create a geometry collection from nodes and ways, usually used for

src/output-flex.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -400,7 +400,7 @@ int output_flex_t::app_as_polygon()
400400
m_way_cache.add_nodes(middle());
401401

402402
auto *geom = create_lua_geometry_object(lua_state());
403-
geom::create_polygon(geom, m_way_cache.get());
403+
geom::create_polygon(geom, m_way_cache.get(), &m_area_buffer);
404404

405405
return 1;
406406
}
@@ -459,7 +459,7 @@ int output_flex_t::app_as_multipolygon()
459459
m_way_cache.add_nodes(middle());
460460

461461
auto *geom = create_lua_geometry_object(lua_state());
462-
geom::create_polygon(geom, m_way_cache.get());
462+
geom::create_polygon(geom, m_way_cache.get(), &m_area_buffer);
463463

464464
return 1;
465465
}
@@ -468,7 +468,8 @@ int output_flex_t::app_as_multipolygon()
468468

469469
auto *geom = create_lua_geometry_object(lua_state());
470470
geom::create_multipolygon(geom, m_relation_cache.get(),
471-
m_relation_cache.members_buffer());
471+
m_relation_cache.members_buffer(),
472+
&m_area_buffer);
472473

473474
return 1;
474475
}
@@ -1173,6 +1174,7 @@ output_flex_t::output_flex_t(output_flex_t const *other,
11731174
m_db_connection(get_options()->connection_params, "out.flex.thread"),
11741175
m_stage2_way_ids(other->m_stage2_way_ids),
11751176
m_copy_thread(std::move(copy_thread)), m_lua_state(other->m_lua_state),
1177+
m_area_buffer(1024, osmium::memory::Buffer::auto_grow::yes),
11761178
m_process_node(other->m_process_node), m_process_way(other->m_process_way),
11771179
m_process_relation(other->m_process_relation),
11781180
m_select_relation_members(other->m_select_relation_members),
@@ -1203,7 +1205,8 @@ output_flex_t::output_flex_t(std::shared_ptr<middle_query_t> const &mid,
12031205
properties_t const &properties)
12041206
: output_t(mid, std::move(thread_pool), options),
12051207
m_db_connection(get_options()->connection_params, "out.flex.main"),
1206-
m_copy_thread(std::make_shared<db_copy_thread_t>(options.connection_params))
1208+
m_copy_thread(std::make_shared<db_copy_thread_t>(options.connection_params)),
1209+
m_area_buffer(1024, osmium::memory::Buffer::auto_grow::yes)
12071210
{
12081211
init_lua(options.style, properties);
12091212

src/output-flex.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,8 @@ class output_flex_t : public output_t
297297
relation_cache_t m_relation_cache;
298298
osmium::Node const *m_context_node = nullptr;
299299

300+
osmium::memory::Buffer m_area_buffer;
301+
300302
prepared_lua_function_t m_process_node{};
301303
prepared_lua_function_t m_process_way{};
302304
prepared_lua_function_t m_process_relation{};

src/output-pgsql.cpp

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void output_pgsql_t::pgsql_out_way(osmium::Way const &way, taglist_t *tags,
9595
bool polygon, bool roads)
9696
{
9797
if (polygon && !way.nodes().empty() && way.is_closed()) {
98-
auto const geom = geom::create_polygon(way);
98+
auto const geom = geom::create_polygon(way, &m_area_buffer);
9999
auto const projected_geom = geom::transform(geom, *m_proj);
100100

101101
auto const wkb = geom_to_ewkb(projected_geom);
@@ -297,9 +297,9 @@ void output_pgsql_t::pgsql_process_relation(osmium::Relation const &rel)
297297

298298
// multipolygons and boundaries
299299
if (make_boundary || make_polygon) {
300-
auto const geoms =
301-
geom::split_multi(geom::create_multipolygon(rel, m_buffer),
302-
!get_options()->enable_multi);
300+
auto const geoms = geom::split_multi(
301+
geom::create_multipolygon(rel, m_buffer, &m_area_buffer),
302+
!get_options()->enable_multi);
303303
for (auto const &sgeom : geoms) {
304304
auto const projected_geom = geom::transform(sgeom, *m_proj);
305305
m_expire.from_geometry_if_3857(projected_geom, m_expire_config);
@@ -439,7 +439,8 @@ output_pgsql_t::output_pgsql_t(std::shared_ptr<middle_query_t> const &mid,
439439
: output_t(mid, std::move(thread_pool), options), m_proj(options.projection),
440440
m_expire(options.expire_tiles_zoom, options.projection),
441441
m_buffer(32768, osmium::memory::Buffer::auto_grow::yes),
442-
m_rels_buffer(1024, osmium::memory::Buffer::auto_grow::yes)
442+
m_rels_buffer(1024, osmium::memory::Buffer::auto_grow::yes),
443+
m_area_buffer(1024, osmium::memory::Buffer::auto_grow::yes)
443444
{
444445
m_expire_config.full_area_limit = get_options()->expire_tiles_max_bbox;
445446
if (get_options()->expire_tiles_max_bbox > 0.0) {
@@ -505,7 +506,8 @@ output_pgsql_t::output_pgsql_t(
505506
m_proj(get_options()->projection), m_expire_config(other->m_expire_config),
506507
m_expire(get_options()->expire_tiles_zoom, get_options()->projection),
507508
m_buffer(1024, osmium::memory::Buffer::auto_grow::yes),
508-
m_rels_buffer(1024, osmium::memory::Buffer::auto_grow::yes)
509+
m_rels_buffer(1024, osmium::memory::Buffer::auto_grow::yes),
510+
m_area_buffer(1024, osmium::memory::Buffer::auto_grow::yes)
509511
{
510512
for (std::size_t i = 0; i < m_tables.size(); ++i) {
511513
//copy constructor will just connect to the already there table

src/output-pgsql.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ class output_pgsql_t : public output_t
109109

110110
osmium::memory::Buffer m_buffer;
111111
osmium::memory::Buffer m_rels_buffer;
112+
osmium::memory::Buffer m_area_buffer;
112113
};
113114

114115
#endif // OSM2PGSQL_OUTPUT_PGSQL_HPP

0 commit comments

Comments
 (0)