Cleaned up; added default input file

This commit is contained in:
Efi Fogel 2024-01-08 16:24:07 +02:00
parent fff5fa5380
commit 36d23e88b7
54 changed files with 934 additions and 2073 deletions

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -47,7 +47,6 @@ using json = nlohmann::ordered_json;
#include <CGAL/Arr_naive_point_location.h>
#include <CGAL/Arr_point_location_result.h>
namespace {
// //#define USE_EPIC
//
@ -71,8 +70,7 @@ namespace {
static Geom_traits s_traits;
// Extended DCEL & Arrangement
struct Flag
{
struct Flag {
bool v;
Flag() : v{ false } {}
Flag(bool init) : v{ init } {}
@ -81,7 +79,7 @@ namespace {
// EXTENDED AOS for analysing the arrangement
using Ext_dcel = CGAL::Arr_extended_dcel<Geom_traits, Flag, Flag, Flag>;
using Ext_topol_traits = CGAL::Arr_spherical_topology_traits_2<Geom_traits,
Ext_dcel>;
Ext_dcel>;
using Ext_aos = CGAL::Arrangement_on_surface_2<Geom_traits, Ext_topol_traits>;
// COUNTRIES AOS for grouping the faces by the country name
@ -91,18 +89,15 @@ namespace {
//using Countries_arr =
// CGAL::Arrangement_on_surface_2<Geom_traits, Countries_topol_traits>;
using Dir3 = Kernel::Direction_3;
std::ostream& operator << (std::ostream& os, const Dir3& d)
{
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)
{
std::ostream& operator << (std::ostream& os, const Approximate_point_2& d) {
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
@ -114,14 +109,12 @@ namespace {
using Direction_3 = Kernel::Direction_3;
std::ostream& operator << (std::ostream& os, const Approximate_Vector_3& v)
{
std::ostream& operator << (std::ostream& os, const Approximate_Vector_3& v) {
os << v.x() << ", " << v.y() << ", " << v.z();
//os << v.hx() << ", " << v.hy() << ", " << v.hz() << ", " << v.hw();
return os;
}
//---------------------------------------------------------------------------
// below are the helper functions used to construct the arcs from KML data
// TODO: Revisit handling of INNER & OUTER boundaries
@ -129,15 +122,13 @@ namespace {
// get curves for the given kml placemark
// NOTE: this is defined here to keep the definitions local to this cpp file
Curves get_arcs(const Kml::Placemark& placemark)
{
Curves get_arcs(const Kml::Placemark& placemark) {
//Geom_traits traits;
auto ctr_p = s_traits.construct_point_2_object();
auto ctr_cv = s_traits.construct_curve_2_object();
std::vector<Curve> xcvs;
for (const auto& polygon : placemark.polygons)
{
for (const auto& polygon : placemark.polygons) {
// colect all rings into a single list (FOR NOW!!!)
// TO-DO: PROCESS OUTER & INNER BOUNDARIES SEPARATELY!!!
Kml::LinearRings linear_rings;
@ -147,11 +138,9 @@ namespace {
// convert the nodes to points on unit-sphere
for (const auto& lring : linear_rings)
{
std::vector<Approximate_Vector_3> sphere_points;
for (const auto& node : lring.nodes)
{
for (const auto& lring : linear_rings) {
std::vector<Approximate_Vector_3> sphere_points;
for (const auto& node : lring.nodes) {
const auto p = node.get_coords_3d();
Approximate_Vector_3 v(p.x, p.y, p.z);
sphere_points.push_back(v);
@ -159,8 +148,7 @@ namespace {
// add geodesic arcs for the current LinearRing
int num_points = sphere_points.size();
for (int i = 0; i < num_points - 1; i++)
{
for (int i = 0; i < num_points - 1; i++) {
const auto p1 = sphere_points[i];
const auto p2 = sphere_points[i + 1];
xcvs.push_back(ctr_cv(ctr_p(p1.x(), p1.y(), p1.z()),
@ -190,10 +178,8 @@ namespace {
num_counted_arcs = 0;
num_counted_polygons = 0;
std::vector<Curve> xcvs;
for (const auto& pm : placemarks)
{
for (const auto& polygon : pm.polygons)
{
for (const auto& pm : placemarks) {
for (const auto& polygon : pm.polygons) {
num_counted_polygons++;
// colect all rings into a single list (FOR NOW!!!)
@ -204,12 +190,10 @@ namespace {
linear_rings.push_back(inner_boundary);
// loop on outer and inner boundaries
for (const auto& lring : linear_rings)
{
for (const auto& lring : linear_rings) {
// convert the nodes to points on unit-sphere
std::vector<Approximate_Vector_3> sphere_points;
for (const auto& node : lring.nodes)
{
for (const auto& node : lring.nodes) {
num_counted_nodes++;
const auto p = node.get_coords_3d();
Approximate_Vector_3 v(p.x, p.y, p.z);
@ -239,8 +223,7 @@ namespace {
}
Aos::Approx_arc get_approx_curve(Curve xcv, double error)
{
Aos::Approx_arc get_approx_curve(Curve xcv, double error) {
//Geom_traits traits;
auto approx = s_traits.approximate_2_object();
std::vector<QVector3D> approx_curve;
@ -257,11 +240,9 @@ namespace {
return approx_curve;
}
Aos::Approx_arcs get_approx_curves(std::vector<Curve>& xcvs, double error)
{
Aos::Approx_arcs get_approx_curves(std::vector<Curve>& xcvs, double error) {
Aos::Approx_arcs approx_curves;
for (const auto& xcv : xcvs)
{
for (const auto& xcv : xcvs) {
auto approx_curve = get_approx_curve(xcv, error);
approx_curves.push_back(std::move(approx_curve));
}
@ -271,8 +252,7 @@ namespace {
}
Aos::Approx_arc Aos::get_approx_identification_curve(double error)
{
Aos::Approx_arc Aos::get_approx_identification_curve(double error) {
//Geom_traits traits;
auto ctr_p = s_traits.construct_point_2_object();
auto ctr_cv = s_traits.construct_curve_2_object();
@ -285,8 +265,7 @@ Aos::Approx_arc Aos::get_approx_identification_curve(double error)
{
std::vector<Approximate_point_2> v;
auto oi2 = approx(xcv, error, std::back_insert_iterator(v));
for (const auto& p : v)
{
for (const auto& p : v) {
const QVector3D arc_point(p.dx(), p.dy(), p.dz());
approx_arc.push_back(arc_point);
}
@ -295,8 +274,8 @@ Aos::Approx_arc Aos::get_approx_identification_curve(double error)
return approx_arc;
}
Aos::Approx_arcs Aos::get_approx_arcs(double error)
{
//! \brief
Aos::Approx_arcs Aos::get_approx_arcs(double error) {
auto ctr_p = s_traits.construct_point_2_object();
auto ctr_cv = s_traits.construct_curve_2_object();
@ -310,15 +289,17 @@ Aos::Approx_arcs Aos::get_approx_arcs(double error)
auto approx_arcs = get_approx_curves(xcvs, error);
return approx_arcs;
}
Aos::Approx_arcs Aos::get_approx_arcs(const Kml::Placemark& placemark, double error)
{
//! \brief
auto Aos::get_approx_arcs(const Kml::Placemark& placemark, double error) ->
Approx_arcs {
auto xcvs = get_arcs(placemark);
auto arcs = ::get_approx_curves(xcvs, error);
return arcs;
}
void Aos::check(const Kml::Placemarks& placemarks)
{
//! \brief
void Aos::check(const Kml::Placemarks& placemarks) {
//Geom_traits traits;
Arrangement arr(&s_traits);
@ -343,8 +324,8 @@ void Aos::check(const Kml::Placemarks& placemarks)
std::cout << "num arr faces = " << arr.number_of_faces() << std::endl;
}
std::vector<QVector3D> Aos::ext_check(const Kml::Placemarks& placemarks)
{
//! \brief
std::vector<QVector3D> Aos::ext_check(const Kml::Placemarks& placemarks) {
// Construct the arrangement from 12 geodesic arcs.
//Geom_traits traits;
Ext_aos arr(&s_traits);
@ -357,39 +338,33 @@ std::vector<QVector3D> Aos::ext_check(const Kml::Placemarks& placemarks)
// 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;
// add arcs
for (auto& xcv : xcvs)
CGAL::insert(arr, xcv);
for (auto& xcv : xcvs) CGAL::insert(arr, xcv);
// extract all vertices that are ADDED when inserting the arcs!
int num_created_vertices = 0;
std::vector<QVector3D> created_vertices;
auto approx = s_traits.approximate_2_object();
for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit)
{
for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) {
auto& d = vit->data();
if (vit->data().v == false)
{
if (vit->data().v == false) {
std::cout << "-------------------------------------\n";
std::cout << vit->point() << std::endl;
if (2 == vit->degree())
;//continue;
if (2 == vit->degree());//continue;
if (1 == vit->degree())
{
if (1 == vit->degree()) {
auto p = vit->point();
auto p2 = p.location();
std::cout << " deg-1 vertex = " << p << std::endl;
std::cout << " deg-1 vertex: " << std::boolalpha << vit->incident_halfedges()->target()->data().v << std::endl;
std::cout << " deg-1 vertex: " << std::boolalpha
<< vit->incident_halfedges()->target()->data().v << std::endl;
}
@ -411,7 +386,8 @@ std::vector<QVector3D> Aos::ext_check(const Kml::Placemarks& placemarks)
auto curr = first;
do {
auto tvh = curr->twin()->target();
//std::cout << std::boolalpha << svh->data().v << " - " << tvh->data().v << std::endl;
//std::cout << std::boolalpha << svh->data().v << " - "
// << tvh->data().v << std::endl;
auto it = vertex_node_map.find(tvh);
if (it != vertex_node_map.end())
std::cout << std::setprecision(16) << it->second << std::endl;
@ -442,14 +418,12 @@ std::vector<QVector3D> Aos::ext_check(const Kml::Placemarks& placemarks)
return created_vertices;
}
std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
{
//! \brief
std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks) {
// Construct the arrangement from 12 geodesic arcs.
//Geom_traits traits;
Ext_aos arr(&s_traits);
//
auto nodes = Kml::generate_ids(placemarks);
//auto nodes = Kml::generate_ids_approx(placemarks, 0.001);
@ -462,8 +436,7 @@ std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
//
std::vector<Point> points;
std::vector<Ext_aos::Vertex_handle> vertices;
for (const auto& node : nodes)
{
for (const auto& node : nodes) {
auto n = node.get_coords_3d();
auto p = ctr_p(n.x, n.y, n.z);
auto v = CGAL::insert_point(arr, p);
@ -475,22 +448,17 @@ std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
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)
{
for (auto& polygon : placemark.polygons)
{
for (auto& placemark : placemarks) {
for (auto& polygon : placemark.polygons) {
num_counted_polygons++;
// TO DO : ADD the outer boundaries!
auto& ids = polygon.outer_boundary.ids;
int num_nodes = ids.size();
for (int i = 0; i < num_nodes - 1; ++i)
{
for (int i = 0; i < num_nodes - 1; ++i) {
num_counted_arcs++;
const auto nid1 = ids[i];
const auto nid2 = ids[i + 1];
@ -509,23 +477,20 @@ std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
int num_created_vertices = 0;
std::vector<QVector3D> created_vertices;
auto approx = s_traits.approximate_2_object();
for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit)
{
for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) {
auto& d = vit->data();
if (vit->data().v == false)
{
if (vit->data().v == false) {
std::cout << "-------------------------------------\n";
std::cout << vit->point() << std::endl;
if (2 == vit->degree())
;//continue;
if (2 == vit->degree());//continue;
if (1 == vit->degree())
{
if (1 == vit->degree()) {
auto p = vit->point();
auto p2 = p.location();
std::cout << "deg-1 vertex = " << p << std::endl;
std::cout << "deg-1 vertex: " << std::boolalpha << vit->incident_halfedges()->target()->data().v << std::endl;
std::cout << "deg-1 vertex: " << std::boolalpha
<< vit->incident_halfedges()->target()->data().v << std::endl;
}
@ -548,7 +513,8 @@ std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
std::cout << std::endl;
}
}
std::cout << "*** num created vertices = " << num_created_vertices << std::endl;
std::cout << "*** num created vertices = " << num_created_vertices
<< std::endl;
std::cout << "-------------------------------\n";
std::cout << "num nodes = " << nodes.size() << std::endl;
@ -565,9 +531,8 @@ std::vector<QVector3D> Aos::ext_check_id_based(Kml::Placemarks& placemarks)
return created_vertices;
}
Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
{
//! brief
auto Aos::find_new_faces(Kml::Placemarks& placemarks) -> Approx_arcs {
//Geom_traits traits;
Ext_aos arr(&s_traits);
auto ctr_p = s_traits.construct_point_2_object();
@ -580,25 +545,21 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
auto nodes = Kml::generate_ids(placemarks);
//-------------------------------------------------------------------------
// define a set of vertex-handles: use this to check if the face is
// obtained from the polygon definition, or if it is an additional face
using Vertex_handle = Ext_aos::Vertex_handle;
std::map<Vertex_handle, int> vertex_id_map;
std::set<std::set<int>> all_polygon_node_ids;
std::map<Vertex_handle, int> vertex_id_map;
std::set<std::set<int>> all_polygon_node_ids;
num_counted_nodes = 0;
num_counted_arcs = 0;
num_counted_polygons = 0;
std::vector<Curve> xcvs;
for (auto& pm : placemarks)
{
for (auto& pm : placemarks) {
std::cout << pm.name << std::endl;
for (auto& polygon : pm.polygons)
{
num_counted_polygons++;
for (auto& polygon : pm.polygons) {
++num_counted_polygons;
// colect all rings into a single list (FOR NOW!!!)
// TO-DO: PROCESS OUTER & INNER BOUNDARIES SEPARATELY!!!
@ -618,9 +579,9 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
// convert the nodes to points on unit-sphere
std::vector<Approximate_Vector_3> sphere_points;
//for (const auto& node : lring->nodes)
//std::cout << " NUM POLYGON-NODES SIZE = " << lring->ids.size() << std::endl;
for (int i = 0; i < lring->ids.size(); ++i)
{
//std::cout << " NUM POLYGON-NODES SIZE = "
// << lring->ids.size() << std::endl;
for (int i = 0; i < lring->ids.size(); ++i) {
num_counted_nodes++;
const auto id = lring->ids[i];
const auto& node = lring->nodes[i];
@ -641,7 +602,8 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
vertex_id_map[vh] = id;
vh->data().v = true;
}
//std::cout << " POLYGON-NODES SET SIZE = " << polygon_node_ids.size() << std::endl;
//std::cout << " POLYGON-NODES SET SIZE = "
// << polygon_node_ids.size() << std::endl;
if (lring->ids.size() != (1 + polygon_node_ids.size()))
std::cout << "*** ASSERTION ERROR!!!!\n";
@ -671,15 +633,10 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
int num_found = 0;
int num_not_found = 0;
std::vector<Curve> new_face_arcs;
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh)
{
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh) {
// skip the spherical face
std::cout << "num outer_ccbs = " << fh->number_of_outer_ccbs() << std::endl;
if (fh->number_of_outer_ccbs() == 0)
{
continue;
}
if (fh->number_of_outer_ccbs() == 0) continue;
// construct the set of all node-ids for the current face
std::set<int> face_node_ids_set;
@ -690,27 +647,28 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
do {
auto vh = curr->source();
// skip if the vertex is due to intersection with the identification curve
if ((vh->data().v == false) && (vh->degree() == 2))
continue;
if ((vh->data().v == false) && (vh->degree() == 2)) continue;
auto id = vertex_id_map[vh];
face_node_ids_set.insert(id);
face_arcs.push_back(ctr_cv(curr->source()->point(), curr->target()->point()));
face_arcs.push_back(ctr_cv(curr->source()->point(),
curr->target()->point()));
} while (++curr != first);
//std::cout << "counted vertices = " << num_vertices << std::endl;
//std::cout << "vertices in the set = " << polygon_node_ids.size() << std::endl;
//std::cout << "vertices in the set = " << polygon_node_ids.size()
// << std::endl;
auto it = all_polygon_node_ids.find(face_node_ids_set);
if (it == all_polygon_node_ids.cend())
{
if (it == all_polygon_node_ids.cend()) {
std::cout << "NOT FOUND!!!\n";
std::cout << "num nodes = " << face_node_ids_set.size() << std::endl;
num_not_found++;
new_face_arcs.insert(new_face_arcs.end(), face_arcs.begin(), face_arcs.end());
new_face_arcs.insert(new_face_arcs.end(), face_arcs.begin(),
face_arcs.end());
}
else
num_found++;
++num_found;
}
std::cout << "num not found = " << num_not_found << std::endl;
@ -718,9 +676,8 @@ Aos::Approx_arcs Aos::find_new_faces(Kml::Placemarks& placemarks)
return approx_arcs;
}
void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
{
//! \brief
void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name) {
#ifndef USE_EPIC
//Geom_traits traits;
Ext_aos arr(&s_traits);
@ -741,8 +698,8 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
using Vertex_handle = Ext_aos::Vertex_handle;
using Halfedge_handle = Ext_aos::Halfedge_handle;
using Face_handle = Ext_aos::Face_handle;
std::map<Vertex_handle, int> vertex_id_map;
std::map<std::set<int>, std::string> all_polygon_node_ids_map;
std::map<Vertex_handle, int> vertex_id_map;
std::map<std::set<int>, std::string> all_polygon_node_ids_map;
// map to associate the created faces with the country names
// CAUTION: the newly created faces
@ -751,11 +708,9 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
num_counted_arcs = 0;
num_counted_polygons = 0;
std::vector<Curve> xcvs;
for (auto& pm : placemarks)
{
for (auto& pm : placemarks) {
std::cout << pm.name << std::endl;
for (auto& polygon : pm.polygons)
{
for (auto& polygon : pm.polygons) {
num_counted_polygons++;
// colect all rings into a single list (FOR NOW!!!)
@ -776,9 +731,9 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
// convert the nodes to points on unit-sphere
std::vector<Approximate_Vector_3> sphere_points;
//for (const auto& node : lring->nodes)
//std::cout << " NUM POLYGON-NODES SIZE = " << lring->ids.size() << std::endl;
for (int i = 0; i < lring->ids.size(); ++i)
{
//std::cout << " NUM POLYGON-NODES SIZE = " << lring->ids.size()
// << std::endl;
for (int i = 0; i < lring->ids.size(); ++i) {
num_counted_nodes++;
const auto id = lring->ids[i];
const auto& node = lring->nodes[i];
@ -799,7 +754,8 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
vertex_id_map[vh] = id;
vh->data().v = true;
}
//std::cout << " POLYGON-NODES SET SIZE = " << polygon_node_ids.size() << std::endl;
//std::cout << " POLYGON-NODES SET SIZE = "
// << polygon_node_ids.size() << std::endl;
if (lring->ids.size() != (1 + polygon_node_ids.size()))
std::cout << "*** ASSERTION ERROR!!!!\n";
@ -808,8 +764,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
// add curves
int num_points = sphere_points.size();
for (int i = 0; i < num_points - 1; i++)
{
for (int i = 0; i < num_points - 1; ++i) {
num_counted_arcs++;
const auto p1 = sphere_points[i];
const auto p2 = sphere_points[i + 1];
@ -825,9 +780,12 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
}
}
std::cout << "*** arr.number_of_faces = " << arr.number_of_faces() << std::endl;
std::cout << "*** arr.number_of_halfedges = " << arr.number_of_halfedges() << std::endl;
std::cout << "*** arr.number_of_vertices = " << arr.number_of_vertices() << std::endl;
std::cout << "*** arr.number_of_faces = " << arr.number_of_faces()
<< std::endl;
std::cout << "*** arr.number_of_halfedges = " << arr.number_of_halfedges()
<< std::endl;
std::cout << "*** arr.number_of_vertices = " << arr.number_of_vertices()
<< std::endl;
// DEFINE JSON OBJECT
json js;
@ -844,9 +802,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
CGAL::Rational_traits<decltype(ex)> rt;
typename CGAL::Algebraic_structure_traits<decltype(ex)>::Simplify simplify;
auto set_num_denum = [&](decltype(ex)& x, json& ratx)
{
auto set_num_denum = [&](decltype(ex)& x, json& ratx) {
simplify(x);
std::stringstream ss_x_num;
CGAL::IO::set_ascii_mode(ss_x_num);
@ -863,17 +819,14 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
ratx["den"] = xden;
};
using Point_ = std::decay_t<decltype(arr.vertices_begin()->point())>;
std::map<void*, int> point_pos_map;
std::vector<Point_> points;
std::map<Vertex_handle, int> vertex_pos_map;
for (auto vh = arr.vertices_begin(); vh != arr.vertices_end(); ++vh)
{
for (auto vh = arr.vertices_begin(); vh != arr.vertices_end(); ++vh) {
// add the vertex if not found in the map
auto it = vertex_pos_map.find(vh);
if (it == vertex_pos_map.end())
{
if (it == vertex_pos_map.end()) {
int new_vh_pos = vertex_pos_map.size();
vertex_pos_map[vh] = new_vh_pos;
@ -901,13 +854,11 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
using Ext_curve = Ext_aos::X_monotone_curve_2;
std::map<Ext_curve*, int> curve_pos_map;
int num_edges = 0;
for (auto eh = arr.edges_begin(); eh != arr.edges_end(); ++eh)
{
for (auto eh = arr.edges_begin(); eh != arr.edges_end(); ++eh) {
num_edges++;
auto& xcv = eh->curve();
auto it = curve_pos_map.find(&xcv);
if (it == curve_pos_map.end())
{
if (it == curve_pos_map.end()) {
int new_xcv_pos = curve_pos_map.size();
curve_pos_map[&xcv] = new_xcv_pos;
@ -947,8 +898,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
// VERTICES
// there is a one-to-one corresponce between vertices and points
auto& js_vertices = js["vertices"] = json::array();
for (auto vh = arr.vertices_begin(); vh != arr.vertices_end(); ++vh)
{
for (auto vh = arr.vertices_begin(); vh != arr.vertices_end(); ++vh) {
json js_vertex;
auto vpos = vertex_pos_map[vh];
js_vertex["point"] = vpos;
@ -999,8 +949,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
//std::map<void*, int> edge_pos_map;
std::map<void*, int> halfedge_pos_map;
//Edge_const_iterator eit;
for (auto eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
{
for (auto eit = arr.edges_begin(); eit != arr.edges_end(); ++eit) {
auto& edge = *eit;
//auto it = edge_pos_map.find(&edge);
//if (it == edge_pos_map.end())
@ -1037,14 +986,10 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
int num_found = 0;
int num_not_found = 0;
std::map<Face_handle, std::string> face_name_map;
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh)
{
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh) {
// skip the spherical face
std::cout << "num outer_ccbs = " << fh->number_of_outer_ccbs() << std::endl;
if (fh->number_of_outer_ccbs() == 0)
{
continue;
}
if (fh->number_of_outer_ccbs() == 0) continue;
// construct the set of all node-ids for the current face
std::set<int> face_node_ids_set;
@ -1088,8 +1033,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
// RECORD FACES
json& js_faces = js["faces"] = json::array();
auto get_ccb_json = [&](Ext_aos::Ccb_halfedge_circulator first)
{
auto get_ccb_json = [&](Ext_aos::Ccb_halfedge_circulator first) {
json js_edges;
auto& ccb_edge_indices = js_edges["halfedges"] = json::array();
auto curr = first;
@ -1115,8 +1059,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
};
int total_num_half_edges = 0;
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh)
{
for (auto fh = arr.faces_begin(); fh != arr.faces_end(); ++fh) {
//// skip the spherical face
//if (fh->number_of_outer_ccbs() == 0)
// continue;
@ -1137,11 +1080,10 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
}
// INNER CCBS
if (fh->number_of_inner_ccbs() > 0)
{
if (fh->number_of_inner_ccbs() > 0) {
auto& js_inner_ccbs = js_face["inner_ccbs"] = json::array();
for (auto ccb = fh->inner_ccbs_begin(); ccb != fh->inner_ccbs_end(); ++ccb)
{
for (auto ccb = fh->inner_ccbs_begin(); ccb != fh->inner_ccbs_end();
++ccb) {
auto js_ccb = get_ccb_json(*ccb);
js_inner_ccbs.push_back(std::move(js_ccb));
}
@ -1158,9 +1100,7 @@ void Aos::save_arr(Kml::Placemarks& placemarks, const std::string& file_name)
#endif
}
namespace
{
namespace {
enum Error_id {
FILE_NOT_FOUND,
ILLEGAL_EXTENSION,
@ -1191,15 +1131,13 @@ namespace
//
struct country {
//! Constructor
country(std::string& name) :
m_name(std::move(name))
{}
country(std::string& name) : m_name(std::move(name)) {}
std::string m_name;
};
/*! Read a json file.
*/
*/
bool read_json(const std::string& filename, nlohmann::json& data) {
using json = nlohmann::json;
std::ifstream infile(filename);
@ -1216,6 +1154,8 @@ namespace
return true;
}
/*!
*/
template <typename FT>
FT to_ft(const nlohmann::json& js_ft) {
using Exact_type = typename FT::Exact_type;
@ -1226,16 +1166,15 @@ namespace
return FT(eft);
}
template <typename Arrangement_, typename Kernel_>
bool read_arrangement(const std::string& filename, Arrangement_& arr,
const Kernel_& kernel) {
template <typename Kernel_, typename Arrangement_>
bool read_arrangement(const std::string& filename, Arrangement_& arr) {
using Arrangement = Arrangement_;
using Kernel = Kernel_;
using json = nlohmann::json;
json data;
auto rc = read_json(filename, data);
if (!rc) return false;
if (! rc) return false;
// points
auto it = data.find("points");
@ -1502,45 +1441,35 @@ namespace
namespace {
/*!
*/
template<typename T>
Aos::Arr_handle get_handle(T* arr)
{
return Aos::Arr_handle(arr, [](void* ptr)
{
Aos::Arr_handle get_handle(T* arr) {
return Aos::Arr_handle(arr, [](void* ptr) {
std::cout << "*** DELETING THE ARRANGEMENT WITH SHARED_PTR DELETER!!\n";
delete reinterpret_cast<T*>(ptr);
});
}
}
Aos::Arr_handle Aos::load_arr(const std::string& file_name)
{
/*!
*/
Aos::Arr_handle Aos::load_arr(const std::string& file_name) {
auto* arr = new Countries_arr(&s_traits);
auto arrh = get_handle(arr);
Kernel kernel;
auto rc = read_arrangement(file_name, *arr, kernel);
if (!rc) {
return nullptr;
}
auto rc = read_arrangement<Kernel>(file_name, *arr);
if (! rc) return nullptr;
return arrh;
}
Aos::Arr_handle Aos::construct(Kml::Placemarks& placemarks)
{
Aos::Arr_handle Aos::construct(Kml::Placemarks& placemarks) {
auto* arr = new Arrangement(&s_traits);
auto arrh = get_handle(arr);
auto xcvs = get_arcs(placemarks, *arr);
for (auto& xcv : xcvs)
CGAL::insert(*arr, xcv);
for (auto& xcv : xcvs) CGAL::insert(*arr, xcv);
return arrh;
}
//std::vector<QVector3D> Aos::get_triangles(Arr_handle arrh)
//{
// using K = CGAL::Exact_predicates_inexact_constructions_kernel;
@ -1798,41 +1727,34 @@ Aos::Arr_handle Aos::construct(Kml::Placemarks& placemarks)
// return result;
//}
Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh)
{
Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh) {
auto& arr = *reinterpret_cast<Countries_arr*>(arrh.get());
// group the faces by their country name,
std::vector<std::string> all_countries;
std::vector<std::string> all_countries;
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)
{
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;
if (country_name.empty()) continue;
country_faces_map[country_name].push_back(&face);
all_countries.push_back(country_name);
}
// prepare a map of neighboring countries
std::map<std::string, std::set<std::string>> country_neighbors_map;
for (auto& [country_name, faces] : country_faces_map)
{
for (auto& [country_name, faces] : country_faces_map) {
// loop on all of the faces of the current country
for (auto* face : faces)
{
for (auto* face : faces) {
auto first = face->outer_ccb();
auto curr = first;
do {
const auto& neighbor_country_name = curr->twin()->face()->data();
// skip the spherical face
if (neighbor_country_name.empty())
continue;
if (neighbor_country_name.empty()) continue;
country_neighbors_map[country_name].insert(neighbor_country_name);
} while (++curr != first);
@ -1841,17 +1763,14 @@ Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh)
// find a color index for each country by looking at its neighbors
Country_color_map result;
for(const auto& country_name : all_countries)
{
for (const auto& country_name : all_countries) {
// first: find a free color index
bool color_used[5] = { false, false, false, false, false };
auto& neighbor_set = country_neighbors_map[country_name];
for (auto& neighbor : neighbor_set)
{
for (auto& neighbor : neighbor_set) {
auto it = result.find(neighbor);
// if there is a country in the map, then it must have been assigned one!
if (it != result.end())
{
if (it != result.end()) {
auto used_color_index = it->second;
color_used[used_color_index] = true;
}
@ -1859,25 +1778,21 @@ Aos::Country_color_map Aos::get_color_mapping(Arr_handle arrh)
// find the first color index not used
bool found = false;
for (int i = 0; i < 5; i++)
{
if (color_used[i] == false)
{
for (int i = 0; i < 5; ++i) {
if (! color_used[i]) {
found = true;
result[country_name] = i;
}
}
// assertion check!!!
if(!found)
if(! found)
std::cout << "*** ASSERTION ERROR: NO INDEX FOUND!!!\n";
}
return result;
}
std::string Aos::locate_country(Arr_handle arrh, const QVector3D& point)
{
std::string Aos::locate_country(Arr_handle arrh, const QVector3D& point) {
using Point_2 = Countries_arr::Point_2;
using Naive_pl = CGAL::Arr_naive_point_location<Countries_arr>;
@ -1903,55 +1818,47 @@ std::string Aos::locate_country(Arr_handle arrh, const QVector3D& point)
auto obj = npl.locate(query_point);
using Arrangement_2 = Countries_arr;
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
using Vertex_const_handle = typename Arrangement_2::Vertex_const_handle;
using Halfedge_const_handle = typename Arrangement_2::Halfedge_const_handle;
using Face_const_handle = typename Arrangement_2::Face_const_handle;
using Face_const_handle = typename Arrangement_2::Face_const_handle;
//const Vertex_const_handle* v;
//const Halfedge_const_handle* e;
//const Face_const_handle* f;
//std::cout << "The point (" << query_point << ") is located ";
std::string country_name = "";
if (auto f = std::get_if<Face_const_handle>(&obj)) // located inside a face
{
if (auto f = std::get_if<Face_const_handle>(&obj)) { // located inside a face
//std::cout << "*** QUERY: FACE\n";
country_name = f->ptr()->data();
}
else if (auto e = std::get_if<Halfedge_const_handle>(&obj))
{
else if (auto e = std::get_if<Halfedge_const_handle>(&obj)) {
// located on an edge: return one of the incident face arbitrarily
//std::cout << "*** QUERY: EDGE\n";
country_name = (*e)->face()->data();
}
else if (auto v = std::get_if<Vertex_const_handle>(&obj))
{
else if (auto v = std::get_if<Vertex_const_handle>(&obj)) {
// located on a vertex
if ((*v)->is_isolated())
{
if ((*v)->is_isolated()) {
//std::cout << "*** QUERY: ISOLATED VERTEX\n";
country_name = (*v)->face()->data();
}
else
{
else {
//std::cout << "*** QUERY: VERTEX\n";
country_name = (*v)->incident_halfedges()->face()->data();
}
}
else
{
else {
CGAL_error_msg("Invalid object.");
}
return country_name;
}
Aos::Approx_arcs Aos::get_approx_arcs_from_faces_edges(Arr_handle arrh,
float error)
{
Aos::Approx_arcs
Aos::get_approx_arcs_from_faces_edges(Arr_handle arrh, float error) {
auto& arr = *reinterpret_cast<Countries_arr*>(arrh.get());
auto ctr_cv = s_traits.construct_curve_2_object();
Curves xcvs;
for (auto eit = arr.halfedges_begin(); eit != arr.halfedges_end(); ++eit)
{
for (auto eit = arr.halfedges_begin(); eit != arr.halfedges_end(); ++eit) {
auto& s = eit->curve();
xcvs.push_back( ctr_cv(s.source(), s.target()) );
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -17,9 +17,7 @@
#include "Kml_reader.h"
class Aos
{
class Aos {
public:
using Approx_arc = std::vector<QVector3D>;
using Approx_arcs = std::vector<Approx_arc>;
@ -32,8 +30,8 @@ public:
static Approx_arcs get_approx_arcs(double error);
// this is used to construct approximate arcs from KML-Placemark data
static Approx_arcs get_approx_arcs(const Kml::Placemark& placemark, double error);
static Approx_arcs get_approx_arcs(const Kml::Placemark& placemark,
double error);
static void get_curves();
@ -45,7 +43,7 @@ public:
// OUTPUT: vertices created during arrangement construction
static std::vector<QVector3D> ext_check(const Kml::Placemarks& placemarks);
// Same as above function but works by identifying the duplicate nodes
// Same as above function but works by identifying the duplicate nodes
static std::vector<QVector3D> ext_check_id_based(Kml::Placemarks& placemarks);
// This function is used to find the newly-created faces during arrangement
@ -59,7 +57,7 @@ public:
static Approx_arcs find_new_faces(Kml::Placemarks& placemarks);
// save the arrangement created with EPEC
static void save_arr(Kml::Placemarks& placemarks,
static void save_arr(Kml::Placemarks& placemarks,
const std::string& file_name);
// loads the arrangement created by the save_arr function
@ -79,9 +77,8 @@ public:
// this will get the approximate arcs of face-edges from the arrangement
// NOTE: this is similar to "get_approx_arcs(KML::Placemarks&, float)" above!
static Approx_arcs get_approx_arcs_from_faces_edges(Arr_handle arrh,
static Approx_arcs get_approx_arcs_from_faces_edges(Arr_handle arrh,
float error);
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -18,7 +18,6 @@
#include <CGAL/Arr_spherical_topology_traits_2.h>
#include <CGAL/Vector_3.h>
//#define USE_EPIC
#ifdef USE_EPIC
@ -40,9 +39,9 @@ using Vertex_handle = Arrangement::Vertex_handle;
// COUNTRIES AOS for grouping the faces by the country name
using Countries_dcel = CGAL::Arr_face_extended_dcel<Geom_traits, std::string>;
using Countries_topol_traits =
CGAL::Arr_spherical_topology_traits_2<Geom_traits, Countries_dcel>;
CGAL::Arr_spherical_topology_traits_2<Geom_traits, Countries_dcel>;
using Countries_arr =
CGAL::Arrangement_on_surface_2<Geom_traits, Countries_topol_traits>;
CGAL::Arrangement_on_surface_2<Geom_traits, Countries_topol_traits>;
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -7,25 +7,19 @@
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "Aos_triangulator.h"
#include <iostream>
#include <iterator>
#include <map>
#include <set>
#include <vector>
#include <unordered_map>
#include <boost/property_map/property_map.hpp>
#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>
@ -34,28 +28,27 @@ using json = nlohmann::ordered_json;
#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>
#include "Aos_defs.h"
#include "Aos_triangulator.h"
//#include "arr_print.h"
//#include "Tools.h"
using json = nlohmann::ordered_json;
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)
{
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)
{
std::ostream& operator << (std::ostream& os, const Approximate_point_2& d) {
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
@ -67,10 +60,8 @@ namespace {
using Direction_3 = Kernel::Direction_3;
}
std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
{
//! \brief
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>;
@ -90,8 +81,7 @@ std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
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)
{
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;
@ -118,21 +108,17 @@ std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
std::cout << "triangulating individual faces\n";
// loop on all approximated faces
for (auto& face_points : all_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)
{
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;
for (const auto& fp : face_points) centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
@ -145,8 +131,7 @@ std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points)
{
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);
@ -162,24 +147,22 @@ std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
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> >
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())
{
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;
if (false == get(in_domain, f)) continue;
for (int i = 0; i < 3; ++i)
{
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());
@ -192,9 +175,8 @@ std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh)
return triangles;
}
Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
{
//! \brief
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>;
@ -212,8 +194,7 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
// 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)
{
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit) {
auto& face = *fit;
const auto& country_name = fit->data();
// skipping spherical-face
@ -223,18 +204,15 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
}
std::cout << "triangulating individual faces\n";
Country_triangles_map result;
for (auto& [country_name, faces] : country_faces_map)
{
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)
{
for (auto* face : faces) {
// skip any face with no OUTER-CCB
if (0 == face->number_of_outer_ccbs())
continue;
if (0 == face->number_of_outer_ccbs()) continue;
std::vector<QVector3D> face_points;
// loop on the egdes of the current outer-ccb
@ -253,13 +231,12 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
// 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)
{
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());
if (face_points.size() == 3) {
triangles.insert(triangles.end(), face_points.begin(),
face_points.end());
continue;
}
@ -279,8 +256,7 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points)
{
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);
@ -296,7 +272,8 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(), true);
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> >
@ -306,14 +283,11 @@ Country_triangles_map Aos_triangulator::get_by_country(Aos::Arr_handle arrh)
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())
{
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;
if (false == get(in_domain, f)) continue;
for (int i = 0; i < 3; ++i)
{
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());

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -17,16 +17,12 @@
#include "Aos.h"
using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>;
class Aos_triangulator
{
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);
};

View File

@ -1,14 +1,20 @@
cmake_minimum_required(VERSION 3.16)
cmake_minimum_required(VERSION 3.1...3.23)
project(earth LANGUAGES CXX)
if(NOT DEFINED INSTALL_EXAMPLESDIR)
set(INSTALL_EXAMPLESDIR "examples")
if(NOT POLICY CMP0070 AND POLICY CMP0053)
# Only set CMP0053 to OLD with CMake<3.10, otherwise there is a warning.
cmake_policy(SET CMP0053 OLD)
endif()
set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/opengl/earth")
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL OpenGLWidgets Widgets Xml)
add_definitions(-DQT_NO_VERSION_TAGGING)
# if(NOT DEFINED INSTALL_EXAMPLESDIR)
# set(INSTALL_EXAMPLESDIR "examples")
# endif()
# set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/opengl/earth")
# CGAL and its components
find_package(CGAL QUIET COMPONENTS)
@ -18,6 +24,9 @@ if (NOT CGAL_FOUND)
return()
endif()
find_package(Qt6 REQUIRED COMPONENTS Core Gui OpenGL OpenGLWidgets Widgets Xml)
add_definitions(-DQT_NO_VERSION_TAGGING)
# Boost and its components
find_package(Boost REQUIRED)
@ -44,7 +53,6 @@ source_group("Aos" FILES ${source_files_aos})
# GIS
file(GLOB source_files_gis
Kml_reader.h Kml_reader.cpp
Shapefile.h Shapefile.cpp
)
source_group("GIS" FILES ${source_files_gis})

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,16 +9,15 @@
#include "Camera.h"
//! \brief
Camera::Camera() :
m_ux(1, 0, 0),
m_uy(0, 1, 0),
m_uz(0, 0, 1)
{
}
{}
void Camera::perspective(float fov, float aspect, float z_near, float z_far)
{
//! \brief
void Camera::perspective(float fov, float aspect, float z_near, float z_far) {
m_z_near = z_near;
m_z_far = z_far;
@ -26,18 +25,16 @@ void Camera::perspective(float fov, float aspect, float z_near, float z_far)
m_projection.perspective(fov, aspect, z_near, z_far);
}
QMatrix4x4 Camera::get_view_matrix() const
{
//! \brief
QMatrix4x4 Camera::get_view_matrix() const {
QMatrix4x4 view;
const QVector3D center = m_pos - m_uz;
view.lookAt(m_pos, center, m_uy);
return view;
}
void Camera::rotate_from_init_config(float theta, float phi)
{
//! \brief
void Camera::rotate_from_init_config(float theta, float phi) {
// TO-DO: use the following logic to eliminate the QT-deprecation warnings!
//QMatrix4x4 rot;
//rot.rotate(theta, m_ux);
@ -72,32 +69,32 @@ void Camera::rotate_from_init_config(float theta, float phi)
m_uz = r.map(QVector3D(0, 0, 1));
}
void Camera::rotate(QMatrix4x4 rot)
{
//! \brief
void Camera::rotate(QMatrix4x4 rot) {
m_pos = rot.map(m_pos);
m_ux = rot.map(m_ux);
m_uy = rot.map(m_uy);
m_uz = rot.map(m_uz);
}
void Camera::save_config()
{
//! \brief
void Camera::save_config() {
m_saved_pos = m_pos;
m_saved_ux = m_ux;
m_saved_uy = m_uy;
m_saved_uz = m_uz;
}
void Camera::rotate_from_saved_config(QMatrix4x4 rot)
{
//! \brief
void Camera::rotate_from_saved_config(QMatrix4x4 rot) {
m_pos = rot.map(m_saved_pos);
m_ux = rot.map(m_saved_ux);
m_uy = rot.map(m_saved_uy);
m_uz = rot.map(m_saved_uz);
}
void Camera::move_forward(float distance)
{
//! \brief
void Camera::move_forward(float distance) {
// recall that in OpenGL camera model, camera's z-axis points always
// out of the screen (towards the user).
m_pos -= distance * m_uz;

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -10,15 +10,11 @@
#ifndef CAMERA_H
#define CAMERA_H
#include <qvector3d.h>
#include <qmatrix4x4.h>
class Camera
{
class Camera {
public:
Camera();
void set_pos(const QVector3D& pos) { m_pos = pos; }
@ -30,7 +26,7 @@ public:
float get_z_near() const { return m_z_near; }
QMatrix4x4 get_view_matrix() const;
QMatrix4x4 get_projection_matrix() const { return m_projection; }
// theta: angle around y-axis
// phi: angle from the xz-plane (= rotated x-axis after the above rotation)
void rotate_from_init_config(float theta, float phi);
@ -59,5 +55,4 @@ private:
QMatrix4x4 m_projection;
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University(Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,8 +9,4 @@
#include "Camera_manip.h"
Camera_manip::Camera_manip(Camera& camera) :
m_camera(camera)
{
}
Camera_manip::Camera_manip(Camera& camera) : m_camera(camera) {}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -16,9 +16,7 @@
#include "Camera.h"
#include "GUI_event_handler.h"
class Camera_manip : public GUI_event_handler
{
class Camera_manip : public GUI_event_handler {
public:
Camera_manip(Camera& camera);

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,20 +9,13 @@
#include "Camera_manip_rot.h"
Camera_manip_rot::Camera_manip_rot(Camera& camera) : Camera_manip(camera) {}
Camera_manip_rot::Camera_manip_rot(Camera& camera) :
Camera_manip(camera)
{
}
void Camera_manip_rot::mouse_move_event(QMouseEvent* e)
{
if (m_left_mouse_button_down)
{
void Camera_manip_rot::mouse_move_event(QMouseEvent* e) {
if (m_left_mouse_button_down) {
const float rotation_scale_factor = 0.1f;
m_theta += rotation_scale_factor * m_diff.x();
m_phi += rotation_scale_factor * m_diff.y();
m_camera.rotate_from_init_config(-m_theta, -m_phi);
}
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,9 +15,7 @@
#include "Camera_manip.h"
class Camera_manip_rot : public Camera_manip
{
class Camera_manip_rot : public Camera_manip {
public:
Camera_manip_rot(Camera& camera);
@ -25,7 +23,8 @@ protected:
virtual void mouse_move_event(QMouseEvent* e) override;
private:
float m_theta = 0, m_phi = 0;
float m_theta = 0;
float m_phi = 0;
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,22 +9,19 @@
#include "Camera_manip_rot_bpa.h"
Camera_manip_rot_bpa::Camera_manip_rot_bpa(Camera& camera) :
//! \brief
Camera_manip_rot_bpa::Camera_manip_rot_bpa(Camera& camera) :
Camera_manip(camera)
{
{}
//! \brief
void Camera_manip_rot_bpa::mouse_press_event(QMouseEvent* e) {
// for the backprojected diff-vector method:
if (m_left_mouse_button_down) m_camera.save_config();
}
void Camera_manip_rot_bpa::mouse_press_event(QMouseEvent* e)
{
// for the backprojected diff-vector method:
if (m_left_mouse_button_down)
{
m_camera.save_config();
}
}
void Camera_manip_rot_bpa::mouse_move_event(QMouseEvent* e)
{
//! \brief
void Camera_manip_rot_bpa::mouse_move_event(QMouseEvent* e) {
const float rotation_scale_factor = 0.1f;
// ROTATION AROUND AN AXIS ORTHOGONAL TO THE BACKPROJECTED DIF-VECTOR
@ -52,14 +49,13 @@ void Camera_manip_rot_bpa::mouse_move_event(QMouseEvent* e)
rot_matrix.rotate(-rot_angle, rot_axis);
m_camera.rotate_from_saved_config(rot_matrix);
}
}
void Camera_manip_rot_bpa::mouse_release_event(QMouseEvent* e)
{
}
void Camera_manip_rot_bpa::resize(int w, int h)
{
//! \brief
void Camera_manip_rot_bpa::mouse_release_event(QMouseEvent* e) {}
//! \brief
void Camera_manip_rot_bpa::resize(int w, int h) {
m_vp_width = w;
m_vp_height = h;
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,9 +15,7 @@
#include "Camera_manip.h"
class Camera_manip_rot_bpa : public Camera_manip
{
class Camera_manip_rot_bpa : public Camera_manip {
public:
Camera_manip_rot_bpa(Camera& camera);

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -11,26 +11,19 @@
#include "Message_manager.h"
Camera_manip_zoom::Camera_manip_zoom(Camera& camera) : Camera_manip(camera) {}
Camera_manip_zoom::Camera_manip_zoom(Camera& camera) :
Camera_manip(camera)
{
}
void Camera_manip_zoom::mouse_move_event(QMouseEvent* e)
{
if (m_middle_mouse_button_down)
{
//! \brief
void Camera_manip_zoom::mouse_move_event(QMouseEvent* e) {
if (m_middle_mouse_button_down) {
const float zoom_scale_factor = 0.01f;
const auto distance = zoom_scale_factor * m_diff.y();
m_camera.move_forward(distance);
}
}
void Camera_manip_zoom::mouse_release_event(QMouseEvent* e)
{
if (e->button() == Qt::MiddleButton)
{
Message_manager::notify_all("zoom_changed");
}
}
//! \brief
void Camera_manip_zoom::mouse_release_event(QMouseEvent* e) {
if (e->button() == Qt::MiddleButton)
Message_manager::notify_all("zoom_changed");
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,17 +15,13 @@
#include "Camera_manip.h"
class Camera_manip_zoom : public Camera_manip
{
class Camera_manip_zoom : public Camera_manip {
public:
Camera_manip_zoom(Camera& camera);
protected:
virtual void mouse_move_event(QMouseEvent* e) override;
virtual void mouse_release_event(QMouseEvent* e) override;
private:
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -10,14 +10,9 @@
#ifndef COMMON_DEFS_H
#define COMMON_DEFS_H
#include <qopenglfunctions_3_3_core.h>
//#include <qopenglfunctions_4_5_core.h>
using OpenGLFunctionsBase = QOpenGLFunctions_3_3_Core;
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -11,19 +11,16 @@
//#include <qvector3d.h>
//! \brief
GUI_country_pick_handler::GUI_country_pick_handler(Main_widget& main_widget) :
m_main_widget(main_widget),
m_camera(main_widget.get_camera())
{
{}
}
void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e)
{
//! \brief
void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e) {
// handle country selection
if (e->button() == Qt::RightButton)
{
if (e->button() == Qt::RightButton) {
auto p = e->pos();
QVector3D sp0(p.x(), m_vp_height - p.y(), 0);
QVector3D sp1(p.x(), m_vp_height - p.y(), 1);
@ -51,30 +48,23 @@ void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e)
auto d = b * b - 4 * a * c;
float ti = -1;
if (abs(d) < std::numeric_limits<float>::epsilon())
{
if (abs(d) < std::numeric_limits<float>::epsilon()) {
// single intersection
ti = -b / (2 * a);
}
else
{
if (d < 0)
{
else {
if (d < 0) {
// no intersection
return;
}
else
{
else {
// two intersections
auto sd = sqrt(d);
auto t1 = (-b - sd) / (2 * a);
auto t2 = (-b + sd) / (2 * a);
if (t1 > 0 && t2 > 0)
ti = std::min(t1, t2);
else if (t1 > 0)
ti = t1;
else
ti = t2;
if (t1 > 0 && t2 > 0) ti = std::min(t1, t2);
else if (t1 > 0) ti = t1;
else ti = t2;
}
}
@ -110,8 +100,9 @@ void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e)
// prev_picked_country = picked_country;
}
}
void GUI_country_pick_handler::resize(int w, int h)
{
//! \brief
void GUI_country_pick_handler::resize(int w, int h) {
m_vp_width = w;
m_vp_height = h;
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -16,19 +16,18 @@
#include "GUI_event_handler.h"
#include "Main_widget.h"
class GUI_country_pick_handler : public GUI_event_handler
{
class GUI_country_pick_handler : public GUI_event_handler {
public:
GUI_country_pick_handler(Main_widget& main_widget);
protected:
virtual void mouse_press_event(QMouseEvent* e) override;
virtual void resize(int w, int h) override;
Main_widget& m_main_widget;
Camera& m_camera;
int m_vp_width, m_vp_height;
Main_widget& m_main_widget;
Camera& m_camera;
int m_vp_width;
int m_vp_height;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,30 +9,31 @@
#include "GUI_event_handler.h"
void GUI_event_handler::set_mouse_button_pressed_flag(QMouseEvent* e, bool flag)
{
switch (e->button())
{
case Qt::LeftButton:
//! \brief
void
GUI_event_handler::set_mouse_button_pressed_flag(QMouseEvent* e, bool flag) {
switch (e->button()) {
case Qt::LeftButton:
m_left_mouse_button_down = flag;
break;
case Qt::MiddleButton:
case Qt::MiddleButton:
m_middle_mouse_button_down = flag;
break;
}
}
void GUI_event_handler::mousePressEvent(QMouseEvent* e)
{
//! \brief
void GUI_event_handler::mousePressEvent(QMouseEvent* e) {
set_mouse_button_pressed_flag(e, true);
m_mouse_press_pos = m_last_mouse_pos = QVector2D(e->position());
// call the function overridden by the derived class
mouse_press_event(e);
}
void GUI_event_handler::mouseMoveEvent(QMouseEvent* e)
{
//! \brief
void GUI_event_handler::mouseMoveEvent(QMouseEvent* e) {
m_current_mouse_pos = QVector2D(e->position());
m_diff = m_current_mouse_pos - m_last_mouse_pos;
@ -41,15 +42,14 @@ void GUI_event_handler::mouseMoveEvent(QMouseEvent* e)
m_last_mouse_pos = m_current_mouse_pos;
}
void GUI_event_handler::mouseReleaseEvent(QMouseEvent* e)
{
//! \brief
void GUI_event_handler::mouseReleaseEvent(QMouseEvent* e) {
set_mouse_button_pressed_flag(e, false);
// call the function overridden by the derived class
mouse_release_event(e);
}
void GUI_event_handler::resizeGL(int w, int h)
{
resize(w, h);
}
//! \brief
void GUI_event_handler::resizeGL(int w, int h) { resize(w, h); }

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -13,9 +13,7 @@
#include <qevent.h>
#include <qvector2d.h>
class GUI_event_handler
{
class GUI_event_handler {
public:
virtual ~GUI_event_handler() {};
@ -32,7 +30,6 @@ protected:
virtual void mouse_release_event(QMouseEvent* e) {}
virtual void resize(int w, int h) {}
bool m_left_mouse_button_down = false;
bool m_middle_mouse_button_down = false;
QVector2D m_current_mouse_pos;

View File

@ -1,5 +1,11 @@
#include "Geodesic_arcs.h"
// Copyright(c) 2023, 2024 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 <iostream>
#include <iterator>
@ -15,47 +21,40 @@
#include <CGAL/Vector_3.h>
#include "arr_print.h"
#include "Geodesic_arcs.h"
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Geom_traits = CGAL::Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
using Point = Geom_traits::Point_2;
using Curve = Geom_traits::Curve_2;
using Topol_traits = CGAL::Arr_spherical_topology_traits_2<Geom_traits>;
using Arrangement = CGAL::Arrangement_on_surface_2<Geom_traits, Topol_traits>;
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
using Geom_traits = CGAL::Arr_geodesic_arc_on_sphere_traits_2<Kernel>;
using Point = Geom_traits::Point_2;
using Curve = Geom_traits::Curve_2;
using Topol_traits = CGAL::Arr_spherical_topology_traits_2<Geom_traits>;
using Arrangement = CGAL::Arrangement_on_surface_2<Geom_traits, Topol_traits>;
using Dir3 = Kernel::Direction_3 ;
std::ostream& operator << (std::ostream& os, const Dir3& d)
{
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)
{
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_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;
using Direction_3 = Kernel::Direction_3;
std::ostream& operator << (std::ostream& os, const Approximate_Vector_3& v)
{
std::ostream& operator << (std::ostream& os, const Approximate_Vector_3& v) {
os << v.x() << ", " << v.y() << ", " << v.z();
//os << v.hx() << ", " << v.hy() << ", " << v.hz() << ", " << v.hw();
return os;
}
Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(double error)
{
auto Geodesic_arcs::get_approx_arcs(double error) -> Approx_arcs {
// Construct the arrangement from 12 geodesic arcs.
Geom_traits traits;
Arrangement arr(&traits);
@ -63,8 +62,7 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(double error)
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
std::vector<Curve> xcvs;
std::vector<Curve> xcvs;
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)));
@ -73,37 +71,31 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(double error)
auto approx = traits.approximate_2_object();
std::vector<std::vector<QVector3D>> arcs;
for (const auto& xcv : xcvs)
{
std::vector<std::vector<QVector3D>> arcs;
for (const auto& xcv : xcvs) {
std::vector<Approximate_point_2> v;
auto oi2 = approx(xcv, error, std::back_insert_iterator(v));
std::vector<QVector3D> arc_points;
for (const auto& p : v)
{
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;
}
Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
placemark, double error)
{
auto Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
placemark, double error) -> Approx_arcs {
Geom_traits traits;
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
std::vector<Curve> xcvs;
for (const auto& polygon : placemark.polygons)
{
for (const auto& polygon : placemark.polygons) {
// colect all rings into a single list (FOR NOW!!!)
// TO-DO: PROCESS OUTER & INNER BOUNDARIES SEPARATELY!!!
Kml::LinearRings linear_rings;
@ -113,11 +105,9 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
// convert the nodes to points on unit-sphere
for (const auto& lring : linear_rings)
{
std::vector<Approximate_Vector_3> sphere_points;
for (const auto& node : lring.nodes)
{
for (const auto& lring : linear_rings) {
std::vector<Approximate_Vector_3> sphere_points;
for (const auto& node : lring.nodes) {
const auto p = node.get_coords_3d();
Approximate_Vector_3 v(p.x, p.y, p.z);
sphere_points.push_back(v);
@ -125,8 +115,7 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
// add geodesic arcs for the current LinearRing
int num_points = sphere_points.size();
for (int i = 0; i < num_points - 1; i++)
{
for (int i = 0; i < num_points - 1; ++i) {
const auto p1 = sphere_points[i];
const auto p2 = sphere_points[i + 1];
xcvs.push_back(ctr_cv(ctr_p(p1.x(), p1.y(), p1.z()),
@ -137,14 +126,12 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
auto approx = traits.approximate_2_object();
std::vector<std::vector<QVector3D>> arcs;
for (const auto& xcv : xcvs)
{
for (const auto& xcv : xcvs) {
std::vector<Approximate_point_2> v;
auto oi2 = approx(xcv, error, std::back_insert_iterator(v));
std::vector<QVector3D> arc_points;
for (const auto& p : v)
{
for (const auto& p : v) {
const QVector3D arc_point(p.dx(), p.dy(), p.dz());
arc_points.push_back(arc_point);
}
@ -182,7 +169,7 @@ Geodesic_arcs::Approx_arcs Geodesic_arcs::get_approx_arcs(const Kml::Placemark&
// {
// 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()),
// xcvs.push_back(ctr_cv(ctr_p(p1.x(), p1.y(), p1.z()),
// ctr_p(p2.x(), p2.y(), p2.z())));
// }
// }

View File

@ -1,3 +1,11 @@
// Copyright(c) 2023, 2024 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 GEODESIC_ARCS_H
#define GEODESIC_ARCS_H
@ -7,15 +15,12 @@
#include "Kml_reader.h"
class Geodesic_arcs
{
class Geodesic_arcs {
public:
using Approx_arcs = std::vector<std::vector<QVector3D>>;
Approx_arcs get_approx_arcs(double error);
// generate approximate arcs from KML data
Approx_arcs get_approx_arcs(const Kml::Placemark& placemark, double error);
Approx_arcs get_approx_arcs(const Kml::Placemarks& placemarks, double error);

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -17,20 +17,19 @@
#include <qfile.h>
#include <qxmlstream.h>
double Kml::Node::distance_to(const Node& r) const
{
//! \brief
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);
}
//! \brief
bool Kml::Node::operator == (const Node& r) const
{
return (lon == r.lon) && (lat == r.lat);
}
Kml::Vec3d Kml::Node::get_coords_3d(const double r) const
{
{ return (lon == r.lon) && (lat == r.lat); }
//! \brief
Kml::Vec3d Kml::Node::get_coords_3d(const double r) const {
const long double phi = qDegreesToRadians(lat);
const long double theta = qDegreesToRadians(lon);
const auto z = r * std::sin(phi);
@ -40,71 +39,61 @@ Kml::Vec3d Kml::Node::get_coords_3d(const double r) const
return Vec3d{ (double)x, (double)y, (double)z };
}
QVector3D Kml::Node::get_coords_3f(const double r) const
{
//! \brief
QVector3D Kml::Node::get_coords_3f(const double r) const {
const auto v = get_coords_3d(r);
return QVector3D(v.x, v.y, v.z);
}
std::ostream& operator << (std::ostream& os, const Kml::Node& n)
{
//! \brief
std::ostream& operator << (std::ostream& os, const Kml::Node& n) {
os << n.lon << ", " << n.lat;
return os;
}
int Kml::get_number_of_polygons(Placemarks& placemarks)
{
//! \brief
int Kml::get_number_of_polygons(Placemarks& placemarks) {
int total_number_of_polygons = 0;
for (auto& placemark : placemarks)
{
total_number_of_polygons += placemark.polygons.size();
}
return total_number_of_polygons;
}
Kml::Placemarks Kml::read(const std::string& file_name)
{
LinearRing lring;
Polygon polygon;
Placemark placemark;
Placemarks placemarks;
//! \brief
Kml::Placemarks Kml::read(const std::string& file_name) {
LinearRing lring;
Polygon polygon;
Placemark placemark;
Placemarks placemarks;
QFile file(file_name.c_str());
if (file.open(QIODevice::ReadOnly))
{
if (file.open(QIODevice::ReadOnly)) {
QXmlStreamReader xmlReader;
xmlReader.setDevice(&file);
xmlReader.readNext();
// Reading from the file
while (!xmlReader.isEndDocument())
{
while (!xmlReader.isEndDocument()) {
QString name = xmlReader.name().toString();
if (xmlReader.isStartElement())
{
if (name == "Placemark")
{
if (xmlReader.isStartElement()) {
if (name == "Placemark") {
placemark = Placemark{};
}
else if (name == "Polygon")
{
else if (name == "Polygon") {
polygon = Polygon{};
}
else if (name == "LinearRing")
{
else if (name == "LinearRing") {
lring = LinearRing{};
}
else if (name == "coordinates")
{
else if (name == "coordinates") {
xmlReader.readNext();
auto str = xmlReader.text().toString();
auto node_strs = str.split(" ");
for (const auto& node_str : node_strs)
{
if (node_str.isEmpty())
continue;
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();
@ -112,8 +101,7 @@ Kml::Placemarks Kml::read(const std::string& file_name)
lring.nodes.push_back(Node{ lon, lat });
}
}
else if (name == "SimpleData")
{
else if (name == "SimpleData") {
auto attributes = xmlReader.attributes();
auto attr_name = attributes[0].name().toString();
auto attr_value = attributes[0].value().toString();
@ -124,31 +112,25 @@ Kml::Placemarks Kml::read(const std::string& file_name)
}
}
}
else if (xmlReader.isEndElement())
{
else if (xmlReader.isEndElement()) {
if (name == "Placemark")
{
placemarks.push_back(std::move(placemark));
}
else if (name == "Polygon")
{
else if (name == "Polygon") {
placemark.polygons.push_back(std::move(polygon));
}
else if (name == "outerBoundaryIs")
{
else if (name == "outerBoundaryIs") {
polygon.outer_boundary = std::move(lring);
}
else if (name == "innerBoundaryIs")
{
else if (name == "innerBoundaryIs") {
polygon.inner_boundaries.push_back(std::move(lring));
}
else if (name == "LinearRing")
{
else if (name == "LinearRing") {
// LinearRing is moved to the correct locations via other tags above
assert(*lring.nodes.begin() == *(--lring.nodes.end()));
}
else if (name == "coordinates")
{
else if (name == "coordinates") {
// no need to do anything here: the coordinates are read above!
}
}
@ -156,8 +138,7 @@ Kml::Placemarks Kml::read(const std::string& file_name)
xmlReader.readNext();
}
if (xmlReader.hasError())
{
if (xmlReader.hasError()) {
std::cout << "XML error: " << xmlReader.errorString().data() << std::endl;
}
}
@ -165,26 +146,22 @@ Kml::Placemarks Kml::read(const std::string& file_name)
return placemarks;
}
Kml::Nodes Kml::get_duplicates(const Placemarks& placemarks)
{
//! \brief
Kml::Nodes Kml::get_duplicates(const Placemarks& placemarks) {
// collect all nodes into a single vector
int polygon_count = 0;
std::vector<Kml::Node> nodes;
for (const auto& pm : placemarks)
{
for (const auto& polygon : pm.polygons)
{
for (const auto& pm : placemarks) {
for (const auto& polygon : pm.polygons) {
polygon_count++;
Kml::LinearRings linear_rings;
linear_rings.push_back(polygon.outer_boundary);
for (const auto& inner_boundary : polygon.inner_boundaries)
linear_rings.push_back(inner_boundary);
for(const auto& lring : linear_rings)
{
for (const auto& node : lring.nodes)
nodes.push_back(node);
for(const auto& lring : linear_rings) {
for (const auto& node : lring.nodes) nodes.push_back(node);
}
}
}
@ -199,38 +176,30 @@ Kml::Nodes Kml::get_duplicates(const Placemarks& placemarks)
std::unordered_map<int, int> dup_count_map;
Nodes duplicate_nodes;
for (int i = 0; i < count; ++i)
{
for (int i = 0; i < count; ++i) {
// if the current node has been detected as duplicate skip it
if (num_duplicates[i] > 0)
continue;
const auto& curr_node = nodes[i];
std::vector<int> curr_dup; // current set of duplicates
for (int j = i + 1; j < count; ++j)
{
if (curr_node == nodes[j])
{
curr_dup.push_back(j);
}
for (int j = i + 1; j < count; ++j) {
if (curr_node == nodes[j]) curr_dup.push_back(j);
}
// if duplicates found
if (!curr_dup.empty())
{
if (!curr_dup.empty()) {
dup_count++;
int num_dup = curr_dup.size() + 1; // +1 for the i'th node
num_duplicates[i] = num_dup;
for (const auto di : curr_dup)
num_duplicates[di] = num_dup;
for (const auto di : curr_dup) num_duplicates[di] = num_dup;
duplicate_nodes.push_back(curr_node);
dup_count_map[num_dup]++;
}
}
qDebug() << "dup count = " << dup_count;
for (const auto& p : dup_count_map)
{
for (const auto& p : dup_count_map) {
const auto dup_count = p.first;
const auto num_nodes_with_this_dup_count = p.second;
qDebug() << dup_count << ": " << num_nodes_with_this_dup_count;
@ -239,16 +208,13 @@ Kml::Nodes Kml::get_duplicates(const Placemarks& placemarks)
return duplicate_nodes;
}
Kml::Nodes Kml::generate_ids(Placemarks& placemarks)
{
//! \brief
Kml::Nodes Kml::generate_ids(Placemarks& placemarks) {
// collect all nodes into a single vector
int polygon_count = 0;
std::vector<Node> nodes;
for (auto& pm : placemarks)
{
for (auto& polygon : pm.polygons)
{
for (auto& pm : placemarks) {
for (auto& polygon : pm.polygons) {
polygon_count++;
std::vector<LinearRing*> linear_rings;
@ -256,34 +222,27 @@ Kml::Nodes Kml::generate_ids(Placemarks& placemarks)
for (auto& inner_boundary : polygon.inner_boundaries)
linear_rings.push_back(&inner_boundary);
for (auto* lring : linear_rings)
{
for (const auto& node : lring->nodes)
{
for (auto* lring : linear_rings) {
for (const auto& node : lring->nodes) {
// check if the node is in the nodes
auto it = std::find(nodes.begin(), nodes.end(), node);
if (nodes.end() == it)
{
if (nodes.end() == it) {
// insert new node
nodes.push_back(node);
const int node_id = nodes.size() - 1;
lring->ids.push_back(node_id);
}
else
{
else {
// get the existing node
const int node_id = std::distance(nodes.begin(), it);
lring->ids.push_back(node_id);
assert(nodes[node_id] == node);
}
}
assert(lring->nodes.size() == lring->ids.size());
for (int i = 0; i < lring->nodes.size(); ++i)
{
assert(lring->nodes[i] == nodes[lring->ids[i]]);
}
}
}
}
@ -291,15 +250,13 @@ Kml::Nodes Kml::generate_ids(Placemarks& placemarks)
return nodes;
}
Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps)
{
//! \breif
Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps) {
// collect all nodes into a single vector
int polygon_count = 0;
std::vector<Node> nodes;
for (auto& pm : placemarks)
{
for (auto& polygon : pm.polygons)
{
for (auto& pm : placemarks) {
for (auto& polygon : pm.polygons) {
polygon_count++;
std::vector<LinearRing*> linear_rings;
@ -307,34 +264,27 @@ Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps)
for (auto& inner_boundary : polygon.inner_boundaries)
linear_rings.push_back(&inner_boundary);
for (auto* lring : linear_rings)
{
for (auto* lring : linear_rings) {
lring->ids.clear();
for (const auto& node : lring->nodes)
{
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)
{
for (int i = 0; i < nodes.size(); ++i) {
const auto dist = node.distance_to(nodes[i]);
if (dist < eps)
{
if (dist < eps) {
node_index = i;
break;
}
}
if (node_index < 0)
{
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
{
else {
// get the existing node
const int node_id = node_index;
lring->ids.push_back(node_id);
@ -354,13 +304,10 @@ Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps)
double min_dist = std::numeric_limits<double>::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)
{
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)
{
if (min_dist > dist) {
min_dist = dist;
ni1 = i;
ni2 = j;
@ -376,16 +323,14 @@ Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps)
return nodes;
}
Kml::Nodes Kml::Polygon::get_all_nodes() const
{
//! \brief
Kml::Nodes Kml::Polygon::get_all_nodes() const {
Nodes all_nodes;
auto source_first = outer_boundary.nodes.begin();
auto source_last = outer_boundary.nodes.end();
all_nodes.insert(all_nodes.begin(), source_first, source_last);
for (const auto& inner_boundary : inner_boundaries)
{
for (const auto& inner_boundary : inner_boundaries) {
auto source_first = inner_boundary.nodes.begin();
auto source_last = inner_boundary.nodes.end();
all_nodes.insert(all_nodes.begin(), source_first, source_last);
@ -393,8 +338,9 @@ Kml::Nodes Kml::Polygon::get_all_nodes() const
return all_nodes;
}
std::vector<Kml::LinearRing*> Kml::Polygon::get_all_boundaries()
{
//! \brief
std::vector<Kml::LinearRing*> Kml::Polygon::get_all_boundaries() {
std::vector<LinearRing*> linear_rings;
linear_rings.push_back(&outer_boundary);
for (auto& inner_boundary : inner_boundaries)
@ -403,11 +349,10 @@ std::vector<Kml::LinearRing*> Kml::Polygon::get_all_boundaries()
return linear_rings;
}
Kml::Nodes Kml::Placemark::get_all_nodes() const
{
//! \brief
Kml::Nodes Kml::Placemark::get_all_nodes() const {
Nodes all_nodes;
for (const auto& polygon : polygons)
{
for (const auto& polygon : polygons) {
auto polygon_nodes = polygon.get_all_nodes();
auto first = std::make_move_iterator(polygon_nodes.begin());
auto last = std::make_move_iterator(polygon_nodes.end());
@ -416,41 +361,39 @@ Kml::Nodes Kml::Placemark::get_all_nodes() const
return all_nodes;
}
int Kml::Placemark::get_all_nodes_count() const
{
//! \brief
int Kml::Placemark::get_all_nodes_count() const {
int num_nodes = 0;
for (const auto& polygon : polygons)
{
for (const auto& polygon : polygons) {
auto polygon_nodes = polygon.get_all_nodes();
num_nodes += polygon_nodes.size();
}
return num_nodes;
}
Kml::Arcs Kml::LinearRing::get_arcs() const
{
//! \brief
Kml::Arcs Kml::LinearRing::get_arcs() const {
Arcs arcs;
const int num_nodes = nodes.size();
for (int i = 0; i < num_nodes - 1; ++i)
{
for (int i = 0; i < num_nodes - 1; ++i) {
const auto from = nodes[i];
const auto to = nodes[i + 1];
arcs.push_back(Arc{ from, to });
}
return arcs;
}
void Kml::LinearRing::get_arcs(Arcs& arcs) const
{
//! \brief
void Kml::LinearRing::get_arcs(Arcs& arcs) const {
auto a = get_arcs();
arcs.insert(arcs.end(), a.begin(), a.end());
}
Kml::Arcs Kml::Placemark::get_all_arcs() const
{
Kml::Arcs Kml::Placemark::get_all_arcs() const {
Arcs all_arcs;
for (const auto& polygon : polygons)
{
for (const auto& polygon : polygons) {
polygon.outer_boundary.get_arcs(all_arcs);
for (const auto& inner_boundary : polygon.inner_boundaries)
inner_boundary.get_arcs(all_arcs);
@ -458,4 +401,3 @@ Kml::Arcs Kml::Placemark::get_all_arcs() const
return all_arcs;
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -16,24 +16,19 @@
#include <qvector3d.h>
class Kml
{
class Kml {
public:
// double precision 3D-point (QVector3D has float coordinates)
struct Vec3d
{
struct Vec3d {
double x, y, z;
friend std::ostream& operator << (std::ostream& os, const Vec3d& v)
{
friend std::ostream& operator << (std::ostream& os, const Vec3d& v) {
os << v.x << ", " << v.y << ", " << v.z;
return os;
}
};
struct Node
{
struct Node {
double lon, lat;
Node() : lon(-1111), lat(-1111) {};
@ -48,14 +43,13 @@ public:
};
using Nodes = std::vector<Node>;
struct Arc
{
struct Arc {
Node from, to;
};
using Arcs = std::vector<Arc>;
struct LinearRing
{
struct LinearRing {
std::vector<Node> nodes;
std::vector<int> ids;
@ -64,22 +58,18 @@ public:
};
using LinearRings = std::vector<LinearRing>;
struct Polygon
{
struct Polygon {
LinearRing outer_boundary;
LinearRings inner_boundaries;
// when collecting nodes start from the outer boundary and then get nodes
// from individual inner boundaries in the order
Nodes get_all_nodes() const;
std::vector<LinearRing*> get_all_boundaries();
};
struct Placemark
{
struct Placemark {
std::vector<Polygon> polygons;
std::string name;
@ -89,11 +79,11 @@ public:
Arcs get_all_arcs() const;
};
using Placemarks = std::vector<Placemark>;
static int get_number_of_polygons(Placemarks& placemarks);
static Placemarks read(const std::string& file_name);
static Nodes get_duplicates(const Placemarks& placemarks);
@ -107,5 +97,4 @@ public:
static Nodes generate_ids_approx(Placemarks& placemarks, const double eps);
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -7,13 +7,12 @@
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "Line_strips.h"
#include <iostream>
#include "Line_strips.h"
Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points)
{
//! \brief
Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points) {
initializeOpenGLFunctions();
std::vector<QVector3D> vertex_data;
@ -24,7 +23,6 @@ Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points)
const auto end_of_current_arc_points = vertex_data.size();
m_offsets.push_back(end_of_current_arc_points);
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
@ -34,19 +32,14 @@ Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points)
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(QVector3D) * vertex_data.size();
auto vertex_buffer_data = reinterpret_cast<const void*>(vertex_data.data());
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_STATIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 0;
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
@ -54,27 +47,23 @@ Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points)
glBindVertexArray(0);
}
Line_strips::Line_strips(std::vector<std::vector<QVector3D>>& arcs)
{
//! \brief
Line_strips::Line_strips(std::vector<std::vector<QVector3D>>& arcs) {
initializeOpenGLFunctions();
std::vector<QVector3D> vertex_data;
m_offsets.push_back(0);
for (const auto& arc : arcs)
{
for(const auto& p : arc)
vertex_data.push_back(p);
for (const auto& arc : arcs) {
for(const auto& p : arc) vertex_data.push_back(p);
const auto end_of_current_arc_points = vertex_data.size();
m_offsets.push_back(end_of_current_arc_points);
}
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
// Vertex Buffer
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
@ -89,10 +78,7 @@ Line_strips::Line_strips(std::vector<std::vector<QVector3D>>& arcs)
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 0;
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
@ -100,31 +86,26 @@ Line_strips::Line_strips(std::vector<std::vector<QVector3D>>& arcs)
glBindVertexArray(0);
}
int Line_strips::get_num_line_strips() const
{
return m_offsets.size() - 1;
}
//! \brief
int Line_strips::get_num_line_strips() const { return m_offsets.size() - 1; }
void Line_strips::draw(int line_strip_index)
{
//! \brief
void Line_strips::draw(int line_strip_index) {
glBindVertexArray(m_vao);
const auto first = m_offsets[line_strip_index];
const auto count = m_offsets[line_strip_index + 1] - first;
glDrawArrays(GL_LINE_STRIP, first, count);
const auto first = m_offsets[line_strip_index];
const auto count = m_offsets[line_strip_index + 1] - first;
glDrawArrays(GL_LINE_STRIP, first, count);
glBindVertexArray(0);
}
void Line_strips::draw()
{
//! \brief
void Line_strips::draw() {
glBindVertexArray(m_vao);
{
for (int i = 1; i < m_offsets.size(); i++)
{
const auto first = m_offsets[i - 1];
const auto count = m_offsets[i] - first;
glDrawArrays(GL_LINE_STRIP, first, count);
}
for (int i = 1; i < m_offsets.size(); i++) {
const auto first = m_offsets[i - 1];
const auto count = m_offsets[i] - first;
glDrawArrays(GL_LINE_STRIP, first, count);
}
glBindVertexArray(0);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -14,9 +14,7 @@
#include <qvector3d.h>
#include "Common_defs.h"
class Line_strips : protected OpenGLFunctionsBase
{
class Line_strips : protected OpenGLFunctionsBase {
public:
Line_strips(std::vector<QVector3D>& line_strip_points);
Line_strips(std::vector<std::vector<QVector3D>>& arcs);
@ -25,11 +23,11 @@ public:
void draw(int line_strip_index);
void draw();
private:
GLuint m_vao, m_vbo;
std::vector<GLuint> m_offsets;
GLuint m_vao;
GLuint m_vbo;
std::vector<GLuint> m_offsets;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -23,92 +23,82 @@
#include "GUI_country_pick_handler.h"
#include "Kml_reader.h"
#include "Message_manager.h"
#include "Shapefile.h"
#include "Timer.h"
#include "Tools.h"
#include "Verification.h"
//! \brief
Main_widget::Main_widget(const QString& file_name) : m_file_name(file_name) {}
Main_widget::Main_widget(const QString& file_name) :
m_file_name(file_name)
{
}
Main_widget::~Main_widget()
{
//! \brief
Main_widget::~Main_widget() {
// Make sure the context is current when deleting the texture and the buffers.
makeCurrent();
doneCurrent();
}
//! \brief
void Main_widget::set_mouse_pos(const QVector3D mouse_pos)
{
m_gr_mouse_vertex->set_pos(mouse_pos);
{ m_gr_mouse_vertex->set_pos(mouse_pos); }
//! \brief
void Main_widget::hightlight_country(const std::string& country_name) {
static std::string prev_picked_country;
if (! prev_picked_country.empty()) {
// dim the previous country color
auto& prev_country = m_gr_country_triangles[prev_picked_country];
auto color = prev_country->get_color();
color *= m_dimming_factor;
color.setW(1);
prev_country->set_color(color);
}
if (! country_name.empty()) {
// highlight the current country color
auto& curr_country = m_gr_country_triangles[country_name];
auto color = curr_country->get_color();
color /= m_dimming_factor;
color.setW(1);
curr_country->set_color(color);
qDebug() << "SELECTED COUNTRY: " << country_name;
}
prev_picked_country = country_name;
}
void Main_widget::hightlight_country(const std::string& country_name)
{
static std::string prev_picked_country;
if (!prev_picked_country.empty())
{
// dim the previous country color
auto& prev_country = m_gr_country_triangles[prev_picked_country];
auto color = prev_country->get_color();
color *= m_dimming_factor;
color.setW(1);
prev_country->set_color(color);
}
if (!country_name.empty())
{
// highlight the current country color
auto& curr_country = m_gr_country_triangles[country_name];
auto color = curr_country->get_color();
color /= m_dimming_factor;
color.setW(1);
curr_country->set_color(color);
qDebug() << "SELECTED COUNTRY: " << country_name;
}
prev_picked_country = country_name;
}
void Main_widget::mousePressEvent(QMouseEvent* e)
{
//! \brief
void Main_widget::mousePressEvent(QMouseEvent* e) {
// forward the event to the camera manipulators
m_camera_manip_rot->mousePressEvent(e);
m_camera_manip_zoom->mousePressEvent(e);
m_pick_handler->mousePressEvent(e);
}
void Main_widget::mouseMoveEvent(QMouseEvent* e)
{
//! \brief
void Main_widget::mouseMoveEvent(QMouseEvent* e) {
// forward the event to the camera manipulator
m_camera_manip_rot->mouseMoveEvent(e);
m_camera_manip_zoom->mouseMoveEvent(e);
m_pick_handler->mouseMoveEvent(e);
}
void Main_widget::mouseReleaseEvent(QMouseEvent* e)
{
//! \brief
void Main_widget::mouseReleaseEvent(QMouseEvent* e) {
// forward the event to the camera manipulator
m_camera_manip_rot->mouseReleaseEvent(e);
m_camera_manip_zoom->mouseReleaseEvent(e);
m_pick_handler->mouseReleaseEvent(e);
}
void Main_widget::timerEvent(QTimerEvent*)
{
update();
}
//! \brief
void Main_widget::timerEvent(QTimerEvent*) { update(); }
void Main_widget::keyPressEvent(QKeyEvent* event)
{
}
//! \brief
void Main_widget::keyPressEvent(QKeyEvent* event) {}
void Main_widget::initializeGL()
{
//! \brief
void Main_widget::initializeGL() {
m_pick_handler = std::make_unique<GUI_country_pick_handler>(*this);
QVector3D initial_mouse_pos(0, -1, 0);
@ -121,8 +111,7 @@ void Main_widget::initializeGL()
//m_arrh = Aos::load_arr("../../../Data/data/arrangements_3/sphere/ne_110m_admin_0_countries.json");
//m_arrh = Aos::load_arr("C:/work/gsoc2023/ne_110m_admin_0_countries.json");
m_arrh = Aos::load_arr(m_file_name.toStdString());
if (m_arrh == nullptr)
{
if (m_arrh == nullptr) {
qDebug() << "FAILED TO LOAD THE ARRANGEMENT !!!";
exit(1);
}
@ -136,8 +125,7 @@ void Main_widget::initializeGL()
//qDebug() << "color map size = " << color_map.size();
qDebug() << "num countries = " << country_triangles_map.size();
auto rndm = [] {return rand() / double(RAND_MAX); };
for (auto& [country_name, triangle_points] : country_triangles_map)
{
for (auto& [country_name, triangle_points] : country_triangles_map) {
auto country_triangles = std::make_unique<Triangles>(triangle_points);
auto color = QVector4D(rndm(), rndm(), rndm(), 1);
auto m = std::max(color.x(), std::max(color.y(), color.z()));
@ -153,7 +141,6 @@ void Main_widget::initializeGL()
//m_gr_all_triangles = std::make_unique<Triangles>(triangle_points);
}
initializeOpenGLFunctions();
init_camera();
@ -171,9 +158,8 @@ void Main_widget::initializeGL()
m_timer.start(12, this);
}
void Main_widget::init_camera()
{
//! \brief
void Main_widget::init_camera() {
m_camera.set_pos(0, 0, 3);
m_camera_manip_rot = std::make_unique<Camera_manip_rot>(m_camera);
//m_camera_manip_rot = std::make_unique<Camera_manip_rot_bpa>(m_camera);
@ -183,18 +169,19 @@ void Main_widget::init_camera()
m_model.rotate(-90, 1, 0, 0);
// register the zoom-changed function
Message_manager::add("zoom_changed", [&]
{
qDebug() << "ZOOM CHANGED!!!";
//const auto error = compute_backprojected_error(0.5);
//qDebug() << "new error = " << error;
m_update_approx_error = true;
//qDebug() << "re-initializing the country borders..";
//init_country_borders(error);
});
Message_manager::add("zoom_changed",
[&] {
qDebug() << "ZOOM CHANGED!!!";
//const auto error = compute_backprojected_error(0.5);
//qDebug() << "new error = " << error;
m_update_approx_error = true;
//qDebug() << "re-initializing the country borders..";
//init_country_borders(error);
});
}
void Main_widget::init_geometry()
{
//! \brief
void Main_widget::init_geometry() {
// SPHERE
int num_slices, num_stacks;
num_slices = num_stacks = 64;
@ -211,16 +198,17 @@ void Main_widget::init_geometry()
const float axes_length = 2;
m_gr_world_coord_axes = std::make_unique<World_coord_axes>(axes_length);
}
void Main_widget::init_shader_programs()
{
//! \brief
void Main_widget::init_shader_programs() {
Shader_program::set_shader_path("shaders/");
m_sp_smooth.init_with_vs_fs("smooth");;
m_sp_per_vertex_color.init_with_vs_fs("per_vertex_color");
m_sp_arc.init_with_vs_fs("arc");
}
void Main_widget::init_country_borders(float error)
{
//! \brief
void Main_widget::init_country_borders(float error) {
// this part does the same as the code below but using arrangement!
// NOTE: the old code interferes with some logic (NEEDS REFACTORING!!!)
m_gr_all_country_borders.reset(nullptr);
@ -229,9 +217,8 @@ void Main_widget::init_country_borders(float error)
m_gr_all_country_borders = std::make_unique<Line_strips>(all_approx_arcs);
}
float Main_widget::compute_backprojected_error(float pixel_error)
{
//! \brief
float Main_widget::compute_backprojected_error(float pixel_error) {
// compute the back-projected error
QRect vp(0, 0, m_vp_width, m_vp_height);
auto proj = m_camera.get_projection_matrix();
@ -254,9 +241,8 @@ float Main_widget::compute_backprojected_error(float pixel_error)
return err;
}
void Main_widget::resizeGL(int w, int h)
{
//! \brief
void Main_widget::resizeGL(int w, int h) {
m_camera_manip_rot->resizeGL(w, h);
m_pick_handler->resizeGL(w, h);
@ -272,22 +258,17 @@ void Main_widget::resizeGL(int w, int h)
m_update_approx_error = true;
}
//! \brief
template<typename T>
void draw_safe(T& ptr)
{
if (ptr)
ptr->draw();
}
void draw_safe(T& ptr) { if (ptr) ptr->draw(); }
void Main_widget::paintGL()
{
if (m_update_approx_error)
{
//! \brief
void Main_widget::paintGL() {
if (m_update_approx_error) {
const auto error = compute_backprojected_error(0.5);
qDebug() << "new approx error = " << error;
qDebug() << "current error = " << m_current_approx_error;
if(error < m_current_approx_error)
{
if (error < m_current_approx_error) {
init_country_borders(error);
m_current_approx_error = error;
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -10,15 +10,15 @@
#ifndef MAIN_WIDGET_H
#define MAIN_WIDGET_H
#include <functional>
#include <memory>
#include <QOpenGLWidget>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QVector2D>
#include <QBasicTimer>
#include <functional>
#include <memory>
#include <qopenglwidget.h>
#include "Aos.h"
@ -35,18 +35,15 @@
#include "Vertices.h"
#include "World_coordinate_axes.h"
class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase
{
class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase {
Q_OBJECT
public:
using QOpenGLWidget::QOpenGLWidget;
Main_widget(const QString& file_name);
~Main_widget();
auto& get_camera() { return m_camera; }
auto& get_model_matrix() { return m_model; }
auto& get_arr_handle() { return m_arrh; }
@ -66,64 +63,63 @@ protected:
void resizeGL(int w, int h) override;
void paintGL() override;
void init_camera();
void init_geometry();
void init_geometry();
void init_shader_programs();
void init_country_borders(float error);
// This is called when the required approximation of the arcs is below the
// This is called when the required approximation of the arcs is below the
// currently required one defined by the zoom level and window size. If you
// zoom-in or increase the window-size this can be called. But once a minimum
// approximation error is needed, it will stay there until futher change.
// SEE the definition of "m_current_approx_error" member variable below!
float compute_backprojected_error(float pixel_error);
private:
// COUNTRY ARRANGEMENT SPECIFIC DATA
QString m_file_name;
Aos::Arr_handle m_arrh;
std::unique_ptr<Line_strips> m_gr_all_country_borders;
QString m_file_name;
Aos::Arr_handle m_arrh;
std::unique_ptr<Line_strips> m_gr_all_country_borders;
// used when dimming / highlighting selected countries
const float m_dimming_factor = 0.4;
const float m_dimming_factor = 0.4;
// GUI: event handler for picking with right mouse button
std::unique_ptr<GUI_event_handler> m_pick_handler;
std::unique_ptr<GUI_event_handler> m_pick_handler;
// These are used to highlight the picked position by right-mouse click
std::unique_ptr<Single_vertex> m_gr_mouse_vertex;
std::unique_ptr<Single_vertex> m_gr_mouse_vertex;
// TRIANGLES for rendering the countries in solid
std::unique_ptr<Triangles> m_gr_all_triangles;
std::unique_ptr<Triangles> m_gr_all_triangles;
std::map<std::string, std::unique_ptr<Triangles>> m_gr_country_triangles;
// -------------------------------
// --> COMMON SETUP FOR ALL SCENES
// Basic objects in the scene
std::unique_ptr<Sphere> m_gr_sphere;
std::unique_ptr<Sphere> m_gr_sphere;
std::unique_ptr<World_coord_axes> m_gr_world_coord_axes;
std::unique_ptr<Line_strips> m_gr_identification_curve;
std::unique_ptr<Line_strips> m_gr_identification_curve;
// Shaders
Shader_program m_sp_smooth;
Shader_program m_sp_per_vertex_color;
Shader_program m_sp_arc;
Shader_program m_sp_smooth;
Shader_program m_sp_per_vertex_color;
Shader_program m_sp_arc;
// Camera & controls
Camera m_camera;
std::unique_ptr<GUI_event_handler> m_camera_manip_rot;
std::unique_ptr<GUI_event_handler> m_camera_manip_zoom;
QMatrix4x4 m_model;
std::unique_ptr<GUI_event_handler> m_camera_manip_rot;
std::unique_ptr<GUI_event_handler> m_camera_manip_zoom;
QMatrix4x4 m_model;
// view-port
int m_vp_width = 0, m_vp_height = 0;
// view-port
int m_vp_width = 0;
int m_vp_height = 0;
// After zooming in or making the viewport larger, the approximation-error
// needs to be updated and checked against the old value. If a lower approxi-

View File

@ -1,657 +0,0 @@
// Copyright(c) 2023 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 "Main_widget.h"
#include <cmath>
#include <iostream>
#include <string>
#include <QMouseEvent>
#include "Aos.h"
#include "Aos_triangulator.h"
#include "Camera_manip_rot.h"
#include "Camera_manip_rot_bpa.h"
#include "Camera_manip_zoom.h"
#include "Kml_reader.h"
#include "Message_manager.h"
#include "Shapefile.h"
#include "Timer.h"
#include "Tools.h"
#include "Verification.h"
namespace {
// used when dimming / highlighting selected countries
float s_dimming_factor = 0.4;
}
Main_widget::~Main_widget() {
// Make sure the context is current when deleting the texture and the buffers.
makeCurrent();
doneCurrent();
}
void Main_widget::handle_country_picking(QMouseEvent* e) {
//// handle country selection
//if (e->button() == Qt::RightButton)
//{
// auto p = e->pos();
// QVector3D sp0(p.x(), m_vp_height - p.y(), 0);
// QVector3D sp1(p.x(), m_vp_height - p.y(), 1);
// auto proj = m_camera.get_projection_matrix();
// auto view = m_camera.get_view_matrix();
// auto model_view = view * m_model;
// QRect viewport(0, 0, m_vp_width, m_vp_height);
// auto wp0 = sp0.unproject(model_view, proj, viewport);
// auto wp1 = sp1.unproject(model_view, proj, viewport);
// // ASSERTION!!!
// m_mouse_pos = wp0;
// // define a ray from the camera pos to the world-point
// //auto o = m_camera.get_pos();
// //auto u = wp - o;
// auto o = wp0;
// auto u = wp1 - wp0;
// // solve the quadratic equation to check for intersection of ray with sphere
// auto a = QVector3D::dotProduct(u, u);
// auto b = 2 * QVector3D::dotProduct(u, o);
// auto c = QVector3D::dotProduct(o, o) - 1;
// auto d = b * b - 4 * a * c;
// float ti = -1;
// if (abs(d) < std::numeric_limits<float>::epsilon())
// {
// // single intersection
// ti = -b / (2 * a);
// }
// else
// {
// if (d < 0)
// {
// // no intersection
// return;
// }
// else
// {
// // two intersections
// auto sd = sqrt(d);
// auto t1 = (-b - sd) / (2 * a);
// auto t2 = (-b + sd) / (2 * a);
// if (t1 > 0 && t2 > 0)
// ti = std::min(t1, t2);
// else if (t1 > 0)
// ti = t1;
// else
// ti = t2;
// }
// }
// m_mouse_pos = o + ti * u;
// static std::string prev_picked_country;
// auto picked_country = Aos::locate_country(m_arrh, m_mouse_pos);
// if (!prev_picked_country.empty())
// {
// // dim the previous country color
// auto& prev_country = m_country_triangles[prev_picked_country];
// auto color = prev_country->get_color();
// color *= s_dimming_factor;
// color.setW(1);
// prev_country->set_color(color);
// }
// if (!picked_country.empty())
// {
// // highlight the current country color
// auto& curr_country = m_country_triangles[picked_country];
// auto color = curr_country->get_color();
// color /= s_dimming_factor;
// color.setW(1);
// curr_country->set_color(color);
// qDebug() << "SELECTED COUNTRY: " << picked_country;
// }
// prev_picked_country = picked_country;
//}
}
void Main_widget::hightlight_country(const std::string& country_name) {
static std::string prev_picked_country;
if (!prev_picked_country.empty()) {
// dim the previous country color
auto& prev_country = m_country_triangles[prev_picked_country];
auto color = prev_country->get_color();
color *= s_dimming_factor;
color.setW(1);
prev_country->set_color(color);
}
if (! country_name.empty()) {
// highlight the current country color
auto& curr_country = m_country_triangles[country_name];
auto color = curr_country->get_color();
color /= s_dimming_factor;
color.setW(1);
curr_country->set_color(color);
qDebug() << "SELECTED COUNTRY: " << country_name;
}
prev_picked_country = country_name;
}
void Main_widget::mousePressEvent(QMouseEvent* e) {
// forward the event to the camera manipulators
m_camera_manip_rot->mousePressEvent(e);
m_camera_manip_zoom->mousePressEvent(e);
m_pick_handler->mousePressEvent(e);
//handle_country_picking(e);
}
void Main_widget::mouseMoveEvent(QMouseEvent* e) {
// forward the event to the camera manipulator
m_camera_manip_rot->mouseMoveEvent(e);
m_camera_manip_zoom->mouseMoveEvent(e);
m_pick_handler->mouseMoveEvent(e);
}
void Main_widget::mouseReleaseEvent(QMouseEvent* e) {
// forward the event to the camera manipulator
m_camera_manip_rot->mouseReleaseEvent(e);
m_camera_manip_zoom->mouseReleaseEvent(e);
m_pick_handler->mouseReleaseEvent(e);
}
void Main_widget::timerEvent(QTimerEvent*) { update(); }
void Main_widget::keyPressEvent(QKeyEvent* event) {
switch (event->key()) {
case Qt::Key_Q:
{
auto num_arcs =
m_country_borders[m_selected_country_index]->get_num_line_strips();
if (++m_selected_arc_index == num_arcs) m_selected_arc_index--;
qDebug() << "---------------------------------------";
qDebug() << "selected arc index = " << m_selected_arc_index;
const auto& arc = m_selected_country_arcs[m_selected_arc_index];
std::cout << arc.from << " TO " << arc.to << std::endl;
}
break;
case Qt::Key_A:
{
auto num_arcs =
m_country_borders[m_selected_country_index]->get_num_line_strips();
if (--m_selected_arc_index < 0) m_selected_arc_index = 0;
std::cout << "selected arc = " << m_selected_arc_index << std::endl;
}
break;
case Qt::Key_Up:
m_selected_country_index++;
if (m_selected_country_index == m_country_names.size())
m_selected_country_index--;
std::cout << m_selected_country_index << ": "
<< m_country_names[m_selected_country_index] << std::endl;
m_selected_arc_index = 0;
m_selected_country = &m_countries[m_selected_country_index];
m_selected_country_nodes = m_selected_country->get_all_nodes();
m_selected_country_arcs = m_selected_country->get_all_arcs();
{
auto num_arcs =
m_country_borders[m_selected_country_index]->get_num_line_strips();
qDebug() << "num KML arcs = " << m_selected_country_arcs.size();
qDebug() << "num arcs = " << num_arcs;
}
break;
case Qt::Key_Down:
m_selected_country_index--;
if (m_selected_country_index < 0) m_selected_country_index = 0;
std::cout << m_selected_country_index << ": "
<< m_country_names[m_selected_country_index] << std::endl;
m_selected_arc_index = 0;
m_selected_country = &m_countries[m_selected_country_index];
m_selected_country_nodes = m_selected_country->get_all_nodes();
break;
}
}
//!\brief
void Main_widget::init_problematic_nodes() {
Kml::Nodes prob_nodes = {
{23.8058134294668,8.66631887454253},
{24.1940677211877,8.7286964724039 },
{24.5673690121521,8.22918793378547},
{23.8869795808607,8.61972971293307}
};
std::vector<QVector3D> prob_vertices;
for (const auto& node : prob_nodes)
prob_vertices.push_back(node.get_coords_3f());
m_problematic_vertices = std::make_unique<Vertices>(prob_vertices);
}
#include "GUI_country_pick_handler.h"
void Main_widget::initializeGL() {
m_pick_handler = std::make_unique<GUI_country_pick_handler>(*this);
// verify that the node (180.0, -84.71338) in Antarctica is redundant
//Verification::verify_antarctica_node_is_redundant();
//init_problematic_nodes();
m_mouse_pos = QVector3D(0, -1, 0);
m_mouse_vertex = std::make_unique<SingleVertex>(m_mouse_pos);
std::string data_path = "C:/work/gsoc2023/data/";
//std::string shape_file_path = data_path + "ne_110m_admin_0_countries/";
//auto shape_file_name = shape_file_path + "ne_110m_admin_0_countries.shp";
//Shapefile::read(shape_file_name);
//const auto file_name = data_path + "world_countries.kml";
//const auto file_name = data_path + "ne_110m_admin_0_countries.kml";
//const auto file_name = data_path + "ne_110m_admin_0_countries_africa.kml";
const auto file_name = data_path + "ne_110m_admin_0_countries_equatorial_guinea.kml";
m_countries = Kml::read(file_name);
// find the country with the least number of nodes
if (0) {
std::string smallest;
int min_num_nodes = std::numeric_limits<int>::max();
for (auto& p : m_countries) {
int num_nodes = p.get_all_nodes_count();
if (min_num_nodes > num_nodes) {
min_num_nodes = num_nodes;
smallest = p.name;
}
qDebug() << p.name << " = " << p.get_all_nodes_count();
}
qDebug() << "smallest = " << smallest;
exit(0);
}
auto dup_nodes = Kml::get_duplicates(m_countries);
//auto all_nodes = Kml::generate_ids(m_countries);
qDebug() << "*** KML number of polygons = " <<
Kml::get_number_of_polygons(m_countries);
if(0)
{
auto created_faces = Aos::find_new_faces(m_countries);
m_new_faces = std::make_unique<Line_strips>(created_faces);
}
// SAVING ARR
if(0) {
std::string dest_path = "C:/work/gsoc2023/";
//std::string file_name = "ne_110m_admin_0_countries.json";
//std::string file_name = "ne_110m_admin_0_countries_africa_1.json";
std::string file_name = "ne_110m_admin_0_countries_equatorial_guinea.json";
auto full_path = dest_path + file_name;
Aos::save_arr(m_countries, full_path);
qDebug() << "done saving!";
exit(0);
}
// triangulation
{
qDebug() << "loading arr..";
//auto arrh = Aos::construct(m_countries);
m_arrh = Aos::load_arr("C:/work/gsoc2023/ne_110m_admin_0_countries.json");
if (m_arrh == nullptr) {
qDebug() << "** FAILED TO LOAD THE ARRANGEMENT!!!";
exit(1);
}
qDebug() << "generating triangles..";
//auto triangle_points = Aos::get_triangles(arrh);
//auto triangle_points = Aos_triangulator::get_all(arrh);
//auto country_triangles_map = Aos::get_triangles_by_country(m_arrh);
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();
auto rndm = [] {return rand() / double(RAND_MAX); };
//QVector4D colors[] = {
// QVector4D(1,0,0,1),
// QVector4D(0,1,0,1),
// QVector4D(0,0,1,1),
// QVector4D(1,1,0,1),
// QVector4D(1,0,1,1)
//};
for (auto& [country_name, triangle_points] : country_triangles_map) {
auto country_triangles = std::make_unique<Triangles>(triangle_points);
auto color = QVector4D(rndm(), rndm(), rndm(), 1);
auto m = std::max(color.x(), std::max(color.y(), color.z()));
color /= m;
color *= s_dimming_factor;
color.setW(1);
country_triangles->set_color(color);
//country_triangles->set_color(colors[color_map[country_name]]);
m_country_triangles.emplace(country_name, std::move(country_triangles));
}
//qDebug() << "num triangles = " << triangle_points.size() / 3;
//m_all_triangles = std::make_unique<Triangles>(triangle_points);
}
// initialize rendering of DUPLICATE VERTICES
if(0) {
qDebug() << "identifying duplicate nodes";
std::vector<QVector3D> vertices;
for (const auto& node : dup_nodes)
vertices.push_back(node.get_coords_3f());
m_vertices = std::make_unique<Vertices>(vertices);
}
if(0) {
// 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);
m_vertices = std::make_unique<Vertices>(created_vertices);
}
initializeOpenGLFunctions();
init_camera();
init_geometry();
init_shader_programs();
m_current_approx_error = 0.001;
init_country_borders(m_current_approx_error);
init_country_selection();
glClearColor(0, 0, 0, 1);
glEnable(GL_DEPTH_TEST); // Enable depth buffer
//glEnable(GL_CULL_FACE); // Enable back face culling
// Use QBasicTimer because its faster than QTimer
m_timer.start(12, this);
}
void Main_widget::init_camera() {
m_camera.set_pos(0, 0, 3);
m_camera_manip_rot = std::make_unique<Camera_manip_rot>(m_camera);
//m_camera_manip_rot = std::make_unique<Camera_manip_rot_bpa>(m_camera);
m_camera_manip_zoom = std::make_unique<Camera_manip_zoom>(m_camera);
// this makes z-axes point upwards!
m_model.rotate(-90, 1, 0, 0);
// register the zoom-changed function
Message_manager::add("zoom_changed", [&]
{
qDebug() << "ZOOM CHANGED!!!";
//const auto error = compute_backprojected_error(0.5);
//qDebug() << "new error = " << error;
m_update_approx_error = true;
//qDebug() << "re-initializing the country borders..";
//init_country_borders(error);
});
}
void Main_widget::init_geometry() {
// SPHERE
int num_slices, num_stacks;
num_slices = num_stacks = 64;
float r = 1;
m_sphere = std::make_unique<Sphere>(num_slices, num_stacks, r);
const float c = 0.8;
m_sphere->set_color(c, c, c, 1);
// IDENTIFICATION CURVE
const double error = 0.001;
auto approx_ident_curve = Aos::get_approx_identification_curve(error);
m_identification_curve = std::make_unique<Line_strips>(approx_ident_curve);
const float axes_length = 2;
m_world_coord_axes = std::make_unique<World_coord_axes>(axes_length);
}
void Main_widget::init_shader_programs() {
Shader_program::set_shader_path("shaders/");
m_sp_smooth.init_with_vs_fs("smooth");;
m_sp_per_vertex_color.init_with_vs_fs("per_vertex_color");
m_sp_arc.init_with_vs_fs("arc");
}
void Main_widget::init_country_borders(float error) {
// this part does the same as the code below but using arrangement!
// NOTE: the old code interferes with some logic (NEEDS REFACTORING!!!)
{
m_country_borders.clear();
qDebug() << "approximating the arcs of each edge of all faces..";
auto all_approx_arcs = Aos::get_approx_arcs_from_faces_edges(m_arrh, error);
m_gr_all_approx_arcs = std::make_unique<Line_strips>(all_approx_arcs);
return;
}
// TO-DO: move this code to resizeGL (when viewport is initialized)
// has to be defined after camera has been defined:
// because we want to compute the error based on camera parameters!
//const double error = 0.001; // calculate this from cam parameters!
//auto lsa = Aos::get_approx_arcs(countries, error);
//auto lsa = Aos::get_approx_arcs(error);
//m_geodesic_arcs = std::make_unique<Line_strips>(lsa);
m_country_borders.clear();
for (const auto& country : m_countries) {
m_country_names.push_back(country.name);
auto approx_arcs = Aos::get_approx_arcs(country, error);
auto country_border = std::make_unique<Line_strips>(approx_arcs);
m_country_borders.push_back(std::move(country_border));
}
}
void Main_widget::init_country_selection() {
m_selected_country_index = 0;
//m_selected_country_index = 159; // ANTARCTICA
m_selected_country = &m_countries[m_selected_country_index];
m_selected_country_nodes = m_selected_country->get_all_nodes();
m_selected_country_arcs = m_selected_country->get_all_arcs();
m_selected_arc_index = 0;
}
float Main_widget::compute_backprojected_error(float pixel_error) {
// compute the back-projected error
QRect vp(0, 0, m_vp_width, m_vp_height);
auto proj = m_camera.get_projection_matrix();
auto view = m_camera.get_view_matrix();
QMatrix4x4 model;
auto model_view = view * model;
QVector3D p0(m_vp_width / 2, m_vp_height / 2, 0);
QVector3D p1(p0.x() + pixel_error, p0.y(), 0);
auto wp0 = p0.unproject(model_view, proj, vp);
auto wp1 = p1.unproject(model_view, proj, vp);
const float z_near = m_camera.get_z_near();
const float r = 1.f; // sphere radius
const QVector3D origin(0, 0, 0);
const float dist_to_cam = m_camera.get_pos().distanceToPoint(origin);
float d = dist_to_cam - r;
float err = wp0.distanceToPoint(wp1) * (d / z_near);
//find_minimum_projected_error_on_sphere(err);
return err;
}
void Main_widget::resizeGL(int w, int h) {
m_camera_manip_rot->resizeGL(w, h);
m_pick_handler->resizeGL(w, h);
m_vp_width = w;
m_vp_height = h;
// Reset projection
qreal aspect = qreal(w) / qreal(h ? h : 1);
const qreal z_near = 0.1, z_far = 100.0, fov = 45.0;
m_camera.perspective(fov, aspect, z_near, z_far);
// signal to look into the approximation error
m_update_approx_error = true;
}
template <typename T>
void draw_safe(T& ptr) {
if (ptr)
ptr->draw();
}
void Main_widget::paintGL() {
if (m_update_approx_error) {
const auto error = compute_backprojected_error(0.5);
qDebug() << "new approx error = " << error;
qDebug() << "current error = " << m_current_approx_error;
if(error < m_current_approx_error) {
init_country_borders(error);
m_current_approx_error = error;
}
m_update_approx_error = false;
}
const auto view = m_camera.get_view_matrix();
const auto projection = m_camera.get_projection_matrix();
const auto model_view = view * m_model;
const auto mvp = projection * model_view;
const auto normal_matrix = model_view.normalMatrix();
// compute the cutting plane
// remember that we are passing the local vertex positions of the sphere
// between the vertex and fragment shader stages, so we need to convert
// the camera-pos in world coords to sphere's local coords!
auto c = m_model.inverted() * m_camera.get_pos();
const auto d = c.length();
const auto r = 1.0f;
const auto sin_alpha = r / d;
const auto n = (c / d); // plane unit normal vector
const auto cos_beta = sin_alpha;
const auto p = (r * cos_beta) * n;
QVector4D plane(n.x(), n.y(), n.z(), -QVector3D::dotProduct(p, n));
// Clear color and depth buffer
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// SPHERE
{
glEnable(GL_DEPTH_TEST);
auto& sp = m_sp_smooth;
sp.use();
sp.set_uniform("u_mvp", mvp);
sp.set_uniform("u_normal_matrix", normal_matrix);
auto sphere_color = QVector4D(167, 205, 242, 255) / 255;
sp.set_uniform("u_color", sphere_color);
sp.set_uniform("u_plane", QVector4D(0,0,0,0));
//sp.set_uniform("u_color", m_sphere->get_color());
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
m_sphere->draw();
// DRAW SOLID FACES
if(1)
{
glDisable(GL_DEPTH_TEST);
//auto face_color = QVector4D(241, 141, 0, 255) / 255;
//sp.set_uniform("u_color", face_color);
sp.set_uniform("u_plane", plane);
//glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
//m_all_triangles->draw();
for (auto& [country_name, country] : m_country_triangles)
{
sp.set_uniform("u_color", country->get_color());
country->draw();
}
//sp.set_uniform("u_color", QVector4D(0,0,0,1));
//glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
//m_all_triangles->draw();
}
sp.unuse();
}
// WORLD COORDINATE AXES
{
auto& sp = m_sp_per_vertex_color;
sp.use();
sp.set_uniform("u_mvp", mvp);
glEnable(GL_DEPTH_TEST);
m_world_coord_axes->draw();
sp.unuse();
}
// VERTICES & GEODESIC ARCS
{
glDisable(GL_DEPTH_TEST);
auto& sp = m_sp_arc;
sp.use();
sp.set_uniform("u_mvp", mvp);
const QVector4D arc_color(0, 0.5, 1, 1);
glLineWidth(5);
sp.set_uniform("u_plane", plane);
// IDENTIFICATION CURVE
sp.set_uniform("u_color", QVector4D(0, 1, 1, 1));
m_identification_curve->draw(m_selected_arc_index);
// draw all countries
float a = 0.0;
sp.set_uniform("u_color", QVector4D(a, a, a, 1));
//for(auto& country_border : m_country_borders)
// country_border->draw();
m_gr_all_approx_arcs->draw();
//// draw the SELECTED COUNTRY in BLUE
//auto& selected_country = m_country_borders[m_selected_country_index];
//sp.set_uniform("u_color", QVector4D(0, .6, 1, 1));
//selected_country->draw();
//// draw the CURRENT ARC of the selected country in YELLOW
//sp.set_uniform("u_color", QVector4D(1, 1, 0, 1));
//selected_country->draw(m_selected_arc_index);
//const QVector4D vertex_color(1, 0, 0, 1);
//sp.set_uniform("u_color", vertex_color);
//glPointSize(3);
////m_vertices->draw();
//sp.set_uniform("u_color", QVector4D(0,1,0,1));
//glPointSize(2);
////m_problematic_vertices->draw();
//draw_safe(m_problematic_vertices);
//// NEW FACES in RED
//sp.set_uniform("u_color", QVector4D(1, 0, 0, 1));
////m_new_faces->draw();
// MOUSE VERTEX
{
glPointSize(5);
sp.set_uniform("u_color", QVector4D(1, 0, 0, 1));
//auto pos = m_mouse_vertex->get_pos();
//pos.setX(pos.x() + 0.01);
//m_mouse_vertex->set_pos(pos);
m_mouse_vertex->set_pos(m_mouse_pos);
draw_safe(m_mouse_vertex);
}
sp.unuse();
}
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -35,16 +35,13 @@
#include "Vertices.h"
#include "World_coordinate_axes.h"
class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase
{
class Main_widget : public QOpenGLWidget, protected OpenGLFunctionsBase {
Q_OBJECT
public:
using QOpenGLWidget::QOpenGLWidget;
~Main_widget();
auto& get_camera() { return m_camera; }
auto& get_model_matrix() { return m_model; }
auto& get_arr_handle() { return m_arrh; }
@ -64,79 +61,80 @@ protected:
void resizeGL(int w, int h) override;
void paintGL() override;
void init_camera();
void init_geometry();
void init_geometry();
void init_shader_programs();
void init_country_borders(float error);
void init_country_selection();
void handle_country_picking(QMouseEvent* e);
// This is called when the required approximation of the arcs is below the
// This is called when the required approximation of the arcs is below the
// currently required one defined by the zoom level and window size. If you
// zoom-in or increase the window-size this can be called. But once a minimum
// approximation error is needed, it will stay there until futher change.
// SEE the definition of "m_current_approx_error" member variable below!
float compute_backprojected_error(float pixel_error);
// init problematic vertices: these are the vertices incident to deg-4 vertex
void init_problematic_nodes();
private:
// ARRANGEMENT
Aos::Arr_handle m_arrh;
std::unique_ptr<Line_strips> m_gr_all_approx_arcs;
Aos::Arr_handle m_arrh;
std::unique_ptr<Line_strips> m_gr_all_approx_arcs;
// GUI: event handler for picking with right mouse button
std::unique_ptr<GUI_event_handler> m_pick_handler;
// Objects in the scene
std::unique_ptr<Sphere> m_sphere;
std::unique_ptr<Sphere> m_sphere;
std::unique_ptr<World_coord_axes> m_world_coord_axes;
std::unique_ptr<Line_strips> m_geodesic_arcs;
std::unique_ptr<Vertices> m_vertices, m_problematic_vertices;
std::unique_ptr<Line_strips> m_identification_curve;
std::unique_ptr<Line_strips> m_geodesic_arcs;
std::unique_ptr<Vertices> m_vertices, m_problematic_vertices;
std::unique_ptr<Line_strips> m_identification_curve;
// New faces not in the KML-file but created during arr-construction.
// This is used to identify the Caspian Sea!
std::unique_ptr<Line_strips> m_new_faces;
// These are used to highlight the picked position by right-mouse click
QVector3D m_mouse_pos;
std::unique_ptr<SingleVertex> m_mouse_vertex;
QVector3D m_mouse_pos;
std::unique_ptr<SingleVertex> m_mouse_vertex;
// COUNTRY DATA
Kml::Placemarks m_countries;
std::vector<std::string> m_country_names;
std::vector<std::unique_ptr<Line_strips>> m_country_borders;
Kml::Placemarks m_countries;
std::vector<std::string> m_country_names;
std::vector<std::unique_ptr<Line_strips>> m_country_borders;
// boundary-arcs by country
int m_selected_country_index, m_selected_arc_index;
Kml::Nodes m_selected_country_nodes;
Kml::Arcs m_selected_country_arcs;
int m_selected_country_index;
int m_selected_arc_index;
Kml::Nodes m_selected_country_nodes;
Kml::Arcs m_selected_country_arcs;
Kml::Placemark* m_selected_country;
// TRIANGLES for rendering the countries in solid
std::unique_ptr<Triangles> m_all_triangles;
std::map<std::string, std::unique_ptr<Triangles>> m_country_triangles;
// Shaders
Shader_program m_sp_smooth;
Shader_program m_sp_per_vertex_color;
Shader_program m_sp_arc;
Shader_program m_sp_smooth;
Shader_program m_sp_per_vertex_color;
Shader_program m_sp_arc;
// Camera & controls
Camera m_camera;
std::unique_ptr<GUI_event_handler> m_camera_manip_rot;
std::unique_ptr<Camera_manip> m_camera_manip_zoom;
std::unique_ptr<GUI_event_handler> m_camera_manip_rot;
std::unique_ptr<Camera_manip> m_camera_manip_zoom;
QMatrix4x4 m_model;
// view-port
int m_vp_width = 0, m_vp_height = 0;
// view-port
int m_vp_width = 0;
int m_vp_height = 0;
// After zooming in or making the viewport larger, the approximation-error
// needs to be updated and checked against the old value. If a lower approxi-

View File

@ -1,26 +1,16 @@
#include "Message_manager.h"
std::map<std::string, Message_manager::Callbacks>
Message_manager::s_message_map;
std::map<std::string, Message_manager::Callbacks>
Message_manager::s_message_map;
void Message_manager::add(const std::string& msg_name,
void Message_manager::add(const std::string& msg_name,
std::function<void()> callback)
{
s_message_map[msg_name].push_back(callback);
}
{ s_message_map[msg_name].push_back(callback); }
void Message_manager::notify_all(const std::string& msg_name)
{
void Message_manager::notify_all(const std::string& msg_name) {
auto it = s_message_map.find(msg_name);
if (s_message_map.cend() != it)
{
if (s_message_map.cend() != it) {
auto& callbacks = it->second;
for (auto& cb : callbacks)
cb();
for (auto& cb : callbacks) cb();
}
}

View File

@ -1,3 +1,11 @@
// Copyright(c) 2023, 2024 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 MESSAGE_MANAGER_H
#define MESSAGE_MANAGER_H
@ -5,18 +13,16 @@
#include <functional>
#include <map>
#include <string>
#include <vector>
class Message_manager
{
class Message_manager {
public:
static void add(const std::string& msg_name, std::function<void()> callback);
static void notify_all(const std::string& msg_name);
protected:
using Callbacks = std::vector<std::function<void()>>;
static std::map<std::string, Callbacks> s_message_map;
static std::map<std::string, Callbacks> s_message_map;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -7,38 +7,33 @@
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "Shader_program.h"
#include <iostream>
#include "Tools.h"
#include "Shader_program.h"
std::string Shader_program::s_shader_path;
std::string Shader_program::s_shader_path;
//! \brief
void Shader_program::set_shader_path(const char* path)
{
s_shader_path = std::string(path);
}
{ s_shader_path = std::string(path); }
bool Shader_program::init()
{
//! \brief
bool Shader_program::init() {
initializeOpenGLFunctions();
m_program = glCreateProgram();
if (!m_program)
{
if (! m_program) {
std::cout << "error creating shader program!\n";
return false;
}
return true;
}
bool Shader_program::init(const char* vs, const char* gs, const char* fs)
{
if (init() == false)
return false;
//! \brief
bool Shader_program::init(const char* vs, const char* gs, const char* fs) {
if (! init()) return false;
add_shader_from_file(vs, GL_VERTEX_SHADER);
add_shader_from_file(gs, GL_GEOMETRY_SHADER);
@ -49,21 +44,23 @@ bool Shader_program::init(const char* vs, const char* gs, const char* fs)
return true;
}
bool Shader_program::init(const std::string& vs,
const std::string& gs,
//! \brief
bool Shader_program::init(const std::string& vs,
const std::string& gs,
const std::string& fs)
{
return init(vs.c_str(), gs.c_str(), fs.c_str());
}
bool Shader_program::init_with_vs_fs(const char* shader_file_prefix)
{
{ return init(vs.c_str(), gs.c_str(), fs.c_str()); }
//! \brief
bool Shader_program::init_with_vs_fs(const char* shader_file_prefix) {
std::string prefix(shader_file_prefix);
std::string vs = s_shader_path + prefix + "_vs.glsl";
std::string fs = s_shader_path + prefix + "_fs.glsl";
return init(vs, "", fs);
}
void Shader_program::add_shader(const char* shader_code, GLenum shader_type)
{
//! \brief
void Shader_program::add_shader(const char* shader_code, GLenum shader_type) {
GLuint the_shader = glCreateShader(shader_type);
const GLchar* the_code[] = { shader_code };
@ -76,14 +73,12 @@ void Shader_program::add_shader(const char* shader_code, GLenum shader_type)
GLint result = 0;
GLchar elog[1024] = { 0 };
glGetShaderiv(the_shader, GL_COMPILE_STATUS, &result);
if (!result)
{
if (! result) {
std::string shader_type_name;
switch (shader_type)
{
case GL_VERTEX_SHADER: shader_type_name = "VERTEX"; break;
case GL_GEOMETRY_SHADER: shader_type_name = "GEOMETRY"; break;
case GL_FRAGMENT_SHADER: shader_type_name = "FRAGMENT"; break;
switch (shader_type) {
case GL_VERTEX_SHADER: shader_type_name = "VERTEX"; break;
case GL_GEOMETRY_SHADER: shader_type_name = "GEOMETRY"; break;
case GL_FRAGMENT_SHADER: shader_type_name = "FRAGMENT"; break;
}
glGetShaderInfoLog(the_shader, sizeof(elog), NULL, elog);
std::cout << "! error compiling the " << shader_type_name <<
@ -93,33 +88,33 @@ void Shader_program::add_shader(const char* shader_code, GLenum shader_type)
glAttachShader(m_program, the_shader);
}
void Shader_program::add_shader_from_file(const char* shader_file,
GLenum shader_type)
{
if (strlen(shader_file) == 0)
return;
//! \brief
void Shader_program::add_shader_from_file(const char* shader_file,
GLenum shader_type) {
if (strlen(shader_file) == 0) return;
auto src = read_file(shader_file);
add_shader(src.c_str(), shader_type);
}
bool Shader_program::link()
{
//! \brief
bool Shader_program::link() {
GLint result = 0;
GLchar elog[1024] = { 0 };
glLinkProgram(m_program);
glGetProgramiv(m_program, GL_LINK_STATUS, &result);
if (!result)
{
if (! result) {
glGetProgramInfoLog(m_program, sizeof(elog), NULL, elog);
std::cout << "! error linking program:\n" << elog << std::endl;
return false;
}
return true;
}
bool Shader_program::validate()
{
//! \brief
bool Shader_program::validate() {
GLint result = 0;
GLchar elog[1024] = { 0 };
@ -134,47 +129,44 @@ bool Shader_program::validate()
return true;
}
GLint Shader_program::get_uniform_location(const GLchar* name)
{
//! \brief
GLint Shader_program::get_uniform_location(const GLchar* name) {
const auto uniform_loc = glGetUniformLocation(m_program, name);
return uniform_loc;
}
void Shader_program::use()
{
glUseProgram(m_program);
}
void Shader_program::unuse()
{
glUseProgram(0);
}
//! \brief
void Shader_program::use() { glUseProgram(m_program); }
//! \brief
void Shader_program::unuse() { glUseProgram(0); }
//! \brief
void Shader_program::set_uniform(GLint uniform_loc, const QMatrix4x4& m)
{
glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, m.data());
}
void Shader_program::set_uniform(const GLchar* name, const QMatrix4x4& m)
{
{ glUniformMatrix4fv(uniform_loc, 1, GL_FALSE, m.data()); }
//! \brief
void Shader_program::set_uniform(const GLchar* name, const QMatrix4x4& m) {
const auto uniform_loc = get_uniform_location(name);
set_uniform(uniform_loc, m);
}
//! \brief
void Shader_program::set_uniform(GLint uniform_loc, const QMatrix3x3& m)
{
glUniformMatrix3fv(uniform_loc, 1, GL_FALSE, m.data());
}
void Shader_program::set_uniform(const GLchar* name, const QMatrix3x3& m)
{
{ glUniformMatrix3fv(uniform_loc, 1, GL_FALSE, m.data()); }
//! \brief
void Shader_program::set_uniform(const GLchar* name, const QMatrix3x3& m) {
const auto uniform_loc = get_uniform_location(name);
set_uniform(uniform_loc, m);
}
//! \brief
void Shader_program::set_uniform(GLint uniform_loc, const QVector4D& v)
{
glUniform4f(uniform_loc, v.x(), v.y(), v.z(), v.w());
}
void Shader_program::set_uniform(const GLchar* name, const QVector4D& v)
{
{ glUniform4f(uniform_loc, v.x(), v.y(), v.z(), v.w()); }
//! \brief
void Shader_program::set_uniform(const GLchar* name, const QVector4D& v) {
const auto uniform_loc = get_uniform_location(name);
set_uniform(uniform_loc, v);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -12,22 +12,20 @@
#include <string>
#include <qmatrix4x4.h>
#include "Common_defs.h"
class Shader_program : protected OpenGLFunctionsBase
{
class Shader_program : protected OpenGLFunctionsBase {
public:
static void set_shader_path(const char* path);
bool init();
bool init(const char* vs, const char* gs, const char* fs);
bool init(const std::string& vs,
const std::string& gs,
bool init(const std::string& vs, const std::string& gs,
const std::string& fs);
// initialize with just the vertex and fragment shaders
/*! Initialize with just the vertex and fragment shaders
*/
bool init_with_vs_fs(const char* shader_file_prefix);
void add_shader(const char* shader_code, GLenum shader_type);
@ -51,8 +49,8 @@ public:
void set_uniform(const GLchar* name, const QVector4D& v);
private:
GLuint m_program;
static std::string s_shader_path;
GLuint m_program;
static std::string s_shader_path;
};

View File

@ -1,52 +0,0 @@
// 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 "Shapefile.h"
//
//#include <iostream>
//
//#include <shapefil.h>
//
//
//void Shapefile::read(const std::string& filename)
//{
// // Open the shapefile
// SHPHandle shp = SHPOpen(filename.c_str(), "rb");
// if (shp == nullptr) {
// std::cerr << "Failed to open shapefile: " << filename << std::endl;
// return;
// }
//
// // Get shapefile information
// int numEntities, shapeType;
// double minBounds[4], maxBounds[4];
// SHPGetInfo(shp, &numEntities, &shapeType, minBounds, maxBounds);
// std::cout << "Number of entities: " << numEntities << std::endl;
// std::cout << "Shape type: " << shapeType << std::endl;
// std::cout << "Bounds: (" << minBounds[0] << ", " << minBounds[1] << "), ("
// << maxBounds[0] << ", " << maxBounds[1] << ")" << std::endl;
// //SHPT_POLYGON
// // Read individual shapes
// for (int i = 0; i < numEntities; ++i) {
// SHPObject* shape = SHPReadObject(shp, i);
//
// // Process the shape data
// // Example: Print the shape's type and number of points
// std::cout << "Shape " << i << ": Type " << shape->nSHPType
// << ", Number of parts: " << shape->nParts
// << ", Number of points: " << shape->nVertices << std::endl;
//
// // Clean up the shape object
// SHPDestroyObject(shape);
// }
//
// // Close the shapefile
// SHPClose(shp);
//}

View File

@ -1,23 +0,0 @@
// 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 SHAPEFILE_H
//#define SHAPEFILE_H
//
//#include <string>
//
//
//class Shapefile
//{
//public:
// static void read(const std::string& filename);
//};
//
//#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,9 +9,8 @@
#include "Single_vertex.h"
Single_vertex::Single_vertex(const QVector3D& pos)
{
//!\brief
Single_vertex::Single_vertex(const QVector3D& pos) {
initializeOpenGLFunctions();
m_pos = pos;
@ -26,19 +25,14 @@ Single_vertex::Single_vertex(const QVector3D& pos)
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(m_pos);
auto vertex_buffer_data = reinterpret_cast<const void*>(&m_pos);
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_DYNAMIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 0;
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
@ -46,41 +40,33 @@ Single_vertex::Single_vertex(const QVector3D& pos)
glBindVertexArray(0);
}
//!\brief
void Single_vertex::set_visible(bool flag) { m_visible = flag; }
void Single_vertex::set_visible(bool flag)
{
m_visible = flag;
}
void Single_vertex::set_pos(const QVector3D& pos)
{
//!\brief
void Single_vertex::set_pos(const QVector3D& pos) {
m_pos = pos;
m_update = true;
}
const QVector3D& Single_vertex::get_pos() const
{
return m_pos;
}
//!\brief
const QVector3D& Single_vertex::get_pos() const { return m_pos; }
void Single_vertex::draw()
{
if (m_visible)
{
if (m_update)
{
//!\brief
void Single_vertex::draw() {
if (m_visible) {
if (m_update) {
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(m_pos);
auto vertex_buffer_data = reinterpret_cast<const void*>(&m_pos);
auto offset = 0;
glBufferSubData(GL_ARRAY_BUFFER,
offset,
vertex_buffer_size,
glBufferSubData(GL_ARRAY_BUFFER, offset, vertex_buffer_size,
vertex_buffer_data);
m_update = false;
}
glBindVertexArray(m_vao);
glDrawArrays(GL_POINTS, 0, 1);
glDrawArrays(GL_POINTS, 0, 1);
glBindVertexArray(0);
}
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -14,9 +14,7 @@
#include <qvector3d.h>
#include "Common_defs.h"
class Single_vertex : protected OpenGLFunctionsBase
{
class Single_vertex : protected OpenGLFunctionsBase {
public:
Single_vertex(const QVector3D& pos);
@ -27,9 +25,10 @@ public:
void draw();
private:
bool m_visible;
bool m_update = true; // flag to update the VBO (set_pos sets this)
GLuint m_vao, m_vbo;
bool m_visible;
bool m_update = true; // flag to update the VBO (set_pos sets this)
GLuint m_vao;
GLuint m_vbo;
QVector3D m_pos;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -7,16 +7,15 @@
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "Sphere.h"
#include <cmath>
#include <vector>
#include <qvector3d.h>
#include "Sphere.h"
Sphere::Sphere(int num_slices, int num_stacks, float r)
{
//! \brief
Sphere::Sphere(int num_slices, int num_stacks, float r) {
initializeOpenGLFunctions();
num_stacks = std::max<int>(2, num_stacks);
@ -31,15 +30,13 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
normals.push_back(QVector3D(0, 0, -1));
int starting_index_of_middle_vertices = vertices.size();
for (int j = 1; j < num_stacks; ++j)
{
for (int j = 1; j < num_stacks; ++j) {
// Calculate the latitude (vertical angle) for the current stack
float lat = M_PI * j / num_stacks;
float rxy = r * std::sin(lat);
float z = r * std::cos(lat);
for (int i = 0; i < num_slices; ++i)
{
for (int i = 0; i < num_slices; ++i) {
// Calculate the longitude (horizontal angle) for the current slice
float lon = 2 * M_PI * i / num_slices;
@ -56,8 +53,7 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
// strided vertex-data
std::vector<QVector3D> vertex_data;
for (int i = 0; i < vertices.size(); ++i)
{
for (int i = 0; i < vertices.size(); ++i) {
vertex_data.push_back(vertices[i]);
vertex_data.push_back(normals[i]);
}
@ -69,8 +65,7 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
// NORTH CAP
const int north_vertex_index = 0;
const int north_cap_vertex_index_start = starting_index_of_middle_vertices;
for (int i = 0; i < num_slices; i++)
{
for (int i = 0; i < num_slices; i++) {
indices.push_back(north_vertex_index);
indices.push_back(north_cap_vertex_index_start + i);
indices.push_back(north_cap_vertex_index_start + (i + 1) % num_slices);
@ -90,8 +85,7 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
const int south_vertex_index = 1;
const int south_cap_index_start = starting_index_of_middle_vertices +
(num_stacks - 2) * num_slices;
for (int i = 0; i < num_slices; ++i)
{
for (int i = 0; i < num_slices; ++i) {
const auto vi0 = south_vertex_index;
const auto vi1 = south_cap_index_start + i;
const auto vi2 = south_cap_index_start + (i + 1) % num_slices;
@ -101,13 +95,11 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
}
// MIDDLE TRIANGLES
for (int k = 0; k < num_stacks - 2; ++k)
{
for (int k = 0; k < num_stacks - 2; ++k) {
const int stack_start_index = starting_index_of_middle_vertices +
k * num_slices;
const int next_stack_start_index = stack_start_index + num_slices;
for (int i = 0; i < num_slices; ++i)
{
for (int i = 0; i < num_slices; ++i) {
// check why the following code snippet does not work (winding order?)
//int vi0 = stackStartIndex + i;
//int vi1 = nextStackStartIndex + i;
@ -129,7 +121,6 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
}
m_num_indices = indices.size();
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
@ -139,41 +130,30 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_ibo);
auto indices_size = sizeof(GLuint) * indices.size();
auto indices_data = reinterpret_cast<const void*>(indices.data());
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
indices_size,
indices_data,
GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_size, indices_data,
GL_STATIC_DRAW);
// Vertex Buffer
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(QVector3D) * vertex_data.size();
auto vertex_buffer_data = reinterpret_cast<const void*>(vertex_data.data());
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_STATIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 6 * sizeof(float);
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
position_offset);
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
// Normal Vertex-Attribute
GLint normal_attrib_index = 1;
auto* normal_offset = reinterpret_cast<const void*>(3 * sizeof(float));
glVertexAttribPointer(normal_attrib_index,
3,
GL_FLOAT,
GL_FALSE,
stride,
normal_offset);
glVertexAttribPointer(normal_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
normal_offset);
glEnableVertexAttribArray(normal_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
@ -182,17 +162,18 @@ Sphere::Sphere(int num_slices, int num_stacks, float r)
// Note: calling this before glBindVertexArray(0) results in no output!
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
//! \brief
void Sphere::set_color(float r, float g, float b, float a)
{
m_color = QVector4D(r, g, b, a);
}
void Sphere::draw()
{
{ m_color = QVector4D(r, g, b, a); }
//! \brief
void Sphere::draw() {
// DRAW TRIANGLES
glBindVertexArray(m_vao);
{
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, m_num_indices, GL_UNSIGNED_INT, 0);
}
//glDrawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
glDrawElements(GL_TRIANGLES, m_num_indices, GL_UNSIGNED_INT, 0);
glBindVertexArray(0);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -13,9 +13,7 @@
#include "Common_defs.h"
#include <qvector4d.h>
class Sphere : protected OpenGLFunctionsBase
{
class Sphere : protected OpenGLFunctionsBase {
public:
Sphere(int num_slices, int num_stacks, float r);
@ -25,7 +23,10 @@ public:
void draw();
private:
GLuint m_vao, m_vbo, m_ibo, m_num_indices;
GLuint m_vao;
GLuint m_vbo;
GLuint m_ibo;
GLuint m_num_indices;
QVector4D m_color;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -14,46 +14,33 @@
#include <iostream>
#include <string>
class Timer
{
class Timer {
public:
Timer()
{
reset();
}
Timer() { reset(); }
void reset()
{
m_Start = std::chrono::high_resolution_clock::now();
}
void reset() { m_Start = std::chrono::high_resolution_clock::now(); }
float elapsed()
{
float elapsed() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now() - m_Start).count()
std::chrono::high_resolution_clock::now() - m_Start).count()
* 0.001f * 0.001f * 0.001f;
}
float elapsed_millis()
{
return elapsed() * 1000.0f;
}
float elapsed_millis() { return elapsed() * 1000.0f; }
private:
std::chrono::time_point<std::chrono::high_resolution_clock> m_Start;
};
class ScopedTimer
{
class ScopedTimer {
public:
ScopedTimer(const std::string& name)
: m_Name(name) {}
~ScopedTimer()
{
ScopedTimer(const std::string& name) : m_Name(name) {}
~ScopedTimer() {
float time = m_Timer.elapsed_millis();
std::cout << "[TIMER] " << m_Name << " - " << time << "ms\n";
}
private:
std::string m_Name;
Timer m_Timer;

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -13,14 +13,12 @@
#include <iostream>
#include <vector>
std::string read_file(const std::string& file_name)
{
//! \brief
std::string read_file(const std::string& file_name) {
const auto flags = std::ios::in | std::ios::binary | std::ios::ate;
std::ifstream ifs(file_name.c_str(), flags);
if (ifs.is_open() == false)
{
if (! ifs.is_open()) {
std::cout << "could not open file: " << file_name << std::endl;
return "";
}
@ -34,18 +32,20 @@ std::string read_file(const std::string& file_name)
return std::string(&bytes[0], file_size);
}
std::ostream& operator << (std::ostream& os, const QVector2D& v)
{
//! \brief
std::ostream& operator << (std::ostream& os, const QVector2D& v) {
os << v.x() << ", " << v.y();
return os;
}
std::ostream& operator << (std::ostream& os, const QVector3D& v)
{
//! \brief
std::ostream& operator << (std::ostream& os, const QVector3D& v) {
os << v.x() << ", " << v.y() << ", " << v.z();
return os;
}
std::ostream& operator << (std::ostream& os, const QVector4D& v)
{
//! \brief
std::ostream& operator << (std::ostream& os, const QVector4D& v) {
os << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w();
return os;
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,7 +15,6 @@
#include <QVector2D>
#include <QVector3D>
std::string read_file(const std::string& file_name);
std::ostream& operator << (std::ostream& os, const QVector2D& v);

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -11,15 +11,13 @@
#include <iostream>
Triangles::Triangles(std::vector<QVector3D>& vertices)
{
//! \brief
Triangles::Triangles(std::vector<QVector3D>& vertices) {
initializeOpenGLFunctions();
// computer the normals of each vertex
std::vector<QVector3D> normals;
for(const auto& p : vertices)
{
for(const auto& p : vertices) {
auto n = p;
n.normalize();
normals.push_back(n);
@ -29,12 +27,10 @@ Triangles::Triangles(std::vector<QVector3D>& vertices)
// strided vertex-data
std::vector<QVector3D> vertex_data;
for (int i = 0; i < vertices.size(); ++i)
{
for (int i = 0; i < vertices.size(); ++i) {
vertex_data.push_back(vertices[i]);
vertex_data.push_back(normals[i]);
}
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
@ -46,30 +42,21 @@ Triangles::Triangles(std::vector<QVector3D>& vertices)
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(QVector3D) * vertex_data.size();
auto vertex_buffer_data = reinterpret_cast<const void*>(vertex_data.data());
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_STATIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 6 * sizeof(float);
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
// Normal Vertex-Attribute
GLint normal_attrib_index = 1;
auto* normal_offset = reinterpret_cast<const void*>(3 * sizeof(float));
glVertexAttribPointer(normal_attrib_index,
3,
GL_FLOAT,
GL_FALSE,
stride,
glVertexAttribPointer(normal_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
normal_offset);
glEnableVertexAttribArray(normal_attrib_index);
@ -77,20 +64,17 @@ Triangles::Triangles(std::vector<QVector3D>& vertices)
glBindVertexArray(0);
}
//! \brief
void Triangles::set_color(const QVector4D& rgba)
{
m_color = rgba;
}
const QVector4D& Triangles::get_color() const
{
return m_color;
}
{ m_color = rgba; }
void Triangles::draw()
{
//! \brief
const QVector4D& Triangles::get_color() const { return m_color; }
//! \brief
void Triangles::draw() {
// DRAW TRIANGLES
glBindVertexArray(m_vao);
glDrawArrays(GL_TRIANGLES, 0, m_num_vertices);
glDrawArrays(GL_TRIANGLES, 0, m_num_vertices);
glBindVertexArray(0);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -14,9 +14,7 @@
#include <qvector3d.h>
#include "Common_defs.h"
class Triangles : protected OpenGLFunctionsBase
{
class Triangles : protected OpenGLFunctionsBase {
public:
// IMPORTANT: we assume that the triangles are on the sphere!
// this means that all vertex-normals are actually the normal vector on the
@ -28,10 +26,11 @@ public:
const QVector4D& get_color() const;
void draw();
private:
GLuint m_vao, m_vbo;
int m_num_vertices;
GLuint m_vao;
GLuint m_vbo;
int m_num_vertices;
QVector4D m_color;
};

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -13,10 +13,10 @@
#include "Kml_reader.h"
void Verification::find_minimum_projected_error_on_sphere(float we, Camera& cam,
int vp_width, int vp_height)
{
void Verification::find_minimum_projected_error_on_sphere(float we,
Camera& cam,
int vp_width,
int vp_height) {
QRect vp(0, 0, vp_width, vp_height);
auto proj = cam.get_projection_matrix();
auto view = cam.get_view_matrix();
@ -33,14 +33,12 @@ void Verification::find_minimum_projected_error_on_sphere(float we, Camera& cam,
const float r1 = 1.f;
const float r2 = r1 - we;
for (int i = 0; i <= num_divs; i++)
{
for (int i = 0; i <= num_divs; ++i) {
const float theta = dtheta * i;
const float cos_theta = std::cos(theta);
const float sin_theta = std::sin(theta);
for (int j = 0; j <= num_divs; j++)
{
for (int j = 0; j <= num_divs; ++j) {
QVector3D p1, p2;
const float phi = dphi * j;
const float cos_phi = std::cos(phi);
@ -62,8 +60,7 @@ void Verification::find_minimum_projected_error_on_sphere(float we, Camera& cam,
auto wp2 = p2.project(model_view, proj, vp);
const auto pe = wp1.distanceToPoint(wp2);
if (max_err < pe)
{
if (max_err < pe) {
max_err = pe;
max_theta = theta;
max_phi = phi;
@ -99,8 +96,8 @@ void Verification::find_minimum_projected_error_on_sphere(float we, Camera& cam,
//std::cout << QVector3D(0, 0, 0).project(model_view, proj, vp) << std::endl;
}
void Verification::verify_antarctica_node_is_redundant()
{
//! \brief
void Verification::verify_antarctica_node_is_redundant() {
Kml::Node n1(178.277211542064, -84.4725179992025),
n2(180.0, -84.71338),
n3(-179.942499356179, -84.7214433735525);
@ -116,11 +113,11 @@ void Verification::verify_antarctica_node_is_redundant()
// 2) check if it is between its neighbors (check if r,s > 0)
auto det = [](float ax, float ay, float bx, float by)
{ return ax * by - ay * bx; };
{ return ax * by - ay * bx; };
auto D = det(v1.x(), v1.y(), v3.x(), v3.y());
auto Dr = det(v2.x(), v2.y(), v3.x(), v3.y());
auto Ds = det(v1.x(), v1.y(), v2.x(), v2.y());
auto r = Dr / D;
auto s = Ds / D;
std::cout << "r = " << r << "\ns=" << s << std::endl;
}
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,23 +15,18 @@
#include "Camera.h"
//
// This class contains code to verify or compute certain hypotheses
//
class Verification
{
class Verification {
public:
// Use this to find the approximate of the true minimum projected error.
// we are ot using this complicated method, but provide it for completeness.
static void find_minimum_projected_error_on_sphere(float we, Camera& cam,
int vp_width, int vp_height);
static void find_minimum_projected_error_on_sphere(float we, Camera& cam,
int vp_width,
int vp_height);
// verify that the node (180.0, -84.71338) in Antarctica is redundant
static void verify_antarctica_node_is_redundant();
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -9,9 +9,8 @@
#include "Vertices.h"
Vertices::Vertices(const std::vector<QVector3D>& vertices)
{
//! brief
Vertices::Vertices(const std::vector<QVector3D>& vertices) {
initializeOpenGLFunctions();
auto& vertex_data = vertices;
@ -26,31 +25,24 @@ Vertices::Vertices(const std::vector<QVector3D>& vertices)
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(QVector3D) * vertex_data.size();
auto vertex_buffer_data = reinterpret_cast<const void*>(vertex_data.data());
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_STATIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 0;
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
position_offset);
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
void Vertices::draw()
{
//! brief
void Vertices::draw() {
glBindVertexArray(m_vao);
{
glDrawArrays(GL_POINTS, 0, m_num_indices);
}
glDrawArrays(GL_POINTS, 0, m_num_indices);
glBindVertexArray(0);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -12,20 +12,20 @@
#include <vector>
#include <qvector3d.h>
#include "Common_defs.h"
class Vertices : protected OpenGLFunctionsBase
{
class Vertices : protected OpenGLFunctionsBase {
public:
Vertices(const std::vector<QVector3D>& vertices);
void draw();
private:
GLuint m_vao, m_vbo, m_num_indices;
std::vector<GLuint> m_offsets;
GLuint m_vao;
GLuint m_vbo;
GLuint m_num_indices;
std::vector<GLuint> m_offsets;
};
#endif

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -7,15 +7,14 @@
//
// Author(s): Engin Deniz Diktas <denizdiktas@gmail.com>
#include "World_coordinate_axes.h"
#include <vector>
#include <qvector3d.h>
#include "World_coordinate_axes.h"
World_coord_axes::World_coord_axes(float length)
{
//! \brief
World_coord_axes::World_coord_axes(float length) {
initializeOpenGLFunctions();
const auto a = length;
@ -31,41 +30,30 @@ World_coord_axes::World_coord_axes(float length)
QVector3D(0,0,a), QVector3D(c,c,1)
};
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
// Vertex Buffer
glGenBuffers(1, &m_vbo);
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
auto vertex_buffer_size = sizeof(QVector3D) * vertex_data.size();
auto vertex_buffer_data = reinterpret_cast<const void*>(vertex_data.data());
glBufferData(GL_ARRAY_BUFFER,
vertex_buffer_size,
vertex_buffer_data,
GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertex_buffer_size, vertex_buffer_data,
GL_STATIC_DRAW);
// Position Vertex-Attribute
GLint position_attrib_index = 0;
const void* position_offset = 0;
GLsizei stride = 6 * sizeof(float);
glVertexAttribPointer(position_attrib_index,
3,
GL_FLOAT, GL_FALSE,
stride,
glVertexAttribPointer(position_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
// Color Vertex-Attribute
GLint color_attrib_index = 1;
auto* color_offset = reinterpret_cast<const void*>(3 * sizeof(float));
glVertexAttribPointer(color_attrib_index,
3,
GL_FLOAT,
GL_FALSE,
stride,
glVertexAttribPointer(color_attrib_index, 3, GL_FLOAT, GL_FALSE, stride,
color_offset);
glEnableVertexAttribArray(color_attrib_index);
@ -73,12 +61,10 @@ World_coord_axes::World_coord_axes(float length)
glBindVertexArray(0);
}
void World_coord_axes::draw()
{
//! \brief
void World_coord_axes::draw() {
glBindVertexArray(m_vao);
{
const int count = 2 * 3; // = 2 * number of lines
glDrawArrays(GL_LINES, 0, count);
}
const int count = 2 * 3; // = 2 * number of lines
glDrawArrays(GL_LINES, 0, count);
glBindVertexArray(0);
}

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -10,19 +10,19 @@
#ifndef WORLD_COORD_AXES_H
#define WORLD_COORD_AXES_H
#include "Common_defs.h"
#include <qvector4d.h>
#include "Common_defs.h"
class World_coord_axes : protected OpenGLFunctionsBase
{
class World_coord_axes : protected OpenGLFunctionsBase {
public:
World_coord_axes(float length);
void draw();
private:
GLuint m_vao, m_vbo;
GLuint m_vao;
GLuint m_vbo;
};

View File

@ -1,10 +1,19 @@
#ifndef _PRINT_ARR_H_
#define _PRINT_ARR_H_
//-----------------------------------------------------------------------------
// Print all neighboring vertices to a given arrangement vertex.
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
template<class Arrangement>
// 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>
// : Efi Fogel <efifogel@gmail.com>
#ifndef PRINT_ARR_H
#define PRINT_ARR_H
/*! Print all neighboring vertices to a given arrangement vertex.
*/
template <typename Arrangement>
void print_neighboring_vertices(typename Arrangement::Vertex_const_handle v) {
if (v->is_isolated()) {
std::cout << "The vertex (" << v->point() << ") is isolated\n";
@ -19,10 +28,9 @@ void print_neighboring_vertices(typename Arrangement::Vertex_const_handle v) {
std::cout << std::endl;
}
//-----------------------------------------------------------------------------
// Print all vertices (points) and edges (curves) along a connected component
// boundary.
//
/*! Print all vertices (points) and edges (curves) along a connected component
* boundary.
*/
template <typename Arrangement>
void print_ccb(typename Arrangement::Ccb_halfedge_const_circulator circ) {
std::cout << "(" << circ->source()->point() << ")";
@ -35,9 +43,8 @@ void print_ccb(typename Arrangement::Ccb_halfedge_const_circulator circ) {
std::cout << std::endl;
}
//-----------------------------------------------------------------------------
// Print the boundary description of an arrangement face.
//
/*! Print the boundary description of an arrangement face.
*/
template <typename Arrangement>
void print_face(typename Arrangement::Face_const_handle f) {
// Print the outer boundary.
@ -66,9 +73,8 @@ void print_face(typename Arrangement::Face_const_handle f) {
}
}
//-----------------------------------------------------------------------------
// Print the given arrangement.
//
/*! Print the given arrangement.
*/
template <typename Arrangement>
void print_arrangement(const Arrangement& arr) {
CGAL_precondition(arr.is_valid());
@ -92,9 +98,8 @@ void print_arrangement(const Arrangement& arr) {
print_face<Arrangement>(fit);
}
//-----------------------------------------------------------------------------
// Print the size of the given arrangement.
//
/*! Print the size of the given arrangement.
*/
template <typename Arrangement>
void print_arrangement_size(const Arrangement& arr) {
std::cout << "The arrangement size:\n"
@ -103,9 +108,8 @@ void print_arrangement_size(const Arrangement& arr) {
<< ", |F| = " << arr.number_of_faces() << std::endl;
}
//-----------------------------------------------------------------------------
// Print the size of the given unbounded arrangement.
//
/*! Print the size of the given unbounded arrangement.
*/
template <typename Arrangement>
void print_unbounded_arrangement_size(const Arrangement& arr) {
std::cout << "The arrangement size:\n"

View File

@ -1,4 +1,4 @@
// Copyright(c) 2012, 2020 Tel - Aviv University(Israel).
// Copyright(c) 2023, 2024 Tel-Aviv University (Israel).
// All rights reserved.
//
// This file is part of CGAL (www.cgal.org).
@ -15,19 +15,14 @@
#include "Main_widget.h"
#endif
int main(int argc, char* argv[])
{
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
auto args = QCoreApplication::arguments();
if (2 != args.size())
{
qDebug() << "Usage: earth <arragement-file.json>";
exit(1);
if (args.size() > 2) {
qDebug() << "Usage: earth [<arragement-file.json>]";
return(-1);
}
QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
@ -40,7 +35,8 @@ int main(int argc, char* argv[])
app.setApplicationName("Earth");
app.setApplicationVersion("0.1");
#ifndef QT_NO_OPENGL
auto& file_name = args.at(1);
const char* file_name = (argc > 1) ? argv[1] :
"../../../Data/data/arrangements_3/sphere/ne_110m_admin_0_countries.json";
//qDebug() << "file name = " << file_name;
Main_widget widget(file_name);
widget.show();