Libosmium  2.5.4
Fast and flexible C++ library for working with OpenStreetMap data
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 <cassert>
38 #include <cstring>
39 #include <iostream>
40 #include <iterator>
41 #include <list>
42 #include <set>
43 #include <string>
44 #include <map>
45 #include <vector>
46 
48 #include <osmium/memory/buffer.hpp>
49 #include <osmium/osm/area.hpp>
50 #include <osmium/osm/location.hpp>
51 #include <osmium/osm/relation.hpp>
52 #include <osmium/tags/filter.hpp>
53 
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>
58 
59 namespace osmium {
60 
61  namespace area {
62 
63  using osmium::area::detail::ProtoRing;
64 
65  struct AssemblerConfig {
66 
68 
69  // Enables debug output to stderr
70  bool debug;
71 
72  explicit AssemblerConfig(osmium::area::ProblemReporter* pr = nullptr, bool d = false) :
73  problem_reporter(pr),
74  debug(d) {
75  }
76 
81  void enable_debug_output(bool d = true) {
82  debug = d;
83  }
84 
85  }; // struct AssemblerConfig
86 
92  class Assembler {
93 
95 
96  // The way segments
97  osmium::area::detail::SegmentList m_segment_list;
98 
99  // The rings we are building from the way segments
100  std::list<ProtoRing> m_rings;
101 
102  std::vector<ProtoRing*> m_outer_rings;
103  std::vector<ProtoRing*> m_inner_rings;
104 
106 
107  bool debug() const {
108  return m_config.debug;
109  }
110 
117  bool has_same_location(const osmium::NodeRef& nr1, const osmium::NodeRef& nr2) {
118  if (nr1.location() != nr2.location()) {
119  return false;
120  }
121  if (nr1.ref() != nr2.ref()) {
122  if (m_config.problem_reporter) {
123  m_config.problem_reporter->report_duplicate_node(nr1.ref(), nr2.ref(), nr1.location());
124  }
125  }
126  return true;
127  }
128 
129  void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Way& way) const {
130  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
131  for (const osmium::Tag& tag : way.tags()) {
132  tl_builder.add_tag(tag.key(), tag.value());
133  }
134  }
135 
136  void add_common_tags(osmium::builder::TagListBuilder& tl_builder, std::set<const osmium::Way*>& ways) const {
137  std::map<std::string, size_t> counter;
138  for (const osmium::Way* way : ways) {
139  for (const auto& tag : way->tags()) {
140  std::string kv {tag.key()};
141  kv.append(1, '\0');
142  kv.append(tag.value());
143  ++counter[kv];
144  }
145  }
146 
147  size_t num_ways = ways.size();
148  for (const auto& t_c : counter) {
149  if (debug()) {
150  std::cerr << " tag " << t_c.first << " is used " << t_c.second << " times in " << num_ways << " ways\n";
151  }
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);
155  }
156  }
157  }
158 
160 
161  MPFilter() : osmium::tags::KeyFilter(true) {
162  add(false, "type");
163  add(false, "created_by");
164  add(false, "source");
165  add(false, "note");
166  add(false, "test:id");
167  add(false, "test:section");
168  }
169 
170  }; // struct MPFilter
171 
172  static MPFilter& filter() {
173  static MPFilter filter;
174  return filter;
175  }
176 
177  void add_tags_to_area(osmium::builder::AreaBuilder& builder, const osmium::Relation& relation) const {
178  const auto count = std::count_if(relation.tags().begin(), relation.tags().end(), filter());
179 
180  if (debug()) {
181  std::cerr << " found " << count << " tags on relation (without ignored ones)\n";
182  }
183 
184  if (count > 0) {
185  if (debug()) {
186  std::cerr << " use tags from relation\n";
187  }
188 
189  // write out all tags except type=*
190  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
191  for (const osmium::Tag& tag : relation.tags()) {
192  if (strcmp(tag.key(), "type")) {
193  tl_builder.add_tag(tag.key(), tag.value());
194  }
195  }
196  } else {
197  if (debug()) {
198  std::cerr << " use tags from outer ways\n";
199  }
200  std::set<const osmium::Way*> ways;
201  for (const auto& ring : m_outer_rings) {
202  ring->get_ways(ways);
203  }
204  if (ways.size() == 1) {
205  if (debug()) {
206  std::cerr << " only one outer way\n";
207  }
208  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
209  for (const osmium::Tag& tag : (*ways.begin())->tags()) {
210  tl_builder.add_tag(tag.key(), tag.value());
211  }
212  } else {
213  if (debug()) {
214  std::cerr << " multiple outer ways, get common tags\n";
215  }
216  osmium::builder::TagListBuilder tl_builder(builder.buffer(), &builder);
217  add_common_tags(tl_builder, ways);
218  }
219  }
220  }
221 
229  bool open_rings = false;
230 
231  for (const auto& ring : m_rings) {
232  if (!ring.closed()) {
233  open_rings = true;
234  if (m_config.problem_reporter) {
235  m_config.problem_reporter->report_ring_not_closed(ring.get_segment_front().first().location(), ring.get_segment_back().second().location());
236  }
237  }
238  }
239 
240  return open_rings;
241  }
242 
250  bool possibly_combine_rings_back(ProtoRing& ring) {
251  const osmium::NodeRef& nr = ring.get_segment_back().second();
252 
253  if (debug()) {
254  std::cerr << " possibly_combine_rings_back()\n";
255  }
256  for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
257  if (&*it != &ring && !it->closed()) {
258  if (has_same_location(nr, it->get_segment_front().first())) {
259  if (debug()) {
260  std::cerr << " ring.last=it->first\n";
261  }
262  ring.merge_ring(*it, debug());
263  m_rings.erase(it);
264  return true;
265  }
266  if (has_same_location(nr, it->get_segment_back().second())) {
267  if (debug()) {
268  std::cerr << " ring.last=it->last\n";
269  }
270  ring.merge_ring_reverse(*it, debug());
271  m_rings.erase(it);
272  return true;
273  }
274  }
275  }
276  return false;
277  }
278 
286  bool possibly_combine_rings_front(ProtoRing& ring) {
287  const osmium::NodeRef& nr = ring.get_segment_front().first();
288 
289  if (debug()) {
290  std::cerr << " possibly_combine_rings_front()\n";
291  }
292  for (auto it = m_rings.begin(); it != m_rings.end(); ++it) {
293  if (&*it != &ring && !it->closed()) {
294  if (has_same_location(nr, it->get_segment_back().second())) {
295  if (debug()) {
296  std::cerr << " ring.first=it->last\n";
297  }
298  ring.swap_segments(*it);
299  ring.merge_ring(*it, debug());
300  m_rings.erase(it);
301  return true;
302  }
303  if (has_same_location(nr, it->get_segment_front().first())) {
304  if (debug()) {
305  std::cerr << " ring.first=it->first\n";
306  }
307  ring.reverse();
308  ring.merge_ring(*it, debug());
309  m_rings.erase(it);
310  return true;
311  }
312  }
313  }
314  return false;
315  }
316 
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) {
318  if (debug()) {
319  std::cerr << " subring found at: " << *it << "\n";
320  }
321  ProtoRing new_ring(it_begin, it_end);
322  ring.remove_segments(it_begin, it_end);
323  if (debug()) {
324  std::cerr << " split into two rings:\n";
325  std::cerr << " " << new_ring << "\n";
326  std::cerr << " " << ring << "\n";
327  }
328  m_rings.push_back(std::move(new_ring));
329  }
330 
331  bool has_closed_subring_back(ProtoRing& ring, const NodeRef& nr) {
332  if (ring.segments().size() < 3) {
333  return false;
334  }
335  if (debug()) {
336  std::cerr << " has_closed_subring_back()\n";
337  }
338  const auto end = ring.segments().end();
339  for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
340  if (has_same_location(nr, it->first())) {
341  split_off_subring(ring, it, it, end);
342  return true;
343  }
344  }
345  return false;
346  }
347 
348  bool has_closed_subring_front(ProtoRing& ring, const NodeRef& nr) {
349  if (ring.segments().size() < 3) {
350  return false;
351  }
352  if (debug()) {
353  std::cerr << " has_closed_subring_front()\n";
354  }
355  const auto end = ring.segments().end();
356  for (auto it = ring.segments().begin() + 1; it != end - 1; ++it) {
357  if (has_same_location(nr, it->second())) {
358  split_off_subring(ring, it, ring.segments().begin(), it+1);
359  return true;
360  }
361  }
362  return false;
363  }
364 
365  bool check_for_closed_subring(ProtoRing& ring) {
366  if (debug()) {
367  std::cerr << " check_for_closed_subring()\n";
368  }
369 
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) {
374  return has_same_location(s1.first(), s2.first());
375  });
376  if (it == segments.end()) {
377  return false;
378  }
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());
383 
384  if (debug()) {
385  std::cerr << " found subring in ring " << ring << " at " << it->first() << "\n";
386  }
387 
388  const auto m = std::minmax(r1, r2);
389 
390  ProtoRing new_ring(m.first, m.second);
391  ring.remove_segments(m.first, m.second);
392 
393  if (debug()) {
394  std::cerr << " split ring1=" << new_ring << "\n";
395  std::cerr << " split ring2=" << ring << "\n";
396  }
397 
398  m_rings.emplace_back(new_ring);
399 
400  return true;
401  }
402 
403  void combine_rings_front(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
404  if (debug()) {
405  std::cerr << " => match at front of ring\n";
406  }
407  ring.add_segment_front(segment);
408  has_closed_subring_front(ring, segment.first());
409  if (possibly_combine_rings_front(ring)) {
411  }
412  }
413 
414  void combine_rings_back(const osmium::area::detail::NodeRefSegment& segment, ProtoRing& ring) {
415  if (debug()) {
416  std::cerr << " => match at back of ring\n";
417  }
418  ring.add_segment_back(segment);
419  has_closed_subring_back(ring, segment.second());
420  if (possibly_combine_rings_back(ring)) {
422  }
423  }
424 
430  for (const ProtoRing* ring : m_outer_rings) {
431  if (debug()) {
432  std::cerr << " ring " << *ring << " is outer\n";
433  }
434  {
435  osmium::builder::OuterRingBuilder ring_builder(builder.buffer(), &builder);
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());
439  }
440  }
441  for (ProtoRing* inner : ring->inner_rings()) {
442  osmium::builder::InnerRingBuilder ring_builder(builder.buffer(), &builder);
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());
446  }
447  }
448  }
449  }
450 
451  bool add_to_existing_ring(osmium::area::detail::NodeRefSegment segment) {
452  int n = 0;
453  for (auto& ring : m_rings) {
454  if (debug()) {
455  std::cerr << " check against ring " << n << " " << ring;
456  }
457  if (ring.closed()) {
458  if (debug()) {
459  std::cerr << " => ring CLOSED\n";
460  }
461  } else {
462  if (has_same_location(ring.get_segment_back().second(), segment.first())) {
463  combine_rings_back(segment, ring);
464  return true;
465  }
466  if (has_same_location(ring.get_segment_back().second(), segment.second())) {
467  segment.swap_locations();
468  combine_rings_back(segment, ring);
469  return true;
470  }
471  if (has_same_location(ring.get_segment_front().first(), segment.first())) {
472  segment.swap_locations();
473  combine_rings_front(segment, ring);
474  return true;
475  }
476  if (has_same_location(ring.get_segment_front().first(), segment.second())) {
477  combine_rings_front(segment, ring);
478  return true;
479  }
480  if (debug()) {
481  std::cerr << " => no match\n";
482  }
483  }
484 
485  ++n;
486  }
487  return false;
488  }
489 
490  void check_inner_outer(ProtoRing& ring) {
491  const osmium::NodeRef& min_node = ring.min_node();
492  if (debug()) {
493  std::cerr << " check_inner_outer min_node=" << min_node << "\n";
494  }
495 
496  int count = 0;
497  int above = 0;
498 
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)) {
501  if (debug()) {
502  std::cerr << " segments for count: " << *it;
503  }
504  if (it->to_left_of(min_node.location())) {
505  ++count;
506  if (debug()) {
507  std::cerr << " counted\n";
508  }
509  } else {
510  if (debug()) {
511  std::cerr << " not counted\n";
512  }
513  }
514  if (it->first().location() == min_node.location()) {
515  if (it->second().location().y() > min_node.location().y()) {
516  ++above;
517  }
518  }
519  if (it->second().location() == min_node.location()) {
520  if (it->first().location().y() > min_node.location().y()) {
521  ++above;
522  }
523  }
524  }
525  }
526 
527  if (debug()) {
528  std::cerr << " count=" << count << " above=" << above << "\n";
529  }
530 
531  count += above % 2;
532 
533  if (count % 2) {
534  ring.set_inner();
535  }
536  }
537 
539  if (debug()) {
540  std::cerr << " check_inner_outer_roles\n";
541  }
542 
543  for (const auto ringptr : m_outer_rings) {
544  for (const auto& segment : ringptr->segments()) {
545  if (!segment.role_outer()) {
547  if (debug()) {
548  std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'outer'\n";
549  }
550  if (m_config.problem_reporter) {
551  m_config.problem_reporter->report_role_should_be_outer(segment.way()->id(), segment.first().location(), segment.second().location());
552  }
553  }
554  }
555  }
556  for (const auto ringptr : m_inner_rings) {
557  for (const auto& segment : ringptr->segments()) {
558  if (!segment.role_inner()) {
560  if (debug()) {
561  std::cerr << " segment " << segment << " from way " << segment.way()->id() << " should have role 'inner'\n";
562  }
563  if (m_config.problem_reporter) {
564  m_config.problem_reporter->report_role_should_be_inner(segment.way()->id(), segment.first().location(), segment.second().location());
565  }
566  }
567  }
568  }
569  }
570 
574  bool create_rings() {
575  m_segment_list.sort();
576  m_segment_list.erase_duplicate_segments();
577 
578  // Now we look for segments crossing each other. If there are
579  // any, the multipolygon is invalid.
580  // In the future this could be improved by trying to fix those
581  // cases.
582  if (m_segment_list.find_intersections(m_config.problem_reporter)) {
583  return false;
584  }
585 
586  // Now iterator over all segments and add them to rings. Each segment
587  // is tacked on to either end of an existing ring if possible, or a
588  // new ring is started with it.
589  for (const auto& segment : m_segment_list) {
590  if (debug()) {
591  std::cerr << " checking segment " << segment << "\n";
592  }
593  if (!add_to_existing_ring(segment)) {
594  if (debug()) {
595  std::cerr << " new ring for segment " << segment << "\n";
596  }
597  m_rings.emplace_back(segment);
598  }
599  }
600 
601  if (debug()) {
602  std::cerr << " Rings:\n";
603  for (const auto& ring : m_rings) {
604  std::cerr << " " << ring;
605  if (ring.closed()) {
606  std::cerr << " (closed)";
607  }
608  std::cerr << "\n";
609  }
610  }
611 
612  if (check_for_open_rings()) {
613  if (debug()) {
614  std::cerr << " not all rings are closed\n";
615  }
616  return false;
617  }
618 
619  if (debug()) {
620  std::cerr << " Find inner/outer...\n";
621  }
622 
623  if (m_rings.size() == 1) {
624  m_outer_rings.push_back(&m_rings.front());
625  } else {
626  for (auto& ring : m_rings) {
627  check_inner_outer(ring);
628  if (ring.outer()) {
629  if (!ring.is_cw()) {
630  ring.reverse();
631  }
632  m_outer_rings.push_back(&ring);
633  } else {
634  if (ring.is_cw()) {
635  ring.reverse();
636  }
637  m_inner_rings.push_back(&ring);
638  }
639  }
640 
641  if (m_outer_rings.size() == 1) {
642  for (auto inner : m_inner_rings) {
643  m_outer_rings.front()->add_inner_ring(inner);
644  }
645  } else {
646  // sort outer rings by size, smallest first
647  std::sort(m_outer_rings.begin(), m_outer_rings.end(), [](ProtoRing* a, ProtoRing* b) {
648  return a->area() < b->area();
649  });
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);
654  break;
655  }
656  }
657  }
658  }
659  }
660 
662 
663  return true;
664  }
665 
666  public:
667 
669 
670  explicit Assembler(const config_type& config) :
671  m_config(config),
672  m_segment_list(config.debug) {
673  }
674 
675  ~Assembler() = default;
676 
681  void operator()(const osmium::Way& way, osmium::memory::Buffer& out_buffer) {
682  if (m_config.problem_reporter) {
684  }
685 
686  if (!way.ends_have_same_id()) {
687  if (m_config.problem_reporter) {
688  m_config.problem_reporter->report_duplicate_node(way.nodes().front().ref(), way.nodes().back().ref(), way.nodes().front().location());
689  }
690  }
691 
692  m_segment_list.extract_segments_from_way(way, "outer");
693 
694  if (debug()) {
695  std::cerr << "\nBuild way id()=" << way.id() << " segments.size()=" << m_segment_list.size() << "\n";
696  }
697 
698  // Now create the Area object and add the attributes and tags
699  // from the relation.
700  {
701  osmium::builder::AreaBuilder builder(out_buffer);
702  builder.initialize_from_object(way);
703 
704  if (create_rings()) {
705  add_tags_to_area(builder, way);
706  add_rings_to_area(builder);
707  }
708  }
709  out_buffer.commit();
710  }
711 
718  void operator()(const osmium::Relation& relation, const std::vector<size_t>& members, const osmium::memory::Buffer& in_buffer, osmium::memory::Buffer& out_buffer) {
719  if (m_config.problem_reporter) {
721  }
722 
723  m_segment_list.extract_segments_from_ways(relation, members, in_buffer);
724 
725  if (debug()) {
726  std::cerr << "\nBuild relation id()=" << relation.id() << " members.size()=" << members.size() << " segments.size()=" << m_segment_list.size() << "\n";
727  }
728 
729  size_t area_offset = out_buffer.committed();
730 
731  // Now create the Area object and add the attributes and tags
732  // from the relation.
733  {
734  osmium::builder::AreaBuilder builder(out_buffer);
735  builder.initialize_from_object(relation);
736 
737  if (create_rings()) {
738  add_tags_to_area(builder, relation);
739  add_rings_to_area(builder);
740  }
741  }
742  out_buffer.commit();
743 
744  const osmium::TagList& area_tags = out_buffer.get<osmium::Area>(area_offset).tags(); // tags of the area we just built
745 
746  // Find all closed ways that are inner rings and check their
747  // tags. If they are not the same as the tags of the area we
748  // just built, add them to a list and later build areas for
749  // them, too.
750  std::vector<const osmium::Way*> ways_that_should_be_areas;
751  if (m_inner_outer_mismatches == 0) {
752  auto memit = relation.members().begin();
753  for (size_t offset : members) {
754  if (!std::strcmp(memit->role(), "inner")) {
755  const osmium::Way& way = in_buffer.get<const osmium::Way>(offset);
756  if (way.is_closed() && way.tags().size() > 0) {
757  auto d = std::count_if(way.tags().begin(), way.tags().end(), filter());
758  if (d > 0) {
759  osmium::tags::KeyFilter::iterator way_fi_begin(filter(), way.tags().begin(), way.tags().end());
760  osmium::tags::KeyFilter::iterator way_fi_end(filter(), way.tags().end(), way.tags().end());
761  osmium::tags::KeyFilter::iterator area_fi_begin(filter(), area_tags.begin(), area_tags.end());
762  osmium::tags::KeyFilter::iterator area_fi_end(filter(), area_tags.end(), area_tags.end());
763 
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);
766  }
767  }
768  }
769  }
770  ++memit;
771  }
772  }
773 
774  // Now build areas for all ways found in the last step.
775  for (const osmium::Way* way : ways_that_should_be_areas) {
776  Assembler assembler(m_config);
777  assembler(*way, out_buffer);
778  }
779  }
780 
781  }; // class Assembler
782 
783  } // namespace area
784 
785 } // namespace osmium
786 
787 #endif // OSMIUM_AREA_ASSEMBLER_HPP
WayNodeList & nodes()
Definition: way.hpp:75
Definition: tag.hpp:48
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
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: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: area.hpp:113
Definition: assembler.hpp:65
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: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
Definition: way.hpp:65
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
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: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
Filter< std::string > KeyFilter
Definition: filter.hpp:155
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