mirror of https://github.com/CGAL/cgal
refactor: moved triangulation code to a separate class
This commit is contained in:
parent
8d99ac39ee
commit
544942e8ab
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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} )
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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[] = {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue