Merge remote-tracking branch 'cgal/master' into Triangulation_3-CDT_3-lrineau

This commit is contained in:
Laurent Rineau 2024-04-26 14:40:04 +02:00
commit b828719c7c
179 changed files with 369490 additions and 949 deletions

View File

@ -36,7 +36,7 @@ namespace CGAL
std::declval<int>())) reference;
// typedef decltype(
// typename GeomTraits::Construct_vertex_3()(
// *std::declval<key_type&>(), 0)) reference; // fails polyhedron demo!
// *std::declval<key_type&>(), 0)) reference; // fails CGAL Lab!
typedef boost::readable_property_map_tag category;
typedef Point_from_cell_iterator_proprety_map<GeomTraits, Iterator> Self;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,84 @@
// 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 AOS_H
#define AOS_H
#include <map>
#include <memory>
#include <vector>
#include <qvector3d.h>
#include "Kml_reader.h"
class Aos {
public:
using Approx_arc = std::vector<QVector3D>;
using Approx_arcs = std::vector<Approx_arc>;
//using Arr_handle = void*;
using Arr_handle = std::shared_ptr<void>;
static Approx_arc get_approx_identification_curve(double error);
// this constructs some sample arcs manually (used to check the visual output)
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 void get_curves();
static void check(const Kml::Placemarks& placemarks);
// Extended check: here we use the extended version of the DCEL to understand
// what is going on with the additional vertices and faces.
// INPUT: GIS data
// 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
static std::vector<QVector3D> ext_check_id_based(Kml::Placemarks& placemarks);
// This function is used to find the newly-created faces during arrangement
// construction. It uses the extended DCEL structure (see: above 2 functions).
// NOTE: The need for this function arises due to the following observation:
// when constructing the arrangement from our data-set I observed a newly
// created face which is not defined explicitly in the data-set. My intiution
// tells me that this is the Caspian sea, because it is the only land-locked
// polygon whose boundaries are not defined in the data-set and its boundaries
// are defined indirecly by its surrounding countries.
static Approx_arcs find_new_faces(Kml::Placemarks& placemarks);
// save the arrangement created with EPEC
static void save_arr(Kml::Placemarks& placemarks,
const std::string& file_name);
// loads the arrangement created by the save_arr function
// NOTE: This one loads the arrangement as "Country_arr" type
static Arr_handle load_arr(const std::string& file_name);
static Arr_handle construct(Kml::Placemarks& placemarks);
//static std::vector<QVector3D> get_triangles(Arr_handle arrh);
//using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>;
//static Country_triangles_map get_triangles_by_country(Arr_handle arrh);
using Country_color_map = std::map<std::string, std::size_t>;
static Country_color_map get_color_mapping(Arr_handle arrh);
static std::string locate_country(Arr_handle arrh, const QVector3D& point);
// this will get the approximate arcs of face-edges from the arrangement
// NOTE: this is similar to "get_approx_arcs(KML::Placemarks&, double)" above!
static Approx_arcs get_approx_arcs_from_faces_edges(Arr_handle arrh,
double error);
};
#endif

View File

@ -0,0 +1,47 @@
// 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 AOS_DEFS_H
#define AOS_DEFS_H
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Arrangement_on_surface_2.h>
#include <CGAL/Arr_extended_dcel.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Arr_spherical_topology_traits_2.h>
#include <CGAL/Vector_3.h>
//#define USE_EPIC
#ifdef USE_EPIC
using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel;
#else
using Kernel = CGAL::Exact_predicates_exact_constructions_kernel;
#endif
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>;
// the following is from "arr_inexact_construction_segments.h":
using Segment = Geom_traits::X_monotone_curve_2;
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>;
using Countries_arr =
CGAL::Arrangement_on_surface_2<Geom_traits, Countries_topol_traits>;
#endif

View File

@ -0,0 +1,318 @@
// 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>
#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>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Constrained_Delaunay_triangulation_2.h>
// #include <CGAL/draw_triangulation_2.h>
#include <CGAL/mark_domain_in_triangulation.h>
#include <CGAL/Polygon_2.h>
#include <CGAL/point_generators_3.h>
#include <CGAL/Arr_batched_point_location.h>
#include "Aos_defs.h"
#include "Aos_triangulator.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;
using Approximate_number_type = Geom_traits::Approximate_number_type;
using Approximate_kernel = Geom_traits::Approximate_kernel;
using Approximate_Vector_3 = CGAL::Vector_3<Approximate_kernel>;
using Approximate_Direction_3 = Approximate_kernel::Direction_3;
using Direction_3 = Kernel::Direction_3;
}
//! \brief
std::vector<QVector3D> Aos_triangulator::get_all(Aos::Arr_handle arrh) {
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using Vb = CGAL::Triangulation_vertex_base_2<K>;
using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
using Face_handle = CDT::Face_handle;
using Polygon_2 = CGAL::Polygon_2<K>;
auto& arr = *reinterpret_cast<Arrangement*>(arrh.get());
//Geom_traits traits;
auto approx = s_traits.approximate_2_object();
std::vector<std::vector<QVector3D>> all_faces;
// loop on all faces of the arrangement
for (auto fh : arr.face_handles()) {
// skip any face with no OUTER-CCB
if (0 == fh->number_of_outer_ccbs()) continue;
// COMPUTE THE CENTROID OF ALL FACE-POINTS
std::vector<QVector3D> face_points;
// loop on the egdes of the current outer-ccb
auto first = fh->outer_ccb();
auto curr = first;
do {
auto ap = approx(curr->source()->point());
QVector3D p(ap.dx(), ap.dy(), ap.dz());
p.normalize();
face_points.push_back(p);
} while (++curr != first);
all_faces.push_back(std::move(face_points));
}
// RESULTING TRIANGLE POINTS (every 3 point => triangle)
std::vector<QVector3D> triangles;
std::cout << "triangulating individual faces\n";
// loop on all approximated faces
for (auto& face_points : all_faces) {
std::cout << "num face points = " << face_points.size() << std::endl;
// no need to triangulate if the number of points is 3
if (face_points.size() == 3) {
triangles.insert(triangles.end(), face_points.begin(), face_points.end());
continue;
}
// find the centroid of all face-points
QVector3D centroid(0, 0, 0);
for (const auto& fp : face_points) centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
K::Point_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
K::Plane_3 plane(plane_origin, plane_normal);
Polygon_2 polygon;
// project all points onto the plane
K::Point_3 origin(0, 0, 0);
for (const auto& fp : face_points) {
// define a ray through the origin and the current point
K::Point_3 current_point(fp.x(), fp.y(), fp.z());
K::Ray_3 ray(origin, current_point);
auto intersection = CGAL::intersection(plane, ray);
if (!intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = std::get<K::Point_3>(intersection.value());
auto ip2 = plane.to_2d(ip);
// add this to the polygon constraint
polygon.push_back(ip2);
}
CDT cdt;
cdt.insert_constraint(polygon.vertices_begin(), polygon.vertices_end(),
true);
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool>>
in_domain(in_domain_map);
//Mark facets that are inside the domain bounded by the polygon
CGAL::mark_domain_in_triangulation(cdt, in_domain);
// loop on all the triangles ("faces" in triangulation doc)
for (Face_handle f : cdt.finite_face_handles()) {
// if the current triangles is not inside the polygon -> skip it
if (! get(in_domain, f)) continue;
for (int i = 0; i < 3; ++i) {
auto tp = f->vertex(i)->point();
auto tp3 = plane.to_3d(tp);
QVector3D p3(tp3.x(), tp3.y(), tp3.z());
p3.normalize();
triangles.push_back(p3);
}
}
}
return triangles;
}
//! \brief
Country_triangles_map
Aos_triangulator::get_by_country(Aos::Arr_handle arrh, float error,
std::size_t num_uniform_points) {
using K = CGAL::Exact_predicates_inexact_constructions_kernel;
using Pnt_2 = typename K::Point_2;
using Pnt_3 = typename K::Point_3;
using Vb = CGAL::Triangulation_vertex_base_2<K>;
using Fb = CGAL::Constrained_triangulation_face_base_2<K>;
using TDS = CGAL::Triangulation_data_structure_2<Vb, Fb>;
using Itag = CGAL::Exact_predicates_tag;
using CDT = CGAL::Constrained_Delaunay_triangulation_2<K, TDS, Itag>;
using Face_handle = CDT::Face_handle;
using Approximate_point_2 = Geom_traits::Approximate_point_2;
using Aos = Countries_arr;
using Aos_pnt = Aos::Point_2;
auto& arr = *reinterpret_cast<Aos*>(arrh.get());
auto approx = s_traits.approximate_2_object();
// group the faces by their country name
using Face_const_handle = Countries_arr::Face_const_handle;
std::map<std::string, std::vector<Face_const_handle>> country_faces_map;
for (auto fh : arr.face_handles()) {
const auto& country_name = fh->data();
// skipping spherical-face
if (country_name.empty()) continue;
country_faces_map[country_name].push_back(fh);
}
// Generate random point uniformly distributed
std::vector<Pnt_3> rps;
rps.reserve(num_uniform_points);
CGAL::Random_points_in_sphere_3<Pnt_3> g(1.0);
std::copy_n(g, rps.capacity(), std::back_inserter(rps));
std::map<Face_const_handle, std::vector<Pnt_3>> face_random_points;
using Point_location_result = CGAL::Arr_point_location_result<Aos>;
using Query_result = std::pair<Aos_pnt, Point_location_result::Type>;
std::vector<Aos_pnt> rqs(rps.size());
auto ctr_p = arr.geometry_traits()->construct_point_2_object();
std::transform(rps.begin(), rps.end(), rqs.begin(),
[&](const Pnt_3& rp) -> Aos_pnt {
return ctr_p(rp.x(), rp.y(), rp.z());
});
std::list<Query_result> results;
CGAL::locate(arr, rqs.begin(), rqs.end(), std::back_inserter(results));
for (auto& [q, res] : results) {
const Aos::Face_const_handle* f;
if ((f = std::get_if<Face_const_handle>(&res))) {
auto x = CGAL::to_double(q.dx());
auto y = CGAL::to_double(q.dy());
auto z = CGAL::to_double(q.dz());
face_random_points[*f].push_back(Pnt_3(x, y, z));
}
}
// Triangulate the faces
Country_triangles_map result;
for (auto& [country_name, fhs] : country_faces_map) {
// std::cout << "processing country " << country_name << std::endl;
auto& triangles = result[country_name];
// CONVERT the face-points to QVector3D
for (auto fh : fhs) {
// skip any face with no OUTER-CCB
if (0 == fh->number_of_outer_ccbs()) continue;
std::vector<QVector3D> face_points;
// Loop on the egdes of the current outer-ccb
auto first = fh->outer_ccb();
auto curr = first;
do {
std::vector<Approximate_point_2> apx_points;
const auto& xcv = curr->curve();
approx(xcv, error, std::back_insert_iterator(apx_points),
curr->direction() == CGAL::ARR_LEFT_TO_RIGHT);
for (auto it = apx_points.begin(); it != apx_points.end()-1; ++it) {
const auto& apx_p = *it;
const QVector3D p(apx_p.dx(), apx_p.dy(), apx_p.dz());
face_points.push_back(p);
}
} while (++curr != first);
// no need to triangulate if the number of points is 3
if (face_points.size() == 3) {
triangles.insert(triangles.end(), face_points.begin(),
face_points.end());
continue;
}
// Calculate the centroid of all face-points
QVector3D centroid(0, 0, 0);
for (const auto& fp : face_points) centroid += fp;
centroid /= face_points.size();
centroid.normalize();
auto normal = centroid;
Pnt_3 plane_origin(centroid.x(), centroid.y(), centroid.z());
K::Vector_3 plane_normal(normal.x(), normal.y(), normal.z());
K::Plane_3 plane(plane_origin, plane_normal);
// Project all points onto the plane
std::vector<Pnt_2> planar_points(face_points.size());
std::transform(face_points.begin(), face_points.end(),
planar_points.begin(),
[&](const QVector3D& fp) -> Pnt_2 {
// define a ray through the origin and the current point
Pnt_3 p3(fp.x(), fp.y(), fp.z());
K::Ray_3 ray(CGAL::ORIGIN, p3);
auto intersection = CGAL::intersection(plane, ray);
if (! intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = std::get<Pnt_3>(intersection.value());
return plane.to_2d(ip);
});
CDT cdt;
// Insert points uniformly distributed into the triangulation
auto it = face_random_points.find(fh);
if (it != face_random_points.end()) {
const auto& points = it->second;
for (const auto& p3 : points) {
K::Ray_3 ray(CGAL::ORIGIN, p3);
auto intersection = CGAL::intersection(plane, ray);
if (! intersection.has_value())
std::cout << "INTERSECTION ASSERTION ERROR!!!\n";
auto ip = std::get<Pnt_3>(intersection.value());
auto p2 = plane.to_2d(ip);
cdt.insert(p2);
}
}
// Insert the constraints into the triangulation
cdt.insert_constraint(planar_points.begin(), planar_points.end(), true);
// Mark facets that are inside the domain bounded by the polygon
std::unordered_map<Face_handle, bool> in_domain_map;
boost::associative_property_map< std::unordered_map<Face_handle, bool>>
in_domain(in_domain_map);
CGAL::mark_domain_in_triangulation(cdt, in_domain);
// Loop on all the triangles ("faces" in triangulation doc)
for (Face_handle f : cdt.finite_face_handles()) {
// If the current triangles is not inside the polygon -> skip it
if (! get(in_domain, f)) continue;
for (int i = 0; i < 3; ++i) {
auto tp = f->vertex(i)->point();
auto tp3 = plane.to_3d(tp);
QVector3D p3(tp3.x(), tp3.y(), tp3.z());
p3.normalize();
triangles.push_back(p3);
}
}
}
}
return result;
}

View File

@ -0,0 +1,31 @@
// 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 AOS_TRIANGULATOR_H
#define AOS_TRIANGULATOR_H
#include <map>
#include <vector>
#include <qvector3d.h>
#include "Aos.h"
using Country_triangles_map = std::map<std::string, std::vector<QVector3D>>;
class Aos_triangulator {
public:
static std::vector<QVector3D> get_all(Aos::Arr_handle arrh);
static Country_triangles_map get_by_country(Aos::Arr_handle arrh,
float error,
std::size_t num_uniform_points);
};
#endif

View File

@ -0,0 +1,128 @@
# This is the CMake script for compiling a CGAL application.
cmake_minimum_required(VERSION 3.1...3.23)
project(Arrangement_on_surface_2_earth_Demo)
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()
if(POLICY CMP0071)
cmake_policy(SET CMP0071 NEW)
endif()
find_package(Qt6 QUIET COMPONENTS Core Gui OpenGL OpenGLWidgets Widgets Xml)
find_package(CGAL COMPONENTS Qt6)
find_package(nlohmann_json 3.9)
if (NOT CGAL_FOUND OR NOT CGAL_Qt6_FOUND OR NOT Qt6_FOUND OR NOT Boost_FOUND OR NOT nlohmann_json_FOUND)
if (NOT CGAL_FOUND)
set(MISSING_DEPS "the CGAL library, ${MISSING_DEPS}")
endif()
if (NOT CGAL_Qt6_FOUND)
set(MISSING_DEPS "the CGAL Qt6 component, ${MISSING_DEPS}")
endif()
if (NOT Qt6_FOUND)
set(MISSING_DEPS "the Qt6 library, ${MISSING_DEPS}")
endif()
if (NOT Boost_FOUND)
set(MISSING_DEPS "the Boost library, ${MISSING_DEPS}")
endif()
if (NOT nlohmann_json_FOUND)
set(MISSING_DEPS "JSON for Modern C++ 3.9+ (know as nlohmann_json), ${MISSING_DEPS}")
endif()
message(STATUS "This project requires ${MISSING_DEPS} and will not be compiled.")
return()
endif()
add_definitions(-DQT_NO_VERSION_TAGGING)
# AOS
file(GLOB source_files_aos Aos.h Aos.cpp Aos_defs.h
Aos_triangulator.h Aos_triangulator.cpp)
source_group("Aos" FILES ${source_files_aos})
# GIS
file(GLOB source_files_gis Kml_reader.h Kml_reader.cpp)
source_group("GIS" FILES ${source_files_gis})
# GRAPHICS
file(GLOB source_files_graphics Camera.h Camera.cpp
Shader_program.h Shader_program.cpp)
source_group("Graphics" FILES ${source_files_graphics})
# GRAPHICS-GEOMETRY (Graphics-related)
file(GLOB source_files_graphics_geometry
Line_strips.h Line_strips.cpp
Single_vertex.h Single_vertex.cpp
Sphere.h Sphere.cpp
Triangles.h Triangles.cpp
Vertices.h Vertices.cpp
World_coordinate_axes.h World_coordinate_axes.cpp)
source_group("Graphics_Geometry" FILES ${source_files_graphics_geometry})
# GUI
file(GLOB source_files_gui
Camera_manip.h Camera_manip.cpp
Camera_manip_rot.h Camera_manip_rot.cpp
Camera_manip_rot_bpa.h Camera_manip_rot_bpa.cpp
Camera_manip_zoom.h Camera_manip_zoom.cpp
GUI_country_pick_handler.h GUI_country_pick_handler.cpp
GUI_event_handler.h GUI_event_handler.cpp)
source_group("GUI" FILES ${source_files_gui})
#SOURCE FILES (NOT CATEGORIZED YET)
file(GLOB source_files Common_defs.h earth.cpp Timer.h
Main_widget.h Main_widget.cpp
Message_manager.h Message_manager.cpp
Tools.h Tools.cpp
Verification.h Verification.cpp)
source_group("Source Files" FILES ${source_files})
set(CMAKE_AUTOMOC ON)
qt_add_executable(earth
${source_files_aos}
${source_files_gis}
${source_files_graphics}
${source_files_graphics_geometry}
${source_files_gui}
${source_files}
)
set_target_properties(earth PROPERTIES
WIN32_EXECUTABLE TRUE
MACOSX_BUNDLE TRUE
)
if (MSVC)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /SUBSYSTEM:CONSOLE")
endif (MSVC)
target_link_libraries(earth PRIVATE
Qt6::Core
Qt6::Gui
Qt6::OpenGL
Qt6::OpenGLWidgets
Qt6::Widgets
Qt6::Xml
CGAL::CGAL
CGAL::Data
nlohmann_json::nlohmann_json)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/shaders
DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
# install(TARGETS earth
# RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
# BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
# LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
# )
add_to_cached_list(CGAL_EXECUTABLE_TARGETS earth)
include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake)
cgal_add_compilation_test(earth)

View File

@ -0,0 +1,101 @@
// 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 "Camera.h"
//! \brief
Camera::Camera() :
m_ux(1, 0, 0),
m_uy(0, 1, 0),
m_uz(0, 0, 1)
{}
//! \brief
void Camera::perspective(qreal fov, qreal aspect, qreal z_near, qreal z_far) {
m_z_near = z_near;
m_z_far = z_far;
m_projection.setToIdentity();
m_projection.perspective(fov, aspect, z_near, z_far);
}
//! \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;
}
//! \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);
//auto pos = m_pos.toVector4D(); pos.setW(1);
//auto uy = m_uy.toVector4D(); uy.setW(0);
//auto uz = m_uz.toVector4D(); uz.setW(0);
//pos = pos * rot;
//uy = uy * rot;
//uz = uz * rot;
//m_pos = pos.toVector3D();
//m_uy = uy.toVector3D();
//m_uz = uz.toVector3D();
QMatrix4x4 r1;
QVector3D ey(0, 1, 0);
r1.rotate(theta, ey);
// rx = rotated x axis
auto rx = r1.map(QVector3D(1, 0, 0));
QMatrix4x4 r2;
r2.rotate(phi, rx);
// total rotation:
auto r = r2 * r1;
const auto dist_cam_to_origin = m_pos.length();
m_pos = r.map(QVector3D(0, 0, dist_cam_to_origin));
m_ux = r.map(QVector3D(1, 0, 0)); // should be the same as rx (sanity check?)
m_uy = r.map(QVector3D(0, 1, 0));
m_uz = r.map(QVector3D(0, 0, 1));
}
//! \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);
}
//! \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;
}
//! \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);
}
//! \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

@ -0,0 +1,58 @@
// 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 CAMERA_H
#define CAMERA_H
#include <qvector3d.h>
#include <qmatrix4x4.h>
class Camera {
public:
Camera();
void set_pos(const QVector3D& pos) { m_pos = pos; }
void set_pos(float x, float y, float z) { m_pos = QVector3D(x,y,z); }
const QVector3D& get_pos() const { return m_pos; }
void perspective(qreal fov, qreal aspect_ratio, qreal z_near, qreal z_far);
qreal 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);
void rotate(QMatrix4x4 rot);
// save config & rotate from saved config (move to separate class?)
void save_config();
void rotate_from_saved_config(QMatrix4x4 rot);
// move the camera forward around its own z-axis
void move_forward(float distance);
private:
QVector3D m_pos;
QVector3D m_ux;
QVector3D m_uy;
QVector3D m_uz;
QVector3D m_saved_pos;
QVector3D m_saved_ux;
QVector3D m_saved_uy;
QVector3D m_saved_uz;
qreal m_z_near, m_z_far;
QMatrix4x4 m_projection;
};
#endif

