Exemplo n.º 1
0
                /**
                 * Find intersection between segments.
                 *
                 * @param problem_reporter Any intersections found are reported to this object.
                 * @returns true if there are intersections.
                 */
                bool find_intersections(osmium::area::ProblemReporter* problem_reporter) const {
                    if (m_segments.empty()) {
                        return false;
                    }

                    bool found_intersections = false;

                    for (auto it1 = m_segments.begin(); it1 != m_segments.end()-1; ++it1) {
                        const NodeRefSegment& s1 = *it1;
                        for (auto it2 = it1+1; it2 != m_segments.end(); ++it2) {
                            const NodeRefSegment& s2 = *it2;

                            assert(s1 != s2); // erase_duplicate_segments() should have made sure of that

                            if (outside_x_range(s2, s1)) {
                                break;
                            }

                            if (y_range_overlap(s1, s2)) {
                                osmium::Location intersection = calculate_intersection(s1, s2);
                                if (intersection) {
                                    found_intersections = true;
                                    if (m_debug) {
                                        std::cerr << "  segments " << s1 << " and " << s2 << " intersecting at " << intersection << "\n";
                                    }
                                    if (problem_reporter) {
                                        problem_reporter->report_intersection(s1.way()->id(), s1.first().location(), s1.second().location(), s2.way()->id(), s2.first().location(), s2.second().location(), intersection);
                                    }
                                }
                            }
                        }
                    }

                    return found_intersections;
                }
Exemplo n.º 2
0
                /**
                 * Find duplicate segments (ie same start and end point) in the
                 * list and remove them. This will always remove pairs of the
                 * same segment. So if there are three, for instance, two will
                 * be removed and one will be left.
                 */
                uint32_t erase_duplicate_segments(osmium::area::ProblemReporter* problem_reporter) {
                    uint32_t duplicate_segments = 0;

                    while (true) {
                        auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
                        if (it == m_segments.end()) {
                            break;
                        }
                        if (m_debug) {
                            std::cerr << "  erase duplicate segment: " << *it << "\n";
                        }

                        // Only count and report duplicate segments if they
                        // belong to the same way or if they don't both have
                        // the role "inner". Those cases are definitely wrong.
                        // If the duplicate segments belong to different
                        // "inner" ways, they could be touching inner rings
                        // which are perfectly okay. Note that for this check
                        // the role has to be correct in the member data.
                        if (it->way() == std::next(it)->way() || !it->role_inner() || !std::next(it)->role_inner()) {
                            ++duplicate_segments;
                            if (problem_reporter) {
                                problem_reporter->report_duplicate_segment(it->first(), it->second());
                            }
                        }
                        m_segments.erase(it, it+2);
                    }

                    return duplicate_segments;
                }
Exemplo n.º 3
0
 /**
  * Find duplicate segments (ie same start and end point) in the
  * list and remove them. This will always remove pairs of the same
  * segment. So if there are three, for instance, two will be
  * removed and one will be left.
  */
 void erase_duplicate_segments() {
     while (true) {
         auto it = std::adjacent_find(m_segments.begin(), m_segments.end());
         if (it == m_segments.end()) {
             return;
         }
         if (m_debug) {
             std::cerr << "  erase duplicate segment: " << *it << "\n";
         }
         m_segments.erase(it, it+2);
     }
 }
Exemplo n.º 4
0
                uint32_t extract_segments_from_way_impl(osmium::area::ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Way& way, role_type role) {
                    uint32_t invalid_locations = 0;

                    osmium::NodeRef previous_nr;
                    for (const osmium::NodeRef& nr : way.nodes()) {
                        if (!nr.location().valid()) {
                            ++invalid_locations;
                            if (problem_reporter) {
                                problem_reporter->report_invalid_location(way.id(), nr.ref());
                            }
                            continue;
                        }
                        if (previous_nr.location()) {
                            if (previous_nr.location() != nr.location()) {
                                m_segments.emplace_back(previous_nr, nr, role, &way);
                            } else {
                                ++duplicate_nodes;
                                if (problem_reporter) {
                                    problem_reporter->report_duplicate_node(previous_nr.ref(), nr.ref(), nr.location());
                                }
                            }
                        }
                        previous_nr = nr;
                    }

                    return invalid_locations;
                }
