Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions flex-config/compatible.lua
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ local keep_coastlines = false
-- Set this to the table name prefix (what used to be option -p|--prefix).
local prefix = 'planet_osm'

-- Set this to true if multipolygons should be written as polygons into db
-- (what used to be option -G|--multi-geometry).
-- Set this to true if multipolygons should be written as multipolygons into
-- db (what used to be option -G|--multi-geometry).
local multi_geometry = false

-- Set this to true if you want an hstore column (what used to be option
Expand Down Expand Up @@ -724,7 +724,10 @@ function osm2pgsql.process_relation(object)
end

if make_boundary or make_polygon then
output.way = { create = 'area', multi = multi_geometry }
output.way = { create = 'area' }
if not multi_geometry then
output.way.split_at = 'multi'
end
tables.polygon:add_row(output)
end
end
Expand Down
47 changes: 33 additions & 14 deletions src/geom-transform.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ bool geom_transform_point_t::is_compatible_with(

geom::osmium_builder_t::wkbs_t
geom_transform_point_t::run(geom::osmium_builder_t *builder,
table_column_type /*target_geom_type*/,
osmium::Node const &node) const
{
assert(builder);
Expand Down Expand Up @@ -49,6 +50,7 @@ bool geom_transform_line_t::is_compatible_with(

geom::osmium_builder_t::wkbs_t
geom_transform_line_t::run(geom::osmium_builder_t *builder,
table_column_type /*target_geom_type*/,
osmium::Way *way) const
{
assert(builder);
Expand All @@ -59,6 +61,7 @@ geom_transform_line_t::run(geom::osmium_builder_t *builder,

geom::osmium_builder_t::wkbs_t
geom_transform_line_t::run(geom::osmium_builder_t *builder,
table_column_type /*target_geom_type*/,
osmium::Relation const & /*relation*/,
osmium::memory::Buffer const &buffer) const
{
Expand All @@ -69,61 +72,77 @@ geom_transform_line_t::run(geom::osmium_builder_t *builder,

bool geom_transform_area_t::set_param(char const *name, lua_State *lua_state)
{
if (std::strcmp(name, "multi") != 0) {
if (std::strcmp(name, "multi") == 0) {
throw std::runtime_error{
"The 'multi' field in the geometry transformation has been"
" removed. See docs on how to use 'split_at' instead."};
}

if (std::strcmp(name, "split_at") != 0) {
return false;
}

if (lua_type(lua_state, -1) != LUA_TBOOLEAN) {
auto const val = lua_tostring(lua_state, -1);

if (!val) {
throw std::runtime_error{
"The 'multi' field in a geometry transformation "
"description must be a boolean."};
"The 'split_at' field in a geometry transformation "
"description must be a string."};
}
m_multi = lua_toboolean(lua_state, -1);

return true;
if (std::strcmp(val, "multi") == 0) {
m_multi = false;
return true;
}

throw std::runtime_error{"Unknown value for 'split_at' field in a geometry"
" transformation: '{}'"_format(val)};
}

bool geom_transform_area_t::is_compatible_with(
table_column_type geom_type) const noexcept
{
if (m_multi) {
return geom_type == table_column_type::multipolygon ||
geom_type == table_column_type::geometry;
}

return geom_type == table_column_type::polygon ||
geom_type == table_column_type::multipolygon ||
geom_type == table_column_type::geometry;
}

geom::osmium_builder_t::wkbs_t
geom_transform_area_t::run(geom::osmium_builder_t *builder,
table_column_type target_geom_type,
osmium::Way *way) const
{
assert(builder);
assert(way);

geom::osmium_builder_t::wkbs_t result;

if (!way->is_closed()) {
return {};
return result;
}

geom::osmium_builder_t::wkbs_t result;
result.push_back(builder->get_wkb_polygon(*way));

if (result.front().empty()) {
result.clear();
} else if (target_geom_type == table_column_type::multipolygon) {
builder->wrap_in_multipolygon(&result);
}

return result;
}

geom::osmium_builder_t::wkbs_t
geom_transform_area_t::run(geom::osmium_builder_t *builder,
table_column_type target_geom_type,
osmium::Relation const &relation,
osmium::memory::Buffer const &buffer) const
{
assert(builder);

return builder->get_wkb_multipolygon(relation, buffer, m_multi);
bool const wrap_multi = target_geom_type == table_column_type::multipolygon;

return builder->get_wkb_multipolygon(relation, buffer, m_multi, wrap_multi);
}

std::unique_ptr<geom_transform_t> create_geom_transform(char const *type)
Expand Down
16 changes: 12 additions & 4 deletions src/geom-transform.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,22 @@ class geom_transform_t

virtual geom::osmium_builder_t::wkbs_t
run(geom::osmium_builder_t * /*builder*/,
table_column_type /*target_geom_type*/,
osmium::Node const & /*node*/) const
{
return {};
}

virtual geom::osmium_builder_t::wkbs_t
run(geom::osmium_builder_t * /*builder*/, osmium::Way * /*way*/) const
run(geom::osmium_builder_t * /*builder*/,
table_column_type /*target_geom_type*/, osmium::Way * /*way*/) const
{
return {};
}

virtual geom::osmium_builder_t::wkbs_t
run(geom::osmium_builder_t * /*builder*/,
table_column_type /*target_geom_type*/,
osmium::Relation const & /*relation*/,
osmium::memory::Buffer const & /*buffer*/) const
{
Expand All @@ -60,6 +63,7 @@ class geom_transform_point_t : public geom_transform_t
noexcept override;

geom::osmium_builder_t::wkbs_t run(geom::osmium_builder_t *builder,
table_column_type target_geom_type,
osmium::Node const &node) const override;

}; // class geom_transform_point_t
Expand All @@ -73,10 +77,12 @@ class geom_transform_line_t : public geom_transform_t
noexcept override;

geom::osmium_builder_t::wkbs_t run(geom::osmium_builder_t *builder,
table_column_type target_geom_type,
osmium::Way *way) const override;

geom::osmium_builder_t::wkbs_t
run(geom::osmium_builder_t *builder, osmium::Relation const &relation,
run(geom::osmium_builder_t *builder, table_column_type target_geom_type,
osmium::Relation const &relation,
osmium::memory::Buffer const &buffer) const override;

private:
Expand All @@ -93,14 +99,16 @@ class geom_transform_area_t : public geom_transform_t
noexcept override;

geom::osmium_builder_t::wkbs_t run(geom::osmium_builder_t *builder,
table_column_type target_geom_type,
osmium::Way *way) const override;

geom::osmium_builder_t::wkbs_t
run(geom::osmium_builder_t *builder, osmium::Relation const &relation,
run(geom::osmium_builder_t *builder, table_column_type target_geom_type,
osmium::Relation const &relation,
osmium::memory::Buffer const &buffer) const override;

private:
bool m_multi = false;
bool m_multi = true;

}; // class geom_transform_area_t

Expand Down
70 changes: 39 additions & 31 deletions src/osmium-builder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,26 @@ void add_nodes_to_builder(osmium::builder::WayNodeListBuilder &builder,

namespace geom {

void osmium_builder_t::wrap_in_multipolygon(
osmium_builder_t::wkbs_t *geometries)
{
assert(!geometries->empty());

m_writer.multipolygon_start();
for (auto const &p : *geometries) {
m_writer.add_sub_geometry(p);
}
(*geometries)[0] = m_writer.multipolygon_finish(geometries->size());
geometries->resize(1);
}

void osmium_builder_t::wrap_in_multipolygon(osmium_builder_t::wkb_t *geometry)
{
m_writer.multipolygon_start();
m_writer.add_sub_geometry(*geometry);
*geometry = m_writer.multipolygon_finish(1);
}

osmium_builder_t::wkb_t
osmium_builder_t::get_wkb_node(osmium::Location const &loc) const
{
Expand Down Expand Up @@ -145,28 +165,41 @@ osmium_builder_t::get_wkb_polygon(osmium::Way const &way)

auto const wkbs = create_polygons(m_buffer.get<osmium::Area>(0));

return wkbs.empty() ? wkb_t() : wkbs[0];
return wkbs.empty() ? wkb_t{} : wkbs[0];
}

osmium_builder_t::wkbs_t
osmium_builder_t::get_wkb_multipolygon(osmium::Relation const &rel,
osmium::memory::Buffer const &ways,
bool build_multigeoms)
bool build_multigeoms, bool wrap_multi)
{
wkbs_t ret;
osmium::area::AssemblerConfig area_config;
area_config.ignore_invalid_locations = true;
osmium::area::GeomAssembler assembler{area_config};

m_buffer.clear();

wkbs_t ret;
if (assembler(rel, ways, m_buffer)) {
auto const &area = m_buffer.get<osmium::Area>(0);

// This returns a vector of one or more polygons
ret = create_polygons(area);
assert(!ret.empty());

if (build_multigeoms) {
ret.push_back(create_multipolygon(m_buffer.get<osmium::Area>(0)));
if (ret.size() > 1 || wrap_multi) {
wrap_in_multipolygon(&ret);
}
} else {
ret = create_polygons(m_buffer.get<osmium::Area>(0));
if (wrap_multi) {
for (auto &wkb : ret) {
// wrap each polygon into its own multipolygon
wrap_in_multipolygon(&wkb);
}
}
}
}

return ret;
}

Expand Down Expand Up @@ -345,31 +378,6 @@ size_t osmium_builder_t::add_mp_points(osmium::NodeRefList const &nodes)
return num_points;
}

osmium_builder_t::wkb_t
osmium_builder_t::create_multipolygon(osmium::Area const &area)
{
wkb_t ret;

auto const polys = create_polygons(area);

switch (polys.size()) {
case 0:
break; //nothing
case 1:
ret = polys[0];
break;
default:
m_writer.multipolygon_start();
for (auto const &p : polys) {
m_writer.add_sub_geometry(p);
}
ret = m_writer.multipolygon_finish(polys.size());
break;
}

return ret;
}

osmium_builder_t::wkbs_t
osmium_builder_t::create_polygons(osmium::Area const &area)
{
Expand Down
15 changes: 13 additions & 2 deletions src/osmium-builder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,24 @@ class osmium_builder_t

wkbs_t get_wkb_multipolygon(osmium::Relation const &rel,
osmium::memory::Buffer const &ways,
bool build_multigeoms);
bool build_multigeoms, bool wrap_multi = false);

wkbs_t get_wkb_multiline(osmium::memory::Buffer const &ways,
double split_at);

/**
* Wrap the geometries (must be one or more polygons) in the parameter
* into a single multipolygon which is returned in-place in geometries.
*/
void wrap_in_multipolygon(wkbs_t *geometries);

/**
* Wrap the polygon geometry in the parameter into a multipolygon which
* is returned in-place in geometry.
*/
void wrap_in_multipolygon(wkb_t *geometry);

private:
wkb_t create_multipolygon(osmium::Area const &area);
wkbs_t create_polygons(osmium::Area const &area);
size_t add_mp_points(osmium::NodeRefList const &nodes);

Expand Down
12 changes: 8 additions & 4 deletions src/output-flex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -967,25 +967,28 @@ get_default_transform(flex_table_column_t const &column,
geom::osmium_builder_t::wkbs_t
output_flex_t::run_transform(geom::osmium_builder_t *builder,
geom_transform_t const *transform,
table_column_type target_geom_type,
osmium::Node const &node)
{
return transform->run(builder, node);
return transform->run(builder, target_geom_type, node);
}

geom::osmium_builder_t::wkbs_t
output_flex_t::run_transform(geom::osmium_builder_t *builder,
geom_transform_t const *transform,
table_column_type target_geom_type,
osmium::Way const & /*way*/)
{
if (get_way_nodes() <= 1U) {
return {};
}
return transform->run(builder, m_context_way);
return transform->run(builder, target_geom_type, m_context_way);
}

geom::osmium_builder_t::wkbs_t
output_flex_t::run_transform(geom::osmium_builder_t *builder,
geom_transform_t const *transform,
table_column_type target_geom_type,
osmium::Relation const &relation)
{
m_buffer.clear();
Expand All @@ -1000,7 +1003,7 @@ output_flex_t::run_transform(geom::osmium_builder_t *builder,
m_mid->nodes_get_list(&(way.nodes()));
}

return transform->run(builder, relation, m_buffer);
return transform->run(builder, target_geom_type, relation, m_buffer);
}

template <typename OBJECT>
Expand Down Expand Up @@ -1035,7 +1038,8 @@ void output_flex_t::add_row(table_connection_t *table_connection,
}

auto *builder = table_connection->get_builder();
auto const wkbs = run_transform(builder, transform, object);
auto const wkbs =
run_transform(builder, transform, table.geom_column().type(), object);
for (auto const &wkb : wkbs) {
m_expire.from_wkb(wkb.c_str(), id);
write_row(table_connection, object.type(), id, wkb,
Expand Down
Loading