View File

@ -0,0 +1,12 @@
// 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 "Camera_manip.h"
Camera_manip::Camera_manip(Camera& camera) : m_camera(camera) {}

View File

@ -0,0 +1,28 @@
// 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 CAMERA_MANIP_H
#define CAMERA_MANIP_H
#include <qevent.h>
#include <qvector2d.h>
#include "Camera.h"
#include "GUI_event_handler.h"
class Camera_manip : public GUI_event_handler {
public:
Camera_manip(Camera& camera);
protected:
Camera& m_camera;
};
#endif

View File

@ -0,0 +1,21 @@
// 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 "Camera_manip_rot.h"
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) {
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

@ -0,0 +1,30 @@
// 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 CAMERA_MANIP_ROT_H
#define CAMERA_MANIP_ROT_H
#include <qevent.h>
#include <qvector2d.h>
#include "Camera_manip.h"
class Camera_manip_rot : public Camera_manip {
public:
Camera_manip_rot(Camera& camera);
protected:
virtual void mouse_move_event(QMouseEvent* e) override;
private:
float m_theta = 0;
float m_phi = 0;
};
#endif

View File

@ -0,0 +1,61 @@
// 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 "Camera_manip_rot_bpa.h"
//! \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();
}
//! \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
//QVector3D p0(m_last_mouse_pos.x(), m_vp_height - m_last_mouse_pos.y(), 0);
QVector3D p0(m_mouse_press_pos.x(), m_vp_height - m_mouse_press_pos.y(), 0);
QVector3D p1(m_current_mouse_pos.x(), m_vp_height - m_current_mouse_pos.y(), 0);
auto dp = p1 - p0; // difference vector in OpenGL window coords.
QVector3D rdp(-dp.y(), dp.x(), 0); // rotate diff-vector CCW by 90-deg
QVector3D rp = p0 + rdp; // r1 rotated CCW by 90 deg
QMatrix4x4 model; // this is different from Sphere's model matrix!!!
auto proj = m_camera.get_projection_matrix();
auto view = m_camera.get_view_matrix();
auto model_view = view * model;
QRect viewport(0, 0, m_vp_width, m_vp_height);
auto wp0 = p0.unproject(model_view, proj, viewport);
auto wrp = rp.unproject(model_view, proj, viewport);
// rotation axis & angle
auto rot_axis = wrp - wp0;
rot_axis.normalize();
const auto rot_angle = rotation_scale_factor * dp.length();
QMatrix4x4 rot_matrix;
rot_matrix.rotate(-rot_angle, rot_axis);
m_camera.rotate_from_saved_config(rot_matrix);
}
//! \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

@ -0,0 +1,32 @@
// 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 CAMERA_MANIP_ROT_BPA_H
#define CAMERA_MANIP_ROT_BPA_H
#include <qevent.h>
#include <qvector2d.h>
#include "Camera_manip.h"
class Camera_manip_rot_bpa : public Camera_manip {
public:
Camera_manip_rot_bpa(Camera& camera);
protected:
virtual void mouse_press_event(QMouseEvent* e) override;
virtual void mouse_move_event(QMouseEvent* e) override;
virtual void mouse_release_event(QMouseEvent* e) override;
virtual void resize(int w, int h) override;
private:
int m_vp_width, m_vp_height;
};
#endif

View File

@ -0,0 +1,29 @@
// 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 "Camera_manip_zoom.h"
#include "Message_manager.h"
Camera_manip_zoom::Camera_manip_zoom(Camera& camera) : Camera_manip(camera) {}
//! \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);
}
}
//! \brief
void Camera_manip_zoom::mouse_release_event(QMouseEvent* e) {
if (e->button() == Qt::MiddleButton)
Message_manager::notify_all("zoom_changed");
}

View File

@ -0,0 +1,27 @@
// 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 CAMERA_MANIP_ZOOM_H
#define CAMERA_MANIP_ZOOM_H
#include <qevent.h>
#include <qvector2d.h>
#include "Camera_manip.h"
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;
};
#endif

View File

@ -0,0 +1,18 @@
// 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 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

@ -0,0 +1,108 @@
// 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 "GUI_country_pick_handler.h"
//#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())
{}
//! \brief
void GUI_country_pick_handler::mouse_press_event(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_main_widget.get_model_matrix();
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_main_widget.set_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;
auto pos = o + ti * u;
m_main_widget.set_mouse_pos(pos);
static std::string prev_picked_country;
auto& arrh = m_main_widget.get_arr_handle();
auto picked_country = Aos::locate_country(arrh, pos);
m_main_widget.hightlight_country(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 (!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;
}
}
//! \brief
void GUI_country_pick_handler::resize(int w, int h) {
m_vp_width = w;
m_vp_height = h;
}

View File

@ -0,0 +1,34 @@
// 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 GUI_COUNTRY_PICK_HANDLER_H
#define GUI_COUNTRY_PICK_HANDLER_H
#include <qevent.h>
#include <qvector2d.h>
#include "GUI_event_handler.h"
#include "Main_widget.h"
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;
int m_vp_height;
};
#endif

View File

@ -0,0 +1,57 @@
// 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 "GUI_event_handler.h"
//! \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:
m_middle_mouse_button_down = flag;
break;
default: break;
}
}
//! \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);
}
//! \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;
// call the function overridden by the derived class
mouse_move_event(e);
m_last_mouse_pos = m_current_mouse_pos;
}
//! \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);
}
//! \brief
void GUI_event_handler::resizeGL(int w, int h) { resize(w, h); }

View File

@ -0,0 +1,42 @@
// 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 GUI_EVENT_HANDLER_H
#define GUI_EVENT_HANDLER_H
#include <qevent.h>
#include <qvector2d.h>
class GUI_event_handler {
public:
virtual ~GUI_event_handler() {};
void mousePressEvent(QMouseEvent* e);
void mouseMoveEvent(QMouseEvent* e);
void mouseReleaseEvent(QMouseEvent* e);
void resizeGL(int w, int h);
protected:
void set_mouse_button_pressed_flag(QMouseEvent* e, bool flag);
virtual void mouse_press_event(QMouseEvent* /* e */) {}
virtual void mouse_move_event(QMouseEvent* /* e */) {}
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;
QVector2D m_last_mouse_pos;
QVector2D m_mouse_press_pos;
QVector2D m_diff;
};
#endif

View File

@ -0,0 +1,143 @@
// 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>
#include <vector>
#include <qmath.h>
#include <qvector3d.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arrangement_on_surface_2.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Arr_spherical_topology_traits_2.h>
#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 Dir3 = Kernel::Direction_3;
std::ostream& operator << (std::ostream& os, const Dir3& d) {
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
using Approximate_point_2 = Geom_traits::Approximate_point_2;
std::ostream& operator << (std::ostream& os, const Approximate_point_2& d) {
os << d.dx() << ", " << d.dy() << ", " << d.dz();
return os;
}
using Approximate_number_type = Geom_traits::Approximate_number_type;
using Approximate_kernel = Geom_traits::Approximate_kernel;
using Approximate_Vector_3 = CGAL::Vector_3<Approximate_kernel>;
using Approximate_Direction_3 = Approximate_kernel::Direction_3;
using Direction_3 = Kernel::Direction_3;
std::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;
}
auto Geodesic_arcs::get_approx_arcs(double error) -> Approx_arcs {
// Construct the arrangement from 12 geodesic arcs.
Geom_traits traits;
Arrangement arr(&traits);
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
std::vector<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)));
//xcvs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 1, 0), Dir3(0, 0, -1)));
//xcvs.push_back(ctr_cv(Dir3(0, 0, -1)));
auto approx = traits.approximate_2_object();
std::vector<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) {
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;
}
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) {
// colect all rings into a single list (FOR NOW!!!)
// TO-DO: PROCESS OUTER & INNER BOUNDARIES SEPARATELY!!!
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);
// 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) {
const auto p = node.get_coords_3d();
Approximate_Vector_3 v(p.x, p.y, p.z);
sphere_points.push_back(v);
}
// add geodesic arcs for the current LinearRing
int num_points = sphere_points.size();
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()),
ctr_p(p2.x(), p2.y(), p2.z())));
}
}
}
auto approx = traits.approximate_2_object();
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) {
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;
}

View File

@ -0,0 +1,30 @@
// 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
#include <vector>
#include <qvector3d.h>
#include "Kml_reader.h"
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);
};
#endif

View File

@ -0,0 +1,404 @@
// 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 <algorithm>
#include <iostream>
#include <unordered_map>
#include <limits>
#include <qdebug.h>
#include <qfile.h>
#include <qxmlstream.h>
#include "Kml_reader.h"
//! \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); }
//! \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);
const auto rxy = r * std::cos(phi);
const auto x = rxy * std::cos(theta);
const auto y = rxy * std::sin(theta);
return Vec3d{ (double)x, (double)y, (double)z };
}
//! \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);
}
//! \brief
std::ostream& operator << (std::ostream& os, const Kml::Node& n) {
os << n.lon << ", " << n.lat;
return os;
}
//! \brief
std::size_t Kml::get_number_of_polygons(Placemarks& placemarks) {
std::size_t total_number_of_polygons = 0;
for (auto& placemark : placemarks)
total_number_of_polygons += placemark.polygons.size();
return total_number_of_polygons;
}
//! \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)) {
QXmlStreamReader xmlReader;
xmlReader.setDevice(&file);
xmlReader.readNext();
// Reading from the file
while (!xmlReader.isEndDocument()) {
QString name = xmlReader.name().toString();
if (xmlReader.isStartElement()) {
if (name == "Placemark") {
placemark = Placemark{};
}
else if (name == "Polygon") {
polygon = Polygon{};
}
else if (name == "LinearRing") {
lring = LinearRing{};
}
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;
auto coord_strs = node_str.split(",");
const auto lon = coord_strs[0].toDouble();
const auto lat = coord_strs[1].toDouble();
lring.nodes.push_back(Node{ lon, lat });
}
}
else if (name == "SimpleData") {
auto attributes = xmlReader.attributes();
auto attr_name = attributes[0].name().toString();
auto attr_value = attributes[0].value().toString();
if ((attr_name == "name") && (attr_value == "ADMIN"))
{
xmlReader.readNext();
placemark.name = xmlReader.text().toString().toStdString();;
}
}
}
else if (xmlReader.isEndElement()) {
if (name == "Placemark")
{
placemarks.push_back(std::move(placemark));
}
else if (name == "Polygon") {
placemark.polygons.push_back(std::move(polygon));
}
else if (name == "outerBoundaryIs") {
polygon.outer_boundary = std::move(lring);
}
else if (name == "innerBoundaryIs") {
polygon.inner_boundaries.push_back(std::move(lring));
}
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") {
// no need to do anything here: the coordinates are read above!
}
}
xmlReader.readNext();
}
if (xmlReader.hasError()) {
std::cout << "XML error: " << xmlReader.errorString().data() << std::endl;
}
}
return placemarks;
}
//! \brief
Kml::Nodes Kml::get_duplicates(const Placemarks& placemarks) {
// collect all nodes into a single vector
std::size_t polygon_count = 0;
std::vector<Kml::Node> nodes;
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);
}
}
}
qDebug() << "polygon count = " << polygon_count;
auto count = nodes.size();
std::vector<std::size_t> num_duplicates(count, 0);
qDebug() << "node count (with duplicates) = " << count;
std::size_t dup_count = 0;
// this keeps track of how many nodes there are with certain dup-count
std::unordered_map<std::size_t, std::size_t> dup_count_map;
Nodes duplicate_nodes;
for (std::size_t 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<std::size_t> curr_dup; // current set of duplicates
for (std::size_t j = i + 1; j < count; ++j) {
if (curr_node == nodes[j]) curr_dup.push_back(j);
}
// if duplicates found
if (!curr_dup.empty()) {
++dup_count;
std::size_t 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;
duplicate_nodes.push_back(curr_node);
dup_count_map[num_dup]++;
}
}
qDebug() << "dup count = " << dup_count;
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;
}
return duplicate_nodes;
}
//! \brief
Kml::Nodes Kml::generate_ids(Placemarks& placemarks) {
// collect all nodes into a single vector
// std::size_t polygon_count = 0;
std::vector<Node> nodes;
for (auto& pm : placemarks) {
for (auto& polygon : pm.polygons) {
// polygon_count++;
std::vector<LinearRing*> linear_rings;
linear_rings.push_back(&polygon.outer_boundary);
for (auto& inner_boundary : polygon.inner_boundaries)
linear_rings.push_back(&inner_boundary);
for (auto* lring : linear_rings) {
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) {
// insert new node
nodes.push_back(node);
const std::size_t node_id = nodes.size() - 1;
lring->ids.push_back(node_id);
}
else {
// get the existing node
const std::size_t 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 (std::size_t i = 0; i < lring->nodes.size(); ++i)
assert(lring->nodes[i] == nodes[lring->ids[i]]);
}
}
}
return nodes;
}
//! \breif
Kml::Nodes Kml::generate_ids_approx(Placemarks& placemarks, const double eps) {
// collect all nodes into a single vector
// std::size_t polygon_count = 0;
std::vector<Node> nodes;
for (auto& pm : placemarks) {
for (auto& polygon : pm.polygons) {
// ++polygon_count;
std::vector<LinearRing*> linear_rings;
linear_rings.push_back(&polygon.outer_boundary);
for (auto& inner_boundary : polygon.inner_boundaries)
linear_rings.push_back(&inner_boundary);
for (auto* lring : linear_rings) {
lring->ids.clear();
for (const auto& node : lring->nodes) {
// check if there is a node sufficiently close to the current one
auto node_index = std::numeric_limits<std::size_t>::max();
for (std::size_t i = 0; i < nodes.size(); ++i) {
const auto dist = node.distance_to(nodes[i]);
if (dist < eps) {
node_index = i;
break;
}
}
if (node_index == std::numeric_limits<std::size_t>::max()) {
// insert new node
nodes.push_back(node);
const auto node_id = nodes.size() - 1;
lring->ids.push_back(node_id);
}
else {
// get the existing node
const auto node_id = node_index;
lring->ids.push_back(node_id);
}
auto it = std::unique(lring->ids.begin(), lring->ids.end());
std::vector<std::size_t> new_ids(lring->ids.begin(), it);
if (new_ids.size() < lring->ids.size())
std::cout << "** REDUCED!\n";
lring->ids = std::move(new_ids);
}
}
}
}
// find the pair of closest nodes
double min_dist = std::numeric_limits<double>::max();
std::size_t ni1 = 0;
std::size_t ni2 = 0;
std::size_t num_nodes = nodes.size();
for (std::size_t i = 0; i < num_nodes - 1; ++i) {
for (std::size_t j = i + 1; j < num_nodes; ++j) {
const auto dist = nodes[i].distance_to(nodes[j]);
if (min_dist > dist) {
min_dist = dist;
ni1 = i;
ni2 = j;
}
}
}
std::cout << "min dist = " << min_dist << std::endl;
std::cout << "node 1 = " << nodes[ni1] << std::endl;
std::cout << "node 2 = " << nodes[ni2] << std::endl;
std::cout << "node 1 = " << nodes[ni1].get_coords_3d() << std::endl;
std::cout << "node 2 = " << nodes[ni2].get_coords_3d() << std::endl;
return nodes;
}
//! \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) {
auto source_first = inner_boundary.nodes.begin();
auto source_last = inner_boundary.nodes.end();
all_nodes.insert(all_nodes.begin(), source_first, source_last);
}
return all_nodes;
}
//! \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)
linear_rings.push_back(&inner_boundary);
return linear_rings;
}
//! \brief
Kml::Nodes Kml::Placemark::get_all_nodes() const {
Nodes all_nodes;
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());
all_nodes.insert(all_nodes.end(), first, last);
}
return all_nodes;
}
//! \brief
std::size_t Kml::Placemark::get_all_nodes_count() const {
std::size_t num_nodes = 0;
for (const auto& polygon : polygons) {
auto polygon_nodes = polygon.get_all_nodes();
num_nodes += polygon_nodes.size();
}
return num_nodes;
}
//! \brief
Kml::Arcs Kml::LinearRing::get_arcs() const {
Arcs arcs;
const auto num_nodes = nodes.size();
for (std::size_t 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;
}
//! \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 {
Arcs all_arcs;
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);
}
return all_arcs;
}

View File

@ -0,0 +1,100 @@
// 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 KML_READER_H
#define KML_READER_H
#include <iostream>
#include <string>
#include <vector>
#include <qvector3d.h>
class Kml {
public:
// double precision 3D-point (QVector3D has float coordinates)
struct Vec3d {
double x, y, z;
friend std::ostream& operator << (std::ostream& os, const Vec3d& v) {
os << v.x << ", " << v.y << ", " << v.z;
return os;
}
};
struct Node {
double lon, lat;
Node() : lon(-1111), lat(-1111) {};
Node(double longitude, double latitude) : lon(longitude), lat(latitude) {};
double distance_to(const Node& r) const;
bool operator == (const Node& r) const;
Vec3d get_coords_3d(const double r = 1.0) const;
QVector3D get_coords_3f(const double r=1.0) const;
friend std::ostream& operator << (std::ostream& os, const Node& n);
};
using Nodes = std::vector<Node>;
struct Arc {
Node from, to;
};
using Arcs = std::vector<Arc>;
struct LinearRing {
std::vector<Node> nodes;
std::vector<std::size_t> ids;
Arcs get_arcs() const;
void get_arcs(Arcs& arcs) const;
};
using LinearRings = std::vector<LinearRing>;
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 {
std::vector<Polygon> polygons;
std::string name;
// collects all nodes from all polygons
Nodes get_all_nodes() const;
std::size_t get_all_nodes_count() const;
Arcs get_all_arcs() const;
};
using Placemarks = std::vector<Placemark>;
static std::size_t get_number_of_polygons(Placemarks& placemarks);
static Placemarks read(const std::string& file_name);
static Nodes get_duplicates(const Placemarks& placemarks);
// Outputs all used nodes without duplications!
// NOTE: this function modifies Placemarks data-structure!
static Nodes generate_ids(Placemarks& placemarks);
// same as above but by collapsing close-by nodes based on distance bound
static Nodes generate_ids_approx(Placemarks& placemarks, const double eps);
};
#endif

View File

