1 #ifndef OSMIUM_AREA_ASSEMBLER_HPP
2 #define OSMIUM_AREA_ASSEMBLER_HPP
54 #include <osmium/area/detail/proto_ring.hpp>
55 #include <osmium/area/detail/node_ref_segment.hpp>
56 #include <osmium/area/detail/segment_list.hpp>
63 using osmium::area::detail::ProtoRing;
108 return m_config.
debug;
121 if (nr1.
ref() != nr2.
ref()) {
132 tl_builder.
add_tag(tag.key(), tag.value());
137 std::map<std::string, size_t> counter;
139 for (
const auto& tag : way->tags()) {
140 std::string kv {tag.key()};
142 kv.append(tag.value());
147 size_t num_ways = ways.size();
148 for (
const auto& t_c : counter) {
150 std::cerr <<
" tag " << t_c.first <<
" is used " << t_c.second <<
" times in " << num_ways <<
" ways\n";
152 if (t_c.second == num_ways) {
153 size_t len = std::strlen(t_c.first.c_str());
154 tl_builder.
add_tag(t_c.first.c_str(), t_c.first.c_str() + len + 1);
163 add(
false,
"created_by");
164 add(
false,
"source");
166 add(
false,
"test:id");
167 add(
false,
"test:section");
181 std::cerr <<
" found " << count <<
" tags on relation (without ignored ones)\n";
186 std::cerr <<
" use tags from relation\n";
192 if (strcmp(tag.key(),
"type")) {
193 tl_builder.
add_tag(tag.key(), tag.value());
198 std::cerr <<
" use tags from outer ways\n";
200 std::set<const osmium::Way*> ways;
201 for (
const auto& ring : m_outer_rings) {
202 ring->get_ways(ways);
204 if (ways.size() == 1) {
206 std::cerr <<
" only one outer way\n";
209 for (
const osmium::Tag& tag : (*ways.begin())->tags()) {
210 tl_builder.
add_tag(tag.key(), tag.value());
214 std::cerr <<
" multiple outer ways, get common tags\n";
229 bool open_rings =
false;
231 for (
const auto& ring : m_rings) {
232 if (!ring.closed()) {
254 std::cerr <<
" possibly_combine_rings_back()\n";
256 for (
auto it = m_rings.begin(); it != m_rings.end(); ++it) {
257 if (&*it != &ring && !it->closed()) {
260 std::cerr <<
" ring.last=it->first\n";
262 ring.merge_ring(*it,
debug());
268 std::cerr <<
" ring.last=it->last\n";
270 ring.merge_ring_reverse(*it,
debug());
290 std::cerr <<
" possibly_combine_rings_front()\n";
292 for (
auto it = m_rings.begin(); it != m_rings.end(); ++it) {
293 if (&*it != &ring && !it->closed()) {
296 std::cerr <<
" ring.first=it->last\n";
298 ring.swap_segments(*it);
299 ring.merge_ring(*it,
debug());
305 std::cerr <<
" ring.first=it->first\n";
308 ring.merge_ring(*it,
debug());
317 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) {
319 std::cerr <<
" subring found at: " << *it <<
"\n";
321 ProtoRing new_ring(it_begin, it_end);
322 ring.remove_segments(it_begin, it_end);
324 std::cerr <<
" split into two rings:\n";
325 std::cerr <<
" " << new_ring <<
"\n";
326 std::cerr <<
" " << ring <<
"\n";
328 m_rings.push_back(std::move(new_ring));
332 if (ring.segments().size() < 3) {
336 std::cerr <<
" has_closed_subring_back()\n";
338 const auto end = ring.segments().end();
339 for (
auto it = ring.segments().begin() + 1; it !=
end - 1; ++it) {
349 if (ring.segments().size() < 3) {
353 std::cerr <<
" has_closed_subring_front()\n";
355 const auto end = ring.segments().end();
356 for (
auto it = ring.segments().begin() + 1; it !=
end - 1; ++it) {
367 std::cerr <<
" check_for_closed_subring()\n";
370 osmium::area::detail::ProtoRing::segments_type segments(ring.segments().size());
371 std::copy(ring.segments().begin(), ring.segments().end(), segments.begin());
372 std::sort(segments.begin(), segments.end());
373 const auto it = std::adjacent_find(segments.begin(), segments.end(), [
this](
const osmium::area::detail::NodeRefSegment& s1,
const osmium::area::detail::NodeRefSegment& s2) {
376 if (it == segments.end()) {
379 const auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
380 assert(r1 != ring.segments().end());
381 const auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
382 assert(r2 != ring.segments().end());
385 std::cerr <<
" found subring in ring " << ring <<
" at " << it->first() <<
"\n";
388 const auto m = std::minmax(r1, r2);
390 ProtoRing new_ring(m.first, m.second);
391 ring.remove_segments(m.first, m.second);
394 std::cerr <<
" split ring1=" << new_ring <<
"\n";
395 std::cerr <<
" split ring2=" << ring <<
"\n";
398 m_rings.emplace_back(new_ring);
405 std::cerr <<
" => match at front of ring\n";
407 ring.add_segment_front(segment);
416 std::cerr <<
" => match at back of ring\n";
418 ring.add_segment_back(segment);
430 for (
const ProtoRing* ring : m_outer_rings) {
432 std::cerr <<
" ring " << *ring <<
" is outer\n";
436 ring_builder.
add_node_ref(ring->get_segment_front().first());
437 for (
const auto& segment : ring->segments()) {
438 ring_builder.add_node_ref(segment.second());
441 for (ProtoRing* inner : ring->inner_rings()) {
443 ring_builder.
add_node_ref(inner->get_segment_front().first());
444 for (
const auto& segment : inner->segments()) {
445 ring_builder.add_node_ref(segment.second());
453 for (
auto& ring : m_rings) {
455 std::cerr <<
" check against ring " << n <<
" " << ring;
459 std::cerr <<
" => ring CLOSED\n";
467 segment.swap_locations();
472 segment.swap_locations();
481 std::cerr <<
" => no match\n";
493 std::cerr <<
" check_inner_outer min_node=" << min_node <<
"\n";
499 for (
auto it = m_segment_list.begin(); it != m_segment_list.end() && it->first().location().x() <= min_node.
location().
x(); ++it) {
500 if (!ring.contains(*it)) {
502 std::cerr <<
" segments for count: " << *it;
504 if (it->to_left_of(min_node.
location())) {
507 std::cerr <<
" counted\n";
511 std::cerr <<
" not counted\n";
514 if (it->first().location() == min_node.
location()) {
515 if (it->second().location().y() > min_node.
location().
y()) {
519 if (it->second().location() == min_node.
location()) {
520 if (it->first().location().y() > min_node.
location().
y()) {
528 std::cerr <<
" count=" << count <<
" above=" << above <<
"\n";
540 std::cerr <<
" check_inner_outer_roles\n";
543 for (
const auto ringptr : m_outer_rings) {
544 for (
const auto& segment : ringptr->segments()) {
545 if (!segment.role_outer()) {
548 std::cerr <<
" segment " << segment <<
" from way " << segment.way()->id() <<
" should have role 'outer'\n";
556 for (
const auto ringptr : m_inner_rings) {
557 for (
const auto& segment : ringptr->segments()) {
558 if (!segment.role_inner()) {
561 std::cerr <<
" segment " << segment <<
" from way " << segment.way()->id() <<
" should have role 'inner'\n";
575 m_segment_list.sort();
576 m_segment_list.erase_duplicate_segments();
589 for (
const auto& segment : m_segment_list) {
591 std::cerr <<
" checking segment " << segment <<
"\n";
595 std::cerr <<
" new ring for segment " << segment <<
"\n";
597 m_rings.emplace_back(segment);
602 std::cerr <<
" Rings:\n";
603 for (
const auto& ring : m_rings) {
604 std::cerr <<
" " << ring;
606 std::cerr <<
" (closed)";
614 std::cerr <<
" not all rings are closed\n";
620 std::cerr <<
" Find inner/outer...\n";
623 if (m_rings.size() == 1) {
624 m_outer_rings.push_back(&m_rings.front());
626 for (
auto& ring : m_rings) {
632 m_outer_rings.push_back(&ring);
637 m_inner_rings.push_back(&ring);
641 if (m_outer_rings.size() == 1) {
642 for (
auto inner : m_inner_rings) {
643 m_outer_rings.front()->add_inner_ring(inner);
647 std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
648 return a->area() < b->area();
650 for (
auto inner : m_inner_rings) {
651 for (
auto outer : m_outer_rings) {
652 if (inner->is_in(outer)) {
653 outer->add_inner_ring(inner);
672 m_segment_list(config.
debug) {
692 m_segment_list.extract_segments_from_way(way,
"outer");
695 std::cerr <<
"\nBuild way id()=" << way.
id() <<
" segments.size()=" << m_segment_list.size() <<
"\n";
723 m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
726 std::cerr <<
"\nBuild relation id()=" << relation.
id() <<
" members.size()=" << members.size() <<
" segments.size()=" << m_segment_list.size() <<
"\n";
729 size_t area_offset = out_buffer.
committed();
750 std::vector<const osmium::Way*> ways_that_should_be_areas;
753 for (
size_t offset : members) {
754 if (!std::strcmp(memit->role(),
"inner")) {
764 if (!std::equal(way_fi_begin, way_fi_end, area_fi_begin) || d !=
std::distance(area_fi_begin, area_fi_end)) {
765 ways_that_should_be_areas.push_back(&way);
775 for (
const osmium::Way* way : ways_that_should_be_areas) {
777 assembler(*way, out_buffer);
787 #endif // OSMIUM_AREA_ASSEMBLER_HPP
WayNodeList & nodes()
Definition: way.hpp:75
std::vector< ProtoRing * > m_outer_rings
Definition: assembler.hpp:102
osmium::area::ProblemReporter * problem_reporter
Definition: assembler.hpp:67
iterator end()
Definition: collection.hpp:127
osmium::memory::Buffer & buffer() noexcept
Return the buffer this builder is using.
Definition: builder.hpp:179
RelationMemberList & members()
Definition: relation.hpp:177
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:377
void add_rings_to_area(osmium::builder::AreaBuilder &builder) const
Definition: assembler.hpp:429
bool ends_have_same_id() const
Definition: way.hpp:102
void operator()(const osmium::Way &way, osmium::memory::Buffer &out_buffer)
Definition: assembler.hpp:681
Definition: relation.hpp:165
void check_inner_outer(ProtoRing &ring)
Definition: assembler.hpp:490
Definition: assembler.hpp:65
void combine_rings_back(const osmium::area::detail::NodeRefSegment &segment, ProtoRing &ring)
Definition: assembler.hpp:414
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:718
void add_tags_to_area(osmium::builder::AreaBuilder &builder, const osmium::Relation &relation) const
Definition: assembler.hpp:177
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:317
iterator begin()
Definition: collection.hpp:123
double distance(const osmium::geom::Coordinates &c1, const osmium::geom::Coordinates &c2)
Definition: haversine.hpp:64
bool debug
Definition: assembler.hpp:70
void add_common_tags(osmium::builder::TagListBuilder &tl_builder, std::set< const osmium::Way * > &ways) const
Definition: assembler.hpp:136
int m_inner_outer_mismatches
Definition: assembler.hpp:105
std::list< ProtoRing > m_rings
Definition: assembler.hpp:100
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:156
osmium::area::detail::SegmentList m_segment_list
Definition: assembler.hpp:97
size_type size() const noexcept
Definition: tag.hpp:115
bool has_closed_subring_front(ProtoRing &ring, const NodeRef &nr)
Definition: assembler.hpp:348
Namespace for everything in the Osmium library.
Definition: assembler.hpp:59
void check_inner_outer_roles()
Definition: assembler.hpp:538
bool check_for_closed_subring(ProtoRing &ring)
Definition: assembler.hpp:365
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:286
void set_object(osmium::item_type object_type, osmium::object_id_type object_id) noexcept
Definition: problem_reporter.hpp:77
Definition: assembler.hpp:159
osmium::io::InputIterator< osmium::io::Reader > end(osmium::io::Reader &)
Definition: reader_iterator.hpp:45
constexpr osmium::object_id_type ref() const noexcept
Definition: node_ref.hpp:65
const TagList & tags() const
Get the list of tags for this object.
Definition: object.hpp:295
AssemblerConfig(osmium::area::ProblemReporter *pr=nullptr, bool d=false)
Definition: assembler.hpp:72
size_t committed() const noexcept
Definition: buffer.hpp:241
static MPFilter & filter()
Definition: assembler.hpp:172
bool has_closed_subring_back(ProtoRing &ring, const NodeRef &nr)
Definition: assembler.hpp:331
const NodeRef & front() const noexcept
Definition: node_ref_list.hpp:92
void add_tags_to_area(osmium::builder::AreaBuilder &builder, const osmium::Way &way) const
Definition: assembler.hpp:129
const AssemblerConfig m_config
Definition: assembler.hpp:94
Assembler(const config_type &config)
Definition: assembler.hpp:670
osmium::Location & location() noexcept
Definition: node_ref.hpp:79
osmium::area::AssemblerConfig config_type
Definition: assembler.hpp:668
bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment)
Definition: assembler.hpp:451
bool debug() const
Definition: assembler.hpp:107
void combine_rings_front(const osmium::area::detail::NodeRefSegment &segment, ProtoRing &ring)
Definition: assembler.hpp:403
Definition: buffer.hpp:97
T & get(const size_t offset) const
Definition: buffer.hpp:375
std::vector< ProtoRing * > m_inner_rings
Definition: assembler.hpp:103
object_id_type id() const noexcept
Get ID of this object.
Definition: object.hpp:110
constexpr int32_t x() const noexcept
Definition: location.hpp:163
bool create_rings()
Definition: assembler.hpp:574
bool is_closed() const
Definition: way.hpp:98
bool check_for_open_rings()
Definition: assembler.hpp:228
MPFilter()
Definition: assembler.hpp:161
bool has_same_location(const osmium::NodeRef &nr1, const osmium::NodeRef &nr2)
Definition: assembler.hpp:117
Definition: node_ref.hpp:50
Definition: assembler.hpp:92
const NodeRef & back() const noexcept
Definition: node_ref_list.hpp:102
bool possibly_combine_rings_back(ProtoRing &ring)
Definition: assembler.hpp:250
constexpr int32_t y() const noexcept
Definition: location.hpp:167
void enable_debug_output(bool d=true)
Definition: assembler.hpp:81
void add_tag(const char *key, const char *value)
Definition: osm_object_builder.hpp:80
Definition: osm_object_builder.hpp:62
size_t commit()
Definition: buffer.hpp:331
void add_node_ref(const NodeRef &node_ref)
Definition: osm_object_builder.hpp:168
Definition: osm_object_builder.hpp:366