diff --git a/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.cpp b/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.cpp index 7d70e4f6af0..aac4eb95680 100644 --- a/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.cpp +++ b/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -53,8 +54,7 @@ std::ostream& operator << (std::ostream& os, const Approximate_Vector_3& v) } -std::vector> Geodesic_arcs::get_approximate_arcs(double - error) +Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(double error) { // Construct the arrangement from 12 geodesic arcs. Geom_traits traits; @@ -92,3 +92,74 @@ std::vector> Geodesic_arcs::get_approximate_arcs(double return arcs; } + + +Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs( + const Kml::Placemarks& placemarks, double error) +{ + // Construct the arrangement from 12 geodesic arcs. + Geom_traits traits; + Arrangement arr(&traits); + + auto ctr_p = traits.construct_point_2_object(); + auto ctr_cv = traits.construct_curve_2_object(); + + + std::vector xcvs; + for (const auto& pm : placemarks) + { + for (const auto& lring : pm.polygons) + { + // convert the nodes to points on unit-sphere + std::vector sphere_points; + for (const auto& node : lring.nodes) + { + const auto phi = qDegreesToRadians(node.lat); + const auto theta = qDegreesToRadians(node.lon); + const auto z = sin(phi); + const auto rxy = cos(phi); + const auto x = rxy * cos(theta); + const auto y = rxy * sin(theta); + Approximate_Vector_3 v(x,y,z); + sphere_points.push_back(v); + } + + // add curves + int num_points = sphere_points.size(); + for (int i = 0; i < sphere_points.size(); i++) + { + const auto p1 = sphere_points[i]; + const auto p2 = sphere_points[(i+1) % num_points]; + xcvs.push_back(ctr_cv(ctr_p(p1.x(), p1.y(), p1.z()), + ctr_p(p2.x(), p2.y(), p2.z()))); + } + } + } + + //xcvs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 1, 0))); + //xcvs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 0, 1))); + //xcvs.push_back(ctr_cv(ctr_p(0, 1, 0), ctr_p(0, 0, 1))); + //xcvs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 1, 0), Dir3(0, 0, -1))); + //xcvs.push_back(ctr_cv(Dir3(0, 0, -1))); + + auto approx = traits.approximate_2_object(); + + + std::vector> arcs; + for (const auto& xcv : xcvs) + { + std::vector v; + auto oi2 = approx(xcv, error, std::back_insert_iterator(v)); + + std::vector arc_points; + for (const auto& p : v) + { + const QVector3D arc_point(p.dx(), p.dy(), p.dz()); + arc_points.push_back(arc_point); + } + arcs.push_back(std::move(arc_points)); + } + //std::cout << "offset count = " << m_arc_offsets.size() << std::endl; + + return arcs; +} \ No newline at end of file diff --git a/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.h b/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.h index 68742b692f8..14532f6417b 100644 --- a/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.h +++ b/Arrangement_on_surface_2/demo/earth/Geodesic_arcs.h @@ -5,14 +5,19 @@ #include #include +#include "Kml_reader.h" + class Geodesic_arcs { public: + using Approx_arcs = std::vector>; - std::vector> get_approximate_arcs(double error); - //Line_strip_approx get_approximate_arcs(double error); + Approx_arcs get_approx_arcs(double error); + + // generate approximate arcs from KML data + Approx_arcs get_approx_arcs(const Kml::Placemarks& placemarks, double error); }; diff --git a/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp b/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp index b2ce85684a4..77c38f2cc51 100644 --- a/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp +++ b/Arrangement_on_surface_2/demo/earth/Kml_reader.cpp @@ -3,9 +3,31 @@ #include +#include #include #include +namespace { + + std::vector split(const std::string& str, const char *delim) + { + std::string sc = str; + char* token = strtok(sc.data(), delim); + char* str_end = token + str.length(); + + // Keep printing tokens while one of the delimiters present in str[]. + std::vector results; + while (token != NULL) + { + const auto first = token; + //printf("%s\n", token); + token = strtok(NULL, " "); + results.push_back(std::string(first, token==nullptr ? str_end : token)); + } + + return results; + } +} Kml::Placemarks Kml::read(const std::string& file_name) { @@ -42,18 +64,40 @@ Kml::Placemarks Kml::read(const std::string& file_name) else if (name == "coordinates") { xmlReader.readNext(); - auto str = xmlReader.text().toString(); - auto node_strs = str.split(" "); + auto qstr = xmlReader.text().toString(); + auto ptr = qstr.data(); + auto str = qstr.toUtf8().toStdString(); + auto node_strs = split(str, " "); + for (const auto& node_str : node_strs) { - if (node_str.isEmpty()) + if (node_str.empty()) continue; - auto coord_strs = node_str.split(","); - const auto lon = coord_strs[0].toDouble(); - const auto lat = coord_strs[1].toDouble(); + auto coord_strs = split(node_str, ","); + const auto lon = std::stod(coord_strs[0]); + const auto lat = std::stod(coord_strs[1]); lring.nodes.push_back(Node{ lon, lat }); } + + + //qDebug() << "---------------------------------------"; + //for (const auto& node_str : node_strs) + // std::cout << node_str << std::endl; + + //qDebug() << qstr; + //auto node_qstrs = qstr.split(" "); + //qDebug() << node_qstrs.size(); + //for (const auto& node_str : node_strs) + //{ + // if (node_str.isEmpty()) + // continue; + + // auto coord_strs = node_str.split(","); + // const auto lon = coord_strs[0].toDouble(); + // const auto lat = coord_strs[1].toDouble(); + // lring.nodes.push_back(Node{ lon, lat }); + //} } else if (name == "SimpleData") { diff --git a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp index 55a8c91450d..264ae2daa05 100644 --- a/Arrangement_on_surface_2/demo/earth/Main_widget.cpp +++ b/Arrangement_on_surface_2/demo/earth/Main_widget.cpp @@ -108,11 +108,8 @@ void Main_widget::timerEvent(QTimerEvent*) void Main_widget::initializeGL() { - - { - const auto file_name = "C:/work/gsoc2023/data/world_countries.kml"; - auto countries = Kml::read(file_name); - } + const auto file_name = "C:/work/gsoc2023/data/world_countries.kml"; + auto countries = Kml::read(file_name); initializeOpenGLFunctions(); @@ -127,7 +124,8 @@ void Main_widget::initializeGL() // because we want to compute the error based on camera parameters! Geodesic_arcs ga; const double error = 0.001; // calculate this from cam parameters! - auto lsa = ga.get_approximate_arcs(error); + auto lsa = ga.get_approx_arcs(countries, error); + //auto lsa = ga.get_approx_arcs(error); m_geodesic_arcs = std::make_unique(lsa); } @@ -258,7 +256,7 @@ void Main_widget::resizeGL(int w, int h) // Reset projection qreal aspect = qreal(w) / qreal(h ? h : 1); - const qreal z_near = 1.0, z_far = 100.0, fov = 45.0; + const qreal z_near = 0.1, z_far = 100.0, fov = 45.0; m_camera.perspective(fov, aspect, z_near, z_far); {