@ -0,0 +1,112 @@
// 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 "Line_strips.h"
//! \brief
Line_strips::Line_strips(std::vector<QVector3D>& line_strip_points) {
initializeOpenGLFunctions();
std::vector<QVector3D> vertex_data;
m_offsets.push_back(0);
for (const auto& p : line_strip_points)
vertex_data.push_back(p);
const auto end_of_current_arc_points = static_cast<GLuint>(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);
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);
// 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);
glEnableVertexAttribArray(position_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//! \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);
const auto end_of_current_arc_points = static_cast<GLuint>(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);
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);
// 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);
glEnableVertexAttribArray(position_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//! \brief
std::size_t Line_strips::get_num_line_strips() const
{ return m_offsets.size() - 1; }
//! \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);
glBindVertexArray(0);
}
//! \brief
void Line_strips::draw() {
glBindVertexArray(m_vao);
for (std::size_t 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

@ -0,0 +1,35 @@
// 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 LINE_STRIPS_H
#define LINE_STRIPS_H
#include <vector>
#include <qvector3d.h>
#include "Common_defs.h"
class Line_strips : protected OpenGLFunctionsBase {
public:
Line_strips(std::vector<QVector3D>& line_strip_points);
Line_strips(std::vector<std::vector<QVector3D>>& arcs);
std::size_t get_num_line_strips() const;
void draw(int line_strip_index);
void draw();
private:
GLuint m_vao;
GLuint m_vbo;
std::vector<GLuint> m_offsets;
};
#endif

View File

@ -0,0 +1,394 @@
// 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 "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 "GUI_country_pick_handler.h"
#include "Kml_reader.h"
#include "Message_manager.h"
#include "Timer.h"
#include "Tools.h"
#include "Verification.h"
//! \brief
Main_widget::Main_widget(const QString& file_name) : m_file_name(file_name) {}
//! \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); }
//! \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.c_str();
}
prev_picked_country = country_name;
}
//! \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);
update();
}
//! \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);
update();
}
//! \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);
update();
}
//! \brief
// void Main_widget::timerEvent(QTimerEvent* event) { update(); }
//! \brief
void Main_widget::keyPressEvent(QKeyEvent* /* event */) {}
//! \brief
void Main_widget::initializeGL() {
m_pick_handler = std::make_unique<GUI_country_pick_handler>(*this);
QVector3D initial_mouse_pos(0, -1, 0);
m_gr_mouse_vertex = std::make_unique<Single_vertex>(initial_mouse_pos);
initializeOpenGLFunctions();
init_camera();
init_geometry();
init_shader_programs();
m_current_approx_error = 0.001f;
m_num_uniform_points = 4096;
qDebug() << "loading arrangement..";
m_arrh = Aos::load_arr(m_file_name.toStdString());
if (m_arrh == nullptr) {
std::string msg("Error: failed to load file ");
msg += m_file_name.toStdString();
throw std::runtime_error(msg);
return;
}
init_country_borders(m_current_approx_error);
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, m_current_approx_error,
m_num_uniform_points);
//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); };
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 *= m_dimming_factor;
color.setW(1);
country_triangles->set_color(color);
//country_triangles->set_color(colors[color_map[country_name]]);
m_gr_country_triangles.emplace(country_name, std::move(country_triangles));
}
country_triangles_map.clear();
//qDebug() << "num triangles = " << triangle_points.size() / 3;
//m_gr_all_triangles = std::make_unique<Triangles>(triangle_points);
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);
}
//! \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);
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);
});
}
//! \brief
void Main_widget::init_geometry() {
// SPHERE
std::size_t num_slices = 64;
std::size_t num_stacks = 64;
float r = 1.0f;
m_gr_sphere = std::make_unique<Sphere>(num_slices, num_stacks, r);
const float c = 0.8f;
m_gr_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_gr_identification_curve = std::make_unique<Line_strips>(approx_ident_curve);
const float axes_length = 2;
m_gr_world_coord_axes = std::make_unique<World_coord_axes>(axes_length);
}
//! \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");
}
//! \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);
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_country_borders = std::make_unique<Line_strips>(all_approx_arcs);
}
//! \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();
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;
}
//! \brief
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;
}
//! \brief
template<typename T>
void draw_safe(T& ptr) { if (ptr) ptr->draw(); }
//! \brief
void Main_widget::paintGL() {
if (m_update_approx_error) {
const auto error = compute_backprojected_error(0.5);
qDebug() << "current error = " << m_current_approx_error;
qDebug() << "new approx error = " << error;
if (error < m_current_approx_error) {
init_country_borders(error);
m_current_approx_error = error;
auto ratio = static_cast<double>(m_current_approx_error) / error;
m_num_uniform_points *= ratio*ratio;
std::cout << "num uniform points = " << m_num_uniform_points
<< std::endl;
}
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().map(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);
// SMOTH RENDERING
{
glEnable(GL_DEPTH_TEST);
auto& sp = m_sp_smooth;
sp.use();
// SPHERE
{
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_gr_sphere->draw();
}
// DRAW SOLID FACES
{
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_gr_all_triangles->draw();
for (auto& [country_name, country] : m_gr_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_gr_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_gr_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_gr_identification_curve->draw();
// draw all countries' borders
float a = 0.0;
sp.set_uniform("u_color", QVector4D(a, a, a, 1));
m_gr_all_country_borders->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_gr_mouse_vertex->set_pos(m_mouse_pos);
draw_safe(m_gr_mouse_vertex);
}
sp.unuse();
}
}

View File

@ -0,0 +1,139 @@
// 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 MAIN_WIDGET_H
#define MAIN_WIDGET_H
#include <functional>
#include <memory>
#include <QOpenGLWidget>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QVector2D>
#include <QBasicTimer>
#include <qopenglwidget.h>
#include "Aos.h"
#include "Camera.h"
#include "Camera_manip.h"
#include "Common_defs.h"
#include "GUI_event_handler.h"
#include "Kml_reader.h"
#include "Line_strips.h"
#include "Shader_program.h"
#include "Single_vertex.h"
#include "Sphere.h"
#include "Triangles.h"
#include "Vertices.h"
#include "World_coordinate_axes.h"
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; }
void set_mouse_pos(const QVector3D mouse_pos);
void hightlight_country(const std::string& country_name);
protected:
void mousePressEvent(QMouseEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
// void timerEvent(QTimerEvent* e) override;
void keyPressEvent(QKeyEvent* event) override;
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void init_camera();
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
// 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;
// used when dimming / highlighting selected countries
const float m_dimming_factor = 0.4f;
// GUI: event handler for picking with right mouse button
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;
// TRIANGLES for rendering the countries in solid
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<World_coord_axes> m_gr_world_coord_axes;
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;
// 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;
// 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-
// mation error is needed the necessary graphics-side updates need to be made
// INSIDE the paintGL (or whereever the OpenGL context is active)!
bool m_update_approx_error = false;
float m_current_approx_error;
std::size_t m_num_uniform_points;
// Timer for continuous screen-updates
// QBasicTimer m_timer;
// <-- COMMON SETUP FOR ALL SCENES
// -------------------------------
};
#endif

View File

@ -0,0 +1,150 @@
// 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 MAIN_WIDGET_H
#define MAIN_WIDGET_H
#include <QOpenGLWidget>
#include <QMatrix4x4>
#include <QQuaternion>
#include <QVector2D>
#include <QBasicTimer>
#include <functional>
#include <memory>
#include <qopenglwidget.h>
#include "Aos.h"
#include "Camera.h"
#include "Camera_manip.h"
#include "Common_defs.h"
#include "GUI_event_handler.h"
#include "Kml_reader.h"
#include "Line_strips.h"
#include "Shader_program.h"
#include "SingleVertex.h"
#include "Sphere.h"
#include "Triangles.h"
#include "Vertices.h"
#include "World_coordinate_axes.h"
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; }
void set_mouse_pos(const QVector3D mouse_pos) { m_mouse_pos = mouse_pos; }
void hightlight_country(const std::string& country_name);
protected:
void mousePressEvent(QMouseEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
void timerEvent(QTimerEvent* e) override;
void keyPressEvent(QKeyEvent* event) override;
void initializeGL() override;
void resizeGL(int w, int h) override;
void paintGL() override;
void init_camera();
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
// 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;
// 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<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;
// 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;
// COUNTRY DATA
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;
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;
// Camera & controls
Camera m_camera;
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;
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-
// mation error is needed the necessary graphics-side updates need to be made
// INSIDE the paintGL (or whereever the OpenGL context is active)!
bool m_update_approx_error = false;
float m_current_approx_error;
// Timer for continuous screen-updates
QBasicTimer m_timer;
};
#endif

View File

@ -0,0 +1,25 @@
// 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 "Message_manager.h"
std::map<std::string, Message_manager::Callbacks>
Message_manager::s_message_map;
void Message_manager::add(const std::string& msg_name,
std::function<void()> callback)
{ s_message_map[msg_name].push_back(callback); }
void Message_manager::notify_all(const std::string& msg_name) {
auto it = s_message_map.find(msg_name);
if (s_message_map.cend() != it) {
auto& callbacks = it->second;
for (auto& cb : callbacks) cb();
}
}

View File

@ -0,0 +1,29 @@
// 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
#include <functional>
#include <map>
#include <string>
#include <vector>
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;
};
#endif

View File

@ -0,0 +1,172 @@
// 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 "Tools.h"
#include "Shader_program.h"
std::string Shader_program::s_shader_path;
//! \brief
void Shader_program::set_shader_path(const char* path)
{ s_shader_path = std::string(path); }
//! \brief
bool Shader_program::init() {
initializeOpenGLFunctions();
m_program = glCreateProgram();
if (! m_program) {
std::cout << "error creating shader program!\n";
return false;
}
return true;
}
//! \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);
add_shader_from_file(fs, GL_FRAGMENT_SHADER);
link();
validate();
return true;
}
//! \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()); }
//! \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);
}
//! \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 };
GLint code_length[] = { static_cast<GLint>(strlen(shader_code)) };
glShaderSource(the_shader, 1, the_code, code_length);
glCompileShader(the_shader);
GLint result = 0;
GLchar elog[1024] = { 0 };
glGetShaderiv(the_shader, GL_COMPILE_STATUS, &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;
}
glGetShaderInfoLog(the_shader, sizeof(elog), NULL, elog);
std::cout << "! error compiling the " << shader_type_name <<
" shader:\n" << elog << std::endl;
return;
}
glAttachShader(m_program, the_shader);
}
//! \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);
}
//! \brief
bool Shader_program::link() {
GLint result = 0;
GLchar elog[1024] = { 0 };
glLinkProgram(m_program);
glGetProgramiv(m_program, GL_LINK_STATUS, &result);
if (! result) {
glGetProgramInfoLog(m_program, sizeof(elog), NULL, elog);
std::cout << "! error linking program:\n" << elog << std::endl;
return false;
}
return true;
}
//! \brief
bool Shader_program::validate() {
GLint result = 0;
GLchar elog[1024] = { 0 };
glValidateProgram(m_program);
glGetProgramiv(m_program, GL_VALIDATE_STATUS, &result);
if (!result)
{
glGetProgramInfoLog(m_program, sizeof(elog), NULL, elog);
std::cout << "! error validating program:\n" << elog << std::endl;
return false;
}
return true;
}
//! \brief
GLint Shader_program::get_uniform_location(const GLchar* name) {
const auto uniform_loc = glGetUniformLocation(m_program, name);
return uniform_loc;
}
//! \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()); }
//! \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()); }
//! \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()); }
//! \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

