From 83d22ace8093ece203d37bedd6fc1dffa2707e63 Mon Sep 17 00:00:00 2001 From: denizdiktas Date: Mon, 10 Jul 2023 20:12:51 +0300 Subject: [PATCH] node-collapsing (very basic) --- Arrangement_on_surface_2/demo/earth/Aos.cpp | 34 ++++--- .../demo/earth/Kml_reader.cpp | 92 +++++++++++++++++++ .../demo/earth/Kml_reader.h | 5 + .../demo/earth/Main_widget.cpp | 5 +- 4 files changed, 119 insertions(+), 17 deletions(-) diff --git a/Arrangement_on_surface_2/demo/earth/Aos.cpp b/Arrangement_on_surface_2/demo/earth/Aos.cpp index 220eb0f35b5..08d879858bc 100644 --- a/Arrangement_on_surface_2/demo/earth/Aos.cpp +++ b/Arrangement_on_surface_2/demo/earth/Aos.cpp @@ -396,7 +396,8 @@ std::vector Aos::ext_check_id_based(Kml::Placemarks& placemarks) Ext_aos arr(&traits), arr2(&traits2); // - auto nodes = Kml::generate_ids(placemarks); + //auto nodes = Kml::generate_ids(placemarks); + auto nodes = Kml::generate_ids_approx(placemarks, 0.001); //Segment s() auto ctr_p = traits.construct_point_2_object(); @@ -419,6 +420,12 @@ std::vector Aos::ext_check_id_based(Kml::Placemarks& placemarks) } std::cout << "num nodes = " << nodes.size() << std::endl; std::cout << "num points = " << points.size() << std::endl; + // MARK all vertices as true + for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) + { + vit->set_data(Flag(true)); + } + for (auto& placemark : placemarks) { @@ -455,31 +462,25 @@ std::vector Aos::ext_check_id_based(Kml::Placemarks& placemarks) num_counted_arcs++; const auto nid1 = ids[i]; const auto nid2 = ids[i + 1]; - assert(nodes[nid1] == polygon.outer_boundary.nodes[i]); - assert(nodes[nid2] == polygon.outer_boundary.nodes[i+1]); + //assert(nodes[nid1] == polygon.outer_boundary.nodes[i]); + //assert(nodes[nid2] == polygon.outer_boundary.nodes[i+1]); auto p1 = points[nid1]; auto p2 = points[nid2]; //std::cout << p1 << std::endl; //std::cout << p2 << std::endl; //Segment s(p1, p2); - auto v1 = vertices[nid1]; - auto v2 = vertices[nid2]; - Segment s(v1->point(), v2->point()); + //auto v1 = vertices[nid1]; + //auto v2 = vertices[nid2]; + //Segment s(v1->point(), v2->point()); //arr.insert_from_left_vertex() - arr.insert_at_vertices(s, v1, v2); + //arr.insert_at_vertices(s, v1, v2); //arr.insert_at_vertices(Segment(p1, p2), v1, v2); - //CGAL::insert(arr, ctr_cv(p1,p2)); + CGAL::insert(arr, ctr_cv(p1,p2)); } } } - // MARK all vertices as true - for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) - { - vit->set_data(Flag(true)); - } - std::cout << "-------------------------------\n"; std::cout << "num arr vertices (before adding arcs) = " << arr.number_of_vertices() << std::endl; @@ -494,6 +495,9 @@ std::vector Aos::ext_check_id_based(Kml::Placemarks& placemarks) auto& d = vit->data(); if (vit->data().v == false) { + std::cout << "-------------------------------------\n"; + std::cout << vit->point() << std::endl; + if (2 == vit->degree()) ;//continue; @@ -522,7 +526,7 @@ std::vector Aos::ext_check_id_based(Kml::Placemarks& placemarks) //do { //} while (++curr != first); - + std::cout << std::endl; } } std::cout << "*** num created vertices = " << num_created_vertices << std::endl; diff --git a/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp b/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp index 89165c26ff9..61ed47aed80 100644 --- a/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp +++ b/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp @@ -10,6 +10,13 @@ #include +double Kml::Node::distance_to(const Node& r) const +{ + const auto dx = lon - r.lon; + const auto dy = lat - r.lat; + return sqrt(dx * dx + dy * dy); +} + bool Kml::Node::operator == (const Node& r) const { return (lon == r.lon) && (lat == r.lat); @@ -266,6 +273,91 @@ Kml::Nodes Kml::generate_ids(Placemarks& placemarks) return nodes; } +Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps) +{ + // collect all nodes into a single vector + int polygon_count = 0; + std::vector nodes; + for (auto& pm : placemarks) + { + for (auto& polygon : pm.polygons) + { + polygon_count++; + + std::vector linear_rings; + linear_rings.push_back(&polygon.outer_boundary); + for (auto& inner_boundary : polygon.inner_boundaries) + linear_rings.push_back(&inner_boundary); + + for (auto* lring : linear_rings) + { + lring->ids.clear(); + + for (const auto& node : lring->nodes) + { + // check if there is a node sufficiently close to the current one + int node_index = -1; + for (int i = 0; i < nodes.size(); ++i) + { + const auto dist = node.distance_to(nodes[i]); + if (dist < eps) + { + node_index = i; + break; + } + } + + + if (node_index < 0) + { + // insert new node + nodes.push_back(node); + const int node_id = nodes.size() - 1; + lring->ids.push_back(node_id); + } + else + { + // get the existing node + const int node_id = node_index; + lring->ids.push_back(node_id); + } + + auto it = std::unique(lring->ids.begin(), lring->ids.end()); + std::vector new_ids(lring->ids.begin(), it); + if (new_ids.size() < lring->ids.size()) + std::cout << "** REDUCED!\n"; + lring->ids = std::move(new_ids); + } + } + } + } + + // find the pair of closest nodes + double min_dist = std::numeric_limits::max(); + int ni1, ni2; + int num_nodes = nodes.size(); + for (int i = 0; i < num_nodes - 1; ++i) + { + for (int j = i + 1; j < num_nodes; ++j) + { + const auto dist = nodes[i].distance_to(nodes[j]); + if (min_dist > dist) + { + min_dist = dist; + ni1 = i; + ni2 = j; + } + } + } + std::cout << "min dist = " << min_dist << std::endl; + std::cout << "node 1 = " << nodes[ni1] << std::endl; + std::cout << "node 2 = " << nodes[ni2] << std::endl; + std::cout << "node 1 = " << nodes[ni1].get_coords_3d() << std::endl; + std::cout << "node 2 = " << nodes[ni2].get_coords_3d() << std::endl; + + return nodes; +} + Kml::Nodes Kml::Polygon::get_all_nodes() const { diff --git a/Arrangement_on_surface_2/demo/earth/Kml_reader.h b/Arrangement_on_surface_2/demo/earth/Kml_reader.h index d47c020152b..2a14fede675 100644 --- a/Arrangement_on_surface_2/demo/earth/Kml_reader.h +++ b/Arrangement_on_surface_2/demo/earth/Kml_reader.h @@ -31,6 +31,8 @@ public: Node() : lon(-1111), lat(-1111) {}; Node(double longitude, double latitude) : lon(longitude), lat(latitude) {}; + double distance_to(const Node& r) const; + bool operator == (const Node& r) const; Vec3d get_coords_3d(const double r = 1.0) const; QVector3D get_coords_3f(const double r=1.0) const; @@ -89,6 +91,9 @@ public: // Outputs all used nodes without duplications! // NOTE: this function modifies Placemarks data-structure! static Nodes generate_ids(Placemarks& placemarks); + + // same as above but by collapsing close-by nodes based on distance bound + static Nodes generate_ids_approx(Placemarks& placemarks, const double eps); }; diff --git a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp index 11193e7b9b1..7e891757e3d 100644 --- a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp +++ b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp @@ -213,6 +213,7 @@ void Main_widget::initializeGL() m_countries = Kml::read(file_name); auto dup_nodes = Kml::get_duplicates(m_countries); + qDebug() << "identifying duplicate nodes"; //auto all_nodes = Kml::generate_ids(m_countries); // initialize rendering of DUPLICATE VERTICES @@ -227,8 +228,8 @@ void Main_widget::initializeGL() else { // check the arrangement constructed from the GIS data-set - auto created_vertices = Aos::ext_check(m_countries); - //auto created_vertices = Aos::ext_check_id_based(m_countries); + //auto created_vertices = Aos::ext_check(m_countries); + auto created_vertices = Aos::ext_check_id_based(m_countries); m_vertices = std::make_unique(created_vertices); }