1 #ifndef OSMIUM_AREA_ASSEMBLER_HPP
2 #define OSMIUM_AREA_ASSEMBLER_HPP
50 #include <osmium/area/detail/proto_ring.hpp>
51 #include <osmium/area/detail/node_ref_segment.hpp>
52 #include <osmium/area/detail/segment_list.hpp>
59 using osmium::area::detail::ProtoRing;
104 return m_config.
debug;
117 if (nr1.
ref() != nr2.
ref()) {
128 tl_builder.
add_tag(tag.key(), tag.value());
133 std::map<std::string, size_t> counter;
135 for (
const auto& tag : way->tags()) {
136 std::string kv {tag.key()};
138 kv.append(tag.value());
143 size_t num_ways = ways.size();
144 for (
const auto& t_c : counter) {
146 std::cerr <<
" tag " << t_c.first <<
" is used " << t_c.second <<
" times in " << num_ways <<
" ways\n";
148 if (t_c.second == num_ways) {
149 size_t len = std::strlen(t_c.first.c_str());
150 tl_builder.
add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1);
159 add(
false,
"created_by");
160 add(
false,
"source");
162 add(
false,
"test:id");
163 add(
false,
"test:section");
177 std::cerr <<
" found " << count <<
" tags on relation (without ignored ones)\n";
182 std::cerr <<
" use tags from relation\n";
188 if (strcmp(tag.key(),
"type")) {
189 tl_builder.
add_tag(tag.key(), tag.value());
194 std::cerr <<
" use tags from outer ways\n";
196 std::set<const osmium::Way*> ways;
197 for (
const auto& ring : m_outer_rings) {
198 ring->get_ways(ways);
200 if (ways.size() == 1) {
202 std::cerr <<
" only one outer way\n";
205 for (
const osmium::Tag& tag : (*ways.begin())->tags()) {
206 tl_builder.
add_tag(tag.key(), tag.value());
210 std::cerr <<
" multiple outer ways, get common tags\n";
225 bool open_rings =
false;
227 for (
const auto& ring : m_rings) {
228 if (!ring.closed()) {
250 std::cerr <<
" possibly_combine_rings_back()\n";
252 for (
auto it = m_rings.begin(); it != m_rings.end(); ++it) {
253 if (&*it != &ring && !it->closed()) {
256 std::cerr <<
" ring.last=it->first\n";
258 ring.merge_ring(*it,
debug());
264 std::cerr <<
" ring.last=it->last\n";
266 ring.merge_ring_reverse(*it,
debug());
286 std::cerr <<
" possibly_combine_rings_front()\n";
288 for (
auto it = m_rings.begin(); it != m_rings.end(); ++it) {
289 if (&*it != &ring && !it->closed()) {
292 std::cerr <<
" ring.first=it->last\n";
294 ring.swap_segments(*it);
295 ring.merge_ring(*it,
debug());
301 std::cerr <<
" ring.first=it->first\n";
304 ring.merge_ring(*it,
debug());
313 void split_off_subring(osmium::area::detail::ProtoRing& ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end) {
315 std::cerr <<
" subring found at: " << *it <<
"\n";
317 ProtoRing new_ring(it_begin, it_end);
318 ring.remove_segments(it_begin, it_end);
320 std::cerr <<
" split into two rings:\n";
321 std::cerr <<
" " << new_ring <<
"\n";
322 std::cerr <<
" " << ring <<
"\n";
324 m_rings.push_back(std::move(new_ring));
328 if (ring.segments().size() < 3) {
332 std::cerr <<
" has_closed_subring_back()\n";
334 auto end = ring.segments().end();
335 for (
auto it = ring.segments().begin() + 1; it !=
end - 1; ++it) {
345 if (ring.segments().size() < 3) {
349 std::cerr <<
" has_closed_subring_front()\n";
351 auto end = ring.segments().end();
352 for (
auto it = ring.segments().begin() + 1; it !=
end - 1; ++it) {
363 std::cerr <<
" check_for_closed_subring()\n";
366 osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size());
367 std::copy(ring.segments().begin(), ring.segments().end(), segments.begin());
368 std::sort(segments.begin(), segments.end());
369 auto it = std::adjacent_find(segments.begin(), segments.end(), [
this](
const osmium::area::detail::NodeRefSegment& s1,
const osmium::area::detail::NodeRefSegment& s2) {
372 if (it == segments.end()) {
375 auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
376 assert(r1 != ring.segments().end());
377 auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
378 assert(r2 != ring.segments().end());
381 std::cerr <<
" found subring in ring " << ring <<
" at " << it->first() <<
"\n";
384 auto m = std::minmax(r1, r2);
386 ProtoRing new_ring(m.first, m.second);
387 ring.remove_segments(m.first, m.second);
390 std::cerr <<
" split ring1=" << new_ring <<
"\n";
391 std::cerr <<
" split ring2=" << ring <<
"\n";
394 m_rings.emplace_back(new_ring);
401 std::cerr <<
" => match at front of ring\n";
403 ring.add_segment_front(segment);
412 std::cerr <<
" => match at back of ring\n";
414 ring.add_segment_back(segment);
426 for (
const ProtoRing* ring : m_outer_rings) {
428 std::cerr <<
" ring " << *ring <<
" is outer\n";
432 ring_builder.
add_node_ref(ring->get_segment_front().first());
433 for (
const auto& segment : ring->segments()) {
434 ring_builder.add_node_ref(segment.second());
437 for (ProtoRing* inner : ring->inner_rings()) {
439 ring_builder.
add_node_ref(inner->get_segment_front().first());
440 for (
const auto& segment : inner->segments()) {
441 ring_builder.add_node_ref(segment.second());
449 for (
auto& ring : m_rings) {
451 std::cerr <<
" check against ring " << n <<
" " << ring;
455 std::cerr <<
" => ring CLOSED\n";
463 segment.swap_locations();
468 segment.swap_locations();
477 std::cerr <<
" => no match\n";
489 std::cerr <<
" check_inner_outer min_node=" << min_node <<
"\n";
495 for (
auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.
location().
x(); ++it) {
496 if (!ring.contains(*it)) {
498 std::cerr <<
" segments for count: " << *it;
500 if (it->to_left_of(min_node.
location())) {
503 std::cerr <<
" counted\n";
507 std::cerr <<
" not counted\n";
510 if (it->first().location() == min_node.
location()) {
511 if (it->second().location().y() > min_node.
location().
y()) {
515 if (it->second().location() == min_node.
location()) {
516 if (it->first().location().y() > min_node.
location().
y()) {
524 std::cerr <<
" count=" << count <<
" above=" << above <<
"\n";
536 std::cerr <<
" check_inner_outer_roles\n";
539 for (
const auto ringptr : m_outer_rings) {
540 for (
const auto segment : ringptr->segments()) {
541 if (!segment.role_outer()) {
544 std::cerr <<
" segment " << segment <<
" from way " << segment.way()->id() <<
" should have role 'outer'\n";
552 for (
const auto ringptr : m_inner_rings) {
553 for (
const auto segment : ringptr->segments()) {
554 if (!segment.role_inner()) {
557 std::cerr <<
" segment " << segment <<
" from way " << segment.way()->id() <<
" should have role 'inner'\n";
571 m_segment_list.sort();
572 m_segment_list.erase_duplicate_segments();
585 for (
const auto& segment : m_segment_list) {
587 std::cerr <<
" checking segment " << segment <<
"\n";
591 std::cerr <<
" new ring for segment " << segment <<
"\n";
593 m_rings.emplace_back(segment);
598 std::cerr <<
" Rings:\n";
599 for (
const auto& ring : m_rings) {
600 std::cerr <<
" " << ring;
602 std::cerr <<
" (closed)";
610 std::cerr <<
" not all rings are closed\n";
616 std::cerr <<
" Find inner/outer...\n";
619 if (m_rings.size() == 1) {
620 m_outer_rings.push_back(&m_rings.front());
622 for (
auto& ring : m_rings) {
628 m_outer_rings.push_back(&ring);
633 m_inner_rings.push_back(&ring);
637 if (m_outer_rings.size() == 1) {
638 for (
auto inner : m_inner_rings) {
639 m_outer_rings.front()->add_inner_ring(inner);
643 std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
644 return a->area() < b->area();
646 for (
auto inner : m_inner_rings) {
647 for (
auto outer : m_outer_rings) {
648 if (inner->is_in(outer)) {
649 outer->add_inner_ring(inner);
668 m_segment_list(config.
debug) {
688 m_segment_list.extract_segments_from_way(way,
"outer");
691 std::cerr <<
"\nBuild way id()=" << way.
id() <<
" segments.size()=" << m_segment_list.size() <<
"\n";
719 m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
722 std::cerr <<
"\nBuild relation id()=" << relation.
id() <<
" members.size()=" << members.size() <<
" segments.size()=" << m_segment_list.size() <<
"\n";
725 size_t area_offset = out_buffer.
committed();
746 std::vector<const osmium::Way*> ways_that_should_be_areas;
749 for (
size_t offset : members) {
750 if (!std::strcmp(memit->role(),
"inner")) {
760 if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d !=
std::distance(area_fi_begin, area_fi_end)) {
761 ways_that_should_be_areas.push_back(&way);
771 for (
const osmium::Way* way : ways_that_should_be_areas) {
773 assembler(*way, out_buffer);
783 #endif // OSMIUM_AREA_ASSEMBLER_HPP
WayNodeList & nodes()
Definition: way.hpp:75
std::vector< ProtoRing * > m_outer_rings
Definition: assembler.hpp:98
osmium::area::ProblemReporter * problem_reporter
Definition: assembler.hpp:63
iterator end()
Definition: collection.hpp:128
osmium::memory::Buffer & buffer() noexcept
Return the buffer this builder is using.
Definition: builder.hpp:165
RelationMemberList & members()
Definition: relation.hpp:174
virtual void report_duplicate_node(osmium::object_id_type node_id1, osmium::object_id_type node_id2, osmium::Location location)
Definition: problem_reporter.hpp:94
virtual void report_role_should_be_inner(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end)
Definition: problem_reporter.hpp:138
void initialize_from_object(const osmium::OSMObject &source)
Definition: osm_object_builder.hpp:264
void add_rings_to_area(osmium::builder::AreaBuilder &builder) const
Definition: assembler.hpp:425
bool ends_have_same_id() const
Definition: way.hpp:102
void operator()(const osmium::Way &way, osmium::memory::Buffer &out_buffer)
Definition: assembler.hpp:677
Definition: relation.hpp:162
void check_inner_outer(ProtoRing &ring)
Definition: assembler.hpp:486
Definition: assembler.hpp:61
void combine_rings_back(const osmium::area::detail::NodeRefSegment &segment, ProtoRing &ring)
Definition: assembler.hpp:410
Definition: entity_bits.hpp:67
void operator()(const osmium::Relation &relation, const std::vector< size_t > &members, const osmium::memory::Buffer &in_buffer, osmium::memory::Buffer &out_buffer)
Definition: assembler.hpp:714
void add_tags_to_area(osmium::builder::AreaBuilder &builder, const osmium::Relation &relation) const
Definition: assembler.hpp:173
void split_off_subring(osmium::area::detail::ProtoRing &ring, osmium::area::detail::ProtoRing::segments_type::iterator it, osmium::area::detail::ProtoRing::segments_type::iterator it_begin, osmium::area::detail::ProtoRing::segments_type::iterator it_end)
Definition: assembler.hpp:313
iterator begin()
Definition: collection.hpp:124
double distance(const osmium::geom::Coordinates &c1, const osmium::geom::Coordinates &c2)
Definition: haversine.hpp:64
bool debug
Definition: assembler.hpp:66
osmium::object_id_type ref() const noexcept
Definition: node_ref.hpp:62
void add_common_tags(osmium::builder::TagListBuilder &tl_builder, std::set< const osmium::Way * > &ways) const
Definition: assembler.hpp:132
int m_inner_outer_mismatches
Definition: assembler.hpp:101
std::list< ProtoRing > m_rings
Definition: assembler.hpp:96
virtual void report_role_should_be_outer(osmium::object_id_type way_id, osmium::Location seg_start, osmium::Location seg_end)
Definition: problem_reporter.hpp:128
Definition: osm_object_builder.hpp:96
osmium::area::detail::SegmentList m_segment_list
Definition: assembler.hpp:93
bool has_closed_subring_front(ProtoRing &ring, const NodeRef &nr)
Definition: assembler.hpp:344
Namespace for everything in the Osmium library.
Definition: assembler.hpp:55
void check_inner_outer_roles()
Definition: assembler.hpp:534
bool check_for_closed_subring(ProtoRing &ring)
Definition: assembler.hpp:361
virtual void report_ring_not_closed(osmium::Location end1, osmium::Location end2)
Definition: problem_reporter.hpp:118
Definition: problem_reporter.hpp:55
bool possibly_combine_rings_front(ProtoRing &ring)
Definition: assembler.hpp:282
void set_object(osmium::item_type object_type, osmium::object_id_type object_id) noexcept
Definition: problem_reporter.hpp:77
Definition: assembler.hpp:155
osmium::io::InputIterator< osmium::io::Reader > end(osmium::io::Reader &)
Definition: reader_iterator.hpp:45
constexpr int32_t y() const noexcept
Definition: location.hpp:167
const TagList & tags() const
Get the list of tags for this object.
Definition: object.hpp:294
AssemblerConfig(osmium::area::ProblemReporter *pr=nullptr, bool d=false)
Definition: assembler.hpp:68
static MPFilter & filter()
Definition: assembler.hpp:168
bool has_closed_subring_back(ProtoRing &ring, const NodeRef &nr)
Definition: assembler.hpp:327
void add_tags_to_area(osmium::builder::AreaBuilder &builder, const osmium::Way &way) const
Definition: assembler.hpp:125
const AssemblerConfig m_config
Definition: assembler.hpp:90
Assembler(const config_type &config)
Definition: assembler.hpp:666
osmium::Location & location() noexcept
Definition: node_ref.hpp:73
osmium::area::AssemblerConfig config_type
Definition: assembler.hpp:664
bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment)
Definition: assembler.hpp:447
object_id_type id() const noexcept
Get ID of this object.
Definition: object.hpp:109
size_t committed() const noexcept
Definition: buffer.hpp:218
bool debug() const
Definition: assembler.hpp:103
void combine_rings_front(const osmium::area::detail::NodeRefSegment &segment, ProtoRing &ring)
Definition: assembler.hpp:399
Definition: buffer.hpp:95
T & get(const size_t offset) const
Definition: buffer.hpp:307
std::vector< ProtoRing * > m_inner_rings
Definition: assembler.hpp:99
bool create_rings()
Definition: assembler.hpp:570
bool is_closed() const
Definition: way.hpp:98
const NodeRef & front() const noexcept
Definition: node_ref_list.hpp:91
bool check_for_open_rings()
Definition: assembler.hpp:224
constexpr int32_t x() const noexcept
Definition: location.hpp:163
const NodeRef & back() const noexcept
Definition: node_ref_list.hpp:101
MPFilter()
Definition: assembler.hpp:157
bool has_same_location(const osmium::NodeRef &nr1, const osmium::NodeRef &nr2)
Definition: assembler.hpp:113
Definition: node_ref.hpp:50
Definition: assembler.hpp:88
bool possibly_combine_rings_back(ProtoRing &ring)
Definition: assembler.hpp:246
void enable_debug_output(bool d=true)
Definition: assembler.hpp:77
size_type size() const noexcept
Definition: tag.hpp:115
void add_tag(const char *key, const char *value)
Definition: osm_object_builder.hpp:78
Definition: osm_object_builder.hpp:60
size_t commit()
Definition: buffer.hpp:273
void add_node_ref(const NodeRef &node_ref)
Definition: osm_object_builder.hpp:108
Definition: osm_object_builder.hpp:253