@ -0,0 +1,57 @@
// 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 SHADER_PROGRAM_H
#define SHADER_PROGRAM_H
#include <string>
#include <qmatrix4x4.h>
#include "Common_defs.h"
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,
const std::string& fs);
/*! 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);
void add_shader_from_file(const char* shader_file, GLenum shader_type);
bool link();
bool validate();
GLint get_uniform_location(const GLchar* name);
void use();
void unuse();
void set_uniform(GLint uniform_loc, const QMatrix4x4& m);
void set_uniform(const GLchar* name, const QMatrix4x4& m);
void set_uniform(GLint uniform_loc, const QMatrix3x3& m);
void set_uniform(const GLchar* name, const QMatrix3x3& m);
void set_uniform(GLint uniform_loc, const QVector4D& v);
void set_uniform(const GLchar* name, const QVector4D& v);
private:
GLuint m_program;
static std::string s_shader_path;
};
#endif

View File

@ -0,0 +1,72 @@
// 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 "Single_vertex.h"
//!\brief
Single_vertex::Single_vertex(const QVector3D& pos) {
initializeOpenGLFunctions();
m_pos = pos;
m_visible = true;
// 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(m_pos);
auto vertex_buffer_data = reinterpret_cast<const void*>(&m_pos);
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,
position_offset);
glEnableVertexAttribArray(position_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//!\brief
void Single_vertex::set_visible(bool flag) { m_visible = flag; }
//!\brief
void Single_vertex::set_pos(const QVector3D& pos) {
m_pos = pos;
m_update = true;
}
//!\brief
const QVector3D& Single_vertex::get_pos() const { return m_pos; }
//!\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,
vertex_buffer_data);
m_update = false;
}
glBindVertexArray(m_vao);
glDrawArrays(GL_POINTS, 0, 1);
glBindVertexArray(0);
}
}

View File

@ -0,0 +1,36 @@
// 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 SINGLE_VERTEX_H
#define SINGLE_VERTEX_H
#include <vector>
#include <qvector3d.h>
#include "Common_defs.h"
class Single_vertex : protected OpenGLFunctionsBase {
public:
Single_vertex(const QVector3D& pos);
void set_visible(bool flag);
void set_pos(const QVector3D& pos);
const QVector3D& get_pos() const;
void draw();
private:
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;
};
#endif

View File

@ -0,0 +1,178 @@
// 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 <cmath>
#include <vector>
#include <qvector3d.h>
#include "Sphere.h"
//! \brief
Sphere::Sphere(std::size_t num_slices, std::size_t num_stacks, float r) {
initializeOpenGLFunctions();
num_stacks = std::max<std::size_t>(2, num_stacks);
std::vector<QVector3D> vertices, normals;
// NORTH POLE
vertices.push_back(QVector3D(0, 0, r));
normals.push_back(QVector3D(0, 0, 1));
// SOUTH POLE
vertices.push_back(QVector3D(0, 0, -r));
normals.push_back(QVector3D(0, 0, -1));
auto starting_index_of_middle_vertices = vertices.size();
for (std::size_t 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 (std::size_t i = 0; i < num_slices; ++i) {
// Calculate the longitude (horizontal angle) for the current slice
float lon = 2 * M_PI * i / num_slices;
// Convert spherical coordinates to Cartesian coordinates
float x = rxy * std::cos(lon);
float y = rxy * std::sin(lon);
auto p = QVector3D(x, y, z);
auto n = p / p.length();
vertices.push_back(p);
normals.push_back(n);
}
}
// strided vertex-data
std::vector<QVector3D> vertex_data;
for (std::size_t i = 0; i < vertices.size(); ++i) {
vertex_data.push_back(vertices[i]);
vertex_data.push_back(normals[i]);
}
// add the indices for all triangles
std::vector<GLuint> indices;
// NORTH CAP
const GLuint north_vertex_index = 0;
const auto north_cap_vertex_index_start = starting_index_of_middle_vertices;
for (std::size_t i = 0; i < num_slices; ++i) {
indices.push_back(north_vertex_index);
indices.push_back(static_cast<GLuint>(north_cap_vertex_index_start + i));
indices.push_back(static_cast<GLuint>(north_cap_vertex_index_start + (i + 1) % num_slices));
}
// 0 = NORTH VERTEX
// 1 = SOUTH VERTEX
// [2, 2 + (numSlices-1)] = bottom vertices of the stack #1
// [2+numSlices, 2 + (2*numSlices - 1)] = bottom vertices of the stack #2
// ...
// [2+(k-1)*numSlices, 2 + (k*numSlices -1)] = bottom vertices of the stack #k
// ..
// [2+(numStacks-1)*numSlices, 2+(numStacks*numSlices-1)] = bottom vertices of
// the last stack (# numStacks)
// SOUTH CAP
const GLuint south_vertex_index = 1;
const std::size_t south_cap_index_start = starting_index_of_middle_vertices +
(num_stacks - 2) * num_slices;
for (std::size_t i = 0; i < num_slices; ++i) {
const auto vi0 = south_vertex_index;
const auto vi1 = static_cast<GLuint>(south_cap_index_start + i);
const auto vi2 = static_cast<GLuint>(south_cap_index_start + (i + 1) % num_slices);
indices.push_back(vi2);
indices.push_back(vi1);
indices.push_back(vi0);
}
// MIDDLE TRIANGLES
for (std::size_t k = 0; k < num_stacks - 2; ++k) {
const std::size_t stack_start_index =
starting_index_of_middle_vertices + k * num_slices;
const std::size_t next_stack_start_index = stack_start_index + num_slices;
for (std::size_t i = 0; i < num_slices; ++i) {
// check why the following code snippet does not work (winding order?)
//std::size_t vi0 = stackStartIndex + i;
//std::size_t vi1 = nextStackStartIndex + i;
//std::size_t vi2 = nextStackStartIndex + (i + 1) % numSlices;
//std::size_t vi3 = stackStartIndex + (i + 1) % numSlices;
auto vi0 = static_cast<GLuint>(stack_start_index + i);
auto vi1 = static_cast<GLuint>(stack_start_index + (i + 1) % num_slices);
auto vi2 = static_cast<GLuint>(next_stack_start_index + i);
auto vi3 = static_cast<GLuint>(next_stack_start_index + (i + 1) % num_slices);
indices.push_back(vi0);
indices.push_back(vi2);
indices.push_back(vi1);
//
indices.push_back(vi2);
indices.push_back(vi3);
indices.push_back(vi1);
}
}
m_num_indices = static_cast<GLuint>(indices.size());
// DEFINE OPENGL BUFFERS
glGenVertexArrays(1, &m_vao);
glBindVertexArray(m_vao);
// Index buffer
glGenBuffers(1, &m_ibo);
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);
// 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);
// 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);
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);
glEnableVertexAttribArray(normal_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
// 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); }
//! \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);
glBindVertexArray(0);
}

View File

@ -0,0 +1,34 @@
// 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 SPHERE_H
#define SPHERE_H
#include "Common_defs.h"
#include <qvector4d.h>
class Sphere : protected OpenGLFunctionsBase {
public:
Sphere(std::size_t num_slices, std::size_t num_stacks, float r);
void set_color(float r, float g, float b, float a);
const QVector4D& get_color() { return m_color; }
void draw();
private:
GLuint m_vao;
GLuint m_vbo;
GLuint m_ibo;
GLuint m_num_indices;
QVector4D m_color;
};
#endif

View File

@ -0,0 +1,50 @@
// 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 TIMER_H
#define TIMER_H
#include <chrono>
#include <iostream>
#include <string>
class Timer {
public:
Timer() { reset(); }
void reset() { m_Start = std::chrono::high_resolution_clock::now(); }
double elapsed() {
return std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::high_resolution_clock::now() - m_Start).count() *
0.001 * 0.001 * 0.001;
}
double elapsed_millis() { return elapsed() * 1000.0f; }
private:
std::chrono::time_point<std::chrono::high_resolution_clock> m_Start;
};
class ScopedTimer {
public:
ScopedTimer(const std::string& name) : m_name(name) {}
~ScopedTimer() {
double time = m_timer.elapsed_millis();
std::cout << "[TIMER] " << m_name << " - " << time << "ms\n";
}
private:
std::string m_name;
Timer m_timer;
};
#endif

View File

@ -0,0 +1,51 @@
// 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 "Tools.h"
#include <fstream>
#include <iostream>
#include <vector>
//! \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()) {
std::cout << "could not open file: " << file_name << std::endl;
return "";
}
std::ifstream::pos_type file_size = ifs.tellg();
ifs.seekg(0, std::ios::beg);
std::vector<char> bytes(file_size);
ifs.read(&bytes[0], file_size);
return std::string(&bytes[0], file_size);
}
//! \brief
std::ostream& operator << (std::ostream& os, const QVector2D& v) {
os << v.x() << ", " << v.y();
return os;
}
//! \brief
std::ostream& operator << (std::ostream& os, const QVector3D& v) {
os << v.x() << ", " << v.y() << ", " << v.z();
return os;
}
//! \brief
std::ostream& operator << (std::ostream& os, const QVector4D& v) {
os << v.x() << ", " << v.y() << ", " << v.z() << ", " << v.w();
return os;
}

View File

@ -0,0 +1,25 @@
// 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 TOOLS_H
#define TOOLS_H
#include <string>
#include <QVector2D>
#include <QVector3D>
std::string read_file(const std::string& file_name);
std::ostream& operator << (std::ostream& os, const QVector2D& v);
std::ostream& operator << (std::ostream& os, const QVector3D& v);
std::ostream& operator << (std::ostream& os, const QVector4D& v);
#endif

View File

@ -0,0 +1,80 @@
// 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 "Triangles.h"
#include <iostream>
//! \brief
Triangles::Triangles(std::vector<QVector3D>& vertices) {
initializeOpenGLFunctions();
// computer the normals of each vertex
std::vector<QVector3D> normals;
for(const auto& p : vertices) {
auto n = p;
n.normalize();
normals.push_back(n);
}
// std::size_t num_triangles = vertices.size() / 3;
// strided vertex-data
std::vector<QVector3D> vertex_data;
for (std::size_t 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);
glBindVertexArray(m_vao);
m_num_vertices = static_cast<GLsizei>(vertices.size());
// 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);
// 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);
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);
glEnableVertexAttribArray(normal_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//! \brief
void Triangles::set_color(const QVector4D& rgba)
{ m_color = rgba; }
//! \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);
glBindVertexArray(0);
}

View File

@ -0,0 +1,38 @@
// 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 TRIANGLES_H
#define TRIANGLES_H
#include <vector>
#include <qvector3d.h>
#include "Common_defs.h"
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
// sphere at the point of projection of the current vertex on the sphere.
Triangles(std::vector<QVector3D>& vertices);
int get_num_triangles() const;
void set_color(const QVector4D& rgba);
const QVector4D& get_color() const;
void draw();
private:
GLuint m_vao;
GLuint m_vbo;
GLsizei m_num_vertices;
QVector4D m_color;
};
#endif

View File

@ -0,0 +1,123 @@
// 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 "Verification.h"
#include <iostream>
#include "Kml_reader.h"
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();
QMatrix4x4 model;
auto model_view = view * model;
float max_err = 0;
float max_theta = -1;
float max_phi = -1;
int num_divs = 200;
const float dtheta = M_PI_2 / num_divs;
const float dphi = M_PI_2 / num_divs;
const float r1 = 1.f;
const float r2 = r1 - we;
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) {
QVector3D p1, p2;
const float phi = dphi * j;
const float cos_phi = std::cos(phi);
const float sin_phi = std::sin(phi);
// p1
const float r1xz = r1 * sin_phi;
p1.setY(r1 * cos_phi);
p1.setX(r1xz * cos_theta);
p1.setZ(r1xz * sin_theta);
// p2
const float r2xz = r2 * sin_phi;
p2.setY(r2 * cos_phi);
p2.setX(r2xz * cos_theta);
p2.setZ(r2xz * sin_theta);
auto wp1 = p1.project(model_view, proj, vp);
auto wp2 = p2.project(model_view, proj, vp);
const auto pe = wp1.distanceToPoint(wp2);
if (max_err < pe) {
max_err = pe;
max_theta = theta;
max_phi = phi;
}
}
}
std::cout << "max err = " << max_err << std::endl;
std::cout << "max phi = " << max_phi * 180 / M_PI << std::endl;
std::cout << "max theta = " << max_theta * 180 / M_PI << std::endl;
auto wp1 = QVector3D(0, r1, 0).project(model_view, proj, vp);
auto wp2 = QVector3D(0, r2, 0).project(model_view, proj, vp);
auto pe = wp1.distanceToPoint(wp2);
std::cout << "polar err = " << pe << std::endl;
wp1 = QVector3D(r1, 0, 0).project(model_view, proj, vp);
wp2 = QVector3D(r2, 0, 0).project(model_view, proj, vp);
pe = wp1.distanceToPoint(wp2);
std::cout << "x-axis err = " << pe << std::endl;
wp1 = QVector3D(0, 0, 1).project(model_view, proj, vp);
wp2 = QVector3D(we, 0, 1).project(model_view, proj, vp);
pe = wp1.distanceToPoint(wp2);
std::cout << "nearest proj err = " << pe << std::endl;
wp1 = QVector3D(0, 0, -1).project(model_view, proj, vp);
wp2 = QVector3D(we, 0, -1).project(model_view, proj, vp);
pe = wp1.distanceToPoint(wp2);
std::cout << "farthest proj err = " << pe << std::endl;
// project the origin on the screen (to check if it projects to the mid-vp)
//std::cout << QVector3D(0, 0, 0).project(model_view, proj, vp) << std::endl;
}
//! \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);
// 1) check if it is collinear with its neighboring nodes:
// all of the vectors in 3D must lie in the same plane
auto v1 = n1.get_coords_3f();
auto v2 = n2.get_coords_3f();
auto v3 = n3.get_coords_3f();
auto n = QVector3D::crossProduct(v1, v3);
n.normalize();
std::cout << "** DOT PRODUCT = " << QVector3D::dotProduct(n, v2) << std::endl;
// 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; };
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

@ -0,0 +1,32 @@
// 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 VERIFICATION_H
#define VERIFICATION_H
#include <qvector3d.h>
#include <qmatrix4x4.h>
#include "Camera.h"
// This class contains code to verify or compute certain hypotheses
//
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);
// verify that the node (180.0, -84.71338) in Antarctica is redundant
static void verify_antarctica_node_is_redundant();
};
#endif

View File

@ -0,0 +1,48 @@
// 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 "Vertices.h"
//! brief
Vertices::Vertices(const std::vector<QVector3D>& vertices) {
initializeOpenGLFunctions();
auto& vertex_data = vertices;
m_num_indices = static_cast<GLsizei>(vertices.size());
// 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);
// 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);
glEnableVertexAttribArray(position_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//! brief
void Vertices::draw() {
glBindVertexArray(m_vao);
glDrawArrays(GL_POINTS, 0, m_num_indices);
glBindVertexArray(0);
}

View File

@ -0,0 +1,31 @@
// 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 VERTICES_H
#define VERTICES_H
#include <vector>
#include <qvector3d.h>
#include "Common_defs.h"
class Vertices : protected OpenGLFunctionsBase {
public:
Vertices(const std::vector<QVector3D>& vertices);
void draw();
private:
GLuint m_vao;
GLuint m_vbo;
GLsizei m_num_indices;
std::vector<GLuint> m_offsets;
};
#endif

View File

@ -0,0 +1,70 @@
// 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 <vector>
#include <qvector3d.h>
#include "World_coordinate_axes.h"
//! \brief
World_coord_axes::World_coord_axes(float length) {
initializeOpenGLFunctions();
const auto a = length;
const float c = 0.0f;
std::vector<QVector3D> vertex_data {
QVector3D(0, 0, 0), QVector3D(1, 0, 0),
QVector3D(a, 0, 0), QVector3D(1, 0, 0),
QVector3D(0, 0, 0), QVector3D(0, 1, 0),
QVector3D(0, a, 0), QVector3D(0, 1, 0),
QVector3D(0, 0, 0), QVector3D(c, c, 1),
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);
// 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);
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,
color_offset);
glEnableVertexAttribArray(color_attrib_index);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
}
//! \brief
void World_coord_axes::draw() {
glBindVertexArray(m_vao);
const GLsizei count = 2 * 3; // = 2 * number of lines
glDrawArrays(GL_LINES, 0, count);
glBindVertexArray(0);
}

View File

@ -0,0 +1,29 @@
// 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 WORLD_COORD_AXES_H
#define WORLD_COORD_AXES_H
#include <qvector4d.h>
#include "Common_defs.h"
class World_coord_axes : protected OpenGLFunctionsBase {
public:
World_coord_axes(float length);
void draw();
private:
GLuint m_vao;
GLuint m_vbo;
};
#endif

View File

@ -0,0 +1,124 @@
// 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>
// : 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";
return;
}
std::cout << "The neighbors of the vertex (" << v->point() << ") are:";
typename Arrangement::Halfedge_around_vertex_const_circulator first, curr;
first = curr = v->incident_halfedges();
do std::cout << " (" << curr->source()->point() << ")";
while (++curr != first);
std::cout << std::endl;
}
/*! 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() << ")";
typename Arrangement::Ccb_halfedge_const_circulator curr = circ;
do {
typename Arrangement::Halfedge_const_handle e = curr;
std::cout << " [" << e->curve() << "] "
<< "(" << e->target()->point() << ")";
} while (++curr != circ);
std::cout << std::endl;
}
/*! Print the boundary description of an arrangement face.
*/
template <typename Arrangement>
void print_face(typename Arrangement::Face_const_handle f) {
// Print the outer boundary.
if (f->is_unbounded()) std::cout << "Unbounded face.\n";
else {
std::cout << "Outer boundary: ";
print_ccb<Arrangement>(f->outer_ccb());
}
// Print the boundary of each of the holes.
size_t index = 1;
for (auto hole = f->holes_begin(); hole != f->holes_end(); ++hole, ++index) {
std::cout << " Hole #" << index << ": ";
// The following statement pacifies msvc.
typename Arrangement::Ccb_halfedge_const_circulator circ = *hole;
print_ccb<Arrangement>(circ);
}
// Print the isolated vertices.
index = 1;
for (auto iv = f->isolated_vertices_begin();
iv != f->isolated_vertices_end(); ++iv, ++index)
{
std::cout << " Isolated vertex #" << index << ": "
<< "(" << iv->point() << ")" << std::endl;
}
}
/*! Print the given arrangement.
*/
template <typename Arrangement>
void print_arrangement(const Arrangement& arr) {
CGAL_precondition(arr.is_valid());
// Print the arrangement vertices.
std::cout << arr.number_of_vertices() << " vertices:\n";
for (auto vit = arr.vertices_begin(); vit != arr.vertices_end(); ++vit) {
std::cout << "(" << vit->point() << ")";
if (vit->is_isolated()) std::cout << " - Isolated.\n";
else std::cout << " - degree " << vit->degree() << std::endl;
}
// Print the arrangement edges.
std::cout << arr.number_of_edges() << " edges:\n";
for (auto eit = arr.edges_begin(); eit != arr.edges_end(); ++eit)
std::cout << "[" << eit->curve() << "]\n";
// Print the arrangement faces.
std::cout << arr.number_of_faces() << " faces:\n";
for (auto fit = arr.faces_begin(); fit != arr.faces_end(); ++fit)
print_face<Arrangement>(fit);
}
/*! Print the size of the given arrangement.
*/
template <typename Arrangement>
void print_arrangement_size(const Arrangement& arr) {
std::cout << "The arrangement size:\n"
<< " |V| = " << arr.number_of_vertices()
<< ", |E| = " << arr.number_of_edges()
<< ", |F| = " << arr.number_of_faces() << std::endl;
}
/*! 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"
<< " |V| = " << arr.number_of_vertices()
<< " (plus " << arr.number_of_vertices_at_infinity()
<< " at infinity)"
<< ", |E| = " << arr.number_of_edges()
<< ", |F| = " << arr.number_of_faces()
<< " (" << arr.number_of_unbounded_faces() << " unbounded)\n\n";
}
#endif

View File

@ -0,0 +1,62 @@
// 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 <CGAL/config.h>
#include <QApplication>
#include <QLabel>
#include <QSurfaceFormat>
#include <fstream>
#include <string>
#ifndef QT_NO_OPENGL
#include "Main_widget.h"
#endif
int main(int argc, char* argv[]) {
QApplication app(argc, argv);
auto args = QCoreApplication::arguments();
if (args.size() > 2) {
qDebug() << "Usage: earth [<arragement-file.json>]";
return(-1);
}
std::string file_name = (argc > 1) ? argv[1] :
CGAL::data_file_path("geometry_on_sphere/ne_110m_admin_0_countries.json");
if (!std::ifstream(file_name).good()) {
std::cerr << "Error: failed to find file " << file_name << "\n";
return -1;
}
QSurfaceFormat format;
format.setVersion(3, 3);
format.setProfile(QSurfaceFormat::CoreProfile);
//format.setProfile(QSurfaceFormat::CompatibilityProfile);
//format.setOptions(QSurfaceFormat::DeprecatedFunctions);
//QSurfaceFormat::setDefaultFormat(format);
format.setDepthBufferSize(24);
QSurfaceFormat::setDefaultFormat(format);
app.setApplicationName("Earth");
app.setApplicationVersion("0.1");
try {
#ifndef QT_NO_OPENGL
Main_widget widget(file_name.c_str());
widget.show();
#else
QLabel note("OpenGL Support required");
note.show();
#endif
return app.exec();
}
catch (std::exception& e) {
std::cerr << e.what() << std::endl;
std::cerr << "Try `" << argv[0] << " --help' for more information."
<< std::endl;
return -1;
}
return 0;
}

View File

@ -0,0 +1,14 @@
#version 330
uniform vec4 u_color;
uniform vec4 u_plane;
in vec3 v_pos;
out vec4 out_color;
void main() {
if (dot(u_plane, vec4(v_pos, 1)) < 0) discard;
out_color = u_color;
}

View File

@ -0,0 +1,13 @@
#version 330
layout (location = 0) in vec3 a_pos;
uniform mat4 u_mvp;
out vec3 v_pos;
void main() {
v_pos = a_pos;
gl_Position = u_mvp * vec4(a_pos.xyz, 1);
}

View File

@ -0,0 +1,23 @@
#version 330
in vec3 vpos[];
out vec4 vCol;
layout (triangles) in;
layout (triangle_strip, max_vertices = 3) out;
void main() {
const vec3 lightDir = normalize(vec3(1,.5,.5));
// compute the normal for the current triangle
vec3 triNormal = normalize(cross(vpos[1]-vpos[0], vpos[2]-vpos[0]));
//float c = clamp(dot(lightDir,triNormal), 0, 1);
float c = abs(dot(lightDir,triNormal));
vCol = vec4(.2, .2,0,1) + vec4(c,c,0,1);
gl_Position = gl_in[0].gl_Position; EmitVertex();
gl_Position = gl_in[1].gl_Position; EmitVertex();
gl_Position = gl_in[2].gl_Position; EmitVertex();
EndPrimitive();
}

View File

@ -0,0 +1,9 @@
#version 330
uniform vec4 u_plane;
in vec3 v_color;
out vec4 out_color;
void main() {out_color = vec4(v_color, 1); }

View File

@ -0,0 +1,14 @@
#version 330
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_color;
uniform mat4 u_mvp;
out vec3 v_color;
void main() {
v_color = a_color;
gl_Position = u_mvp * vec4(a_pos.xyz, 1);
}

View File

@ -0,0 +1,24 @@
#version 330
uniform vec4 u_color;
uniform vec4 u_plane;
in vec3 v_pos;
in vec3 v_normal;
out vec4 out_color;
void main() {
if (dot(u_plane, vec4(v_pos, 1)) < 0) discard;
const vec3 lightDir = normalize(vec3(0,0,-1));
//float c = clamp(dot(lightDir,triNormal), 0, 1);
vec3 n = normalize(v_normal);
float c = abs(dot(lightDir, n) );
out_color = u_color * (vec4(.2, .2,.2,1) + 0.8 * vec4(c,c,c,1));
//color = vec4(1,1,0,1);
//color = vCol;
}

View File

@ -0,0 +1,19 @@
#version 330
layout (location = 0) in vec3 a_pos;
layout (location = 1) in vec3 a_normal;
//out vec4 v_col;
out vec3 v_pos;
out vec3 v_normal;
uniform mat4 u_mvp;
uniform mat3 u_normal_matrix;
void main() {
v_pos = a_pos;
v_normal = u_normal_matrix * a_normal;
gl_Position = u_mvp * vec4(a_pos.xyz, 1);
//gl_Position = vec4(pos.xyz, 1);
}

View File

@ -1,16 +1,19 @@
\documentclass[12pt]{standalone}
\input{header}
\usepackage[edges]{forest}
\usetikzlibrary{shadows.blur,arrows.meta}
\pagestyle{empty}
\def\name#1{\textsf{\it #1}}
\tikzset{concept/.style={rectangle split,rectangle split parts=1,draw,
fill=white,blur shadow,rounded corners,align=center}}
\begin{document}
\psset{treevshift=0,unit=1em,xunit=2em,yunit=1em,everytree={},
etcratio=.75,triratio=.5}
\jtree[everylabel=\sl,xunit=70pt,arrows=->]
\! = {\psframebox{\concept{ArrangementBasicTraits\_2}}}
<vert>[scaleby=0 1.6]{\psframebox{\concept{ArrangementXMonotoneTraits\_2}}}@axmt !axmt
.
\!axmt = <vert>[scaleby=0 1.6]{\psframebox{\concept{ArrangementTraits\_2}}}@at !at
.
\endjtree
\psset{treevshift=0,unit=1cm,xunit=1cm,yunit=1cm,everytree={},
etcratio=.75,triratio=.5}
\begin{forest}
[\name{ArrangementBasicTraits\_2},
forked edges,
for tree={concept,edge={-latex}}
[\name{ArrangementXMonotoneTraits\_2}
[\name{ArrangementTraits\_2}]
]
]
\end{forest}
\end{document}

View File

@ -1,18 +1,22 @@
\documentclass[12pt]{standalone}
\input{header}
\usepackage[edges]{forest}
\usetikzlibrary{shadows.blur,arrows.meta}
\pagestyle{empty}
\def\name#1{\textsf{\it #1}}
\tikzset{concept/.style={rectangle split,rectangle split parts=1,draw,
fill=white,blur shadow,rounded corners,align=center}}
\begin{document}
\psset{treevshift=0,unit=1em,xunit=2em,yunit=1em,everytree={},
etcratio=.75,triratio=.5}
\jtree[everylabel=\sl,xunit=70pt,arrows=->]
\! = {\psframebox{\concept{ArrangementBasicTraits\_2}}}
<left>[scaleby=1.2 1.6]{\psframebox{\concept{ArrangementApproximateTraits\_2}}}@aat !aat
^<right>[scaleby=1.8 1.6]{\psframebox{\concept{ArrangementConstructXMonotoneCurveTraits\_2}}}@acxmct !acxmct
.
\!aat = <right>[scaleby=1.2 1.6]{\psframebox{\concept{ArrangementLandmarkTraits\_2}}}@alt !alt
.
\ncline{acxmct:b}{alt:t}
\endjtree
\psset{treevshift=0,unit=1cm,xunit=1cm,yunit=1cm,everytree={},
etcratio=.75,triratio=.5}
\begin{forest}
[\name{ArrangementBasicTraits\_2},name=abt,
% forked edges,
for tree={concept,edge={-latex}}
[\name{ArrangementApproximateTraits\_2}
[,phantom]
[\name{ArrangementLandmarkTraits\_2},name=alt,before drawing tree={x=0}]
]
[\name{ArrangementConstructXMonotoneCurveTraits\_2},name=acxmt]
]
\draw[-latex] (acxmt) to (alt);
\end{forest}
\end{document}

View File

@ -24,6 +24,7 @@ if(CGAL_Qt6_FOUND)
target_link_libraries(polylines PUBLIC CGAL::CGAL_Basic_viewer)
target_link_libraries(circles PUBLIC CGAL::CGAL_Basic_viewer)
target_link_libraries(circular_arcs PUBLIC CGAL::CGAL_Basic_viewer)
target_link_libraries(spherical_insert PUBLIC CGAL::CGAL_Basic_viewer)
else()
message(
STATUS

View File

@ -0,0 +1,16 @@
#ifndef ARR_GEODESIC_H
#define ARR_GEODESIC_H
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arrangement_on_surface_2.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Arr_spherical_topology_traits_2.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>;
#endif

View File

@ -2,50 +2,30 @@
// Constructing an arrangement of arcs of great circles.
#include <list>
#include <cmath>
#include <cstdio>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Arrangement_on_surface_2.h>
#include <CGAL/Arr_geodesic_arc_on_sphere_traits_2.h>
#include <CGAL/Arr_spherical_topology_traits_2.h>
#include "arr_geodesic.h"
#include "arr_print.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>;
int main() {
// Construct the arrangement from 12 geodesic arcs.
Geom_traits traits;
Arrangement arr(&traits);
auto ctr_p = traits.construct_point_2_object();
auto ctr_cv = traits.construct_curve_2_object();
Arrangement arr(&traits);
// Observe that the identification curve is a meridian that contains the
// point (-11, 7, 0). The curve (-1,0,0),(0,1,0) intersects the identification
// curve.
std::list<Curve> arcs;
arcs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 0, -1)));
arcs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 0, 1)));
arcs.push_back(ctr_cv(ctr_p(0, 1, 0), ctr_p(0, 0, -1)));
arcs.push_back(ctr_cv(ctr_p(0, 1, 0), ctr_p(0, 0, 1)));
arcs.push_back(ctr_cv(ctr_p(-1, 0, 0), ctr_p(0, 0, -1)));
arcs.push_back(ctr_cv(ctr_p(-1, 0, 0), ctr_p(0, 0, 1)));
arcs.push_back(ctr_cv(ctr_p(0, -1, 0), ctr_p(0, 0, -1)));
arcs.push_back(ctr_cv(ctr_p(0, -1, 0), ctr_p(0, 0, 1)));
arcs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, 1, 0)));
arcs.push_back(ctr_cv(ctr_p(1, 0, 0), ctr_p(0, -1, 0)));
arcs.push_back(ctr_cv(ctr_p(-1, 0, 0), ctr_p(0, 1, 0)));
arcs.push_back(ctr_cv(ctr_p(-1, 0, 0), ctr_p(0, -1, 0)));
CGAL::insert(arr, arcs.begin(), arcs.end());
print_arrangement_size(arr); // print the arrangement size
Point p1 = ctr_p(0, 0, -1), p3 = ctr_p(0, -1, 0), p5 = ctr_p(-1, 0, 0);
Point p2 = ctr_p(0, 0, 1), p4 = ctr_p(0, 1, 0), p6 = ctr_p( 1, 0, 0);
Curve arcs[] = {
ctr_cv(p6, p1), ctr_cv(p6, p2), ctr_cv(p4, p1), ctr_cv(p4, p2),
ctr_cv(p5, p1), ctr_cv(p5, p2), ctr_cv(p3, p1), ctr_cv(p3, p2),
ctr_cv(p6, p4), ctr_cv(p6, p3), ctr_cv(p5, p4), ctr_cv(p5, p3) };
CGAL::insert(arr, arcs, arcs + sizeof(arcs)/sizeof(Curve));
print_arrangement_size(arr);
return 0;
}

View File

@ -2939,9 +2939,9 @@ public:
}
// compute the number of divisions given the requested error
const Approximate_number_type R = 1.0; // radius is always 1
Approximate_number_type dtheta = 2.0 * std::acos(1 - error / R);
int num_segs = std::ceil(theta / dtheta);
const Approximate_number_type radius = 1.0; // radius is always 1
Approximate_number_type dtheta = 2.0 * std::acos(1 - error / radius);
auto num_segs = std::ceil(theta / dtheta);
dtheta = theta / num_segs;
// generate the points approximating the curve

View File

@ -1106,32 +1106,7 @@ public:
// Generic implementation
using Approximate_number_type = void;
using Approximate_point_2 = void;
struct Approximate_2 {
/*! Obtain an approximation of a point coordinate.
* \param p the exact point.
* \param i the coordinate index (either 0 or 1).
* \pre i is either 0 or 1.
* \return An approximation of p's x-coordinate (if i == 0), or an
* approximation of p's y-coordinate (if i == 1).
*/
Approximate_number_type operator()(const Point_2&, int) const
{ CGAL_error_msg("The subtraits does not define Approximate_2!"); }
/*! Obtain an approximation of a point.
*/
Approximate_point_2 operator()(const Point_2&) const
{ CGAL_error_msg("The subtraits does not define Approximate_2!"); }
/*! Obtain an approximation of an \f$x\f$-monotone curve.
*/
template <typename OutputIterator>
OutputIterator operator()(const X_monotone_curve_2&, double,
OutputIterator oi, bool = true) const {
CGAL_error_msg("The subtraits does not define Approximate_2!");
return oi;
}
};
using Approximate_2 = void;
};
template <typename T>

View File