Exemplo n.º 5
0
 /**
  * Extract segments from given way and add them to the list.
  *
  * Segments connecting two nodes with the same location (ie
  * same node or different nodes with same location) are
  * removed after reporting the duplicate node.
  */
 uint32_t extract_segments_from_way(osmium::area::ProblemReporter* problem_reporter, const osmium::Way& way) {
     if (way.nodes().empty()) {
         return 0;
     }
     m_segments.reserve(way.nodes().size() - 1);
     return extract_segments_from_way_impl(problem_reporter, way, role_type::outer);
 }
Exemplo n.º 6
0
 /**
  * Extract segments from given way and add them to the list.
  *
  * Segments connecting two nodes with the same location (ie same
  * node or different node with same location) are removed.
  *
  * XXX should two nodes with same location be reported?
  */
 void extract_segments_from_way(const osmium::Way& way, const char* role) {
     osmium::NodeRef last_nr;
     for (const osmium::NodeRef& nr : way.nodes()) {
         if (last_nr.location() && last_nr.location() != nr.location()) {
             m_segments.emplace_back(last_nr, nr, role, &way);
         }
         last_nr = nr;
     }
 }
Exemplo n.º 7
0
                /**
                 * Extract all segments from all ways that make up this
                 * multipolygon relation and add them to the list.
                 */
                uint32_t extract_segments_from_ways(osmium::area::ProblemReporter* problem_reporter, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
                    assert(relation.members().size() >= members.size());

                    const size_t num_segments = get_num_segments(members);
                    if (problem_reporter) {
                        problem_reporter->set_nodes(num_segments);
                    }
                    m_segments.reserve(num_segments);

                    uint32_t duplicate_nodes = 0;
                    for_each_member(relation, members, [this, &problem_reporter, &duplicate_nodes](const osmium::RelationMember& member, const osmium::Way& way) {
                        duplicate_nodes += extract_segments_from_way_impl(problem_reporter, way, parse_role(member.role()));
                    });

                    return duplicate_nodes;
                }
Exemplo n.º 8
0
                /**
                 * Extract all segments from all ways that make up this
                 * multipolygon relation and add them to the list.
                 */
                uint32_t extract_segments_from_ways(osmium::area::ProblemReporter* problem_reporter, uint64_t& duplicate_nodes, const osmium::Relation& relation, const std::vector<const osmium::Way*>& members) {
                    assert(relation.members().size() >= members.size());

                    const size_t num_segments = get_num_segments(members);
                    if (problem_reporter) {
                        problem_reporter->set_nodes(num_segments);
                    }
                    m_segments.reserve(num_segments);

                    uint32_t invalid_locations = 0;
                    for_each_member(relation, members, [&](const osmium::RelationMember& member, const osmium::Way& way) {
                        const auto role = parse_role(member.role());
                        invalid_locations += extract_segments_from_way_impl(problem_reporter, duplicate_nodes, way, role);
                    });

                    return invalid_locations;
                }
Exemplo n.º 9
0
 /// Sort the list of segments.
 void sort() {
     std::sort(m_segments.begin(), m_segments.end());
 }
Exemplo n.º 10
0
 const_iterator end() const noexcept {
     return m_segments.end();
 }
Exemplo n.º 11
0
 const_iterator begin() const noexcept {
     return m_segments.begin();
 }
Exemplo n.º 12
0
 iterator end() noexcept {
     return m_segments.end();
 }
Exemplo n.º 13
0
 iterator begin() noexcept {
     return m_segments.begin();
 }
Exemplo n.º 14
0
 NodeRefSegment& back() {
     return m_segments.back();
 }
Exemplo n.º 15
0
 /// Is the segment list empty?
 bool empty() const noexcept {
     return m_segments.empty();
 }
Exemplo n.º 16
0
 /// The number of segments in the list.
 size_t size() const noexcept {
     return m_segments.size();
 }
Exemplo n.º 17
0
 /// The number of segments in the list.
 size_t size() const {
     return m_segments.size();
 }
Exemplo n.º 18
0
 bool empty() const {
     return m_segments.empty();
 }
Exemplo n.º 19
0
 NodeRefSegment& operator[](size_t n) noexcept {
     assert(n < m_segments.size());
     return m_segments[n];
 }
Exemplo n.º 20
0
 NodeRefSegment& front() {
     return m_segments.front();
 }
Exemplo n.º 21
0
 /// Clear the list of segments. All segments are removed.
 void clear() {
     m_segments.clear();
 }