refactor: moved triangulation code to a separate class

This commit is contained in:
denizdiktas 2023-08-15 20:53:19 +03:00
parent 8d99ac39ee
commit 544942e8ab
6 changed files with 637 additions and 272 deletions

View File

@ -33,15 +33,15 @@ using json = nlohmann::ordered_json;
#include "arr_print.h" #include "arr_print.h"
#include "Tools.h" #include "Tools.h"
// Includes for Constrained Delaunay Triangulation //// Includes for Constrained Delaunay Triangulation
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> //#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h> //#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/draw_triangulation_2.h> //#include <CGAL/draw_triangulation_2.h>
#include <CGAL/mark_domain_in_triangulation.h> //#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/Polygon_2.h> //#include <CGAL/Polygon_2.h>
//#include <CGAL/Projection_traits_3.h> ////#include <CGAL/Projection_traits_3.h>
#include <unordered_map> //#include <unordered_map>
#include <boost/property_map/property_map.hpp> //#include <boost/property_map/property_map.hpp>
// Include for point location queries // Include for point location queries
#include <CGAL/Arr_naive_point_location.h> #include <CGAL/Arr_naive_point_location.h>
@ -1584,263 +1584,262 @@ Aos::Arr_handle Aos::construct(Kml::Placemarks& placemarks)
} }
std::vector<QVector3D> Aos::get_triangles(Arr_handle arrh) //std::vector<QVector3D> Aos::get_triangles(Arr_handle arrh)
{ //{
using K = CGAL::Exact_predicates_inexact_constructions_kernel; // using K = CGAL::Exact_predicates_inexact_constructions_kernel;
//using K = CGAL::Projection_traits_3<K_epic>; // //using K = CGAL::Projection_traits_3<K_epic>;
using Vb = CGAL::Triangulation_vertex_base_2<K>; // using Vb = CGAL::Triangulation_vertex_base_2<K>;
using Fb = CGAL::Constrained_triangulation_face_base_2<K>; // using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>; // using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
using Itag = CGAL::Exact_predicates_tag; // using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>; // using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
using Face_handle = CDT::Face_handle; // using Face_handle = CDT::Face_handle;
using Point = CDT::Point; // using Point = CDT::Point;
using Polygon_2 = CGAL::Polygon_2<K>; // using Polygon_2 = CGAL::Polygon_2<K>;
//
// auto& arr = *reinterpret_cast<Arrangement*>(arrh.get());
//
// //Geom_traits traits;
// auto approx = s_traits.approximate_2_object();
//
//
// std::vector<std::vector<QVector3D>> all_faces;
// // loop on all faces of the arrangement
// for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
// {
// // skip any face with no OUTER-CCB
// if (0 == fit->number_of_outer_ccbs())
// continue;
//
// // COMPUTE THE CENTROID OF ALL FACE-POINTS
// std::vector<QVector3D> face_points;
//
// // loop on the egdes of the current outer-ccb
// auto first = fit->outer_ccb();
// auto curr = first;
// do {
// auto ap = approx(curr->source()->point());
// QVector3D p(ap.dx(), ap.dy(), ap.dz());
// p.normalize();
// face_points.push_back(p);
// } while (++curr != first);
//
// all_faces.push_back(std::move(face_points));
// }
//
// // RESULTING TRIANGLE POINTS (every 3 point => triangle)
// std::vector<QVector3D> triangles;
//
// std::cout << "triangulating individual faces\n";
//
// // loop on all approximated faces
// for (auto& face_points : all_faces)
// {
// //std::cout << "num face points = " << face_points.size() << std::endl;
// // no need to triangulate if the number of points is 3
// if (face_points.size() == 3)
// {
// triangles.insert(triangles.end(), face_points.begin(), face_points.end());
// continue;
// }
//
//
// // find the centroid of all face-points
// QVector3D centroid(0, 0, 0);
// for (const auto& fp : face_points)
// centroid += fp;
// centroid /= face_points.size();
// centroid.normalize();
// auto normal = centroid;
//
// K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
// K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
// K::Plane_3 plane(plane_origin, plane_normal);
//
// Polygon_2 polygon;
//
// // project all points onto the plane
// K::Point_3 origin(0, 0, 0);
// for (const auto& fp : face_points)
// {
// // define a ray through the origin and the current point
// K::Point_3 current_point(fp.x(), fp.y(), fp.z());
// K::Ray_3 ray(origin, current_point);
//
// auto intersection = CGAL::intersection(plane, ray);
// if (!intersection.has_value())
// std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
// auto ip = boost::get<K::Point_3>(intersection.value());
// auto ip2 = plane.to_2d(ip);
//
// // add this to the polygon constraint
// polygon.push_back(ip2);
// }
//
// CDT cdt;
// cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
//
// std::unordered_map<Face_handle, bool> in_domain_map;
// boost::associative_property_map< std::unordered_map<Face_handle, bool> >
// in_domain(in_domain_map);
//
// //Mark facets that are inside the domain bounded by the polygon
// CGAL::mark_domain_in_triangulation(cdt, in_domain);
//
// // loop on all the triangles ("faces" in triangulation doc)
// for (Face_handle f : cdt.finite_face_handles())
// {
// // if the current triangles is not inside the polygon -> skip it
// if (false == get(in_domain, f))
// continue;
//
// for (int i = 0; i < 3; ++i)
// {
// auto tp = f->vertex(i)->point();
// auto tp3 = plane.to_3d(tp);
// QVector3D p3(tp3.x(), tp3.y(), tp3.z());
// p3.normalize();
// triangles.push_back(p3);
// }
// }
// }
//
// return triangles;
//}
auto& arr = *reinterpret_cast<Arrangement*>(arrh.get()); //Aos::Country_triangles_map Aos::get_triangles_by_country(Arr_handle arrh)
//{
//Geom_traits traits; // using K = CGAL::Exact_predicates_inexact_constructions_kernel;
auto approx = s_traits.approximate_2_object(); // //using K = CGAL::Projection_traits_3<K_epic>;
// using Vb = CGAL::Triangulation_vertex_base_2<K>;
// using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
std::vector<std::vector<QVector3D>> all_faces; // using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
// loop on all faces of the arrangement // using Itag = CGAL::Exact_predicates_tag;
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) // using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
{ // using Face_handle = CDT::Face_handle;
// skip any face with no OUTER-CCB // using Point = CDT::Point;
if (0 == fit->number_of_outer_ccbs()) // using Polygon_2 = CGAL::Polygon_2<K>;
continue; //
// auto& arr = *reinterpret_cast<Countries_arr*>(arrh.get());
// COMPUTE THE CENTROID OF ALL FACE-POINTS // auto approx = s_traits.approximate_2_object();
std::vector<QVector3D> face_points; //
// // group the faces by their country name
// loop on the egdes of the current outer-ccb // using Face_ = Countries_arr::Face_handle::value_type;
auto first = fit->outer_ccb(); // std::map<std::string, std::vector<Face_*>> country_faces_map;
auto curr = first; // for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
do { // {
auto ap = approx(curr->source()->point()); // auto& face = *fit;
QVector3D p(ap.dx(), ap.dy(), ap.dz()); // const auto& country_name = fit->data();
p.normalize(); // // skipping spherical-face
face_points.push_back(p); // if (country_name.empty())
} while (++curr != first); // continue;
// country_faces_map[country_name].push_back(&face);
all_faces.push_back(std::move(face_points)); // }
} //
// std::cout << "triangulating individual faces\n";
// RESULTING TRIANGLE POINTS (every 3 point => triangle) // Country_triangles_map result;
std::vector<QVector3D> triangles; // for (auto& [country_name, faces] : country_faces_map)
// {
std::cout << "triangulating individual faces\n"; // // CONVERT the face-points to QVector3D
// using Face_points = std::vector<QVector3D>;
// loop on all approximated faces // using Faces_ = std::vector<Face_points>;
for (auto& face_points : all_faces) // Faces_ all_faces_of_current_country;
{ // for (auto* face : faces)
//std::cout << "num face points = " << face_points.size() << std::endl; // {
// no need to triangulate if the number of points is 3 // // skip any face with no OUTER-CCB
if (face_points.size() == 3) // if (0 == face->number_of_outer_ccbs())
{ // continue;
triangles.insert(triangles.end(), face_points.begin(), face_points.end()); //
continue; // std::vector<QVector3D> face_points;
} // // loop on the egdes of the current outer-ccb
// auto first = face->outer_ccb();
// auto curr = first;
// find the centroid of all face-points // do {
QVector3D centroid(0, 0, 0); // auto ap = approx(curr->source()->point());
for (const auto& fp : face_points) // QVector3D p(ap.dx(), ap.dy(), ap.dz());
centroid += fp; // p.normalize();
centroid /= face_points.size(); // face_points.push_back(p);
centroid.normalize(); // } while (++curr != first);
auto normal = centroid; //
// all_faces_of_current_country.push_back(std::move(face_points));
K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z()); // }
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z()); //
K::Plane_3 plane(plane_origin, plane_normal); // // RESULTING TRIANGLE POINTS (every 3 point => triangle)
// auto& triangles = result[country_name];
Polygon_2 polygon; // // loop on all approximated faces
// for (auto& face_points : all_faces_of_current_country)
// project all points onto the plane // {
K::Point_3 origin(0, 0, 0); // //std::cout << "num face points = " << face_points.size() << std::endl;
for (const auto& fp : face_points) // // no need to triangulate if the number of points is 3
{ // if (face_points.size() == 3)
// define a ray through the origin and the current point // {
K::Point_3 current_point(fp.x(), fp.y(), fp.z()); // triangles.insert(triangles.end(), face_points.begin(), face_points.end());
K::Ray_3 ray(origin, current_point); // continue;
// }
auto intersection = CGAL::intersection(plane, ray); //
if (!intersection.has_value()) // // find the centroid of all face-points
std::cout << "INTERSECTION ASSERTION ERROR!!!\n"; // QVector3D centroid(0, 0, 0);
auto ip = boost::get<K::Point_3>(intersection.value()); // for (const auto& fp : face_points)
auto ip2 = plane.to_2d(ip); // centroid += fp;
// centroid /= face_points.size();
// add this to the polygon constraint // centroid.normalize();
polygon.push_back(ip2); // auto normal = centroid;
} //
// K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
CDT cdt; // K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true); // K::Plane_3 plane(plane_origin, plane_normal);
//
std::unordered_map<Face_handle, bool> in_domain_map; // Polygon_2 polygon;
boost::associative_property_map< std::unordered_map<Face_handle, bool> > //
in_domain(in_domain_map); // // project all points onto the plane
// K::Point_3 origin(0, 0, 0);
//Mark facets that are inside the domain bounded by the polygon // for (const auto& fp : face_points)
CGAL::mark_domain_in_triangulation(cdt, in_domain); // {
// // define a ray through the origin and the current point
// loop on all the triangles ("faces" in triangulation doc) // K::Point_3 current_point(fp.x(), fp.y(), fp.z());
for (Face_handle f : cdt.finite_face_handles()) // K::Ray_3 ray(origin, current_point);
{ //
// if the current triangles is not inside the polygon -> skip it // auto intersection = CGAL::intersection(plane, ray);
if (false == get(in_domain, f)) // if (!intersection.has_value())
continue; // std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
// auto ip = boost::get<K::Point_3>(intersection.value());
for (int i = 0; i < 3; ++i) // auto ip2 = plane.to_2d(ip);
{ //
auto tp = f->vertex(i)->point(); // // add this to the polygon constraint
auto tp3 = plane.to_3d(tp); // polygon.push_back(ip2);
QVector3D p3(tp3.x(), tp3.y(), tp3.z()); // }
p3.normalize(); //
triangles.push_back(p3); // CDT cdt;
} // cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
} //
} // std::unordered_map<Face_handle, bool> in_domain_map;
// boost::associative_property_map< std::unordered_map<Face_handle, bool> >
return triangles; // in_domain(in_domain_map);
} //
// //Mark facets that are inside the domain bounded by the polygon
// CGAL::mark_domain_in_triangulation(cdt, in_domain);
Aos::Country_triangles_map Aos::get_triangles_by_country(Arr_handle arrh) //
{ // // loop on all the triangles ("faces" in triangulation doc)
using K = CGAL::Exact_predicates_inexact_constructions_kernel; // for (Face_handle f : cdt.finite_face_handles())
//using K = CGAL::Projection_traits_3<K_epic>; // {
using Vb = CGAL::Triangulation_vertex_base_2<K>; // // if the current triangles is not inside the polygon -> skip it
using Fb = CGAL::Constrained_triangulation_face_base_2<K>; // if (false == get(in_domain, f))
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>; // continue;
using Itag = CGAL::Exact_predicates_tag; //
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>; // for (int i = 0; i < 3; ++i)
using Face_handle = CDT::Face_handle; // {
using Point = CDT::Point; // auto tp = f->vertex(i)->point();
using Polygon_2 = CGAL::Polygon_2<K>; // auto tp3 = plane.to_3d(tp);
// QVector3D p3(tp3.x(), tp3.y(), tp3.z());
auto& arr = *reinterpret_cast<Countries_arr*>(arrh.get()); // p3.normalize();
auto approx = s_traits.approximate_2_object(); // triangles.push_back(p3);
// }
// group the faces by their country name // }
using Face_ = Countries_arr::Face_handle::value_type; // }
std::map<std::string, std::vector<Face_*>> country_faces_map; // }
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) //
{ // return result;
auto& face = *fit; //}
const auto& country_name = fit->data();
// skipping spherical-face
if (country_name.empty())
continue;
country_faces_map[country_name].push_back(&face);
}
std::cout << "triangulating individual faces\n";
Country_triangles_map result;
for (auto& [country_name, faces] : country_faces_map)
{
// CONVERT the face-points to QVector3D
using Face_points = std::vector<QVector3D>;
using Faces_ = std::vector<Face_points>;
Faces_ all_faces_of_current_country;
for (auto* face : faces)
{
// skip any face with no OUTER-CCB
if (0 == face->number_of_outer_ccbs())
continue;
std::vector<QVector3D> face_points;
// loop on the egdes of the current outer-ccb
auto first = face->outer_ccb();
auto curr = first;
do {
auto ap = approx(curr->source()->point());
QVector3D p(ap.dx(), ap.dy(), ap.dz());
p.normalize();
face_points.push_back(p);
} while (++curr != first);
all_faces_of_current_country.push_back(std::move(face_points));
}
// RESULTING TRIANGLE POINTS (every 3 point => triangle)
auto& triangles = result[country_name];
// loop on all approximated faces
for (auto& face_points : all_faces_of_current_country)
{
//std::cout << "num face points = " << face_points.size() << std::endl;
// no need to triangulate if the number of points is 3
if (face_points.size() == 3)
{
triangles.insert(triangles.end(), face_points.begin(), face_points.end());
continue;
}
// find the centroid of all face-points
QVector3D centroid(0, 0, 0);
for (const auto& fp : face_points)
centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
K::Plane_3 plane(plane_origin, plane_normal);
Polygon_2 polygon;
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points)
{
// define a ray through the origin and the current point
K::Point_3 current_point(fp.x(), fp.y(), fp.z());
K::Ray_3 ray(origin, current_point);
auto intersection = CGAL::intersection(plane, ray);
if (!intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = boost::get<K::Point_3>(intersection.value());
auto ip2 = plane.to_2d(ip);
// add this to the polygon constraint
polygon.push_back(ip2);
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool> >
in_domain(in_domain_map);
//Mark facets that are inside the domain bounded by the polygon
CGAL::mark_domain_in_triangulation(cdt, in_domain);
// loop on all the triangles ("faces" in triangulation doc)
for (Face_handle f : cdt.finite_face_handles())
{
// if the current triangles is not inside the polygon -> skip it
if (false == get(in_domain, f))
continue;
for (int i = 0; i < 3; ++i)
{
auto tp = f->vertex(i)->point();
auto tp3 = plane.to_3d(tp);
QVector3D p3(tp3.x(), tp3.y(), tp3.z());
p3.normalize();
triangles.push_back(p3);
}
}
}
}
return result;
}
Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh) Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh)