@ -1070,7 +1070,7 @@ public:
/*!
returns a const range (model of `ConstRange`) over handles of the arrangement vertices .
*/
Iterator_range<Prevent_deref<Vertex_iterator> >
Iterator_range<Prevent_deref<Vertex_const_iterator> >
vertex_handles() const
{
return make_prevent_deref_range(vertices_begin(), vertices_end());
@ -1124,7 +1124,7 @@ public:
/*!
returns a const range (model of `ConstRange`) over handles of the arrangement halfedges .
*/
Iterator_range<Prevent_deref<Halfedge_iterator> >
Iterator_range<Prevent_deref<Halfedge_const_iterator> >
halfedge_handles() const
{
return make_prevent_deref_range(halfedges_begin(), halfedges_end());
@ -1174,7 +1174,7 @@ public:
/*!
returns a const range (model of `ConstRange`) over handles of the arrangement edges .
*/
Iterator_range<Prevent_deref<Edge_iterator> >
Iterator_range<Prevent_deref<Edge_const_iterator> >
edge_handles() const
{
return make_prevent_deref_range(edges_begin(), edges_end());
@ -1223,11 +1223,12 @@ public:
/*!
returns a const range (model of `ConstRange`) over handles of the arrangement faces .
*/
Iterator_range<Prevent_deref<Face_iterator> >
Iterator_range<Prevent_deref<Face_const_iterator> >
face_handles() const
{
return make_prevent_deref_range(faces_begin(), faces_end());
}
//! reference_face (const version).
/*! The function returns a reference face of the arrangement.
* All reference faces of arrangements of the same type have a common

View File

@ -11,7 +11,6 @@
// $Id$
// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial
//
//
// Author(s): Efi Fogel <efifogel@gmail.com>
#ifndef CGAL_DRAW_ARRANGEMENT_2_H

View File

@ -20,11 +20,11 @@
#include "Traits_base_test.h"
/*! Traits test */
template <typename Geom_traits_T>
class Traits_test : public Traits_base_test<Geom_traits_T> {
template <typename GeomTraits>
class Traits_test : public Traits_base_test<GeomTraits> {
private:
Traits_test<Geom_traits_T>& operator=(const Traits_test<Geom_traits_T>&);
typedef Geom_traits_T Traits;
Traits_test<GeomTraits>& operator=(const Traits_test<GeomTraits>&);
typedef GeomTraits Traits;
typedef Traits_base_test<Traits> Base;
typedef typename Base::Enum_type Enum_type;
@ -51,8 +51,7 @@ private:
virtual bool exec(std::istringstream& str_stream,
const std::string& str_command,
bool& result)
{
bool& result) {
// str_stream is the input file object.
// Get the appropriate functor. "str_command" consist of the appropriate
// functor string.
@ -170,6 +169,47 @@ private:
/*! Tests Approximate_2.
* Return an approximation of a point coordinate.
*/
/*! Fall threw implementation to handle the case where the
* Approximate_2::operator()(const X_monotone_curve_2& xcv,
* Approximate_number_type error,
* OutputIterator oi,
* bool l2r)
* is not supported.
*/
template <typename GT>
bool approximate_wrapper_impl2(std::istringstream& is, long);
/*! Specialized instance to handle the case where the
* Approximate_2::operator()(const X_monotone_curve_2& xcv,
* Approximate_number_type error,
* OutputIterator oi,
* bool l2r)
* is supported.
*/
template <typename GT,
typename T =
decltype(std::declval<GT>().approximate_2_object().operator()
(std::declval<typename GT::X_monotone_curve_2>(),
0,
(std::declval<int*>())))>
bool approximate_wrapper_impl2(std::istringstream& is, int);
/*! Fall threw implementation to handle the case where the type
* Traits::Approximate_2 does not exist.
*/
template <typename GT>
bool approximate_wrapper_impl1(std::istringstream& is, long);
/*! Specialized instance to handle the case where the type
* Traits::Approximate_2 exists.
*/
template <typename GT,
typename T = decltype(std::declval<GT>().approximate_2_object())>
bool approximate_wrapper_impl1(std::istringstream& is, int);
/*!
*/
bool approximate_wrapper(std::istringstream& line);
/*! tests Construct_x_monotone_curve_2.
@ -260,11 +300,9 @@ public:
/*! Constructor.
* Accepts test data file name.
*/
template <typename Geom_traits_T>
Traits_test<Geom_traits_T>::Traits_test(const Geom_traits_T& traits) :
Base(traits)
{
typedef Geom_traits_T Traits;
template <typename GeomTraits>
Traits_test<GeomTraits>::Traits_test(const GeomTraits& traits) : Base(traits) {
using Traits = GeomTraits;
m_wrappers[std::string("compare_x")] =
&Traits_test<Traits>::compare_x_wrapper;
@ -344,8 +382,8 @@ Base(traits)
/*! Destructor.
*/
template <typename Geom_traits_T>
Traits_test<Geom_traits_T>::~Traits_test() {}
template <typename GeomTraits>
Traits_test<GeomTraits>::~Traits_test() {}
// some polycurve functors needs Segment and x-monotone segment to be defined
// which are normally not found in other geom_traits.
@ -354,9 +392,8 @@ Traits_test<Geom_traits_T>::~Traits_test() {}
TEST_GEOM_TRAITS == POLYCURVE_BEZIER_GEOM_TRAITS || \
TEST_GEOM_TRAITS == POLYLINE_GEOM_TRAITS
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::trim_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::trim_wrapper(std::istringstream& str_stream) {
unsigned int x_curve_id, xcv_trimmed, src_id, tgt_id;
// Read the ID's of the x-curve, source and target points
@ -386,9 +423,8 @@ bool Traits_test<Geom_traits_T>::trim_wrapper(std::istringstream& str_stream)
/* Test Push_back
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
push_back_wrapper(std::istringstream& str_stream)
template <typename GeomTraits>
bool Traits_test<GeomTraits>::push_back_wrapper(std::istringstream& str_stream)
{
//type: 0 for pushing a segment into curve.
// 1 for pushing x-monotone segment into x-monotone curve.
@ -459,10 +495,9 @@ push_back_wrapper(std::istringstream& str_stream)
/*
* Test Push_front
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
push_front_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
push_front_wrapper(std::istringstream& str_stream) {
//type: 0 for pushing a segment into curve.
// 1 for pushing x-monotone segment into x-monotone curve.
unsigned int type;
@ -535,10 +570,9 @@ push_front_wrapper(std::istringstream& str_stream)
* This wrapper will only test for the x-monotone segments. For testing the
* points, compare_x_wrapper can be used.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_x_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
unsigned int expected_answer;
unsigned int real_answer;
@ -581,10 +615,9 @@ compare_x_wrapper(std::istringstream& str_stream)
return this->compare(expected_answer, real_answer);
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_xy_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_xy_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
unsigned int expected_answer;
unsigned int real_answer;
@ -629,12 +662,11 @@ compare_xy_wrapper(std::istringstream& str_stream)
return this->compare(expected_answer, real_answer);
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
number_of_points_wrapper(std::istringstream& str_stream)
{
typedef Geom_traits_T Geom_traits;
typedef typename Geom_traits::size_type size_type;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
number_of_points_wrapper(std::istringstream& str_stream) {
using Geom_traits = GeomTraits;
using size_type = typename Geom_traits::size_type;
unsigned int id;
size_type expected_result;
@ -645,10 +677,9 @@ number_of_points_wrapper(std::istringstream& str_stream)
return this->compare(expected_result, real_answer);
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_endpoints_xy_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_endpoints_xy_wrapper(std::istringstream& str_stream) {
unsigned int id;
str_stream >> id;
@ -662,10 +693,9 @@ compare_endpoints_xy_wrapper(std::istringstream& str_stream)
return this->compare(expected_answer, real_answer);
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
construct_opposite_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
construct_opposite_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
@ -687,10 +717,9 @@ construct_opposite_wrapper(std::istringstream& str_stream)
TEST_GEOM_TRAITS != POLYLINE_GEOM_TRAITS
/*! Test Compare_x_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_x_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
unsigned int exp_answer = this->get_expected_enum(str_stream);
@ -705,10 +734,9 @@ compare_x_wrapper(std::istringstream& str_stream)
/*! Test Compare_xy_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_xy_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_xy_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
unsigned int exp_answer = this->get_expected_enum(str_stream);
@ -726,10 +754,9 @@ compare_xy_wrapper(std::istringstream& str_stream)
/*! Tests Construct_min_vertex_2.
* Degenerate case: vertical curve.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
min_vertex_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
min_vertex_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
Point_2& exp_answer = this->m_points[id2];
@ -744,10 +771,9 @@ min_vertex_wrapper(std::istringstream& str_stream)
/*! Tests Construct_max_vertex_2.
* Degenerate case: vertical curve.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
max_vertex_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
max_vertex_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
Point_2& exp_answer = this->m_points[id2];
@ -759,11 +785,10 @@ max_vertex_wrapper(std::istringstream& str_stream)
return this->compare_points(exp_answer, real_answer);
}
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
is_vertical_wrapper(std::istringstream& str_stream)
{
Traits_test<GeomTraits>::
is_vertical_wrapper(std::istringstream& str_stream) {
unsigned int id;
str_stream >> id;
bool exp_answer = this->get_expected_boolean(str_stream);
@ -780,11 +805,10 @@ is_vertical_wrapper(std::istringstream& str_stream)
* Degenerate cases: The point is an endpoint of the curve.
* The curve is vertical.
*/
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
compare_y_at_x_wrapper(std::istringstream& str_stream)
{
Traits_test<GeomTraits>::
compare_y_at_x_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
unsigned int exp_answer = this->get_expected_enum(str_stream);
@ -804,29 +828,26 @@ compare_y_at_x_wrapper(std::istringstream& str_stream)
* The curves coincide and vertical.
* One of the curves is vertical.
*/
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
compare_y_at_x_left_wrapper(std::istringstream& str_stream)
{
typedef typename Geom_traits_T::Has_left_category Has_left_category;
Traits_test<GeomTraits>::
compare_y_at_x_left_wrapper(std::istringstream& str_stream) {
using Has_left_category = typename GeomTraits::Has_left_category;
return compare_y_at_x_left_wrapper_imp(str_stream, Has_left_category());
}
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
compare_y_at_x_left_wrapper_imp(std::istringstream&, CGAL::Tag_false)
{
Traits_test<GeomTraits>::
compare_y_at_x_left_wrapper_imp(std::istringstream&, CGAL::Tag_false) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
compare_y_at_x_left_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true)
{
Traits_test<GeomTraits>::
compare_y_at_x_left_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true) {
unsigned int id1, id2, id3;
str_stream >> id1 >> id2 >> id3;
unsigned int exp_answer = this->get_expected_enum(str_stream);
@ -846,10 +867,9 @@ compare_y_at_x_left_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true)
* The curves coincide and vertical.
* One of the curves is vertical.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_y_at_x_right_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_y_at_x_right_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2, id3;
str_stream >> id1 >> id2 >> id3;
unsigned int exp_answer = this->get_expected_enum(str_stream);
@ -866,10 +886,9 @@ compare_y_at_x_right_wrapper(std::istringstream& str_stream)
/*! Tests Equal_2::operator()(Point_2, Point_2).
* Check whether two points are the same.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
equal_points_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
equal_points_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
bool exp_answer = this->get_expected_boolean(str_stream);
@ -884,10 +903,9 @@ equal_points_wrapper(std::istringstream& str_stream)
/*! Tests Equal_2::operator()(X_monotone_curve_2, X_monotone_curve_2).
* Check whether two x-monotone curves are the same.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
equal_curves_wrapper(std::istringstream& str_stream)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
equal_curves_wrapper(std::istringstream& str_stream) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
bool exp_answer = this->get_expected_boolean(str_stream);
@ -906,11 +924,11 @@ equal_curves_wrapper(std::istringstream& str_stream)
* segment is vertical. Both first and last are vertical. An internal segment
* is vertical.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
make_x_monotone_wrapper(std::istringstream& str_stream)
{
typedef Geom_traits_T Traits;
typedef GeomTraits Traits;
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
typedef std::variant<Point_2, X_monotone_curve_2> Make_x_monotone_result;
@ -958,12 +976,11 @@ make_x_monotone_wrapper(std::istringstream& str_stream)
* left) endpoint of one curve and the first (resp. last) segment of the
* other coincide.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
intersect_wrapper(std::istringstream& str_stream)
{
typedef Geom_traits_T Traits;
typedef GeomTraits Traits;
typedef typename Traits::Point_2 Point_2;
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
typedef typename Traits::Multiplicity Multiplicity;
@ -971,7 +988,6 @@ intersect_wrapper(std::istringstream& str_stream)
typedef std::pair<Point_2, Multiplicity> Intersection_point;
typedef std::variant<Intersection_point, X_monotone_curve_2>
Intersection_result;
unsigned int id1, id2;
str_stream >> id1 >> id2;
std::vector<Intersection_result> xections;
@ -1022,10 +1038,9 @@ intersect_wrapper(std::istringstream& str_stream)
* Degenerate cases for polylines: the point and a polyline internal point
* coincides.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::split_wrapper(std::istringstream& str_stream)
{
typedef Geom_traits_T Traits;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::split_wrapper(std::istringstream& str_stream) {
typedef GeomTraits Traits;
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
unsigned int id1, id2, id3, id4;
@ -1043,29 +1058,25 @@ bool Traits_test<Geom_traits_T>::split_wrapper(std::istringstream& str_stream)
/*! Tests Are_mergeable_2.
* Check whether it is possible to merge two given x-monotone curves.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
are_mergeable_wrapper(std::istringstream& str_stream)
{
typedef typename Geom_traits_T::Has_merge_category Has_merge_category;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
are_mergeable_wrapper(std::istringstream& str_stream) {
using Has_merge_category = typename GeomTraits::Has_merge_category;
return are_mergeable_wrapper_imp(str_stream, Has_merge_category());
}
template <typename Geom_traits_T>
template <typename GeomTraits>
bool
Traits_test<Geom_traits_T>::
are_mergeable_wrapper_imp(std::istringstream&, CGAL::Tag_false)
{
//waqar
Traits_test<GeomTraits>::
are_mergeable_wrapper_imp(std::istringstream&, CGAL::Tag_false) {
std::cout << "I am at the wrong place" << std::endl;
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
are_mergeable_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
are_mergeable_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
bool exp_answer = this->get_expected_boolean(str_stream);
@ -1081,28 +1092,24 @@ are_mergeable_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true)
/*! Tests Merge_2.
* Merge two given x-monotone curves into a single curve.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::merge_wrapper(std::istringstream& str_stream)
{
typedef typename Geom_traits_T::Has_merge_category Has_merge_category;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::merge_wrapper(std::istringstream& str_stream) {
typedef typename GeomTraits::Has_merge_category Has_merge_category;
return merge_wrapper_imp(str_stream, Has_merge_category());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::merge_wrapper_imp(std::istringstream&,
CGAL::Tag_false)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
merge_wrapper_imp(std::istringstream&, CGAL::Tag_false) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool
Traits_test<Geom_traits_T>::merge_wrapper_imp(std::istringstream& str_stream,
CGAL::Tag_true)
{
typedef Geom_traits_T Traits;
typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
merge_wrapper_imp(std::istringstream& str_stream, CGAL::Tag_true) {
using Traits = GeomTraits ;
using X_monotone_curve_2 = typename Traits::X_monotone_curve_2;
unsigned int id1, id2, id;
str_stream >> id1 >> id2 >> id;
@ -1115,25 +1122,70 @@ Traits_test<Geom_traits_T>::merge_wrapper_imp(std::istringstream& str_stream,
return this->compare_curves(this->m_xcurves[id], cv);
}
//! Fall threw instance
template <typename GeomTraits>
template <typename GT>
bool Traits_test<GeomTraits>::
approximate_wrapper_impl2(std::istringstream&, long) { return false; }
//! Specialized instance
template <typename GeomTraits>
template <typename GT, typename T>
bool Traits_test<GeomTraits>::
approximate_wrapper_impl2(std::istringstream& is, int) {
std::size_t id;
typename GeomTraits::Approximate_number_type error;
bool l2r;
is >> id >> error >> l2r;
const auto& xcv = this->m_xcurves[id];
using Ap2 = typename GeomTraits::Approximate_point_2;
std::vector<Ap2> apoints;
auto approx = this->m_geom_traits.approximate_2_object();
approx(xcv, error, std::back_inserter(apoints), l2r);
std::size_t exp_num_apoints;
is >> exp_num_apoints;
if (apoints.size() != exp_num_apoints) {
std::cout << "xcv: " << xcv << std::endl;
std::cout << "error: " << error << std::endl;
for (const auto& pt : apoints) {
std::cout << pt << std::endl;
}
std::cerr << "Error: no. of inexact points does not match ("
<< apoints.size() << ", " << exp_num_apoints
<< ")!\n";
return false;
}
return true;
}
//! Fall threw instance
template <typename GeomTraits>
template <typename GT>
bool Traits_test<GeomTraits>::
approximate_wrapper_impl1(std::istringstream&, long) { return false; }
//! Specialized instance
template <typename GeomTraits>
template <typename GT, typename T>
bool Traits_test<GeomTraits>::
approximate_wrapper_impl1(std::istringstream& is, int)
{ return approximate_wrapper_impl2<GeomTraits>(is, 0); }
/*! Tests Approximate_2.
* Return an approximation of a point coordinate.
*/
template <typename Geom_traits_T>
bool
Traits_test<Geom_traits_T>::approximate_wrapper(std::istringstream& )
{
return false;
}
template <typename GeomTraits>
bool Traits_test<GeomTraits>::approximate_wrapper(std::istringstream& is)
{ return approximate_wrapper_impl1<GeomTraits>(is, 0); }
/*! tests Construct_x_monotone_curve_2.
* Return an x-monotone curve connecting the two given endpoints.
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
construct_x_monotone_curve_wrapper(std::istringstream& )
{
return false;
}
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
construct_x_monotone_curve_wrapper(std::istringstream&) { return false; }
// ///////////////////////////////////////////////////////////////////////////
// boundary-specific functors
@ -1143,35 +1195,30 @@ construct_x_monotone_curve_wrapper(std::istringstream& )
/*! Test Parameter_space_in_x_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
parameter_space_in_x_wrapper(std::istringstream& str_stream)
{
typedef typename
CGAL::internal::Arr_complete_left_side_category< Geom_traits_T >::Category
Left_side_category;
typedef typename
CGAL::internal::Arr_complete_right_side_category< Geom_traits_T >::Category
Right_side_category;
typedef CGAL::internal::Arr_left_right_implementation_dispatch
<Left_side_category, Right_side_category> LR;
typedef typename LR::Parameter_space_in_x_2_curve_end_tag Psx_tag;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_x_wrapper(std::istringstream& str_stream) {
using Left_side_category = typename
CGAL::internal::Arr_complete_left_side_category<GeomTraits>::Category;
using Right_side_category = typename
CGAL::internal::Arr_complete_right_side_category<GeomTraits>::Category;
using LR = CGAL::internal::Arr_left_right_implementation_dispatch
<Left_side_category, Right_side_category>;
using Psx_tag = typename LR::Parameter_space_in_x_2_curve_end_tag;
return parameter_space_in_x_wrapper_imp(str_stream, Psx_tag());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
parameter_space_in_x_wrapper_imp(std::istringstream&, CGAL::Arr_use_dummy_tag)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_x_wrapper_imp(std::istringstream&, CGAL::Arr_use_dummy_tag) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_x_wrapper_imp(std::istringstream& str_stream,
CGAL::Arr_use_traits_tag)
{
CGAL::Arr_use_traits_tag) {
CGAL::Arr_parameter_space exp_answer, real_answer;
unsigned int id;
str_stream >> id;
@ -1211,36 +1258,31 @@ parameter_space_in_x_wrapper_imp(std::istringstream& str_stream,
/*! Test Compare_y_near_boundary_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_y_near_boundary_wrapper(std::istringstream& str_stream)
{
typedef typename
CGAL::internal::Arr_complete_left_side_category<Geom_traits_T >::Category
Left_side_category;
typedef typename
CGAL::internal::Arr_complete_right_side_category<Geom_traits_T >::Category
Right_side_category;
typedef CGAL::internal::Arr_left_right_implementation_dispatch
<Left_side_category, Right_side_category> LR;
typedef typename LR::Compare_y_near_boundary_2_curve_ends_tag Cmp_tag;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_y_near_boundary_wrapper(std::istringstream& str_stream) {
using Left_side_category = typename
CGAL::internal::Arr_complete_left_side_category<GeomTraits >::Category;
using Right_side_category = typename
CGAL::internal::Arr_complete_right_side_category<GeomTraits >::Category;
using LR = CGAL::internal::Arr_left_right_implementation_dispatch
<Left_side_category, Right_side_category>;
using Cmp_tag = typename LR::Compare_y_near_boundary_2_curve_ends_tag;
return compare_y_near_boundary_wrapper_imp(str_stream, Cmp_tag());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_y_near_boundary_wrapper_imp(std::istringstream&,
CGAL::Arr_use_dummy_tag)
{
CGAL::Arr_use_dummy_tag) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_y_near_boundary_wrapper_imp(std::istringstream& str_stream,
CGAL::Arr_use_traits_tag)
{
CGAL::Arr_use_traits_tag) {
unsigned int id1, id2;
str_stream >> id1 >> id2;
std::pair<Enum_type, unsigned int> next_input =
@ -1272,35 +1314,30 @@ compare_y_near_boundary_wrapper_imp(std::istringstream& str_stream,
/*! Test Parameter_space_in_y_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
parameter_space_in_y_wrapper(std::istringstream& str_stream)
{
typedef typename
CGAL::internal::Arr_complete_bottom_side_category<Geom_traits_T>::Category
Bottom_side_category;
typedef typename
CGAL::internal::Arr_complete_top_side_category<Geom_traits_T>::Category
Top_side_category;
typedef CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category> BT;
typedef typename BT::Parameter_space_in_y_2_curve_end_tag Psy_tag;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_y_wrapper(std::istringstream& str_stream) {
using Bottom_side_category = typename
CGAL::internal::Arr_complete_bottom_side_category<GeomTraits>::Category;
using Top_side_category = typename
CGAL::internal::Arr_complete_top_side_category<GeomTraits>::Category;
using BT = CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category>;
using Psy_tag = typename BT::Parameter_space_in_y_2_curve_end_tag;
return parameter_space_in_y_wrapper_imp(str_stream, Psy_tag());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
parameter_space_in_y_wrapper_imp(std::istringstream&, CGAL::Arr_use_dummy_tag)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_y_wrapper_imp(std::istringstream&, CGAL::Arr_use_dummy_tag) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
parameter_space_in_y_wrapper_imp(std::istringstream& str_stream,
CGAL::Arr_use_traits_tag)
{
CGAL::Arr_use_traits_tag) {
unsigned int id;
str_stream >> id;
std::pair<Enum_type, unsigned int> next_input =
@ -1340,36 +1377,31 @@ parameter_space_in_y_wrapper_imp(std::istringstream& str_stream,
/* Compare_x_near_boundary_2
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_x_near_boundary_wrapper(std::istringstream& str_stream)
{
typedef typename
CGAL::internal::Arr_complete_bottom_side_category<Geom_traits_T>::Category
Bottom_side_category;
typedef typename
CGAL::internal::Arr_complete_top_side_category<Geom_traits_T>::Category
Top_side_category;
typedef CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category> BT;
typedef typename BT::Compare_x_near_boundary_2_curve_ends_tag Cmp_tag;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_near_boundary_wrapper(std::istringstream& str_stream) {
using Bottom_side_category = typename
CGAL::internal::Arr_complete_bottom_side_category<GeomTraits>::Category;
using Top_side_category = typename
CGAL::internal::Arr_complete_top_side_category<GeomTraits>::Category;
using BT = CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category>;
using Cmp_tag = typename BT::Compare_x_near_boundary_2_curve_ends_tag;
return compare_x_near_boundary_wrapper_imp(str_stream, Cmp_tag());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_near_boundary_wrapper_imp(std::istringstream&,
CGAL::Arr_use_dummy_tag)
{
CGAL::Arr_use_dummy_tag) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_near_boundary_wrapper_imp(std::istringstream& str_stream,
CGAL::Arr_use_traits_tag)
{
CGAL::Arr_use_traits_tag) {
std::cout << "Test: compare_x_near_boundary( ";
unsigned int id1, id2;
@ -1400,42 +1432,34 @@ compare_x_near_boundary_wrapper_imp(std::istringstream& str_stream,
/* Compare_x_on_boundary
*/
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_x_on_boundary_wrapper(std::istringstream& str_stream)
{
typedef typename
CGAL::internal::Arr_complete_bottom_side_category<Geom_traits_T>::Category
Bottom_side_category;
typedef typename
CGAL::internal::Arr_complete_top_side_category<Geom_traits_T>::Category
Top_side_category;
typedef CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category> BT;
typedef typename BT::Compare_x_on_boundary_2_points_tag Cmp_tag1;
typedef typename BT::Compare_x_on_boundary_2_point_curve_end_tag Cmp_tag2;
typedef typename BT::Compare_x_on_boundary_2_curve_ends_tag Cmp_tag3;
typedef typename CGAL::internal::Or_traits<Cmp_tag1, Cmp_tag2>::type
Cmp_tag12;
typedef typename CGAL::internal::Or_traits<Cmp_tag12, Cmp_tag3>::type
Cmp_tag;
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_on_boundary_wrapper(std::istringstream& str_stream) {
using Bottom_side_category = typename
CGAL::internal::Arr_complete_bottom_side_category<GeomTraits>::Category;
using Top_side_category = typename
CGAL::internal::Arr_complete_top_side_category<GeomTraits>::Category;
using BT = CGAL::internal::Arr_bottom_top_implementation_dispatch
<Bottom_side_category, Top_side_category>;
using Cmp_tag1 = typename BT::Compare_x_on_boundary_2_points_tag;
using Cmp_tag2 = typename BT::Compare_x_on_boundary_2_point_curve_end_tag;
using Cmp_tag3 = typename BT::Compare_x_on_boundary_2_curve_ends_tag;
using Cmp_tag12 = typename CGAL::internal::Or_traits<Cmp_tag1, Cmp_tag2>::type;
using Cmp_tag = typename CGAL::internal::Or_traits<Cmp_tag12, Cmp_tag3>::type;
return compare_x_on_boundary_wrapper_imp(str_stream, Cmp_tag());
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
compare_x_on_boundary_wrapper_imp(std::istringstream&,
CGAL::Arr_use_dummy_tag)
{
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_on_boundary_wrapper_imp(std::istringstream&, CGAL::Arr_use_dummy_tag) {
CGAL_error();
return false;
}
template <typename Geom_traits_T>
bool Traits_test<Geom_traits_T>::
template <typename GeomTraits>
bool Traits_test<GeomTraits>::
compare_x_on_boundary_wrapper_imp(std::istringstream& str_stream,
CGAL::Arr_use_traits_tag)
{
CGAL::Arr_use_traits_tag) {
// TBD: points
std::cout << "Test: compare_x_on_boundary( ";

View File

@ -118,6 +118,7 @@ set(IS_BETWEEN_CW 26)
set(COMPARE_CW_AROUND_POINT 27)
set(PUSH_BACK 28)
set(PUSH_FRONT 29)
set(APPROXIMATE 30)
set(NUMBER_OF_POINTS 32)
set(COMPARE_ENDPOINTS_XY 33)
set(CONSTRUCT_OPPOSITE 34)
@ -240,22 +241,30 @@ function(execute_commands_old_structure data_dir traits_type_name)
# the old structure is default, so this function executes all commands
# except the commands that are given as arguments
set(commands_indicator_APPROXIMATE 1)
set(commands_indicator_ARE_MERGEABLE 1)
set(commands_indicator_ASSERTIONS 1)
set(commands_indicator_COMPARE 1)
set(commands_indicator_VERTEX 1)
set(commands_indicator_IS_VERTICAL 1)
set(commands_indicator_COMPARE_Y_AT_X 1)
set(commands_indicator_COMPARE_Y_AT_X_LEFT 1)
set(commands_indicator_COMPARE_Y_AT_X_RIGHT 1)
set(commands_indicator_MAKE_X_MONOTONE 1)
set(commands_indicator_INTERSECT 1)
set(commands_indicator_SPLIT 1)
set(commands_indicator_ARE_MERGEABLE 1)
set(commands_indicator_MERGE 1)
set(commands_indicator_ASSERTIONS 1)
set(commands_indicator_CONSTRUCTOR 1)
set(commands_indicator_INTERSECT 1)
set(commands_indicator_IS_VERTICAL 1)
set(commands_indicator_MAKE_X_MONOTONE 1)
set(commands_indicator_MERGE 1)
set(commands_indicator_SPLIT 1)
set(commands_indicator_VERTEX 1)
foreach(arg ${ARGN})
set(commands_indicator_${arg} 0)
endforeach()
if(commands_indicator_APPROXIMATE)
run_trapped_test(test_traits
data/empty.zero data/${data_dir}/approximate.xcv
data/empty.zero data/${data_dir}/approximate ${traits_type_name})
endif()
if(commands_indicator_COMPARE)
run_trapped_test(test_traits
data/compare.pt data/empty.zero
@ -278,18 +287,21 @@ function(execute_commands_old_structure data_dir traits_type_name)
endif()
if(commands_indicator_COMPARE_Y_AT_X_LEFT)
run_trapped_test(test_traits
data/${data_dir}/compare_y_at_x_left.pt data/${data_dir}/compare_y_at_x_left.xcv
data/${data_dir}/compare_y_at_x_left.pt
data/${data_dir}/compare_y_at_x_left.xcv
data/empty.zero data/${data_dir}/compare_y_at_x_left ${traits_type_name})
endif()
if(commands_indicator_COMPARE_Y_AT_X_RIGHT)
run_trapped_test(test_traits
data/${data_dir}/compare_y_at_x_right.pt data/${data_dir}/compare_y_at_x_right.xcv
data/${data_dir}/compare_y_at_x_right.pt
data/${data_dir}/compare_y_at_x_right.xcv
data/empty.zero data/${data_dir}/compare_y_at_x_right ${traits_type_name})
endif()
if(commands_indicator_MAKE_X_MONOTONE)
run_trapped_test(test_traits
data/empty.zero data/${data_dir}/make_x_monotone.xcv
data/${data_dir}/make_x_monotone.cv data/${data_dir}/make_x_monotone ${traits_type_name})
data/${data_dir}/make_x_monotone.cv
data/${data_dir}/make_x_monotone ${traits_type_name})
endif()
if(commands_indicator_INTERSECT)
run_trapped_test(test_traits
@ -319,7 +331,8 @@ function(execute_commands_old_structure data_dir traits_type_name)
if(commands_indicator_CONSTRUCTOR)
run_trapped_test(test_traits
data/empty.zero data/${data_dir}/constructor.xcv
data/${data_dir}/constructor.cv data/${data_dir}/constructor ${traits_type_name})
data/${data_dir}/constructor.cv data/${data_dir}/constructor
${traits_type_name})
endif()
endfunction()
@ -332,133 +345,166 @@ function(execute_commands_new_structure data_dir traits_type_name)
# the new structure is not default, so this function executes only
# commands that are given as arguments
set(commands_indicator_APPROXIMATE 0)
set(commands_indicator_ARE_MERGEABLE 0)
set(commands_indicator_ASSERTIONS 0)
set(commands_indicator_COMPARE 0)
set(commands_indicator_VERTEX 0)
set(commands_indicator_IS_VERTICAL 0)
set(commands_indicator_COMPARE_X_ON_BOUNDARY 0)
set(commands_indicator_COMPARE_ENDPOINTS_XY 0)
set(commands_indicator_COMPARE_X_NEAR_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_NEAR_BOUNDARY 0)
set(commands_indicator_PARAMETER_SPACE_X 0)
set(commands_indicator_PARAMETER_SPACE_Y 0)
set(commands_indicator_COMPARE_X_ON_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_AT_X 0)
set(commands_indicator_COMPARE_Y_AT_X_LEFT 0)
set(commands_indicator_COMPARE_Y_AT_X_RIGHT 0)
set(commands_indicator_MAKE_X_MONOTONE 0)
set(commands_indicator_INTERSECT 0)
set(commands_indicator_SPLIT 0)
set(commands_indicator_ARE_MERGEABLE 0)
set(commands_indicator_MERGE 0)
set(commands_indicator_ASSERTIONS 0)
set(commands_indicator_COMPARE_Y_NEAR_BOUNDARY 0)
set(commands_indicator_CONSTRUCTOR 0)
set(commands_indicator_CONSTRUCT_OPPOSITE 0)
set(commands_indicator_EQUAL 0)
set(commands_indicator_INTERSECT 0)
set(commands_indicator_IS_VERTICAL 0)
set(commands_indicator_MAKE_X_MONOTONE 0)
set(commands_indicator_MERGE 0)
set(commands_indicator_NUMBER_OF_POINTS 0)
set(commands_indicator_PARAMETER_SPACE_X 0)
set(commands_indicator_PARAMETER_SPACE_Y 0)
set(commands_indicator_PUSH_BACK 0)
set(commands_indicator_PUSH_FRONT 0)
set(commands_indicator_NUMBER_OF_POINTS 0)
set(commands_indicator_COMPARE_ENDPOINTS_XY 0)
set(commands_indicator_CONSTRUCT_OPPOSITE 0)
set(commands_indicator_SPLIT 0)
set(commands_indicator_TRIM 0)
set(commands_indicator_VERTEX 0)
foreach(arg ${ARGN})
set(commands_indicator_${arg} 1)
endforeach()
if(commands_indicator_APPROXIMATE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/approximate ${traits_type_name})
endif()
if(commands_indicator_COMPARE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare ${traits_type_name})
endif()
if(commands_indicator_VERTEX)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/vertex ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/vertex ${traits_type_name})
endif()
if(commands_indicator_IS_VERTICAL)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/is_vertical ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/is_vertical ${traits_type_name})
endif()
if(commands_indicator_COMPARE_X_ON_BOUNDARY)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_x_on_boundary ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_x_on_boundary ${traits_type_name})
endif()
if(commands_indicator_COMPARE_X_NEAR_BOUNDARY)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_x_near_boundary ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_x_near_boundary ${traits_type_name})
endif()
if(commands_indicator_COMPARE_Y_NEAR_BOUNDARY)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_y_near_boundary ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_y_near_boundary ${traits_type_name})
endif()
if(commands_indicator_PARAMETER_SPACE_X)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/parameter_space_x ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/parameter_space_x ${traits_type_name})
endif()
if(commands_indicator_PARAMETER_SPACE_Y)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/parameter_space_y ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/parameter_space_y ${traits_type_name})
endif()
if(commands_indicator_COMPARE_Y_AT_X)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_y_at_x ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_y_at_x ${traits_type_name})
endif()
if(commands_indicator_COMPARE_Y_AT_X_LEFT)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_y_at_x_left ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_y_at_x_left ${traits_type_name})
endif()
if(commands_indicator_COMPARE_Y_AT_X_RIGHT)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_y_at_x_right ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_y_at_x_right ${traits_type_name})
endif()
if(commands_indicator_MAKE_X_MONOTONE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/make_x_monotone ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/make_x_monotone ${traits_type_name})
endif()
if(commands_indicator_INTERSECT)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/intersect ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/intersect ${traits_type_name})
endif()
if(commands_indicator_SPLIT)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/split ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/split ${traits_type_name})
endif()
if(commands_indicator_ARE_MERGEABLE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/are_mergeable ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/are_mergeable ${traits_type_name})
endif()
if(commands_indicator_MERGE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/merge ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/merge ${traits_type_name})
endif()
if(commands_indicator_ASSERTIONS)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/assertions ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/assertions ${traits_type_name})
endif()
if(commands_indicator_CONSTRUCTOR)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/constructor ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/constructor ${traits_type_name})
endif()
if(commands_indicator_EQUAL)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/equal ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/equal ${traits_type_name})
endif()
if(commands_indicator_PUSH_BACK)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/push_back ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/push_back ${traits_type_name})
endif()
if(commands_indicator_PUSH_FRONT)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/push_front ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/push_front ${traits_type_name})
endif()
if(commands_indicator_NUMBER_OF_POINTS)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/number_of_points ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/number_of_points ${traits_type_name})
endif()
if(commands_indicator_COMPARE_ENDPOINTS_XY)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/compare_endpoints_xy ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/compare_endpoints_xy ${traits_type_name})
endif()
if(commands_indicator_CONSTRUCT_OPPOSITE)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/construct_opposite ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/construct_opposite ${traits_type_name})
endif()
if(commands_indicator_TRIM)
run_trapped_test(test_traits data/${data_dir}/points
data/${data_dir}/xcurves data/${data_dir}/curves data/${data_dir}/trim ${traits_type_name})
data/${data_dir}/xcurves data/${data_dir}/curves
data/${data_dir}/trim ${traits_type_name})
endif()
endfunction()
@ -467,26 +513,32 @@ function(execute_commands_traits_adaptor data_dir traits_type_name)
# the new structure is not default, so this function executes only
# commands that are given as arguments
set(commands_indicator_PARAMETER_SPACE_X 0)
set(commands_indicator_PARAMETER_SPACE_Y 0)
set(commands_indicator_ARE_MERGEABLE 0)
set(commands_indicator_COMPARE_CW_AROUND_POINT 0)
set(commands_indicator_COMPARE_XY 0)
set(commands_indicator_COMPARE_X_ON_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_AT_X_LEFT 0)
set(commands_indicator_COMPARE_X_NEAR_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_NEAR_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_AT_X_LEFT 0)
set(commands_indicator_ARE_MERGEABLE 0)
set(commands_indicator_MERGE 0)
set(commands_indicator_X_ON_IDENTIFICATION 0)
set(commands_indicator_Y_ON_IDENTIFICATION 0)
set(commands_indicator_IS_BOUNDED 0)
set(commands_indicator_IS_IN_X_RANGE 0)
set(commands_indicator_COMPARE_X_ON_BOUNDARY 0)
set(commands_indicator_COMPARE_Y_POSITION 0)
set(commands_indicator_IS_BETWEEN_CW 0)
set(commands_indicator_COMPARE_CW_AROUND_POINT 0)
set(commands_indicator_IS_BOUNDED 0)
set(commands_indicator_IS_IN_X_RANGE 0)
set(commands_indicator_MERGE 0)
set(commands_indicator_PARAMETER_SPACE_X 0)
set(commands_indicator_PARAMETER_SPACE_Y 0)
set(commands_indicator_X_ON_IDENTIFICATION 0)
set(commands_indicator_Y_ON_IDENTIFICATION 0)
foreach(arg ${ARGN})
set(commands_indicator_${arg} 1)
endforeach()
if(commands_indicator_ARE_MERGEABLE)
run_trapped_test(test_traits_adaptor data/test_adaptor/${data_dir}/points
data/test_adaptor/${data_dir}/xcurves data/test_adaptor/${data_dir}/curves
data/test_adaptor/${data_dir}/are_mergeable ${traits_type_name})
endif()
if(commands_indicator_PARAMETER_SPACE_X)
run_trapped_test(test_traits_adaptor data/test_adaptor/${data_dir}/points
data/test_adaptor/${data_dir}/xcurves data/test_adaptor/${data_dir}/curves
@ -524,11 +576,6 @@ function(execute_commands_traits_adaptor data_dir traits_type_name)
data/test_adaptor/${data_dir}/xcurves data/test_adaptor/${data_dir}/curves
data/test_adaptor/${data_dir}/compare_y_at_x_left ${traits_type_name})
endif()
if(commands_indicator_ARE_MERGEABLE)
run_trapped_test(test_traits_adaptor data/test_adaptor/${data_dir}/points
data/test_adaptor/${data_dir}/xcurves data/test_adaptor/${data_dir}/curves
data/test_adaptor/${data_dir}/are_mergeable ${traits_type_name})
endif()
if(commands_indicator_MERGE)
run_trapped_test(test_traits_adaptor data/test_adaptor/${data_dir}/points
data/test_adaptor/${data_dir}/xcurves data/test_adaptor/${data_dir}/curves
@ -582,7 +629,7 @@ function(test_segment_traits_adaptor)
compile_test_with_flags(test_traits_adaptor segments "${flags}")
# if [ -n "${SUCCESS}" ] ; then
execute_commands_traits_adaptor( segments segments_traits_adaptor
execute_commands_traits_adaptor(segments segments_traits_adaptor
COMPARE_XY COMPARE_Y_POSITION COMPARE_CW_AROUND_POINT COMPARE_Y_AT_X_LEFT
ARE_MERGEABLE MERGE IS_IN_X_RANGE IS_BETWEEN_CW)
endfunction()
@ -598,7 +645,7 @@ function(test_linear_traits_adaptor)
compile_test_with_flags( test_traits_adaptor linear "${flags}")
execute_commands_traits_adaptor( linear linear_traits_adaptor
execute_commands_traits_adaptor(linear linear_traits_adaptor
COMPARE_XY COMPARE_Y_AT_X_LEFT ARE_MERGEABLE MERGE IS_IN_X_RANGE
COMPARE_Y_POSITION IS_BETWEEN_CW COMPARE_CW_AROUND_POINT)
endfunction()
@ -615,7 +662,7 @@ function(test_spherical_arcs_traits_adaptor)
compile_test_with_flags( test_traits_adaptor geodesic_arcs_on_sphere "${flags}")
execute_commands_traits_adaptor( spherical_arcs spherical_arcs_traits_adaptor
execute_commands_traits_adaptor(spherical_arcs spherical_arcs_traits_adaptor
COMPARE_XY COMPARE_Y_AT_X_LEFT ARE_MERGEABLE MERGE IS_IN_X_RANGE
COMPARE_Y_POSITION IS_BETWEEN_CW COMPARE_CW_AROUND_POINT)
endfunction()
@ -643,7 +690,7 @@ function(test_construction_segments)
set(kernel ${CARTESIAN_KERNEL})
set(geom_traits ${SEGMENT_GEOM_TRAITS})
set(flags "-DTEST_NT=${nt} -DTEST_KERNEL=${kernel} -DTEST_GEOM_TRAITS=${geom_traits}")
compile_and_run_with_flags( test_construction segments "${flags}")
compile_and_run_with_flags(test_construction segments "${flags}")
endfunction()
#---------------------------------------------------------------------#
@ -655,7 +702,7 @@ function(test_construction_linear_curves)
set(geom_traits ${LINEAR_GEOM_TRAITS})
set(topol_traits ${PLANAR_UNBOUNDED_TOPOL_TRAITS})
set(flags "-DTEST_NT=${nt} -DTEST_KERNEL=${kernel} -DTEST_GEOM_TRAITS=${geom_traits} -DTEST_TOPOL_TRAITS=${topol_traits}")
compile_and_run_with_flags( test_construction linear "${flags}")
compile_and_run_with_flags(test_construction linear "${flags}")
endfunction()
#---------------------------------------------------------------------#
@ -667,7 +714,7 @@ function(test_construction_spherical_arcs)
set(geom_traits ${GEODESIC_ARC_ON_SPHERE_GEOM_TRAITS})
set(topol_traits ${SPHERICAL_TOPOL_TRAITS})
set(flags "-DTEST_NT=${nt} -DTEST_KERNEL=${kernel} -DTEST_GEOM_TRAITS=${geom_traits} -DTEST_TOPOL_TRAITS=${topol_traits}")
compile_and_run_with_flags( test_construction geodesic_arcs_on_sphere "${flags}")
compile_and_run_with_flags(test_construction geodesic_arcs_on_sphere "${flags}")
endfunction()
#---------------------------------------------------------------------#
@ -678,7 +725,7 @@ function(test_construction_polylines)
set(kernel ${CARTESIAN_KERNEL})
set(geom_traits ${POLYLINE_GEOM_TRAITS})
set(flags "-DTEST_NT=${nt} -DTEST_KERNEL=${kernel} -DTEST_GEOM_TRAITS=${geom_traits}")
compile_and_run_with_flags( test_construction polylines "${flags}")
compile_and_run_with_flags(test_construction polylines "${flags}")
endfunction()
@ -837,14 +884,16 @@ function(test_segment_traits)
compile_test_with_flags(test_traits segments "${flags}")
execute_commands_old_structure( segments segment_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT CONSTRUCTOR
COMPARE_Y_AT_X_RIGHT ARE_MERGEABLE)
execute_commands_old_structure(segments segment_traits
APPROXIMATE ARE_MERGEABLE COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT CONSTRUCTOR IS_VERTICAL VERTEX)
execute_commands_new_structure( segments segment_traits
IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT ARE_MERGEABLE)
ARE_MERGEABLE
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
IS_VERTICAL)
run_trapped_test( test_traits
run_trapped_test(test_traits
data/segments/vertex.pt data/segments/xcurves
data/empty.zero data/segments/vertex segment_traits)
endfunction()
@ -861,11 +910,13 @@ function(test_non_caching_segment_traits)
compile_test_with_flags(test_traits non_caching_segments "${flags}")
execute_commands_old_structure(segments non_caching_segment_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT CONSTRUCTOR
COMPARE_Y_AT_X_RIGHT ARE_MERGEABLE ASSERTIONS)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT CONSTRUCTOR COMPARE_Y_AT_X_RIGHT
IS_VERTICAL VERTEX)
execute_commands_new_structure(segments segment_traits
IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT)
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
IS_VERTICAL)
run_trapped_test(test_traits
data/segments/vertex.pt data/segments/xcurves
@ -894,23 +945,20 @@ function(test_polycurve_conic_traits)
# Execute_command_new_structure will only run the test on functors provided as the third, fourth and so on arguments.
# To see how the input data directory should be structured for each functor, check the execute_commands_new_structure function in this file.
execute_commands_new_structure(polycurves_conics polycurve_conic_traits
COMPARE_Y_AT_X
INTERSECT
EQUAL
IS_VERTICAL
SPLIT
ARE_MERGEABLE
COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT
COMPARE_ENDPOINTS_XY COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT
CONSTRUCT_OPPOSITE
EQUAL
INTERSECT
IS_VERTICAL
MAKE_X_MONOTONE
MERGE
NUMBER_OF_POINTS
SPLIT
PUSH_BACK
PUSH_FRONT
NUMBER_OF_POINTS
VERTEX
CONSTRUCT_OPPOSITE
MERGE
COMPARE_ENDPOINTS_XY
TRIM)
TRIM
VERTEX)
endfunction()
@ -925,23 +973,21 @@ function(test_polycurve_circular_arc_traits)
compile_test_with_flags(test_traits circular_arc_polycurve "${flags}")
execute_commands_new_structure(polycurves_circular_arcs polycurve_circular_arc_traits
COMPARE_Y_AT_X
EQUAL
IS_VERTICAL
SPLIT
execute_commands_new_structure(polycurves_circular_arcs
polycurve_circular_arc_traits
ARE_MERGEABLE
COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT
COMPARE_ENDPOINTS_XY COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT
CONSTRUCT_OPPOSITE
EQUAL
INTERSECT
IS_VERTICAL
MAKE_X_MONOTONE
MERGE
NUMBER_OF_POINTS
PUSH_BACK
PUSH_FRONT
NUMBER_OF_POINTS
VERTEX
CONSTRUCT_OPPOSITE
MERGE
COMPARE_ENDPOINTS_XY
INTERSECT)
SPLIT
VERTEX)
endfunction()
#---------------------------------------------------------------------#
@ -960,15 +1006,15 @@ function(test_polycurve_bezier_traits)
compile_test_with_flags(test_traits bezier_polycurve "${flags}")
execute_commands_new_structure(polycurves_bezier test_polycurve_bezier_traits
MERGE
ARE_MERGEABLE
COMPARE_ENDPOINTS_XY
EQUAL
IS_VERTICAL
NUMBER_OF_POINTS
MERGE
PUSH_BACK
PUSH_FRONT
VERTEX
ARE_MERGEABLE
COMPARE_ENDPOINTS_XY
# TODO (add data for these tests)
# COMPARE_Y_AT_X
# SPLIT
@ -993,8 +1039,8 @@ function(test_polyline_traits)
compile_test_with_flags(test_traits test_polylines "${flags}")
execute_commands_old_structure(polylines polyline_traits
CONSTRUCTOR COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE
COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR)
endfunction()
#---------------------------------------------------------------------#
@ -1009,8 +1055,8 @@ function(test_non_caching_polyline_traits)
compile_test_with_flags(test_traits non_caching_polylines "${flags}")
execute_commands_old_structure(polylines non_caching_polyline_traits
CONSTRUCTOR COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE
COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR)
endfunction()
#---------------------------------------------------------------------#
@ -1025,32 +1071,39 @@ function(test_linear_traits)
compile_test_with_flags(test_traits linear "${flags}")
execute_commands_old_structure(linear/segments linear_traits.segments
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT CONSTRUCTOR ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR
IS_VERTICAL VERTEX)
execute_commands_new_structure(linear/segments linear_traits.segments
IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT)
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
IS_VERTICAL)
run_trapped_test(test_traits
data/linear/segments/vertex.pt data/linear/segments/xcurves
data/empty.zero data/linear/segments/vertex linear_traits.segments)
execute_commands_old_structure(linear/rays linear_traits.rays
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT CONSTRUCTOR ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR
IS_VERTICAL VERTEX)
execute_commands_new_structure(linear/rays linear_traits.rays
IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT)
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
IS_VERTICAL)
run_trapped_test(test_traits
data/linear/rays/vertex.pt data/linear/rays/xcurves
data/empty.zero data/linear/rays/vertex linear_traits.rays)
execute_commands_new_structure(linear/lines linear_traits.lines
IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT INTERSECT
SPLIT MERGE
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY COMPARE_Y_NEAR_BOUNDARY
IS_VERTICAL
INTERSECT
MERGE
PARAMETER_SPACE_X PARAMETER_SPACE_Y
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY COMPARE_Y_NEAR_BOUNDARY)
SPLIT)
endfunction()
#---------------------------------------------------------------------#
@ -1069,11 +1122,13 @@ function(test_conic_traits)
compile_test_with_flags(test_traits conics "${flags}")
execute_commands_old_structure(conics conic_traits
INTERSECT SPLIT MERGE COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT
INTERSECT SPLIT MERGE)
execute_commands_new_structure(conics conic_traits
INTERSECT SPLIT MERGE)
INTERSECT
MERGE
SPLIT)
run_trapped_test(test_traits
data/conics/compare.pt data/empty.zero
@ -1092,11 +1147,13 @@ function(test_line_arc_traits)
compile_test_with_flags(test_traits line_arcs "${flags}")
execute_commands_old_structure(circular_lines line_arc_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
ASSERTIONS COMPARE_Y_AT_X_RIGHT MERGE ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT
IS_VERTICAL MERGE VERTEX)
execute_commands_new_structure(circular_lines line_arc_traits
IS_VERTICAL COMPARE_Y_AT_X)
COMPARE_Y_AT_X
IS_VERTICAL)
run_trapped_test(test_traits
data/circular_lines/compare.pt data/empty.zero
@ -1119,11 +1176,14 @@ function(test_circular_arc_traits)
compile_test_with_flags(test_traits circular_arcs "${flags}")
execute_commands_old_structure(circular_arcs circular_arc_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
ASSERTIONS COMPARE_Y_AT_X_RIGHT MERGE ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT
IS_VERTICAL MERGE VERTEX)
execute_commands_new_structure(circular_arcs circular_arc_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X)
COMPARE_Y_AT_X
IS_VERTICAL
VERTEX)
endfunction()
#---------------------------------------------------------------------#
@ -1138,11 +1198,13 @@ function(test_circular_line_arc_traits)
compile_test_with_flags(test_traits circular_line_arcs "${flags}")
execute_commands_old_structure(circular_line_arcs circular_line_arc_traits
VERTEX IS_VERTICAL CONSTRUCTOR COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
ASSERTIONS COMPARE_Y_AT_X_RIGHT MERGE ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR
IS_VERTICAL MERGE VERTEX)
execute_commands_new_structure(circular_line_arcs circular_line_arc_traits
IS_VERTICAL COMPARE_Y_AT_X)
COMPARE_Y_AT_X
IS_VERTICAL)
run_trapped_test(test_traits
data/circular_line_arcs/vertex.pt data/circular_line_arcs/xcurves
@ -1161,8 +1223,12 @@ function(test_circle_segments_traits)
compile_test_with_flags(test_traits circle_segments "${flags}")
execute_commands_old_structure(circle_segments circle_segments_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_Y_AT_X_RIGHT CONSTRUCTOR ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR
IS_VERTICAL VERTEX)
execute_commands_new_structure(circle_segments circle_segments_traits
APPROXIMATE)
run_trapped_test(test_traits
data/circle_segments/points data/circle_segments/xcurves.8
@ -1200,8 +1266,8 @@ function(test_bezier_traits)
compile_test_with_flags(test_traits Bezier "${flags}")
execute_commands_old_structure(bezier bezier_traits
COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT SPLIT
CONSTRUCTOR ASSERTIONS ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT CONSTRUCTOR SPLIT)
endfunction()
#---------------------------------------------------------------------#
@ -1217,14 +1283,14 @@ function(test_spherical_arc_traits)
compile_test_with_flags(test_traits geodesic_arcs_on_sphere "${flags}")
execute_commands_old_structure(spherical_arcs spherical_arc_traits
COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT INTERSECT
CONSTRUCTOR
COMPARE MAKE_X_MONOTONE SPLIT MERGE ASSERTIONS ARE_MERGEABLE)
APPROXIMATE ARE_MERGEABLE ASSERTIONS
COMPARE COMPARE_Y_AT_X_LEFT COMPARE_Y_AT_X_RIGHT INTERSECT CONSTRUCTOR
MAKE_X_MONOTONE MERGE SPLIT)
execute_commands_new_structure(spherical_arcs spherical_arc_traits
INTERSECT
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY
COMPARE_Y_NEAR_BOUNDARY)
APPROXIMATE
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY COMPARE_Y_NEAR_BOUNDARY
INTERSECT)
run_trapped_test(test_traits
data/spherical_arcs/compare.pt data/spherical_arcs/compare.xcv
@ -1251,8 +1317,12 @@ function(test_rational_arc_traits)
data/empty.zero data/compare rational_arc_traits)
execute_commands_new_structure(rational_arcs rational_arc_traits
VERTEX IS_VERTICAL COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT SPLIT MERGE
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY COMPARE_Y_NEAR_BOUNDARY)
COMPARE_Y_AT_X COMPARE_Y_AT_X_LEFT
COMPARE_X_ON_BOUNDARY COMPARE_X_NEAR_BOUNDARY COMPARE_Y_NEAR_BOUNDARY
IS_VERTICAL
MERGE
SPLIT
VERTEX)
endfunction()
#---------------------------------------------------------------------#
@ -1273,8 +1343,13 @@ function(test_algebraic_traits_gmp)
execute_commands_new_structure(algebraic algebraic_traits_gmp
COMPARE COMPARE_Y_AT_X COMPARE_Y_AT_X_RIGHT COMPARE_Y_AT_X_LEFT
MAKE_X_MONOTONE IS_VERTICAL VERTEX SPLIT MERGE INTERSECT
PARAMETER_SPACE_X PARAMETER_SPACE_Y)
IS_VERTICAL
INTERSECT
MAKE_X_MONOTONE
MERGE
PARAMETER_SPACE_X PARAMETER_SPACE_Y
SPLIT
VERTEX)
endfunction()
#---------------------------------------------------------------------#
@ -1292,8 +1367,13 @@ function(test_algebraic_traits_leda)
execute_commands_new_structure(algebraic algebraic_traits_leda
COMPARE COMPARE_Y_AT_X COMPARE_Y_AT_X_RIGHT COMPARE_Y_AT_X_LEFT
MAKE_X_MONOTONE IS_VERTICAL VERTEX SPLIT MERGE INTERSECT
PARAMETER_SPACE_X PARAMETER_SPACE_Y)
IS_VERTICAL
INTERSECT
MAKE_X_MONOTONE
MERGE
PARAMETER_SPACE_X PARAMETER_SPACE_Y
SPLIT
VERTEX)
endfunction()
@ -1315,8 +1395,13 @@ function(test_algebraic_traits_core)
execute_commands_new_structure(algebraic algebraic_traits_core
COMPARE COMPARE_Y_AT_X COMPARE_Y_AT_X_RIGHT COMPARE_Y_AT_X_LEFT
MAKE_X_MONOTONE IS_VERTICAL VERTEX SPLIT MERGE INTERSECT
PARAMETER_SPACE_X PARAMETER_SPACE_Y)
IS_VERTICAL
INTERSECT
MAKE_X_MONOTONE
MERGE
PARAMETER_SPACE_X PARAMETER_SPACE_Y
SPLIT
VERTEX)
endfunction()

