Libosmium  2.4.1
Fast and flexible C++ library for working with OpenStreetMap data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
assembler.hpp
Go to the documentation of this file.
1 #ifndef OSMIUM_AREA_ASSEMBLER_HPP
2 #define OSMIUM_AREA_ASSEMBLER_HPP
3 
4 /*
5 
6 This file is part of Osmium (http://osmcode.org/libosmium).
7 
8 Copyright 2013-2015 Jochen Topf <jochen@topf.org> and others (see README).
9 
10 Boost Software License - Version 1.0 - August 17th, 2003
11 
12 Permission is hereby granted, free of charge, to any person or organization
13 obtaining a copy of the software and accompanying documentation covered by
14 this license (the "Software") to use, reproduce, display, distribute,
15 execute, and transmit the Software, and to prepare derivative works of the
16 Software, and to permit third-parties to whom the Software is furnished to
17 do so, all subject to the following:
18 
19 The copyright notices in the Software and this entire statement, including
20 the above license grant, this restriction and the following disclaimer,
21 must be included in all copies of the Software, in whole or in part, and
22 all derivative works of the Software, unless such copies or derivative
23 works are solely in the form of machine-executable object code generated by
24 a source language processor.
25 
26 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
27 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
28 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
29 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
30 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
31 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
32 DEALINGS IN THE SOFTWARE.
33 
34 */
35 
36 #include <algorithm>
37 #include <iostream>
38 #include <iterator>
39 #include <list>
40 #include <map>
41 #include <vector>
42 
44 #include <osmium/memory/buffer.hpp>
45 #include <osmium/osm/area.hpp>
46 #include <osmium/osm/location.hpp>
47 #include <osmium/osm/relation.hpp>
48 #include <osmium/tags/filter.hpp>
49 
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>
54 
55 namespace osmium {
56 
57  namespace area {
58 
59  using osmium::area::detail::ProtoRing;
60 
61  struct AssemblerConfig {
62 
64 
65  // Enables debug output to stderr
66  bool debug;
67 
68  explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d = false) :
69  problem_reporter(pr),
70  debug(d) {
71  }
72 
77  void enable_debug_output(bool d = true) {
78  debug = d;
79  }
80 
81  }; // struct AssemblerConfig
82 
88  class Assembler {
89 
91 
92  // The way segments
93  osmium::area::detail::SegmentList m_segment_list;
94 
95  // The rings we are building from the way segments
96  std::list<ProtoRing> m_rings;
97 
98  std::vector<ProtoRing*> m_outer_rings;
99  std::vector<ProtoRing*> m_inner_rings;
100 
102 
103  bool debug() const {
104  return m_config.debug;
105  }
106 
113  bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
114  if (nr1.location() != nr2.location()) {
115  return false;
116  }
117  if (nr1.ref() != nr2.ref()) {
118  if (m_config.problem_reporter) {
119  m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location());
120  }
121  }
122  return true;
123  }
124 
125  void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
126  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
127  for (const osmium::Tag& tag : way.tags()) {
128  tl_builder.add_tag(tag.key(), tag.value());
129  }
130  }
131 
132  void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
133  std::map<std::string, size_t> counter;
134  for (const osmium::Way* way : ways) {
135  for (const auto& tag : way->tags()) {
136  std::string kv {tag.key()};
137  kv.append(1, '\0');
138  kv.append(tag.value());
139  ++counter[kv];
140  }
141  }
142 
143  size_t num_ways = ways.size();
144  for (const auto& t_c : counter) {
145  if (debug()) {
146  std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n";
147  }
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);
151  }
152  }
153  }
154 
156 
157  MPFilter() : osmium::tags::KeyFilter(true) {
158  add(false, "type");
159  add(false, "created_by");
160  add(false, "source");
161  add(false, "note");
162  add(false, "test:id");
163  add(false, "test:section");
164  }
165 
166  }; // struct MPFilter
167 
168  static MPFilter& filter() {
169  static MPFilter filter;
170  return filter;
171  }
172 
173  void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const {
174  const auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
175 
176  if (debug()) {
177  std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
178  }
179 
180  if (count > 0) {
181  if (debug()) {
182  std::cerr << " use tags from relation\n";
183  }
184 
185  // write out all tags except type=*
186  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
187  for (const osmium::Tag& tag : relation.tags()) {
188  if (strcmp(tag.key(), "type")) {
189  tl_builder.add_tag(tag.key(), tag.value());
190  }
191  }
192  } else {
193  if (debug()) {
194  std::cerr << " use tags from outer ways\n";
195  }
196  std::set<const osmium::Way*> ways;
197  for (const auto& ring : m_outer_rings) {
198  ring->get_ways(ways);
199  }
200  if (ways.size() == 1) {
201  if (debug()) {
202  std::cerr << " only one outer way\n";
203  }
204  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
205  for (const osmium::Tag& tag : (*ways.begin())->tags()) {
206  tl_builder.add_tag(tag.key(), tag.value());
207  }
208  } else {
209  if (debug()) {
210  std::cerr << " multiple outer ways, get common tags\n";
211  }
212  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
213  add_common_tags(tl_builder, ways);
214  }
215  }
216  }
217 
225  bool open_rings = false;
226 
227  for (const auto& ring : m_rings) {
228  if (!ring.closed()) {
229  open_rings = true;
230  if (m_config.problem_reporter) {
231  m_config.problem_reporter->report_ring_not_closed(ring.get_segment_front().first().location(), ring.get_segment_back().second().location());
232  }
233  }
234  }
235 
236  return open_rings;
237  }
238 
246  bool possibly_combine_rings_back(ProtoRing& ring) {
247  const osmium::NodeRef& nr = ring.get_segment_back().second();
248 
249  if (debug()) {
250  std::cerr << " possibly_combine_rings_back()\n";
251  }
252  for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
253  if (&*it != &ring && !it->closed()) {
254  if (has_same_location(nr, it->get_segment_front().first())) {
255  if (debug()) {
256  std::cerr << " ring.last=it->first\n";
257  }
258  ring.merge_ring(*it, debug());
259  m_rings.erase(it);
260  return true;
261  }
262  if (has_same_location(nr, it->get_segment_back().second())) {
263  if (debug()) {
264  std::cerr << " ring.last=it->last\n";
265  }
266  ring.merge_ring_reverse(*it, debug());
267  m_rings.erase(it);
268  return true;
269  }
270  }
271  }
272  return false;
273  }
274 
282  bool possibly_combine_rings_front(ProtoRing& ring) {
283  const osmium::NodeRef& nr = ring.get_segment_front().first();
284 
285  if (debug()) {
286  std::cerr << " possibly_combine_rings_front()\n";
287  }
288  for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
289  if (&*it != &ring && !it->closed()) {
290  if (has_same_location(nr, it->get_segment_back().second())) {
291  if (debug()) {
292  std::cerr << " ring.first=it->last\n";
293  }
294  ring.swap_segments(*it);
295  ring.merge_ring(*it, debug());
296  m_rings.erase(it);
297  return true;
298  }
299  if (has_same_location(nr, it->get_segment_front().first())) {
300  if (debug()) {
301  std::cerr << " ring.first=it->first\n";
302  }
303  ring.reverse();
304  ring.merge_ring(*it, debug());
305  m_rings.erase(it);
306  return true;
307  }
308  }
309  }
310  return false;
311  }
312 
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) {
314  if (debug()) {
315  std::cerr << " subring found at: " << *it << "\n";
316  }
317  ProtoRing new_ring(it_begin, it_end);
318  ring.remove_segments(it_begin, it_end);
319  if (debug()) {
320  std::cerr << " split into two rings:\n";
321  std::cerr << " " << new_ring << "\n";
322  std::cerr << " " << ring << "\n";
323  }
324  m_rings.push_back(std::move(new_ring));
325  }
326 
327  bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) {
328  if (ring.segments().size() < 3) {
329  return false;
330  }
331  if (debug()) {
332  std::cerr << " has_closed_subring_back()\n";
333  }
334  const auto end = ring.segments().end();
335  for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
336  if (has_same_location(nr, it->first())) {
337  split_off_subring(ring, it, it, end);
338  return true;
339  }
340  }
341  return false;
342  }
343 
344  bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) {
345  if (ring.segments().size() < 3) {
346  return false;
347  }
348  if (debug()) {
349  std::cerr << " has_closed_subring_front()\n";
350  }
351  const auto end = ring.segments().end();
352  for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
353  if (has_same_location(nr, it->second())) {
354  split_off_subring(ring, it, ring.segments().begin(), it+1);
355  return true;
356  }
357  }
358  return false;
359  }
360 
361  bool check_for_closed_subring(ProtoRing& ring) {
362  if (debug()) {
363  std::cerr << " check_for_closed_subring()\n";
364  }
365 
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  const auto it = std::adjacent_find(segments.begin(), segments.end(), [this](const osmium::area::detail::NodeRefSegment& s1, const osmium::area::detail::NodeRefSegment& s2) {
370  return has_same_location(s1.first(), s2.first());
371  });
372  if (it == segments.end()) {
373  return false;
374  }
375  const auto r1 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it, it+1);
376  assert(r1 != ring.segments().end());
377  const auto r2 = std::find_first_of(ring.segments().begin(), ring.segments().end(), it+1, it+2);
378  assert(r2 != ring.segments().end());
379 
380  if (debug()) {
381  std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n";
382  }
383 
384  const auto m = std::minmax(r1, r2);
385 
386  ProtoRing new_ring(m.first, m.second);
387  ring.remove_segments(m.first, m.second);
388 
389  if (debug()) {
390  std::cerr << " split ring1=" << new_ring << "\n";
391  std::cerr << " split ring2=" << ring << "\n";
392  }
393 
394  m_rings.emplace_back(new_ring);
395 
396  return true;
397  }
398 
399  void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
400  if (debug()) {
401  std::cerr << " => match at front of ring\n";
402  }
403  ring.add_segment_front(segment);
404  has_closed_subring_front(ring, segment.first());
405  if (possibly_combine_rings_front(ring)) {
407  }
408  }
409 
410  void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
411  if (debug()) {
412  std::cerr << " => match at back of ring\n";
413  }
414  ring.add_segment_back(segment);
415  has_closed_subring_back(ring, segment.second());
416  if (possibly_combine_rings_back(ring)) {
418  }
419  }
420 
426  for (const ProtoRing* ring : m_outer_rings) {
427  if (debug()) {
428  std::cerr << " ring " << *ring << " is outer\n";
429  }
430  {
431  osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder);
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());
435  }
436  }
437  for (ProtoRing* inner : ring->inner_rings()) {
438  osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder);
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());
442  }
443  }
444  }
445  }
446 
447  bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) {
448  int n = 0;
449  for (auto& ring : m_rings) {
450  if (debug()) {
451  std::cerr << " check against ring " << n << " " << ring;
452  }
453  if (ring.closed()) {
454  if (debug()) {
455  std::cerr << " => ring CLOSED\n";
456  }
457  } else {
458  if (has_same_location(ring.get_segment_back().second(), segment.first())) {
459  combine_rings_back(segment, ring);
460  return true;
461  }
462  if (has_same_location(ring.get_segment_back().second(), segment.second())) {
463  segment.swap_locations();
464  combine_rings_back(segment, ring);
465  return true;
466  }
467  if (has_same_location(ring.get_segment_front().first(), segment.first())) {
468  segment.swap_locations();
469  combine_rings_front(segment, ring);
470  return true;
471  }
472  if (has_same_location(ring.get_segment_front().first(), segment.second())) {
473  combine_rings_front(segment, ring);
474  return true;
475  }
476  if (debug()) {
477  std::cerr << " => no match\n";
478  }
479  }
480 
481  ++n;
482  }
483  return false;
484  }
485 
486  void check_inner_outer(ProtoRing& ring) {
487  const osmium::NodeRef& min_node = ring.min_node();
488  if (debug()) {
489  std::cerr << " check_inner_outer min_node=" << min_node << "\n";
490  }
491 
492  int count = 0;
493  int above = 0;
494 
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)) {
497  if (debug()) {
498  std::cerr << " segments for count: " << *it;
499  }
500  if (it->to_left_of(min_node.location())) {
501  ++count;
502  if (debug()) {
503  std::cerr << " counted\n";
504  }
505  } else {
506  if (debug()) {
507  std::cerr << " not counted\n";
508  }
509  }
510  if (it->first().location() == min_node.location()) {
511  if (it->second().location().y() > min_node.location().y()) {
512  ++above;
513  }
514  }
515  if (it->second().location() == min_node.location()) {
516  if (it->first().location().y() > min_node.location().y()) {
517  ++above;
518  }
519  }
520  }
521  }
522 
523  if (debug()) {
524  std::cerr << " count=" << count << " above=" << above << "\n";
525  }
526 
527  count += above % 2;
528 
529  if (count % 2) {
530  ring.set_inner();
531  }
532  }
533 
535  if (debug()) {
536  std::cerr << " check_inner_outer_roles\n";
537  }
538 
539  for (const auto ringptr : m_outer_rings) {
540  for (const auto& segment : ringptr->segments()) {
541  if (!segment.role_outer()) {
543  if (debug()) {
544  std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n";
545  }
546  if (m_config.problem_reporter) {
547  m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location());
548  }
549  }
550  }
551  }
552  for (const auto ringptr : m_inner_rings) {
553  for (const auto& segment : ringptr->segments()) {
554  if (!segment.role_inner()) {
556  if (debug()) {
557  std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n";
558  }
559  if (m_config.problem_reporter) {
560  m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location());
561  }
562  }
563  }
564  }
565  }
566 
570  bool create_rings() {
571  m_segment_list.sort();
572  m_segment_list.erase_duplicate_segments();
573 
574  // Now we look for segments crossing each other. If there are
575  // any, the multipolygon is invalid.
576  // In the future this could be improved by trying to fix those
577  // cases.
578  if (m_segment_list.find_intersections(m_config.problem_reporter)) {
579  return false;
580  }
581 
582  // Now iterator over all segments and add them to rings. Each segment
583  // is tacked on to either end of an existing ring if possible, or a
584  // new ring is started with it.
585  for (const auto& segment : m_segment_list) {
586  if (debug()) {
587  std::cerr << " checking segment " << segment << "\n";
588  }
589  if (!add_to_existing_ring(segment)) {
590  if (debug()) {
591  std::cerr << " new ring for segment " << segment << "\n";
592  }
593  m_rings.emplace_back(segment);
594  }
595  }
596 
597  if (debug()) {
598  std::cerr << " Rings:\n";
599  for (const auto& ring : m_rings) {
600  std::cerr << " " << ring;
601  if (ring.closed()) {
602  std::cerr << " (closed)";
603  }
604  std::cerr << "\n";
605  }
606  }
607 
608  if (check_for_open_rings()) {
609  if (debug()) {
610  std::cerr << " not all rings are closed\n";
611  }
612  return false;
613  }
614 
615  if (debug()) {
616  std::cerr << " Find inner/outer...\n";
617  }
618 
619  if (m_rings.size() == 1) {
620  m_outer_rings.push_back(&m_rings.front());
621  } else {
622  for (auto& ring : m_rings) {
623  check_inner_outer(ring);
624  if (ring.outer()) {
625  if (!ring.is_cw()) {
626  ring.reverse();
627  }
628  m_outer_rings.push_back(&ring);
629  } else {
630  if (ring.is_cw()) {
631  ring.reverse();
632  }
633  m_inner_rings.push_back(&ring);
634  }
635  }
636 
637  if (m_outer_rings.size() == 1) {
638  for (auto inner : m_inner_rings) {
639  m_outer_rings.front()->add_inner_ring(inner);
640  }
641  } else {
642  // sort outer rings by size, smallest first
643  std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
644  return a->area() < b->area();
645  });
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);
650  break;
651  }
652  }
653  }
654  }
655  }
656 
658 
659  return true;
660  }
661 
662  public:
663 
665 
666  explicit Assembler(const config_type& config) :
667  m_config(config),
668  m_segment_list(config.debug) {
669  }
670 
671  ~Assembler() = default;
672 
677  void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
678  if (m_config.problem_reporter) {
680  }
681 
682  if (!way.ends_have_same_id()) {
683  if (m_config.problem_reporter) {
684  m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
685  }
686  }
687 
688  m_segment_list.extract_segments_from_way(way, "outer");
689 
690  if (debug()) {
691  std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n";
692  }
693 
694  // Now create the Area object and add the attributes and tags
695  // from the relation.
696  {
697  osmium::builder::AreaBuilder builder(out_buffer);
698  builder.initialize_from_object(way);
699 
700  if (create_rings()) {
701  add_tags_to_area(builder, way);
702  add_rings_to_area(builder);
703  }
704  }
705  out_buffer.commit();
706  }
707 
714  void operator()(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) {
715  if (m_config.problem_reporter) {
717  }
718 
719  m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
720 
721  if (debug()) {
722  std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n";
723  }
724 
725  size_t area_offset = out_buffer.committed();
726 
727  // Now create the Area object and add the attributes and tags
728  // from the relation.
729  {
730  osmium::builder::AreaBuilder builder(out_buffer);
731  builder.initialize_from_object(relation);
732 
733  if (create_rings()) {
734  add_tags_to_area(builder, relation);
735  add_rings_to_area(builder);
736  }
737  }
738  out_buffer.commit();
739 
740  const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
741 
742  // Find all closed ways that are inner rings and check their
743  // tags. If they are not the same as the tags of the area we
744  // just built, add them to a list and later build areas for
745  // them, too.
746  std::vector<const osmium::Way*> ways_that_should_be_areas;
747  if (m_inner_outer_mismatches == 0) {
748  auto memit = relation.members().begin();
749  for (size_t offset : members) {
750  if (!std::strcmp(memit->role(), "inner")) {
751  const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
752  if (way.is_closed() && way.tags().size() > 0) {
753  auto d = std::count_if(way.tags().begin(), way.tags().end(), filter());
754  if (d > 0) {
755  osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end());
756  osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end());
757  osmium::tags::KeyFilter::iterator area_fi_begin(filter(), area_tags.begin(), area_tags.end());
758  osmium::tags::KeyFilter::iterator area_fi_end(filter(), area_tags.end(), area_tags.end());
759 
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);
762  }
763  }
764  }
765  }
766  ++memit;
767  }
768  }
769 
770  // Now build areas for all ways found in the last step.
771  for (const osmium::Way* way : ways_that_should_be_areas) {
772  Assembler assembler(m_config);
773  assembler(*way, out_buffer);
774  }
775  }
776 
777  }; // class Assembler
778 
779  } // namespace area
780 
781 } // namespace osmium
782 
783 #endif // OSMIUM_AREA_ASSEMBLER_HPP
WayNodeList & nodes()
Definition: way.hpp:75
Definition: tag.hpp:48
std::vector< ProtoRing * > m_outer_rings
Definition: assembler.hpp:98
osmium::area::ProblemReporter * problem_reporter
Definition: assembler.hpp:63
iterator end()
Definition: collection.hpp:127
Definition: filter.hpp:77
osmium::memory::Buffer & buffer() noexcept
Return the buffer this builder is using.
Definition: builder.hpp:179
Definition: tag.hpp:105
RelationMemberList & members()
Definition: relation.hpp:179
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:290
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:167
void check_inner_outer(ProtoRing &ring)
Definition: assembler.hpp:486
Definition: area.hpp:113
Definition: assembler.hpp:61
Filter & add(bool result, const key_type &key, const value_type &value)
Definition: filter.hpp:119
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:123
double distance(const osmium::geom::Coordinates &c1, const osmium::geom::Coordinates &c2)
Definition: haversine.hpp:64
bool debug
Definition: assembler.hpp:66
Definition: way.hpp:65
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:127
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
boost::filter_iterator< filter_type, osmium::TagList::const_iterator > iterator
Definition: filter.hpp:112
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: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:110
size_t committed() const noexcept
Definition: buffer.hpp:217
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:94
T & get(const size_t offset) const
Definition: buffer.hpp:306
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
Filter< std::string > KeyFilter
Definition: filter.hpp:155
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:272
void add_node_ref(const NodeRef &node_ref)
Definition: osm_object_builder.hpp:139
Definition: osm_object_builder.hpp:279