View File

@ -67,10 +67,10 @@ public:
static Arr_handle load_arr(const std::string& file_name); static Arr_handle load_arr(const std::string& file_name);
static Arr_handle construct(Kml::Placemarks& placemarks); static Arr_handle construct(Kml::Placemarks& placemarks);
static std::vector<QVector3D> get_triangles(Arr_handle arrh); //static std::vector<QVector3D> get_triangles(Arr_handle arrh);
using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>; //using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>;
static Country_triangles_map get_triangles_by_country(Arr_handle arrh); //static Country_triangles_map get_triangles_by_country(Arr_handle arrh);
using Country_color_map = std::map<std::string, int>; using Country_color_map = std::map<std::string, int>;
static Country_color_map get_color_mapping(Arr_handle arrh); static Country_color_map get_color_mapping(Arr_handle arrh);

View File

@ -0,0 +1,328 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "Aos_triangulator.h"
#include <iostream>
#include <iterator>
#include <map>
#include <set>
#include <vector>
#include <qmath.h>
#include <qvector3d.h>
#include <nlohmann/json.hpp>
using json = nlohmann::ordered_json;
// Includes for Arrangements on Sphere (AOS)
#include "Aos_defs.h"
//#include "arr_print.h"
//#include "Tools.h"
// Includes for Constrained Delaunay Triangulation
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
#include <CGAL/draw_triangulation_2.h>
#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/Polygon_2.h>
//#include <CGAL/Projection_traits_3.h>
#include <unordered_map>
#include <boost/property_map/property_map.hpp>
namespace {
// use this traits everytime you construct an arrangment!
static Geom_traits s_traits;
using Dir3 = Kernel::Direction_3;
std::ostream& operator << (std::ostream& os, const Dir3& d)
{
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
using Approximate_point_2 = Geom_traits::Approximate_point_2;
std::ostream& operator << (std::ostream& os, const Approximate_point_2& d)
{
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
using Approximate_number_type = Geom_traits::Approximate_number_type;
using Approximate_kernel = Geom_traits::Approximate_kernel;
using Approximate_Vector_3 = CGAL::Vector_3<Approximate_kernel>;
using Approximate_Direction_3 = Approximate_kernel::Direction_3;
using Direction_3 = Kernel::Direction_3;
}
std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
{
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
//using K = CGAL::Projection_traits_3<K_epic>;
using Vb = CGAL::Triangulation_vertex_base_2<K>;
using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
using Face_handle = CDT::Face_handle;
using Point = CDT::Point;
using Polygon_2 = CGAL::Polygon_2<K>;
auto& arr = *reinterpret_cast<Arrangement*>(arrh.get());
//Geom_traits traits;
auto approx = s_traits.approximate_2_object();
std::vector<std::vector<QVector3D>> all_faces;
// loop on all faces of the arrangement
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
{
// skip any face with no OUTER-CCB
if (0 == fit->number_of_outer_ccbs())
continue;
// COMPUTE THE CENTROID OF ALL FACE-POINTS
std::vector<QVector3D> face_points;
// loop on the egdes of the current outer-ccb
auto first = fit->outer_ccb();
auto curr = first;
do {
auto ap = approx(curr->source()->point());
QVector3D p(ap.dx(), ap.dy(), ap.dz());
p.normalize();
face_points.push_back(p);
} while (++curr != first);
all_faces.push_back(std::move(face_points));
}
// RESULTING TRIANGLE POINTS (every 3 point => triangle)
std::vector<QVector3D> triangles;
std::cout << "triangulating individual faces\n";
// loop on all approximated faces
for (auto& face_points : all_faces)
{
//std::cout << "num face points = " << face_points.size() << std::endl;
// no need to triangulate if the number of points is 3
if (face_points.size() == 3)
{
triangles.insert(triangles.end(), face_points.begin(), face_points.end());
continue;
}
// find the centroid of all face-points
QVector3D centroid(0, 0, 0);
for (const auto& fp : face_points)
centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
K::Plane_3 plane(plane_origin, plane_normal);
Polygon_2 polygon;
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points)
{
// define a ray through the origin and the current point
K::Point_3 current_point(fp.x(), fp.y(), fp.z());
K::Ray_3 ray(origin, current_point);
auto intersection = CGAL::intersection(plane, ray);
if (!intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = boost::get<K::Point_3>(intersection.value());
auto ip2 = plane.to_2d(ip);
// add this to the polygon constraint
polygon.push_back(ip2);
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool> >
in_domain(in_domain_map);
//Mark facets that are inside the domain bounded by the polygon
CGAL::mark_domain_in_triangulation(cdt, in_domain);
// loop on all the triangles ("faces" in triangulation doc)
for (Face_handle f : cdt.finite_face_handles())
{
// if the current triangles is not inside the polygon -> skip it
if (false == get(in_domain, f))
continue;
for (int i = 0; i < 3; ++i)
{
auto tp = f->vertex(i)->point();
auto tp3 = plane.to_3d(tp);
QVector3D p3(tp3.x(), tp3.y(), tp3.z());
p3.normalize();
triangles.push_back(p3);
}
}
}
return triangles;
}
Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
{
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
//using K = CGAL::Projection_traits_3<K_epic>;
using Vb = CGAL::Triangulation_vertex_base_2<K>;
using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
using Face_handle = CDT::Face_handle;
using Point = CDT::Point;
using Polygon_2 = CGAL::Polygon_2<K>;
auto& arr = *reinterpret_cast<Countries_arr*>(arrh.get());
auto approx = s_traits.approximate_2_object();
// group the faces by their country name
using Face_ = Countries_arr::Face_handle::value_type;
std::map<std::string, std::vector<Face_*>> country_faces_map;
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
{
auto& face = *fit;
const auto& country_name = fit->data();
// skipping spherical-face
if (country_name.empty())
continue;
country_faces_map[country_name].push_back(&face);
}
std::cout << "triangulating individual faces\n";
Country_triangles_map result;
for (auto& [country_name, faces] : country_faces_map)
{
// CONVERT the face-points to QVector3D
using Face_points = std::vector<QVector3D>;
using Faces_ = std::vector<Face_points>;
Faces_ all_faces_of_current_country;
for (auto* face : faces)
{
// skip any face with no OUTER-CCB
if (0 == face->number_of_outer_ccbs())
continue;
std::vector<QVector3D> face_points;
// loop on the egdes of the current outer-ccb
auto first = face->outer_ccb();
auto curr = first;
do {
auto ap = approx(curr->source()->point());
QVector3D p(ap.dx(), ap.dy(), ap.dz());
p.normalize();
face_points.push_back(p);
} while (++curr != first);
all_faces_of_current_country.push_back(std::move(face_points));
}
// RESULTING TRIANGLE POINTS (every 3 point => triangle)
auto& triangles = result[country_name];
// loop on all approximated faces
for (auto& face_points : all_faces_of_current_country)
{
//std::cout << "num face points = " << face_points.size() << std::endl;
// no need to triangulate if the number of points is 3
if (face_points.size() == 3)
{
triangles.insert(triangles.end(), face_points.begin(), face_points.end());
continue;
}
// find the centroid of all face-points
QVector3D centroid(0, 0, 0);
for (const auto& fp : face_points)
centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
K::Plane_3 plane(plane_origin, plane_normal);
Polygon_2 polygon;
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points)
{
// define a ray through the origin and the current point
K::Point_3 current_point(fp.x(), fp.y(), fp.z());
K::Ray_3 ray(origin, current_point);
auto intersection = CGAL::intersection(plane, ray);
if (!intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = boost::get<K::Point_3>(intersection.value());
auto ip2 = plane.to_2d(ip);
// add this to the polygon constraint
polygon.push_back(ip2);
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool> >
in_domain(in_domain_map);
//Mark facets that are inside the domain bounded by the polygon
CGAL::mark_domain_in_triangulation(cdt, in_domain);
// loop on all the triangles ("faces" in triangulation doc)
for (Face_handle f : cdt.finite_face_handles())
{
// if the current triangles is not inside the polygon -> skip it
if (false == get(in_domain, f))
continue;
for (int i = 0; i < 3; ++i)
{
auto tp = f->vertex(i)->point();
auto tp3 = plane.to_3d(tp);
QVector3D p3(tp3.x(), tp3.y(), tp3.z());
p3.normalize();
triangles.push_back(p3);
}
}
}
}
return result;
}

View File

@ -0,0 +1,34 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
//
// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#ifndef AOS_TRIANGULATOR_H
#define AOS_TRIANGULATOR_H
#include <map>
#include <vector>
#include <qvector3d.h>
#include "Aos.h"
using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>;
class Aos_triangulator
{
public:
static std::vector<QVector3D> get_all(Aos::Arr_handle arrh);
static Country_triangles_map get_by_country(Aos::Arr_handle arrh);
};
#endif

View File

@ -55,6 +55,7 @@ link_directories(earth PRIVATE ${SHAPELIB_LIB_DIR})
file(GLOB source_files_aos file(GLOB source_files_aos
Aos.h Aos.cpp Aos.h Aos.cpp
Aos_defs.h Aos_defs.h
Aos_triangulator.h Aos_triangulator.cpp
) )
source_group( "Aos" FILES ${source_files_aos} ) source_group( "Aos" FILES ${source_files_aos} )

View File

@ -16,6 +16,7 @@
#include <QMouseEvent> #include <QMouseEvent>
#include "Aos.h" #include "Aos.h"
#include "Aos_triangulator.h"
#include "Camera_manip_rot.h" #include "Camera_manip_rot.h"
#include "Camera_manip_rot_bpa.h" #include "Camera_manip_rot_bpa.h"
#include "Camera_manip_zoom.h" #include "Camera_manip_zoom.h"
@ -329,9 +330,11 @@ void Main_widget::initializeGL()
qDebug() << "generating triangles.."; qDebug() << "generating triangles..";
//auto triangle_points = Aos::get_triangles(arrh); //auto triangle_points = Aos::get_triangles(arrh);
auto country_triangles_map = Aos::get_triangles_by_country(m_arrh); //auto triangle_points = Aos_triangulator::get_all(arrh);
auto color_map = Aos::get_color_mapping(m_arrh); //auto country_triangles_map = Aos::get_triangles_by_country(m_arrh);
qDebug() << "color map size = " << color_map.size(); auto country_triangles_map = Aos_triangulator::get_by_country(m_arrh);
//auto color_map = Aos::get_color_mapping(m_arrh);
//qDebug() << "color map size = " << color_map.size();
qDebug() << "num countries = " << country_triangles_map.size(); qDebug() << "num countries = " << country_triangles_map.size();
auto rndm = [] {return rand() / double(RAND_MAX); }; auto rndm = [] {return rand() / double(RAND_MAX); };
//QVector4D colors[] = { //QVector4D colors[] = {