View File

@ -0,0 +1 @@
approximate 0 0.01 1 9

View File

@ -0,0 +1 @@
x 0 0 1 1 1 1 1 0 1 0 1 1

View File

@ -0,0 +1 @@
approximate 108 0.01 1 7

View File

@ -31,7 +31,7 @@
0 1 0 0 3/4 1/4 0
0 3/4 1/4 0 1/2 1/2 0
0 7/8 1/8 0 5/8 3/8 0
# xz plane
# xz plane 32
0 0 0 -1 1/2 0 -1/2
0 0 0 -1 1/4 0 -3/4
0 1/4 0 -3/4 1/2 0 -1/2
@ -64,7 +64,7 @@
0 0 0 -1 -1/4 0 -3/4
0 -1/4 0 -3/4 -1/2 0 -1/2
0 -1/8 0 -7/8 -1/8 0 -5/8
# yz plane
# yz plane 64
0 0 0 -1 0 1/2 -1/2
0 0 0 -1 0 1/4 -3/4
0 0 1/4 -3/4 0 1/2 -1/2
@ -97,18 +97,20 @@
0 0 0 -1 0 -1/4 -3/4
0 0 -1/4 -3/4 0 -1/2 -1/2
0 0 -1/8 -7/8 0 -1/8 -5/8
#
# 96
1 -1 0 0 1 0 0 0 1 1
1 -1 0 0 1 0 0 0 -1 1
1 1 0 0 -1 0 0 0 1 1
1 1 0 0 -1 0 0 0 -1 1
#
# 100
1 -1 0 0 1 0 0 0 -1 -1
1 -1 0 0 1 0 0 0 1 -1
1 1 0 0 -1 0 0 0 -1 -1
1 1 0 0 -1 0 0 0 1 -1
#
# 104
0 -1 0 0 0 -1 1
0 -1 0 0 0 -1 -1
0 -1 0 0 0 1 1
0 -1 0 0 0 1 -1
# 108
0 -1 0 0 0 -1 0

View File

@ -407,7 +407,7 @@ aforementioned free functions is actually realized by a set overriding
member function.
member functions of the `Polygon_set_2`
(resp. `General_polygon_set_2`) that perform Boolean set-operations
(respectively `General_polygon_set_2`) that perform Boolean set-operations
come in two flavors: for example, `S.join(P, Q)` computes the union of
\f$ P\f$ and \f$ Q\f$ and assigned the result to \f$ S\f$, while
`S.join(P)` performs the operation \f$ S \longleftarrow S \cup P\f$.
@ -579,8 +579,8 @@ template, as described above, an instance of the
`Arr_polyline_traits_2` class template; see Section \ref
arr_ssectr_polylines in the 2D Arrangements package.
<li>Each input linear polygon (resp. linear polygon with holes) is
converted into a general polygon (resp. general polygon with holes)
<li>Each input linear polygon (respectively linear polygon with holes) is
converted into a general polygon (respectively general polygon with holes)
bounded by \f$x\f$-monotone polylines. Then, the resulting generl
polygons, which are also bounded by \f$x\f$-monotone polylines, are
converted back to standard polygons.

View File

@ -900,26 +900,26 @@ template <typename Polygon>
bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
const General_polygon_with_holes_2<Polygon>& pgn2);
/*! Given a range of polygons or a range of polygons with holes (resp. a range
/*! Given a range of polygons or a range of polygons with holes (respectively a range
* of general polygons or a range of general polygons with holes) determines
* whether the open polygons (resp. general polygons) in the range have a common
* whether the open polygons (respectively general polygons) in the range have a common
* point.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons or polygons
* with holes (resp. general polygons or general polygons with holes) in
* with holes (respectively general polygons or general polygons with holes) in
* the range [*begin,*end) overlap, and `false` otherwise.
*/
template <typename InputIterator>
bool do_intersect(InputIterator begin, InputIterator end);
/*! Given a range of polygons or a range of polygons with holes (resp. a range
/*! Given a range of polygons or a range of polygons with holes (respectively a range
* of general polygons or a range of general polygons with holes) determines
* whether the open polygons (resp. general polygons) in the range have a common
* whether the open polygons (respectively general polygons) in the range have a common
* point.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input range are treated as cyclic sequences of single
@ -931,32 +931,32 @@ bool do_intersect(InputIterator begin, InputIterator end);
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
* information.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons or polygons
* with holes (resp. general polygons or general polygons with holes) in
* with holes (respectively general polygons or general polygons with holes) in
* the range [*begin,*end) overlap, and `false` otherwise.
*/
template <typename InputIterator, typename UsePolylines>
bool do_intersect(InputIterator begin, InputIterator end,
UsePolylines = Tag_true());
/*! Given a range of polygons (resp. general polygons) and a range of polygons
* with holes (resp. general polygons with holes) determines whether the open
* polygons (resp. general polygons) in the two ranges have a common point.
/*! Given a range of polygons (respectively general polygons) and a range of polygons
* with holes (respectively general polygons with holes) determines whether the open
* polygons (respectively general polygons) in the two ranges have a common point.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons (resp.
* general polygons) and polygons with holes (resp. general polygons with
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons (respectively
* general polygons) and polygons with holes (respectively general polygons with
* holes) in the ranges [*begin1,*end1) and [*begin2,*end2),
* respectively, overlap, and `false` otherwise.
*/
@ -964,9 +964,9 @@ template <typename InputIterator1, typename InputIterator2>
bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
InputIterator2 begin2, InputIterator2 end2);
/*! Given a range of polygons (resp. general polygons) and a range of polygons
* with holes (resp. general polygons with holes) determines whether the open
* polygons (resp. general polygons) in the two ranges have a common point.
/*! Given a range of polygons (respectively general polygons) and a range of polygons
* with holes (respectively general polygons with holes) determines whether the open
* polygons (respectively general polygons) in the two ranges have a common point.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input ranges are treated as cyclic sequences of single
* (\f$x\f$-monotone) segments or as a cyclic sequences of
@ -977,15 +977,15 @@ bool do_intersect(InputIterator1 begin1, InputIterator1 end1,
* `pgn2` are used as is. Refer to \ref bso_ssectraits_sel for more
* information.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons (resp.
* general polygons) and polygons with holes (resp. general polygons with
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return `true` if the pairwise intersections of all open polygons (respectively
* general polygons) and polygons with holes (respectively general polygons with
* holes) in the ranges [*begin1,*end1) and [*begin2,*end2),
* respectively, overlap, and `false` otherwise.
*/
@ -1112,19 +1112,19 @@ bool do_intersect(const General_polygon_with_holes_2<Polygon>& pgn1,
const General_polygon_with_holes_2<Polygon>& pgn2,
const GpsTraits& traits);
/*! Given a range of polygons or a range of polygons with holes (resp. a range
/*! Given a range of polygons or a range of polygons with holes (respectively a range
* of general polygons or a range of general polygons with holes) determines
* whether the open polygons (resp. general polygons) in the range have a common
* whether the open polygons (respectively general polygons) in the range have a common
* point.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return `true` if the pairwise intersections of all open polygons or polygons
* with holes (resp. general polygons or general polygons with holes) in
* with holes (respectively general polygons or general polygons with holes) in
* the range [*begin,*end) overlap, and `false` otherwise.
* \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`.
*/
@ -1132,20 +1132,20 @@ template <typename InputIterator, typename GpsTraits>
bool do_intersect(InputIterator begin, InputIterator end,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) and a range of polygons
* with holes (resp. general polygons with holes) determines whether the open
* polygons (resp. general polygons) in the two ranges have a common point.
/*! Given a range of polygons (respectively general polygons) and a range of polygons
* with holes (respectively general polygons with holes) determines whether the open
* polygons (respectively general polygons) in the two ranges have a common point.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return `true` if the pairwise intersections of all open polygons (resp.
* general polygons) and polygons with holes (resp. general polygons with
* \return `true` if the pairwise intersections of all open polygons (respectively
* general polygons) and polygons with holes (respectively general polygons with
* holes) in the ranges [*begin1,*end1) and [*begin2,*end2),
* respectively, overlap, and `false` otherwise.
*/
@ -1471,30 +1471,30 @@ OutputIterator intersection(const General_polygon_with_holes_2<Polygon>& pgn1,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection of all polygons in the range and inserts the resulting polygons
* with holes (resp. general polygons with holes) into a container via an output
* with holes (respectively general polygons with holes) into a container via an output
* iterator.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or `Polygon_with_holes_2`
* (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or `Polygon_with_holes_2`
* (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or `Polygon_with_holes_2`
* (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or `Polygon_with_holes_2`
* (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator>
OutputIterator intersection(InputIterator begin, InputIterator end,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection of all polygons in the range and inserts the resulting polygons
* with holes (resp. general polygons with holes) into a container via an output
* with holes (respectively general polygons with holes) into a container via an output
* iterator.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input range are treated as cyclic sequences of single
@ -1507,14 +1507,14 @@ OutputIterator intersection(InputIterator begin, InputIterator end,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator,
@ -1523,22 +1523,22 @@ OutputIterator intersection(InputIterator begin, InputIterator end,
OutputIterator oi,
UsePolylines = Tag_true());
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection of all polygons in the two ranges and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator1, typename InputIterator2,
@ -1547,10 +1547,10 @@ OutputIterator intersection(InputIterator1 begin1, InputIterator1 end1,
InputIterator2 begin2, InputIterator2 end2,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection of all polygons in the two ranges and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input ranges are treated as cyclic sequences of single
@ -1563,16 +1563,16 @@ OutputIterator intersection(InputIterator1 begin1, InputIterator1 end1,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator1, typename InputIterator2,
@ -1744,20 +1744,20 @@ intersection(const General_polygon_with_holes_2<Polygon>& pgn1,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection of all polygons in the range and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre GpsTraits must be a model of `GeneralPolygonSetTraits_2`.
@ -1767,22 +1767,22 @@ OutputIterator intersection(InputIterator begin, InputIterator end,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* intersection between all polygons in the two ranges and inserts the
* resulting polygons with holes (resp. general polygons with holes) into a
* resulting polygons with holes (respectively general polygons with holes) into a
* container via an output iterator.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre GpsTraits must be a model of `GeneralPolygonSetTraits_2`.
@ -2072,30 +2072,30 @@ bool join(const General_polygon_with_holes_2<Polygon>& pgn1,
const General_polygon_with_holes_2<Polygon>& pgn2,
General_polygon_with_holes_2<Polygon>& res);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the range and inserts the resulting polygons
* with holes (resp. general polygons with holes) into a container via an output
* with holes (respectively general polygons with holes) into a container via an output
* iterator.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator>
OutputIterator join(InputIterator begin, InputIterator end,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the range and inserts the resulting polygons
* with holes (resp. general polygons with holes) into a container via an output
* with holes (respectively general polygons with holes) into a container via an output
* iterator.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input range are treated as cyclic sequences of single
@ -2108,14 +2108,14 @@ OutputIterator join(InputIterator begin, InputIterator end,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator,
@ -2124,22 +2124,22 @@ OutputIterator join(InputIterator begin, InputIterator end,
OutputIterator oi,
UsePolylines = Tag_true());
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the two ranges and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator1, typename InputIterator2,
@ -2276,20 +2276,20 @@ bool join(const General_polygon_with_holes_2<Polygon>& pgn1,
General_polygon_with_holes_2<Polygon>& res,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the range and inserts the resulting polygons
* with holes (resp. general polygons with holes) into a container via an output
* with holes (respectively general polygons with holes) into a container via an output
* iterator.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`.
@ -2299,22 +2299,22 @@ OutputIterator join(InputIterator begin, InputIterator end,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the two ranges and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`.
@ -2326,10 +2326,10 @@ OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* union of all polygons in the two ranges and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
* input ranges are treated as cyclic sequences of single
@ -2342,16 +2342,16 @@ OutputIterator join(InputIterator1 begin1, InputIterator1 end1,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
* \pre `GpsTraits` must be a model of the concept `GeneralPolygonSetTraits_2`.
*/
@ -3124,31 +3124,31 @@ symmetric_difference(const General_polygon_with_holes_2<Polygon>& pgn1,
const General_polygon_with_holes_2<Polygon>& pgn2,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference of all polygons in the range and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator. A point is contained in the symmetric difference, if and
* only if it is contained in an odd number of input polygons.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator>
OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference of all polygons in the range and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator. A point is contained in the symmetric difference, if and
* only if it is contained in an odd number of input polygons.
* \tparam UsePolylines determines whether the boundaries of the polygons in the
@ -3162,14 +3162,14 @@ OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator, typename OutputIterator,
@ -3178,24 +3178,24 @@ OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
OutputIterator oi,
UsePolylines = Tag_true());
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference between all polygons in the two ranges and inserts the
* resulting polygons with holes (resp. general polygons with holes) into a
* resulting polygons with holes (respectively general polygons with holes) into a
* container via an output iterator. A point is contained in the symmetric
* difference, if and only if it is contained in an odd number of input
* polygons.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator1, typename InputIterator2,
@ -3204,10 +3204,10 @@ OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
InputIterator2 begin2, InputIterator2 end2,
OutputIterator oi);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference between all polygons in the two ranges and inserts the
* resulting polygons with holes (resp. general polygons with holes) into a
* resulting polygons with holes (respectively general polygons with holes) into a
* container via an output iterator. A point is contained in the symmetric
* difference, if and only if it is contained in an odd number of input
* polygons.
@ -3222,16 +3222,16 @@ OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
* with `CGAL::Tag_false`, `pgn1` and `pgn2` are used as is. Refer to
* \ref bso_ssectraits_sel for more information.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \return the past-the-end iterator of the output container.
*/
template <typename InputIterator1, typename InputIterator2,
@ -3404,21 +3404,21 @@ symmetric_difference(const General_polygon_with_holes_2<Polygon>& pgn1,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) or a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) or a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference of all polygons in the range and inserts the resulting
* polygons with holes (resp. general polygons with holes) into a container via
* polygons with holes (respectively general polygons with holes) into a container via
* an output iterator. A point is contained in the symmetric difference, if and
* only if it is contained in an odd number of input polygons.
* \param begin the first iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end the past-the-end iterator of the input range. Its value type is
* either `Polygon_2` (resp. `General_polygon_2`) or
* `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* either `Polygon_2` (respectively `General_polygon_2`) or
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre GpsTraits must be a model of `GeneralPolygonSetTraits_2`.
@ -3428,24 +3428,24 @@ OutputIterator symmetric_difference(InputIterator begin, InputIterator end,
OutputIterator oi,
const GpsTraits& traits);
/*! Given a range of polygons (resp. general polygons) and a range of
* polygons with holes (resp. general polygons with holes) computes the
/*! Given a range of polygons (respectively general polygons) and a range of
* polygons with holes (respectively general polygons with holes) computes the
* symmetric difference between all polygons in the two ranges and inserts the
* resulting polygons with holes (resp. general polygons with holes) into a
* resulting polygons with holes (respectively general polygons with holes) into a
* container via an output iterator. A point is contained in the symmetric
* difference, if and only if it is contained in an odd number of input
* polygons.
* \param begin1 the first iterator of the 1st input range. Its value type is
* `Polygon_2` (resp. `General_polygon_2`).
* `Polygon_2` (respectively `General_polygon_2`).
* \param end1 the past-the-end iterator of the 1st input range. Its value
* type is `Polygon_2` (resp. `General_polygon_2`).
* type is `Polygon_2` (respectively `General_polygon_2`).
* \param begin2 the first iterator of the 2nd input range. Its value type
* is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param end2 the past-the-end iterator of the 2nd input range. Its value
* type is `Polygon_with_holes_2` (resp. `General_polygon_with_holes_2`).
* type is `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param oi the output iterator for the result.
* Its dereference type must be convertible to
* `Polygon_with_holes_2` (resp. `General_polygons_with_holes_2`).
* `Polygon_with_holes_2` (respectively `General_polygon_with_holes_2`).
* \param traits a traits object.
* \return the past-the-end iterator of the output container.
* \pre GpsTraits must be a model of `GeneralPolygonSetTraits_2`.
@ -3460,4 +3460,3 @@ OutputIterator symmetric_difference(InputIterator1 begin1, InputIterator1 end1,
/// @}
} /* namespace CGAL */

View File

@ -36,7 +36,7 @@
\cgalPkgSince{3.1}
\cgalPkgBib{cgal:kmz-isiobd}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip}
\cgalPkgDemo{CGAL Lab,CGALlab.zip}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd

View File

@ -13,7 +13,7 @@
\cgalPkgSince{3.5}
\cgalPkgBib{cgal:h-emspe}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip}
\cgalPkgDemo{CGAL Lab,CGALlab.zip}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd

View File

@ -35,7 +35,7 @@ degenerate hull may also be possible.
\cgalPkgDependsOn{The dynamic algorithms depend on \ref PkgTriangulation3 "3D Triangulations".}
\cgalPkgBib{cgal:hs-ch3}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip}
\cgalPkgDemo{CGAL Lab,CGALlab.zip}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd

File diff suppressed because it is too large Load Diff

View File

@ -288,7 +288,7 @@ MainWindow::MainWindow()
// Setup input handlers. They get events before the scene gets them
// and the input they generate is passed to the triangulation with
// the signal/slot mechanism
pi = new CGAL::Qt::GraphicsViewPolylineInput<K>(this, &scene, 0, true); // inputs polylines which are not closed
pi = new CGAL::Qt::GraphicsViewPolylineInput<K>(this, &scene, 0, true); // inputs polylines which are closed
QObject::connect(pi, SIGNAL(generate(CGAL::Object)),
this, SLOT(processInput(CGAL::Object)));

View File

@ -24,7 +24,7 @@ source vertices.}
\cgalPkgDependsOn{ \ref PkgSolverInterface}
\cgalPkgBib{cgal:cvf-hm3}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip}
\cgalPkgDemo{CGAL Lab,CGALlab.zip}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd

View File

@ -4,7 +4,7 @@ Release History
[Release 6.0](https://github.com/CGAL/cgal/releases/tag/v6.0)
-----------
Release date: October 2023
Release date: June 2024
### General Changes
@ -17,6 +17,7 @@ Release date: October 2023
- **Breaking change**: The usage of `boost::variant` has been replaced by `std::variant`. Packages affected are 2D Arrangements, and the Kernel intersection.
- **Breaking change**: The file CMake file `UseCGAL.cmake` has been removed from CGAL. Usages of the CMake variables `${CGAL_USE_FILE}` and `${CGAL_LIBRARIES}` must be replaced by a link to the imported target `CGAL::CGAL`, for example: `target_link_library(the_target PRIVATE CGAL::CGAL)`.
- The minimal supported version of Boost is now 1.72.0
- The CGAL demo formerly known as "Polyhedron demo" has been renamed "CGAL Lab".
### Installation
@ -75,8 +76,17 @@ Release date: October 2023
bounding box to a face graph.
### [2D Arrangements](https://doc.cgal.org/6.0/Manual/packages.html#PkgArrangementOnSurface2)
- Fixed a bug in the zone construction code applied to arrangements of geodesic arcs on a sphere,
when inserting an arc that lies on the identification curve.
- **Breaking change**: The type of the result of point location queries changed to
`std::variant`. The support for the old macro `CGAL_ARR_POINT_LOCATION_VERSION`
has been removed.
- Eliminated the error-prone c-type casting that was used to define observers. In general, backward compatibility was maintained; however, the former class template `Arr_observer` was replaced by an alias template. (The former class Arr_observer was renamed to Aos_observer).
- Introduced `Arr_dcel`, which essentially replaces the former `Arr_default_dcel`. Backward compatibility was maintained by the introduction of the alias template `Arr_default_dcel`. `Arr_dcel`, as opposed to the former `Arr_default_dcel` is templated (in addition to the geometry traits) by Vertex, Halfedge, and Face template parameters, and they have default type values. All this enables the layered extension of DCEL records.
- Fixed a bug in the zone construction code applied to arrangements of geodesic arcs on a sphere, when inserting an arc that lies on the identification curve.
- Introduced a new interactive program that demonstrates 2D arrangements embedded on the sphere called `earth`. The program (i) reads a database of all administrative boundaries of the countries in the world, (ii) displays the globe with all countries and land covered by water (which is land not covered by countries) on a window, and (ii) enables interaction with the user.
### [Tetrahedral Remeshing](https://doc.cgal.org/6.0/Manual/packages.html#PkgTetrahedralRemeshing)
- **Breaking change**: The template parameters of

View File

@ -16,7 +16,7 @@
\cgalPkgDependsOn{\ref PkgSolverInterface and \ref thirdpartyEigen}
\cgalPkgBib{cgal:pc-eldp}
\cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip}
\cgalPkgDemo{CGAL Lab,CGALlab.zip}
\cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd

View File

@ -45,16 +45,16 @@ therefore do not appear in the constructors.
\cgalHeading{Example}
\code
typedef Cartesian<double> K;
typedef Aff_transformation_2<K> Transformation;
typedef Point_2<K> Point;
typedef Vector_2<K> Vector;
typedef Direction_2<K> Direction;
typedef CGAL::Simple_cartesian<double> K;
typedef CGAL::Aff_transformation_2<K> Transformation;
typedef CGAL::Point_2<K> Point;
typedef CGAL::Vector_2<K> Vector;
typedef CGAL::Direction_2<K> Direction;
Transformation rotate(ROTATION, sin(pi), cos(pi));
Transformation rational_rotate(ROTATION,Direction(1,1), 1, 100);
Transformation translate(TRANSLATION, Vector(-2, 0));
Transformation scale(SCALING, 3);
Transformation rotate(CGAL::ROTATION, sin(pi), cos(pi));
Transformation rational_rotate(CGAL::ROTATION,Direction(1,1), 1, 100);
Transformation translate(CGAL::TRANSLATION, Vector(-2, 0));
Transformation scale(CGAL::SCALING, 3);
Point q(0, 1);
q = rational_rotate(q);

View File

@ -3,7 +3,7 @@
#include "config.h"
#include "Plugins/Mesh_3/config_mesh_3.h"
// as otherwise it gets set via inclusion of cgallab.h
// as otherwise it gets set via inclusion of CGALlab.h
#include <CGAL/Default.h>
#include "SMesh_type.h"

View File

@ -1,4 +1,4 @@
#include "cgallab.h"
#include "CGALlab.h"
#include "MainWindow.h"
#include <QMessageBox>
#include <CGAL/Qt/resources.h>

View File

@ -1,4 +1,4 @@
#include "cgallab.h"
#include "CGALlab.h"
/*!
* \brief defines the entry point of the demo.

View File

@ -3,7 +3,7 @@
#include <QtCore/qglobal.h>
#include "cgallab_config.h"
#include "CGALlab_config.h"
#include <QApplication>
#include <QScopedPointer>

View File

@ -44,8 +44,8 @@ include(${CGAL_MODULES_DIR}/CGAL_add_test.cmake)
endif()
# Link with CGAL
target_link_libraries( ${plugin_name} PUBLIC CGAL::CGAL )
if(NOT CGAL_TEST_SUITE AND TARGET Polyhedron_3)
add_dependencies( ${plugin_name} Polyhedron_3 )
if(NOT CGAL_TEST_SUITE AND TARGET CGALlab)
add_dependencies( ${plugin_name} CGALlab )
endif()
if(NOT TARGET CGALlab_all_plugins)
add_custom_target(CGALlab_all_plugins)

View File

@ -127,9 +127,9 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
qt6_generate_moc("File_loader_dialog.h"
"${CMAKE_CURRENT_BINARY_DIR}/File_loader_dialog_moc.cpp")
include(${CMAKE_CURRENT_SOURCE_DIR}/cgallab_macros.cmake)
include(${CMAKE_CURRENT_SOURCE_DIR}/CGALlab_macros.cmake)
qt6_add_resources(CGAL_Qt6_RESOURCE_FILES cgallab.qrc)
qt6_add_resources(CGAL_Qt6_RESOURCE_FILES CGALlab.qrc)
find_path(
CGAL_THREE_HEADERS_PATH
NAMES CGAL/Three/Scene_item.h
@ -184,7 +184,7 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
Scene_item_rendering_helper.cpp
Scene_item_rendering_helper_moc.cpp
Primitive_container.cpp
cgallab_plugin_helper.cpp
CGALlab_plugin_helper.cpp
CGAL_double_edit.cpp)
target_link_libraries(demo_framework PUBLIC Qt6::OpenGLWidgets Qt6::Widgets Qt6::Gui Qt6::Qml
CGAL::CGAL_Qt6)
@ -373,17 +373,17 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
target_link_libraries(cgal_lab PRIVATE Qt6::WebSockets)
endif()
cgal_add_compilation_test(cgal_lab)
add_executable(cgallab cgallab.cpp)
target_link_libraries(cgallab PRIVATE cgal_lab)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS cgallab)
cgal_add_compilation_test(cgallab)
add_executable(CGALlab CGALlab.cpp)
target_link_libraries(CGALlab PRIVATE cgal_lab)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGALlab)
cgal_add_compilation_test(CGALlab)
target_link_libraries(cgallab PRIVATE demo_framework)
target_link_libraries(CGALlab PRIVATE demo_framework)
# Link with CGAL
target_link_libraries(cgallab PUBLIC CGAL::CGAL_Qt6)
target_link_libraries(CGALlab PUBLIC CGAL::CGAL_Qt6)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS cgallab)
add_to_cached_list(CGAL_EXECUTABLE_TARGETS CGALlab)
###########
# PLUGINS #
@ -452,8 +452,8 @@ if(CGAL_Qt6_FOUND AND Qt6_FOUND)
NAMESPACE Lab_ APPEND
FILE cgal_lab_targets.cmake)
configure_file(cgallabConfig.cmake.in
cgallabConfig.cmake)
configure_file(CGALlabConfig.cmake.in
CGALlabConfig.cmake)
#TO DO script the activation of all the plugins.
else(CGAL_Qt6_FOUND AND Qt6_FOUND)

View File

@ -1,4 +1,4 @@
#include "cgallab.h"
#include "CGALlab.h"
#include <clocale>
#include <CGAL/Qt/resources.h>
#include <QSurfaceFormat>

View File

@ -14,7 +14,7 @@
<string>CGAL Three</string>
</property>
<property name="windowIcon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/resources/cgal_logo.xpm</normaloff>:/cgal/icons/resources/cgal_logo.xpm</iconset>
</property>
<widget class="QWidget" name="centralwidget">
@ -132,7 +132,7 @@
<string>+</string>
</property>
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/plus</normaloff>:/cgal/icons/plus</iconset>
</property>
</widget>
@ -143,7 +143,7 @@
<string>-</string>
</property>
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/minus</normaloff>:/cgal/icons/minus</iconset>
</property>
</widget>
@ -154,7 +154,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/duplicate</normaloff>:/cgal/icons/duplicate</iconset>
</property>
</widget>
@ -165,7 +165,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/resources/up.png</normaloff>:/cgal/icons/resources/up.png</iconset>
</property>
</widget>
@ -176,7 +176,7 @@
<string>...</string>
</property>
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/resources/down.png</normaloff>:/cgal/icons/resources/down.png</iconset>
</property>
</widget>
@ -344,7 +344,7 @@
</action>
<action name="actionLoad">
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/plus</normaloff>:/cgal/icons/plus</iconset>
</property>
<property name="text">
@ -356,7 +356,7 @@
</action>
<action name="actionErase">
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/minus</normaloff>:/cgal/icons/minus</iconset>
</property>
<property name="text">
@ -368,7 +368,7 @@
</action>
<action name="actionDuplicate">
<property name="icon">
<iconset resource="cgallab.qrc">
<iconset resource="CGALlab.qrc">
<normaloff>:/cgal/icons/duplicate</normaloff>:/cgal/icons/duplicate</iconset>
</property>
<property name="text">
@ -471,8 +471,8 @@
</action>
</widget>
<resources>
<include location="cgallab.qrc"/>
<include location="cgallab.qrc"/>
<include location="CGALlab.qrc"/>
<include location="CGALlab.qrc"/>
</resources>
<connections/>
</ui>

View File

@ -1,4 +1,4 @@
#include "cgallab.h"
#include "CGALlab.h"
#include <clocale>
#include <CGAL/Qt/resources.h>
#include <QSurfaceFormat>

View File

@ -1,4 +1,4 @@
#include "cgallab.h"
#include "CGALlab.h"
#include <clocale>
#include <CGAL/Qt/resources.h>
#include <QSurfaceFormat>

Some files were not shown because too many files have changed in this diff Show More