Merge remote-tracking branch 'cgal/6.1.x-branch' into 'cgal/main'

This commit is contained in:
Sébastien Loriot 2025-11-21 17:41:27 +01:00
commit 9f2fcb5e28
31 changed files with 2400 additions and 1250 deletions

View File

@ -1,35 +1,63 @@
--- ---
# CGAL clang-format configuration
# This file defines the code formatting style for C++ files in the CGAL project.
Language: Cpp Language: Cpp
BasedOnStyle: LLVM BasedOnStyle: LLVM
AccessModifierOffset: -2
AllowShortFunctionsOnASingleLine: true # Indentation
BinPackParameters: false AccessModifierOffset: -2 # Indent public:/private:/protected: 2 spaces to the left
BreakConstructorInitializers: BeforeComma
# Function formatting
AllowShortFunctionsOnASingleLine: Inline # Allow short inline/member functions on one line, but not free functions
AlwaysBreakAfterReturnType: None # Don't force return type on separate line
# Parameter and argument formatting
BinPackParameters: false # Put each parameter on its own line for better readability
# Constructor formatting
BreakConstructorInitializers: BeforeComma # Put comma before each initializer: `MyClass() \n , member1(val1) \n , member2(val2)`
# Brace wrapping configuration
BreakBeforeBraces: Custom BreakBeforeBraces: Custom
BraceWrapping: BraceWrapping:
AfterCaseLabel: false AfterCaseLabel: false # Don't put brace on new line after case labels
AfterClass: true AfterClass: true # Put opening brace on new line after class definition
AfterControlStatement: MultiLine AfterControlStatement: MultiLine # Only break before braces if the control statement spans multiple lines
AfterEnum: false AfterEnum: false # Don't break after enum
AfterFunction: false AfterFunction: false # Don't break after function declaration (keep on same line)
AfterNamespace: false AfterNamespace: false # Don't break after namespace
AfterObjCDeclaration: false AfterObjCDeclaration: false # Objective-C related (not used in CGAL)
AfterStruct: true AfterStruct: true # Put opening brace on new line after struct definition
AfterUnion: false AfterUnion: false # Don't break after union
AfterExternBlock: false AfterExternBlock: false # Don't break after extern "C" blocks
BeforeCatch: false BeforeCatch: false # Don't put catch on new line
BeforeElse: false BeforeElse: false # Don't put else on new line
BeforeLambdaBody: false BeforeLambdaBody: false # Don't break before lambda body
BeforeWhile: false BeforeWhile: false # Don't put while on new line (do-while loops)
IndentBraces: false IndentBraces: false # Don't indent the braces themselves
SplitEmptyFunction: false SplitEmptyFunction: false # Don't split empty functions across lines
SplitEmptyRecord: false SplitEmptyRecord: false # Don't split empty classes/structs across lines
SplitEmptyNamespace: false SplitEmptyNamespace: false # Don't split empty namespaces across lines
ColumnLimit: 120
# Force pointers to the type for C++. # Line length
ColumnLimit: 120 # Maximum line length of 120 characters
# Pointer and reference alignment
# Force pointers and references to align with the type (e.g., `int* ptr` not `int *ptr`)
DerivePointerAlignment: false DerivePointerAlignment: false
PointerAlignment: Left PointerAlignment: Left
# Control the spaces around conditionals
SpacesInConditionalStatement: false # Spacing in control statements
SpaceBeforeParens: false SpacesInConditionalStatement: false # No extra spaces inside conditionals: `if(condition)` not `if( condition )`
SpaceBeforeParens: false # No space before parentheses: `if(` not `if (`
# Include directive handling
SortIncludes: Never # Preserve the original order of #include statements (don't sort them)
# Preprocessor directive formatting
IndentPPDirectives: None # Don't indent preprocessor directives (#ifdef, #include, etc.)
# Blank line handling
MaxEmptyLinesToKeep: 2 # Keep up to 2 consecutive blank lines
... ...

View File

@ -3,7 +3,7 @@
\cgalConcept \cgalConcept
The concept `ConformingConstrainedDelaunayTriangulationCellBase_3` refines the concept The concept `ConformingConstrainedDelaunayTriangulationCellBase_3` refines the concept
`TriangulationCellBase_3` and and describes the requirements for a base cell class of `TriangulationCellBase_3` and describes the requirements for a base cell class of
the `CGAL::Conforming_constrained_Delaunay_triangulation_3` class. the `CGAL::Conforming_constrained_Delaunay_triangulation_3` class.
\cgalRefines{TriangulationCellBase_3, BaseWithTimeStamp} \cgalRefines{TriangulationCellBase_3, BaseWithTimeStamp}

View File

@ -17,6 +17,7 @@
#include <CGAL/Constrained_triangulation_3/internal/config.h> #include <CGAL/Constrained_triangulation_3/internal/config.h>
#include <CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h> #include <CGAL/Conforming_constrained_Delaunay_triangulation_vertex_data_3.h>
#include <CGAL/Real_timer.h>
#include <CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h> #include <CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h>
#include <CGAL/Triangulation_segment_traverser_3.h> #include <CGAL/Triangulation_segment_traverser_3.h>
#include <CGAL/unordered_flat_set.h> #include <CGAL/unordered_flat_set.h>
@ -34,8 +35,209 @@
#ifndef DOXYGEN_RUNNING #ifndef DOXYGEN_RUNNING
#if CGAL_USE_ITT
# include <ittnotify.h>
#endif
namespace CGAL { namespace CGAL {
namespace CDT_3 {
struct Debug_options {
enum class Flags {
Steiner_points = 0,
conforming,
input_faces,
missing_region,
regions,
copy_triangulation_into_hole,
validity,
use_older_cavity_algorithm,
debug_finite_edges_map,
use_finite_edges_map,
debug_subconstraints_to_conform,
verbose_special_cases,
debug_encroaching_vertices,
debug_conforming_validation,
debug_constraint_hierarchy,
debug_geometric_errors,
debug_polygon_insertion,
display_statistics,
nb_of_flags
};
bool Steiner_points() const { return flags[static_cast<int>(Flags::Steiner_points)]; }
void Steiner_points(bool b) { flags.set(static_cast<int>(Flags::Steiner_points), b); }
bool input_faces() const { return flags[static_cast<int>(Flags::input_faces)]; }
void input_faces(bool b) { flags.set(static_cast<int>(Flags::input_faces), b); }
bool missing_region() const { return flags[static_cast<int>(Flags::missing_region)]; }
void missing_region(bool b) { flags.set(static_cast<int>(Flags::missing_region), b); }
bool regions() const { return flags[static_cast<int>(Flags::regions)]; }
void regions(bool b) { flags.set(static_cast<int>(Flags::regions), b); }
bool copy_triangulation_into_hole() const { return flags[static_cast<int>(Flags::copy_triangulation_into_hole)]; }
void copy_triangulation_into_hole(bool b) { flags.set(static_cast<int>(Flags::copy_triangulation_into_hole), b); }
bool validity() const { return flags[static_cast<int>(Flags::validity)]; }
void validity(bool b) { flags.set(static_cast<int>(Flags::validity), b); }
bool use_older_cavity_algorithm() const { return flags[static_cast<int>(Flags::use_older_cavity_algorithm)]; }
bool use_newer_cavity_algorithm() const { return !flags[static_cast<int>(Flags::use_older_cavity_algorithm)]; }
void use_older_cavity_algorithm(bool b) { flags.set(static_cast<int>(Flags::use_older_cavity_algorithm), b); }
bool finite_edges_map() const { return flags[static_cast<int>(Flags::debug_finite_edges_map)]; }
void finite_edges_map(bool b) { flags.set(static_cast<int>(Flags::debug_finite_edges_map), b); }
bool subconstraints_to_conform() const { return flags[static_cast<int>(Flags::debug_subconstraints_to_conform)]; }
void subconstraints_to_conform(bool b) { flags.set(static_cast<int>(Flags::debug_subconstraints_to_conform), b); }
bool use_finite_edges_map_flag() const { return flags[static_cast<int>(Flags::use_finite_edges_map)]; }
void use_finite_edges_map(bool b) { flags.set(static_cast<int>(Flags::use_finite_edges_map), b); }
bool verbose_special_cases() const { return flags[static_cast<int>(Flags::verbose_special_cases)]; }
void verbose_special_cases(bool b) { flags.set(static_cast<int>(Flags::verbose_special_cases), b); }
bool encroaching_vertices() const { return flags[static_cast<int>(Flags::debug_encroaching_vertices)]; }
void encroaching_vertices(bool b) { flags.set(static_cast<int>(Flags::debug_encroaching_vertices), b); }
bool conforming_validation() const { return flags[static_cast<int>(Flags::debug_conforming_validation)]; }
void conforming_validation(bool b) { flags.set(static_cast<int>(Flags::debug_conforming_validation), b); }
bool constraint_hierarchy() const { return flags[static_cast<int>(Flags::debug_constraint_hierarchy)]; }
void constraint_hierarchy(bool b) { flags.set(static_cast<int>(Flags::debug_constraint_hierarchy), b); }
bool geometric_errors() const { return flags[static_cast<int>(Flags::debug_geometric_errors)]; }
void geometric_errors(bool b) { flags.set(static_cast<int>(Flags::debug_geometric_errors), b); }
bool polygon_insertion() const { return flags[static_cast<int>(Flags::debug_polygon_insertion)]; }
void polygon_insertion(bool b) { flags.set(static_cast<int>(Flags::debug_polygon_insertion), b); }
bool display_statistics() const { return flags[static_cast<int>(Flags::display_statistics)]; }
void display_statistics(bool b) { flags.set(static_cast<int>(Flags::display_statistics), b); }
double segment_vertex_epsilon() const { return segment_vertex_epsilon_; }
void set_segment_vertex_epsilon(double eps) { segment_vertex_epsilon_ = eps; }
double vertex_vertex_epsilon() const { return vertex_vertex_epsilon_; }
void set_vertex_vertex_epsilon(double eps) { vertex_vertex_epsilon_ = eps; }
private:
std::bitset<static_cast<int>(Flags::nb_of_flags)> flags{};
double segment_vertex_epsilon_ = 0.0;
double vertex_vertex_epsilon_ = 0.0;
}; // end struct Debug_options
namespace internal {
auto& tasks_manager() {
struct Tasks_manager {
enum {
READ_INPUT = 0,
MERGE_FACETS,
INSERT_VERTICES,
COMPUTE_DISTANCES,
CONFORMING,
CDT,
OUTPUT,
VALIDATION,
NB_TASKS
};
#if CGAL_USE_ITT
__itt_domain* cdt_3_domain = __itt_domain_create("org.cgal.CDT_3");
const std::array<__itt_string_handle*, NB_TASKS> task_handles = {
__itt_string_handle_create("CDT_3: read input file"),
__itt_string_handle_create("CDT_3: merge facets"),
__itt_string_handle_create("CDT_3: insert vertices"),
__itt_string_handle_create("CDT_3: compute distances"),
__itt_string_handle_create("CDT_3: conforming"),
__itt_string_handle_create("CDT_3: cdt"),
__itt_string_handle_create("CDT_3: outputs"),
__itt_string_handle_create("CDT_3: validation")
};
#endif
std::array<CGAL::Real_timer, NB_TASKS> timers{};
struct Scope_guard {
Tasks_manager *instance = nullptr;
int task_id;
Scope_guard(Tasks_manager *instance, int task_id) : instance(instance), task_id(task_id) {
instance->timers[task_id].start();
#if CGAL_USE_ITT
__itt_task_begin(instance->cdt_3_domain, __itt_null, __itt_null, instance->task_handles[task_id]);
#endif
}
auto time() const {
return instance->timers[task_id].time();
}
auto time_ms() const {
return instance->timers[task_id].time() / 1000.;
}
~Scope_guard() {
instance->timers[task_id].stop();
#if CGAL_USE_ITT
__itt_task_end(instance->cdt_3_domain);
#endif
}
};
Scope_guard make_task_scope_guard(int task_id) {
return Scope_guard(this, task_id);
}
Scope_guard READ_INPUT_TASK_guard() { return make_task_scope_guard(READ_INPUT); }
Scope_guard MERGE_FACETS_TASK_guard() { return make_task_scope_guard(MERGE_FACETS); }
Scope_guard INSERT_VERTICES_TASK_guard() { return make_task_scope_guard(INSERT_VERTICES); }
Scope_guard COMPUTE_DISTANCES_TASK_guard() { return make_task_scope_guard(COMPUTE_DISTANCES); }
Scope_guard CONFORMING_TASK_guard() { return make_task_scope_guard(CONFORMING); }
Scope_guard CDT_TASK_guard() { return make_task_scope_guard(CDT); }
Scope_guard OUTPUT_TASK_guard() { return make_task_scope_guard(OUTPUT); }
Scope_guard VALIDATION_TASK_guard() { return make_task_scope_guard(VALIDATION); }
}; // end struct Intel_OneAPI_ITT_API
static Tasks_manager instance;
return instance;
} // end auto& tasks_manager()
} // end namespace internal
} // end namespace CDT_3
inline auto CDT_3_READ_INPUT_TASK_guard() {
return CDT_3::internal::tasks_manager().READ_INPUT_TASK_guard();
}
inline auto CDT_3_MERGE_FACETS_TASK_guard() {
return CDT_3::internal::tasks_manager().MERGE_FACETS_TASK_guard();
}
inline auto CDT_3_INSERT_VERTICES_TASK_guard() {
return CDT_3::internal::tasks_manager().INSERT_VERTICES_TASK_guard();
}
inline auto CDT_3_COMPUTE_DISTANCES_TASK_guard() {
return CDT_3::internal::tasks_manager().COMPUTE_DISTANCES_TASK_guard();
}
inline auto CDT_3_CONFORMING_TASK_guard() {
return CDT_3::internal::tasks_manager().CONFORMING_TASK_guard();
}
inline auto CDT_3_CDT_TASK_guard() {
return CDT_3::internal::tasks_manager().CDT_TASK_guard();
}
inline auto CDT_3_OUTPUT_TASK_guard() {
return CDT_3::internal::tasks_manager().OUTPUT_TASK_guard();
}
inline auto CDT_3_VALIDATION_TASK_guard() {
return CDT_3::internal::tasks_manager().VALIDATION_TASK_guard();
}
template <typename T_3> template <typename T_3>
class Conforming_Delaunay_triangulation_3 : public T_3 { class Conforming_Delaunay_triangulation_3 : public T_3 {
public: public:
@ -50,9 +252,9 @@ public:
using Line = typename T_3::Geom_traits::Line_3; using Line = typename T_3::Geom_traits::Line_3;
using Locate_type = typename T_3::Locate_type; using Locate_type = typename T_3::Locate_type;
inline static With_offset_tag with_offset{}; inline static With_offset_tag with_offset{ -1 };
inline static With_point_tag with_point{}; inline static With_point_tag with_point{ {-1} };
inline static With_point_and_info_tag with_point_and_info{}; inline static With_point_and_info_tag with_point_and_info{ { {-1} } };
Conforming_Delaunay_triangulation_3(const Geom_traits& gt = Geom_traits()) Conforming_Delaunay_triangulation_3(const Geom_traits& gt = Geom_traits())
: T_3(gt) : T_3(gt)
@ -110,7 +312,7 @@ protected:
if(v1 > v2) std::swap(v1, v2); if(v1 > v2) std::swap(v1, v2);
auto v1_index = v1->time_stamp(); auto v1_index = v1->time_stamp();
[[maybe_unused]] auto nb_erased = self->all_finite_edges[v1_index].erase(v2); [[maybe_unused]] auto nb_erased = self->all_finite_edges[v1_index].erase(v2);
if constexpr (cdt_3_can_use_cxx20_format()) if(self->debug_finite_edges_map() && nb_erased > 0) { if constexpr (cdt_3_can_use_cxx20_format()) if(self->debug().finite_edges_map() && nb_erased > 0) {
std::cerr << cdt_3_format("erasing edge {} {}\n", self->display_vert((std::min)(v1, v2)), std::cerr << cdt_3_format("erasing edge {} {}\n", self->display_vert((std::min)(v1, v2)),
self->display_vert((std::max)(v1, v2))); self->display_vert((std::max)(v1, v2)));
} }
@ -169,18 +371,17 @@ protected:
void add_to_subconstraints_to_conform(Vertex_handle va, Vertex_handle vb, void add_to_subconstraints_to_conform(Vertex_handle va, Vertex_handle vb,
Constrained_polyline_id id) { Constrained_polyline_id id) {
const auto pair = make_subconstraint(va, vb); const auto pair = make_subconstraint(va, vb);
#if CGAL_DEBUG_CDT_3 & 32 if(debug().subconstraints_to_conform()) {
std::cerr << "tr().subconstraints_to_conform.push(" std::cerr << "tr().subconstraints_to_conform.push("
<< display_subcstr(pair) << ")\n"; << display_subcstr(pair) << ")\n";
#endif // CGAL_DEBUG_CDT_3 }
subconstraints_to_conform.push({pair, id}); subconstraints_to_conform.push({pair, id});
} }
template <typename Visitor> template <typename Visitor>
Constrained_polyline_id insert_constrained_edge_impl(Vertex_handle va, Vertex_handle vb, Constrained_polyline_id insert_constrained_edge_impl(Vertex_handle va, Vertex_handle vb, Visitor&) {
Visitor&) {
if(va != vb) { if(va != vb) {
if(segment_vertex_epsilon != 0.) { if(debug().segment_vertex_epsilon() != 0.) {
auto [min_dist, min_vertex] = min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb); auto [min_dist, min_vertex] = min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
check_segment_vertex_distance_or_throw(va, vb, min_vertex, CGAL::to_double(min_dist), check_segment_vertex_distance_or_throw(va, vb, min_vertex, CGAL::to_double(min_dist),
Check_distance::NON_SQUARED_DISTANCE); Check_distance::NON_SQUARED_DISTANCE);
@ -217,7 +418,7 @@ protected:
if(tr().is_infinite(v1) || tr().is_infinite(v2)) if(tr().is_infinite(v1) || tr().is_infinite(v2))
return; return;
[[maybe_unused]] auto [_, inserted] = all_finite_edges[v1->time_stamp()].insert(v2); [[maybe_unused]] auto [_, inserted] = all_finite_edges[v1->time_stamp()].insert(v2);
if constexpr (cdt_3_can_use_cxx20_format()) if (debug_finite_edges_map() && inserted) { if constexpr (cdt_3_can_use_cxx20_format()) if (debug().finite_edges_map() && inserted) {
if(v2 < v1) std::swap(v1, v2); if(v2 < v1) std::swap(v1, v2);
std::cerr << cdt_3_format("new_edge({}, {})\n", display_vert(v1), display_vert(v2)); std::cerr << cdt_3_format("new_edge({}, {})\n", display_vert(v1), display_vert(v2));
} }
@ -268,7 +469,7 @@ protected:
if(use_finite_edges_map()) { if(use_finite_edges_map()) {
new_vertex(v); new_vertex(v);
all_finite_edges.clear(); all_finite_edges.clear();
if (debug_finite_edges_map()) std::cerr << "all_finite_edges.clear()\n"; if (debug().finite_edges_map()) std::cerr << "all_finite_edges.clear()\n";
for(auto e: tr().all_edges()) { for(auto e: tr().all_edges()) {
new_edge(e); new_edge(e);
} }
@ -304,7 +505,7 @@ protected:
} }
} }
void update_max_bbox_edge_length() { void update_max_bbox_edge_length() const {
double d_x = bbox.xmax() - bbox.xmin(); double d_x = bbox.xmax() - bbox.xmin();
double d_y = bbox.ymax() - bbox.ymin(); double d_y = bbox.ymax() - bbox.ymin();
double d_z = bbox.zmax() - bbox.zmin(); double d_z = bbox.zmax() - bbox.zmin();
@ -313,85 +514,15 @@ protected:
} }
public: public:
void set_segment_vertex_epsilon(double epsilon) { CDT_3::Debug_options& debug() { return debug_options_; }
segment_vertex_epsilon = epsilon; const CDT_3::Debug_options& debug() const { return debug_options_; }
}
bool debug_Steiner_points() const { // Backward compatibility wrappers (deprecated, use debug().method() instead)
return debug_flags[static_cast<int>(Debug_flags::Steiner_points)]; bool use_older_cavity_algorithm() const { return debug_options_.use_older_cavity_algorithm(); }
} bool use_newer_cavity_algorithm() const { return debug_options_.use_newer_cavity_algorithm(); }
void use_older_cavity_algorithm(bool b) { debug_options_.use_older_cavity_algorithm(b); }
void debug_Steiner_points(bool b) { bool use_finite_edges_map() const { return update_all_finite_edges_ && debug_options_.use_finite_edges_map_flag(); }
debug_flags.set(static_cast<int>(Debug_flags::Steiner_points), b); void use_finite_edges_map(bool b) { debug_options_.use_finite_edges_map(b); }
}
bool debug_input_faces() const {
return debug_flags[static_cast<int>(Debug_flags::input_faces)];
}
void debug_input_faces(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::input_faces), b);
}
bool debug_missing_region() const {
return debug_flags[static_cast<int>(Debug_flags::missing_region)];
}
void debug_missing_region(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::missing_region), b);
}
bool debug_regions() const {
return debug_flags[static_cast<int>(Debug_flags::regions)];
}
void debug_regions(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::regions), b);
}
bool debug_copy_triangulation_into_hole() const {
return debug_flags[static_cast<int>(Debug_flags::copy_triangulation_into_hole)];
}
void debug_copy_triangulation_into_hole(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::copy_triangulation_into_hole), b);
}
bool debug_validity() const {
return debug_flags[static_cast<int>(Debug_flags::validity)];
}
void debug_validity(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::validity), b);
}
bool use_older_cavity_algorithm() const {
return debug_flags[static_cast<int>(Debug_flags::use_older_cavity_algorithm)];
}
bool use_newer_cavity_algorithm() const {
return !debug_flags[static_cast<int>(Debug_flags::use_older_cavity_algorithm)];
}
void use_older_cavity_algorithm(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::use_older_cavity_algorithm), b);
}
bool debug_finite_edges_map() const {
return debug_flags[static_cast<int>(Debug_flags::debug_finite_edges_map)];
}
void debug_finite_edges_map(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::debug_finite_edges_map), b);
}
bool use_finite_edges_map() const {
return update_all_finite_edges_ && debug_flags[static_cast<int>(Debug_flags::use_finite_edges_map)];
}
void use_finite_edges_map(bool b) {
debug_flags.set(static_cast<int>(Debug_flags::use_finite_edges_map), b);
}
Vertex_handle insert(const Point &p, Locate_type lt, Cell_handle c, Vertex_handle insert(const Point &p, Locate_type lt, Cell_handle c,
int li, int lj) int li, int lj)
@ -419,14 +550,14 @@ public:
bool is_edge(Vertex_handle va, Vertex_handle vb) const { bool is_edge(Vertex_handle va, Vertex_handle vb) const {
const bool is_edge_v1 = const bool is_edge_v1 =
((debug_finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr().tds().is_edge(va, vb); ((debug().finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr().tds().is_edge(va, vb);
if(use_finite_edges_map() && va > vb) std::swap(va, vb); if(use_finite_edges_map() && va > vb) std::swap(va, vb);
const auto va_index = va->time_stamp(); const auto va_index = va->time_stamp();
const bool is_edge_v2 = const bool is_edge_v2 =
use_finite_edges_map() && all_finite_edges[va_index].find(vb) != all_finite_edges[va_index].end(); use_finite_edges_map() && all_finite_edges[va_index].find(vb) != all_finite_edges[va_index].end();
if(debug_finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) { if(debug().finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) {
std::cerr << "!! Inconsistent edge status\n"; std::cerr << "!! Inconsistent edge status\n";
std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n'; std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n';
std::cerr << " -> edge " << (is_edge_v1 ? "is" : "is not") << " in the triangulation\n"; std::cerr << " -> edge " << (is_edge_v1 ? "is" : "is not") << " in the triangulation\n";
@ -446,12 +577,12 @@ public:
[this](const auto &sc) { [this](const auto &sc) {
const auto [va, vb] = sc; const auto [va, vb] = sc;
const auto is_edge = this->is_edge(va, vb); const auto is_edge = this->is_edge(va, vb);
#if CGAL_DEBUG_CDT_3 & 128 && CGAL_CAN_USE_CXX20_FORMAT if constexpr (cdt_3_can_use_cxx20_format()) if(debug().conforming_validation()) {
std::cerr << cdt_3_format("is_conforming>> Edge is 3D: {} ({} , {})\n", std::cerr << cdt_3_format("is_conforming>> Edge is 3D: {} ({} , {})\n",
is_edge, is_edge,
CGAL::IO::oformat(va, with_point_and_info), CGAL::IO::oformat(va, with_point_and_info),
CGAL::IO::oformat(vb, with_point_and_info)); CGAL::IO::oformat(vb, with_point_and_info));
#endif // CGAL_DEBUG_CDT_3 }
return is_edge; return is_edge;
}); });
} }
@ -462,14 +593,15 @@ public:
Vertex_handle vb, Vertex_handle vb,
Vertex_handle min_vertex, Vertex_handle min_vertex,
double min_dist, double min_dist,
Check_distance option) Check_distance distance_type = Check_distance::NON_SQUARED_DISTANCE) const
{ {
if(!max_bbox_edge_length) { if(!max_bbox_edge_length) {
update_max_bbox_edge_length(); update_max_bbox_edge_length();
} }
if((option == Check_distance::NON_SQUARED_DISTANCE && min_dist < segment_vertex_epsilon * *max_bbox_edge_length) || if((distance_type == Check_distance::NON_SQUARED_DISTANCE &&
(option == Check_distance::SQUARED_DISTANCE && min_dist < debug().segment_vertex_epsilon() * *max_bbox_edge_length) ||
min_dist < CGAL::square(segment_vertex_epsilon * *max_bbox_edge_length))) (distance_type == Check_distance::SQUARED_DISTANCE &&
min_dist < CGAL::square(debug().segment_vertex_epsilon() * *max_bbox_edge_length)))
{ {
std::stringstream ss; std::stringstream ss;
ss.precision(std::cerr.precision()); ss.precision(std::cerr.precision());
@ -482,6 +614,26 @@ public:
} }
} }
void check_vertex_vertex_distance_or_throw(Vertex_handle va,
Vertex_handle vb,
double min_dist) const
{
if(!max_bbox_edge_length) {
update_max_bbox_edge_length();
}
if(min_dist < debug_options_.vertex_vertex_epsilon() * *max_bbox_edge_length)
{
std::stringstream ss;
ss.precision(std::cerr.precision());
ss << "Two vertices are too close to each other.\n";
ss << " -> vertex " << display_vert(va) << '\n';
ss << " -> vertex " << display_vert(vb) << '\n';
ss << " -> distance = " << min_dist << '\n';
ss << " -> max_bbox_edge_length = " << *max_bbox_edge_length << '\n';
CGAL_error_msg(ss.str().c_str());
}
}
auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const { auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const {
std::pair<Vertex_handle, Vertex_handle> result; std::pair<Vertex_handle, Vertex_handle> result;
CGAL_precondition(v->ccdt_3_data().is_Steiner_vertex_on_edge()); CGAL_precondition(v->ccdt_3_data().is_Steiner_vertex_on_edge());
@ -587,10 +739,10 @@ protected:
if(!constraint_hierarchy.is_subconstraint(va, vb)) { if(!constraint_hierarchy.is_subconstraint(va, vb)) {
continue; continue;
} }
#if CGAL_DEBUG_CDT_3 & 32 if(debug().subconstraints_to_conform()) {
std::cerr << "tr().subconstraints_to_conform.pop()=" std::cerr << "tr().subconstraints_to_conform.pop()="
<< display_subcstr(subconstraint) << "\n"; << display_subcstr(subconstraint) << "\n";
#endif // CGAL_DEBUG_CDT_3 }
conform_subconstraint(subconstraint, constrained_polyline_id, visitor); conform_subconstraint(subconstraint, constrained_polyline_id, visitor);
} }
} }
@ -633,7 +785,7 @@ protected:
const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint); const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint);
[[maybe_unused]] const auto v = [[maybe_unused]] const auto v =
insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor); insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor);
if(debug_Steiner_points()) { if(debug().Steiner_points()) {
const auto [c_start, c_end] = constraint_extremities(constraint); const auto [c_start, c_end] = constraint_extremities(constraint);
std::cerr << "(" << IO::oformat(va, with_offset) << ", " << IO::oformat(vb, with_offset) << ")"; std::cerr << "(" << IO::oformat(va, with_offset) << ", " << IO::oformat(vb, with_offset) << ")";
std::cerr << ": [ " << display_vert(c_start) << " - " << display_vert(c_end) << " ] "; std::cerr << ": [ " << display_vert(c_start) << " - " << display_vert(c_end) << " ] ";
@ -669,10 +821,10 @@ protected:
this->constraint_hierarchy.constraints_end(), c_id) != this->constraint_hierarchy.constraints_end()); this->constraint_hierarchy.constraints_end(), c_id) != this->constraint_hierarchy.constraints_end());
CGAL_assertion(this->constraint_hierarchy.vertices_in_constraint_begin(c_id) != CGAL_assertion(this->constraint_hierarchy.vertices_in_constraint_begin(c_id) !=
this->constraint_hierarchy.vertices_in_constraint_end(c_id)); this->constraint_hierarchy.vertices_in_constraint_end(c_id));
#if CGAL_DEBUG_CDT_3 & 8 if(debug().constraint_hierarchy()) {
std::cerr << "constraint " << (void*) c_id.vl_ptr() << " has " std::cerr << "constraint " << static_cast<void*>(c_id.vl_ptr()) << " has "
<< c_id.vl_ptr()->skip_size() << " vertices\n"; << c_id.vl_ptr()->skip_size() << " vertices\n";
#endif // CGAL_DEBUG_CDT_3 }
const auto begin = this->constraint_hierarchy.vertices_in_constraint_begin(c_id); const auto begin = this->constraint_hierarchy.vertices_in_constraint_begin(c_id);
const auto end = this->constraint_hierarchy.vertices_in_constraint_end(c_id); const auto end = this->constraint_hierarchy.vertices_in_constraint_end(c_id);
const auto c_va = *begin; const auto c_va = *begin;
@ -730,9 +882,9 @@ protected:
encroaching_vertices.insert(v); encroaching_vertices.insert(v);
}; };
auto fill_encroaching_vertices = [&](const auto simplex) { auto fill_encroaching_vertices = [&](const auto simplex) {
#if CGAL_DEBUG_CDT_3 & 0x10 if(debug().encroaching_vertices()) {
std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n'; std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n';
#endif // CGAL_DEBUG_CDT_3 }
auto visit_cell = [&](Cell_handle cell) { auto visit_cell = [&](Cell_handle cell) {
for(int i = 0, end = this->tr().dimension() + 1; i < end; ++i) { for(int i = 0, end = this->tr().dimension() + 1; i < end; ++i) {
const auto v = cell->vertex(i); const auto v = cell->vertex(i);
@ -776,9 +928,9 @@ protected:
std::cerr << "!! The constraint passes through a vertex!\n"; std::cerr << "!! The constraint passes through a vertex!\n";
std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n'; std::cerr << " -> constraint " << display_vert(va) << " " << display_vert(vb) << '\n';
std::cerr << " -> vertex " << display_vert(v) << '\n'; std::cerr << " -> vertex " << display_vert(v) << '\n';
#if CGAL_DEBUG_CDT_3 if(debug().geometric_errors()) {
debug_dump("bug-through-vertex"); debug_dump("bug-through-vertex");
#endif }
CGAL_error(); CGAL_error();
} }
} break; } break;
@ -788,14 +940,14 @@ protected:
std::for_each(tr().segment_traverser_simplices_begin(va, vb), tr().segment_traverser_simplices_end(), std::for_each(tr().segment_traverser_simplices_begin(va, vb), tr().segment_traverser_simplices_end(),
fill_encroaching_vertices); fill_encroaching_vertices);
auto vector_of_encroaching_vertices = encroaching_vertices.extract_sequence(); auto vector_of_encroaching_vertices = encroaching_vertices.extract_sequence();
#if CGAL_DEBUG_CDT_3 & 0x10 if(debug().encroaching_vertices()) {
std::cerr << " -> vector_of_encroaching_vertices (before filter):\n"; std::cerr << " -> vector_of_encroaching_vertices (before filter):\n";
std::for_each(vector_of_encroaching_vertices.begin(), std::for_each(vector_of_encroaching_vertices.begin(),
vector_of_encroaching_vertices.end(), vector_of_encroaching_vertices.end(),
[this](Vertex_handle v){ [this](Vertex_handle v){
std::cerr << " " << this->display_vert(v) << '\n'; std::cerr << " " << this->display_vert(v) << '\n';
}); });
#endif // CGAL_DEBUG_CDT_3 }
auto end = std::remove_if(vector_of_encroaching_vertices.begin(), auto end = std::remove_if(vector_of_encroaching_vertices.begin(),
vector_of_encroaching_vertices.end(), vector_of_encroaching_vertices.end(),
[va, vb, pa, pb, &angle_functor, this](Vertex_handle v) { [va, vb, pa, pb, &angle_functor, this](Vertex_handle v) {
@ -804,13 +956,13 @@ protected:
this->tr().point(v), this->tr().point(v),
pb) == ACUTE; pb) == ACUTE;
}); });
#if CGAL_DEBUG_CDT_3 & 0x10 if(debug().encroaching_vertices()) {
std::cerr << " -> vector_of_encroaching_vertices (after filter):\n"; std::cerr << " -> vector_of_encroaching_vertices (after filter):\n";
std::for_each(vector_of_encroaching_vertices.begin(), end, [&](Vertex_handle v) { std::for_each(vector_of_encroaching_vertices.begin(), end, [&](Vertex_handle v) {
std::cerr << " " << this->display_vert(v) << " angle " << approximate_angle(pa, this->tr().point(v), pb) std::cerr << " " << this->display_vert(v) << " angle " << approximate_angle(pa, this->tr().point(v), pb)
<< '\n'; << '\n';
}); });
#endif // CGAL_DEBUG_CDT_3 }
vector_of_encroaching_vertices.erase(end, vector_of_encroaching_vertices.end()); vector_of_encroaching_vertices.erase(end, vector_of_encroaching_vertices.end());
return vector_of_encroaching_vertices; return vector_of_encroaching_vertices;
} }
@ -840,10 +992,10 @@ protected:
return {midpoint_functor(pa, pb), va->cell(), va}; return {midpoint_functor(pa, pb), va->cell(), va};
} }
#if CGAL_DEBUG_CDT_3 & 0x10 if(debug().encroaching_vertices()) {
std::cerr << "construct_Steiner_point( " << display_vert(va) << " , " std::cerr << "construct_Steiner_point( " << display_vert(va) << " , "
<< display_vert(vb) << " )\n"; << display_vert(vb) << " )\n";
#endif // CGAL_DEBUG_CDT_3 }
const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb); const auto vector_of_encroaching_vertices = encroaching_vertices(va, vb);
CGAL_assertion(vector_of_encroaching_vertices.size() > 0); CGAL_assertion(vector_of_encroaching_vertices.size() > 0);
@ -909,7 +1061,7 @@ protected:
return return_orig_result_point(lambda, orig_pb, orig_pa); return return_orig_result_point(lambda, orig_pb, orig_pa);
} }
} else { } else {
if(segment_vertex_epsilon > 0) { if(debug().segment_vertex_epsilon() > 0) {
if(!max_bbox_edge_length) { if(!max_bbox_edge_length) {
update_max_bbox_edge_length(); update_max_bbox_edge_length();
} }
@ -940,8 +1092,7 @@ protected:
Constraint_hierarchy constraint_hierarchy = {comp}; Constraint_hierarchy constraint_hierarchy = {comp};
static_assert(CGAL::cdt_3_msvc_2019_or_older() || CGAL::is_nothrow_movable_v<Constraint_hierarchy>); static_assert(CGAL::cdt_3_msvc_2019_or_older() || CGAL::is_nothrow_movable_v<Constraint_hierarchy>);
Bbox_3 bbox{}; Bbox_3 bbox{};
double segment_vertex_epsilon = 1e-8; mutable std::optional<double> max_bbox_edge_length;
std::optional<double> max_bbox_edge_length;
using Pair_of_vertex_handles = std::pair<Vertex_handle, Vertex_handle>; using Pair_of_vertex_handles = std::pair<Vertex_handle, Vertex_handle>;
boost::container::map<Pair_of_vertex_handles, Constrained_polyline_id> pair_of_vertices_to_cid; boost::container::map<Pair_of_vertex_handles, Constrained_polyline_id> pair_of_vertices_to_cid;
Insert_in_conflict_visitor insert_in_conflict_visitor = {this}; Insert_in_conflict_visitor insert_in_conflict_visitor = {this};
@ -973,20 +1124,7 @@ protected:
} }
} }
enum class Debug_flags { CDT_3::Debug_options debug_options_{};
Steiner_points = 0,
conforming,
input_faces,
missing_region,
regions,
copy_triangulation_into_hole,
validity,
use_older_cavity_algorithm,
debug_finite_edges_map,
use_finite_edges_map,
nb_of_flags
};
std::bitset<static_cast<int>(Debug_flags::nb_of_flags)> debug_flags{};
bool is_Delaunay = true; bool is_Delaunay = true;
}; };
@ -994,6 +1132,5 @@ protected:
#endif // not DOXYGEN_RUNNING #endif // not DOXYGEN_RUNNING
#
#endif // CGAL_CONFORMING_DELAUNAY_TRIANGULATION_3_H #endif // CGAL_CONFORMING_DELAUNAY_TRIANGULATION_3_H

View File

@ -52,31 +52,33 @@ class Conforming_constrained_Delaunay_triangulation_cell_data_3 {
void clear_mark(CDT_3_cell_marker m) { markers.reset(static_cast<unsigned>(m)); } void clear_mark(CDT_3_cell_marker m) { markers.reset(static_cast<unsigned>(m)); }
void clear_marks() { markers.reset(); } void clear_marks() { markers.reset(); }
static unsigned int uint(int i) { return static_cast<unsigned int>(i); }
template <typename Facet_handle> template <typename Facet_handle>
void set_facet_constraint(int i, CDT_3_signed_index face_id, void set_facet_constraint(int i, CDT_3_signed_index face_id,
Facet_handle facet_2d) Facet_handle facet_2d)
{ {
this->face_id[unsigned(i)] = face_id; this->face_id[uint(i)] = face_id;
this->facet_2d[unsigned(i)] = static_cast<void*>(facet_2d == Facet_handle{} ? nullptr : std::addressof(*facet_2d)); this->facet_2d[uint(i)] = static_cast<void*>(facet_2d == Facet_handle{} ? nullptr : std::addressof(*facet_2d));
} }
template <typename CDT_2> template <typename CDT_2>
auto face_2 (const CDT_2& cdt, int i) const { auto face_2 (const CDT_2& cdt, int i) const {
using Face = typename CDT_2::Face; using Face = typename CDT_2::Face;
auto ptr = static_cast<Face*>(facet_2d[unsigned(i)]); auto ptr = static_cast<Face*>(facet_2d[uint(i)]);
return cdt.tds().faces().iterator_to(*ptr); return cdt.tds().faces().iterator_to(*ptr);
} }
public: public:
/// @{ /// @{
// @cond SKIP_IN_MANUAL // @cond SKIP_IN_MANUAL
bool is_facet_constrained(int i) const { return face_id[unsigned(i)] >= 0; } bool is_facet_constrained(int i) const { return face_id[uint(i)] >= 0; }
CDT_3_signed_index face_constraint_index(int i) const { CDT_3_signed_index face_constraint_index(int i) const {
return face_id[unsigned(i)]; return face_id[uint(i)];
} }
void set_face_constraint_index(int i, CDT_3_signed_index index) { void set_face_constraint_index(int i, CDT_3_signed_index index) {
face_id[unsigned(i)] = index; face_id[uint(i)] = index;
} }
/// @endcond /// @endcond
}; };

View File

@ -16,6 +16,7 @@
#include <CGAL/assertions.h> #include <CGAL/assertions.h>
#include <CGAL/Constrained_triangulation_3/internal/config.h> #include <CGAL/Constrained_triangulation_3/internal/config.h>
#include <CGAL/Constrained_triangulation_3_types.h>
#include <bitset> #include <bitset>
@ -34,7 +35,7 @@ namespace CGAL {
struct Conforming_constrained_Delaunay_triangulation_vertex_data_3 {}; struct Conforming_constrained_Delaunay_triangulation_vertex_data_3 {};
#else // DOXYGEN_RUNNING #else // DOXYGEN_RUNNING
enum class CDT_3_vertex_type { FREE, CORNER, STEINER_ON_EDGE, STEINER_IN_FACE }; enum class CDT_3_vertex_type { FREE, CORNER, INPUT_VERTEX = CORNER, STEINER_ON_EDGE, STEINER_IN_FACE };
enum class CDT_3_vertex_marker { enum class CDT_3_vertex_marker {
CLEAR = 0, CLEAR = 0,
@ -91,6 +92,8 @@ public:
} }
int number_of_incident_constraints() const { int number_of_incident_constraints() const {
if(vertex_type() == CDT_3_vertex_type::STEINER_IN_FACE)
return 0;
CGAL_assertion(u.on_edge.nb_of_incident_constraints >= 0); CGAL_assertion(u.on_edge.nb_of_incident_constraints >= 0);
return u.on_edge.nb_of_incident_constraints; return u.on_edge.nb_of_incident_constraints;
} }

View File

@ -26,13 +26,6 @@ create_single_source_cgal_program( "cdt_3_from_off_with_Epeck.cpp")
target_link_libraries(cdt_3_from_off_with_Epeck PRIVATE CDT_3_dependencies) target_link_libraries(cdt_3_from_off_with_Epeck PRIVATE CDT_3_dependencies)
create_single_source_cgal_program( "snap_and_cdt3.cpp") create_single_source_cgal_program( "snap_and_cdt3.cpp")
if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
add_executable(cdt_3_from_off_CGAL_DEBUG_CDT_3 cdt_3_from_off)
target_compile_definitions(cdt_3_from_off_CGAL_DEBUG_CDT_3 PRIVATE CGAL_DEBUG_CDT_3=255)
target_link_libraries(cdt_3_from_off_CGAL_DEBUG_CDT_3 PRIVATE CDT_3_dependencies)
cgal_add_test(cdt_3_from_off_CGAL_DEBUG_CDT_3)
endif()
add_executable(test_CDT_3_insert_constrained_edge_from_EDG_file cdt_test_insert_constrained_edge_from_EDG_file.cpp) add_executable(test_CDT_3_insert_constrained_edge_from_EDG_file cdt_test_insert_constrained_edge_from_EDG_file.cpp)
target_link_libraries(test_CDT_3_insert_constrained_edge_from_EDG_file PRIVATE CDT_3_dependencies) target_link_libraries(test_CDT_3_insert_constrained_edge_from_EDG_file PRIVATE CDT_3_dependencies)
target_compile_definitions(test_CDT_3_insert_constrained_edge_from_EDG_file PUBLIC CGAL_TEST_CDT_3_USE_CDT) target_compile_definitions(test_CDT_3_insert_constrained_edge_from_EDG_file PUBLIC CGAL_TEST_CDT_3_USE_CDT)
@ -85,7 +78,7 @@ function(CGAL_add_cdt3_from_off_test_aux data_name data_dir)
endfunction() endfunction()
function(CGAL_add_cdt3_from_off_test data_name) function(CGAL_add_cdt3_from_off_test data_name)
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CGAL_DATA_DIR}/meshes) CGAL_add_cdt3_from_off_test_aux(${data_name} ${CGAL_DATA_DIR}/meshes ${ARGN})
endfunction() endfunction()
CGAL_add_cdt3_from_off_test("cube") CGAL_add_cdt3_from_off_test("cube")
@ -95,9 +88,10 @@ CGAL_add_cdt3_from_off_test("mpi")
CGAL_add_cdt3_from_off_test("3torus") CGAL_add_cdt3_from_off_test("3torus")
CGAL_add_cdt3_from_off_test("cheese-selection") CGAL_add_cdt3_from_off_test("cheese-selection")
CGAL_add_cdt3_from_off_test("cheese-selection-2") CGAL_add_cdt3_from_off_test("cheese-selection-2")
CGAL_add_cdt3_from_off_test("non_manifold_face_graph")
function(CGAL_add_cdt3_from_local_off_test data_name) function(CGAL_add_cdt3_from_local_off_test data_name)
CGAL_add_cdt3_from_off_test_aux(${data_name} ${CMAKE_CURRENT_SOURCE_DIR}/data) CGAL_add_cdt3_from_off_test_aux(${data_name} ${CMAKE_CURRENT_SOURCE_DIR}/data ${ARGN})
endfunction() endfunction()
CGAL_add_cdt3_from_local_off_test(cheese18) CGAL_add_cdt3_from_local_off_test(cheese18)
@ -130,17 +124,15 @@ if (CGAL_CDT_TEST_USE_THINGI)
CGAL_add_cdt3_from_local_off_test(1514904-min8) CGAL_add_cdt3_from_local_off_test(1514904-min8)
CGAL_add_cdt3_from_local_off_test(1147177-min1) CGAL_add_cdt3_from_local_off_test(1147177-min1)
CGAL_add_cdt3_from_local_off_test(1452672-min1) CGAL_add_cdt3_from_local_off_test(1452672-min1)
CGAL_add_cdt3_from_local_off_test(135777-min3)
CGAL_add_cdt3_from_local_off_test(196123-min3)
CGAL_add_cdt3_from_local_off_test(200695-min3)
CGAL_add_cdt3_from_local_off_test(285604-min8)
CGAL_add_cdt3_from_local_off_test(error_mesh-p_not_equal_0-min2) CGAL_add_cdt3_from_local_off_test(error_mesh-p_not_equal_0-min2)
include(./Thingi10k-CDT.cmake) include(./Thingi10k-CDT.cmake)
endif() endif()
if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES)
add_test(NAME "execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" COMMAND cdt_3_from_off_CGAL_DEBUG_CDT_3 ${CGAL_DATA_DIR}/meshes/3torus.off)
cgal_add_compilation_test(cdt_3_from_off_CGAL_DEBUG_CDT_3)
cgal_setup_test_properties("execution of cdt_3_from_off_CGAL_DEBUG_CDT_3 3torus" cdt_3_from_off_CGAL_DEBUG_CDT_3)
endif()
get_directory_property(all_tests TESTS) get_directory_property(all_tests TESTS)
foreach(test ${all_tests}) foreach(test ${all_tests})
if(test MATCHES cdt|CDT) if(test MATCHES cdt|CDT)

View File

@ -109,6 +109,152 @@ set(thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20240222_2201
1514904.stl 1514904.stl
) )
set(thingi10k_FAILED_WITH_SEGFAULT_CTest_20251002
1439534.stl
196123.stl
200695.stl
135777.stl
285604.stl
822697.stl
)
set(thingi10k_FAILED_CTest_20251002
100606.stl
100644.stl
101955.stl
109130.stl
116873.stl
116876.stl
135777.stl
139737.stl
1439534.stl
145329.stl
145330.stl
1505036.stl
1514900.stl
196121.stl
196122.stl
196123.stl
196126.stl
196127.stl
199814.stl
199818.stl
200695.stl
215991.stl
230152.stl
230153.stl
239188.stl
276937.stl
285604.stl
285605.stl
288352.stl
288353.stl
288354.stl
288355.stl
39182.stl
39245.stl
472050.stl
55278.stl
61418.stl
622000.stl
669962.stl
67817.stl
702204.stl
723893.stl
822697.stl
904476.stl
91474.stl
95796.stl
95797.stl
97515.stl
)
set(thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20251028
139765.stl
1452677.stl
1452678.stl
1452679.stl
145329.stl
145330.stl
145331.stl
1505036.stl
1514900.stl
153100.stl
1652975.stl
1652976.stl
1706457.stl
186546.stl
196121.stl
196122.stl
196123.stl
196126.stl
196127.stl
196194.stl
199814.stl
199818.stl
206318.stl
215991.stl
230152.stl
230153.stl
237632.stl
239188.stl
255657.stl
255658.stl
276937.stl
285603.stl
286161.stl
288352.stl
288446.stl
360073.stl
362398.stl
37743.stl
383022.stl
39182.stl
39245.stl
39495.stl
39499.stl
40841.stl
41521.stl
42040.stl
44025.stl
44064.stl
44901.stl
472050.stl
50659.stl
51797.stl
57811.stl
61418.stl
61431.stl
622000.stl
62592.stl
62593.stl
65144.stl
65395.stl
65402.stl
669962.stl
68255.stl
702204.stl
70381.stl
71461.stl
723893.stl
72419.stl
726665.stl
77343.stl
84624.stl
90225.stl
906183.stl
91147.stl
91474.stl
93702.stl
93703.stl
95796.stl
95797.stl
97515.stl
97590.stl
97593.stl
99895.stl
)
function(CGAL_add_cdt3_test_from_Thingi10k data_name data_filename) function(CGAL_add_cdt3_test_from_Thingi10k data_name data_filename)
set(options "ONLY_MERGE_FACETS") set(options "ONLY_MERGE_FACETS")
set(oneValueArgs TIMEOUT) set(oneValueArgs TIMEOUT)
@ -145,6 +291,15 @@ foreach(thingi_file_name ${thingi10k_max_10k_solid})
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20240222_2201) if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20240222_2201)
list(APPEND LABELS "CTest_20240222_2201_failed_merge_facets") list(APPEND LABELS "CTest_20240222_2201_failed_merge_facets")
endif() endif()
if(thingi_file_name IN_LIST thingi10k_FAILED_CTest_20251002)
list(APPEND LABELS "CTest_20251002_failed")
endif()
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_SEGFAULT_CTest_20251002)
list(APPEND LABELS "CTest_20251002_failed_segfault")
endif()
if(thingi_file_name IN_LIST thingi10k_FAILED_WITH_MERGE_FACETS_CTest_20251028)
list(APPEND LABELS "CTest_20251028_failed_merge_facets")
endif()
get_filename_component(thingi_ID "${thingi_file_name}" NAME_WE) get_filename_component(thingi_ID "${thingi_file_name}" NAME_WE)
CGAL_add_cdt3_test_from_Thingi10k(Thingi10K_${thingi_ID} ${thingi_file_name} CGAL_add_cdt3_test_from_Thingi10k(Thingi10K_${thingi_ID} ${thingi_file_name}
TIMEOUT 600 LABELS ${LABELS} ${MY_ONLY_MERGE_FACETS}) TIMEOUT 600 LABELS ${LABELS} ${MY_ONLY_MERGE_FACETS})

View File

@ -1,6 +1,3 @@
#if __has_include(<format>)
#define CGAL_DEBUG_CDT_3 1
#endif
#define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1 #define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h> #include <CGAL/Delaunay_triangulation_3.h>

View File

@ -1,6 +1,3 @@
#if __has_include(<format>)
#define CGAL_DEBUG_CDT_3 1
#endif
#define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1 #define CGAL_TRIANGULATION_CHECK_EXPENSIVE 1
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Delaunay_triangulation_3.h> #include <CGAL/Delaunay_triangulation_3.h>

View File

@ -0,0 +1,69 @@
OFF
42 23 0
9.4220000000000006 6.265949 1.2926169999999999
9.4220000000000006 6.4378760000000002 0.4304
9.4299999999999997 6.3669419999999999 1.3120000000000001
9.4220000000000006 6.522742 1.2616000000000001
9.4299999999999997 1.737943 2.867
9.4299999999999997 1.310943 1.46
9.4299999999999997 1.167238 0
9.4299999999999997 5.7969429999999997 6.9269999999999996
9.4299999999999997 16.167649999999998 0
9.4299999999999997 4.499943 6.2329999999999997
9.4299999999999997 3.3639420000000002 5.3010000000000002
9.4299999999999997 2.4309430000000001 4.1639999999999997
12.430999999999999 1.167238 0
12.430999999999999 1.310943 1.46
-7.2230889999999999 -5.1901419999999998 1.2724260000000001
-7.2389999999999999 -5.1100570000000003 1.3959999999999999
3.7330000000000001 -6.7590570000000003 0.79200000000000004
-7.255185 -4.6623049999999999 0.88247529999999996
-7.2552779999999997 -4.6682399999999999 0.88692839999999995
3.7330000000000001 -6.2710569999999999 0.42699999999999999
-7.262251 -4.5335140000000003 0.78721229999999998
-7.7199999999999998 -4.2110570000000003 1.929
-7.6440000000000001 -4.1590579999999999 1.6100000000000001
-7.5739999999999998 -4.3940570000000001 1.726
-7.5469999999999997 -3.6850580000000002 1.224
-7.5369999999999999 -3.8630580000000001 1.3169999999999999
-7.4050000000000002 -4.4780569999999997 1.4410000000000001
-7.3220000000000001 -4.3380580000000002 1.022
-7.4009999999999998 -4.689057 1.677
-7.2534720000000004 -4.6835990000000001 0.89814380000000005
9.4299999999999997 10.06494 1.929
-7.2789999999999999 -4.0440569999999996 0.34699999999999998
9.4299999999999997 6.3669419999999999 1.3120000000000001
-7.2230889999999999 -5.1901419999999998 1.2724260000000001
3.68716 -6.0934090000000003 0
3.7330000000000001 -6.2710569999999999 0.42699999999999999
3.7330000000000001 -6.2710569999999999 0.42699999999999999
-7.262251 -4.5335140000000003 0.78721229999999998
-7.6029999999999998 -4.5610569999999999 2.0139999999999998
-7.4050000000000002 -4.4780569999999997 1.4410000000000001
-7.3220000000000001 -4.3380580000000002 1.022
-7.2599 -4.5207920000000001 0.75421059999999995
3 0 1 2
3 1 3 2
3 4 32 5
3 6 5 32
3 8 32 30
3 9 7 32
3 32 7 30
3 10 32 11
3 4 11 32
3 10 9 32
3 6 32 8
3 13 5 12
3 38 23 21
3 26 25 22
3 24 25 26
3 27 39 28
3 16 19 14
3 35 34 20
3 18 29 36
3 18 28 29
3 15 33 29
3 31 40 41
3 40 17 37

View File

@ -0,0 +1,75 @@
OFF
37 34 0
172.45960998535156 327.00732421875 10.000033378601074
173.35765075683594 327.18472290039062 10.000033378601074
172.45960998535156 327.00732421875 10
174.25531005859375 327.36398315429688 10.000033378601074
175.282470703125 327.571533203125 10
170.58482360839844 325.87066650390625 10
170.58482360839844 325.87066650390625 10.000033378601074
170.58476257324219 326.1373291015625 10
170.58476257324219 326.1373291015625 10.000033378601074
170.58488464355469 326.67068481445312 10.000033378601074
170.58488464355469 326.67068481445312 10
170.58477783203125 326.40402221679688 10.000033378601074
170.58477783203125 326.40402221679688 10
171.21096801757812 326.77630615234375 10
171.21096801757812 326.77630615234375 10.000033378601074
171.83589172363281 326.88851928710938 10.000033378601074
171.83589172363281 326.88851928710938 10
198.59626770019531 331.45306396484375 10
171.3594970703125 325.91452026367188 10
171.3594970703125 325.91452026367188 10.000033378601074
171.10134887695312 325.89859008789062 10
171.10134887695312 325.89859008789062 10.000033378601074
170.84312438964844 325.88397216796875 10.000033378601074
170.84312438964844 325.88397216796875 10
173.88740539550781 326.08248901367188 10.000033378601074
174.88548278808594 326.13330078125 10
173.12164306640625 326.03756713867188 10
172.62298583984375 326.00552368164062 10.000033378601074
176.65058898925781 326.20169067382812 10
179.54045104980469 326.31793212890625 10
182.43142700195312 326.40179443359375 10
192.267333984375 331.10971069335938 10
197.96424865722656 332.17782592773438 10
175.15260314941406 328.56558227539062 10.000033378601074
175.15260314941406 325.1444091796875 10.000033378601074
161.37049865722656 320.09548950195312 10.000033378601074
161.37049865722656 332.70773315429688 10.000033378601074
3 1 3 2
3 2 3 4
3 18 26 27
3 27 26 24
3 4 30 2
3 31 32 17
3 30 29 2
3 2 29 16
3 25 10 28
3 10 25 12
3 18 7 26
3 18 20 7
3 20 23 7
3 23 5 7
3 7 12 26
3 26 12 25
3 10 13 28
3 13 16 28
3 21 19 34
3 21 34 22
3 19 27 34
3 36 11 35
3 3 1 33
3 1 0 33
3 0 15 33
3 15 14 33
3 14 9 33
3 33 9 36
3 11 8 35
3 8 6 35
3 35 6 34
3 6 22 34
3 34 27 24
3 11 36 9

View File

@ -0,0 +1,46 @@
OFF
25 17 0
137.05000305175781 47.498001098632812 132.02400207519531
137.05000305175781 42.498001098632812 132.65000915527344
137.05000305175781 20 131.40000915527344
137.05000305175781 14.998001098632812 90.316001892089844
137.05000305175781 0 133.90000915527344
137.05000305175781 5 131.40000915527344
120.80000305175781 0 133.90000915527344
134.05000305175781 2.9980001449584961 133.90000915527344
136.67401123046875 15.874000549316406 133.90000915527344
137.12800598144531 5 132.33399963378906
137.12800598144531 20 132.33399963378906
137.36601257324219 5 133.24000549316406
137.36601257324219 20 133.24000549316406
137.75401306152344 5 134.09400939941406
137.05000305175781 31.248001098632812 90.316001892089844
137.05000305175781 16.248001098632812 133.90000915527344
118.55000305175781 2.25 133.90000915527344
104.55000305175781 0 133.90000915527344
137.05000305175781 32.498001098632812 133.90000915527344
55.800003051757812 0 133.90000915527344
54.674003601074219 1.124000072479248 133.90000915527344
55.050003051757812 0.74800002574920654 133.90000915527344
136.30000305175781 31.750001907348633 133.90000915527344
39.550003051757812 0 133.90000915527344
137.05000305175781 20 118.12000274658203
3 0 1 2
3 4 5 2
3 7 4 8
3 10 9 11
3 10 11 12
3 12 11 13
3 14 24 3
3 2 15 4
3 15 8 4
3 17 7 16
3 18 2 1
3 7 17 6
3 2 18 15
3 7 8 22
3 15 22 8
3 20 23 21
3 19 21 23

View File

@ -0,0 +1,119 @@
OFF
67 48 0
25.003999710083008 4.125999927520752 5.3249998092651367
24.648000717163086 4.1110000610351562 5.3020000457763672
27.875 4.124000072479248 5.3159999847412109
28.104999542236328 4.0980000495910645 5.3020000457763672
27.547000885009766 -0.76599997282028198 5.3020000457763672
24.26300048828125 4.1999998092651367 5.3020000457763672
24.350000381469727 -1.2070000171661377 5.3020000457763672
22.61199951171875 -1.2680000066757202 5.3020000457763672
18.076999664306641 -0.76700001955032349 5.3020000457763672
20.534172058105469 6.6471333503723145 5.3020000457763672
21.565000534057617 6.2769999504089355 5.3020000457763672
21.576999664306641 6.2220001220703125 5.3020000457763672
24.184999465942383 4.2010002136230469 5.3020000457763672
24.132999420166016 4.2109999656677246 5.3020000457763672
23.76099967956543 4.3359999656677246 5.3020000457763672
23.552000045776367 4.3480663299560547 5.3020000457763672
23.822000503540039 4.2779998779296875 5.3020000457763672
23.259000778198242 4.4369997978210449 5.3029999732971191
22.599832534790039 5.119999885559082 5.3020000457763672
21.814010620117188 5.7782330513000488 5.3020000457763672
22.527999877929688 4.9455761909484863 5.3020000457763672
21.797874450683594 5.8303966522216797 5.3020968437194824
22.527999877929688 4.6591053009033203 5.3020000457763672
21.822000503540039 5.8159999847412109 6.0100002288818359
21.772134780883789 5.687347412109375 5.3039073944091797
21.657405853271484 5.9652857780456543 5.3020000457763672
21.655532836914062 5.9393019676208496 5.3023014068603516
21.794061660766602 5.8427157402038574 5.3020000457763672
21.660037994384766 5.9280643463134766 5.3023800849914551
21.660087585449219 5.9279398918151855 5.3023805618286133
21.820028305053711 5.6319999694824219 5.3020000457763672
21.659999847412109 5.9279999732971191 5.3020000457763672
19.494876861572266 4.9111647605895996 5.3020000457763672
21.641000747680664 5.9800000190734863 5.3020000457763672
21.624000549316406 6.0019998550415039 5.309999942779541
-2.1689999103546143 -0.46799999475479126 5.3020000457763672
20.37629508972168 6.2305684089660645 5.3020000457763672
-2.2790000438690186 -1.3259999752044678 6.0859999656677246
-2.1040000915527344 0.082999996840953827 5.320000171661377
22.329999923706055 5.0479998588562012 5.3020000457763672
19.238409042358398 4.5272407531738281 5.3020000457763672
-1.9989999532699585 0.26600000262260437 6.7109999656677246
18.052036285400391 3.3704285621643066 5.3020000457763672
20.326999664306641 6.2470002174377441 5.0159997940063477
19.670000076293945 6.4640002250671387 3.7780001163482666
18.603000640869141 4.8670001029968262 3.7780001163482666
-0.6029999852180481 6.8179998397827148 2.6359999179840088
0.33100000023841858 3.0639998912811279 5.0159997940063477
-1.143372654914856 4.4346461296081543 5.3020000457763672
-1.1940000057220459 4.5510001182556152 5.0159997940063477
0.83399999141693115 3.4670000076293945 3.7780001163482666
-3.2599999904632568 10 5.0159997940063477
-2.5490000247955322 10 3.7780001163482666
-2.3269999027252197 8.1979999542236328 3.7780001163482666
-1.6699999570846558 6.4640002250671387 3.7780001163482666
-2.1198277473449707 5.846644401550293 5.3020000457763672
-3.0250000953674316 8.0860004425048828 5.0159997940063477
-1.9939999580383301 3.0099999904632568 5.3020000457763672
-1.2384099960327148 4.5272407531738281 5.3020000457763672
-2.2780001163482666 3.7369999885559082 5.3020000457763672
-2.0220000743865967 0.74299997091293335 6.0689997673034668
-1.9220000505447388 1.1330000162124634 5.3020000457763672
-1.9739999771118164 0.92799997329711914 5.314000129699707
-2.1050000190734863 -0.041999999433755875 6.1490001678466797
-2.3269999027252197 6.2470002174377441 5.0159997940063477
-0.6029999852180481 4.8670001029968262 3.7780001163482666
21.659999847412109 5.9279999732971191 5.3020000457763672
3 2 3 0
3 5 1 6
3 3 4 1
3 4 6 1
3 12 5 6
3 13 12 7
3 25 19 30
3 19 25 27
3 24 29 23
3 31 32 25
3 25 30 31
3 34 66 26
3 33 25 32
3 66 34 28
3 10 11 36
3 11 33 36
3 27 18 19
3 17 18 21
3 39 22 32
3 20 19 18
3 40 32 22
3 8 40 22
3 16 8 14
3 6 7 12
3 15 14 8
3 8 16 7
3 36 9 10
3 30 39 32
3 31 30 32
3 36 33 32
3 43 45 44
3 22 15 8
3 8 42 40
3 16 13 7
3 49 58 55
3 57 59 48
3 51 52 56
3 64 56 53
3 65 54 46
3 65 49 54
3 49 64 54
3 47 65 50
3 47 49 65
3 38 62 35
3 62 61 35
3 38 37 63
3 41 60 63
3 63 37 41

View File

@ -40,7 +40,7 @@ int main(int argc, char* argv[])
auto cdt = CGAL::make_conforming_constrained_Delaunay_triangulation_3<CDT>(mesh); auto cdt = CGAL::make_conforming_constrained_Delaunay_triangulation_3<CDT>(mesh);
static_assert(std::is_same_v<decltype(cdt), CDT>); static_assert(std::is_same_v<decltype(cdt), CDT>);
CDT cdt2(mesh); CDT cdt2(mesh);
const auto nb_cstr_facets = cdt2.number_of_constrained_facets(); [[maybe_unused]] const auto nb_cstr_facets = cdt2.number_of_constrained_facets();
assert(cdt.triangulation().number_of_vertices() == cdt2.triangulation().number_of_vertices()); assert(cdt.triangulation().number_of_vertices() == cdt2.triangulation().number_of_vertices());
assert(cdt.number_of_constrained_facets() == cdt2.number_of_constrained_facets()); assert(cdt.number_of_constrained_facets() == cdt2.number_of_constrained_facets());

View File

@ -0,0 +1,39 @@
OFF
24 11 0
1.5 0.5 1
0.5 0.5 0
0.5 0.5 1
0 0 0
0 0.5 0
0.5 0.5 0
0.5 1 0
0 1 0
0.5 0 0
1 0 0
1 0.5 0
1 1 0
1.5 1.5 1
2.5 1.5 1
2.5 0.5 1
-0.5 -0.5 1
2.5 -0.5 1
0.5 1.5 1
-0.5 0.5 1
1.5 0.5 1
1.5 -0.5 1
-0.5 1.5 1
0.5 0.5 1
0.5 -0.5 1
3 2 1 0
4 4 3 8 5
4 7 4 5 6
4 5 8 9 10
4 6 5 10 11
4 12 19 14 13
4 19 20 16 14
4 17 22 19 12
4 22 23 20 19
4 21 18 22 17
4 18 15 23 22

View File

@ -118600,7 +118600,7 @@ both for rendering and for modeling. Contains C code."
@article{ph-ddocs-92 @article{ph-ddocs-92
, author = "J. P. Pratt and V. P. Heuring" , author = "J. P. Pratt and V. P. Heuring"
, title = "Designing digital optical computing systems: power and and crosstalk" , title = "Designing digital optical computing systems: power and crosstalk"
, journal = "Appl. Optics" , journal = "Appl. Optics"
, volume = 31 , volume = 31
, number = 23 , number = 23

View File

@ -462,10 +462,6 @@ namespace CGAL {
} // end of the temporary compatibility with CGAL-4.14 } // end of the temporary compatibility with CGAL-4.14
#endif // CGAL_NO_DEPRECATED_CODE #endif // CGAL_NO_DEPRECATED_CODE
#if __has_include(<version>)
# include <version>
#endif
namespace CGAL { namespace CGAL {
// Typedef for the type of nullptr. // Typedef for the type of nullptr.

View File

@ -14,15 +14,15 @@
namespace CGAL { namespace internal { namespace CGAL { namespace internal {
template < typename T > inline template <typename ...T> inline
void use(const T&) {} void use(T&&...) {}
template<typename> void use_type() {} template<typename> void use_type() {}
} } } }
/// CGAL_USE() is a macro which aims at removing "variable is unused" warnings. /// CGAL_USE() is a macro which aims at removing "variable is unused" warnings.
#define CGAL_USE(x) ::CGAL::internal::use(x) #define CGAL_USE(...) ::CGAL::internal::use(__VA_ARGS__)
/// CGAL_USE_TYPE() is a macro which aims at removing "typedef locally /// CGAL_USE_TYPE() is a macro which aims at removing "typedef locally
/// defined but not used" warnings. /// defined but not used" warnings.

View File

@ -177,7 +177,7 @@ class Interval_for_container : public Interval_
// remove markers for Interval I starting at left, the left endpoint // remove markers for Interval I starting at left, the left endpoint
// of I, and and stopping at the right endpoint of I. // of I, and stopping at the right endpoint of I.
Interval_handle removeMarkers(IntervalSLnode<Interval>* left, Interval_handle removeMarkers(IntervalSLnode<Interval>* left,
const Interval& I); const Interval& I);

View File

@ -1,4 +1,4 @@
// Copyright (c) 2019 // Copyright (c) 2019,2025
// GeometryFactory (France) // GeometryFactory (France)
// //
// This file is part of CGAL (www.cgal.org) // This file is part of CGAL (www.cgal.org)
@ -9,6 +9,8 @@
// //
// //
// Author(s) : Simon Giraudot // Author(s) : Simon Giraudot
//
// Test file: test/Kernel_23/test_hash_functions.cpp
#ifndef CGAL_KERNEL_HASH_FUNCTIONS_H #ifndef CGAL_KERNEL_HASH_FUNCTIONS_H
#define CGAL_KERNEL_HASH_FUNCTIONS_H #define CGAL_KERNEL_HASH_FUNCTIONS_H
@ -16,18 +18,73 @@
#include <boost/functional/hash.hpp> #include <boost/functional/hash.hpp>
#include <type_traits> #include <type_traits>
#include <CGAL/representation_tags.h>
#include <CGAL/Aff_transformation_2.h>
#include <CGAL/Aff_transformation_3.h>
#include <CGAL/Bbox_2.h>
#include <CGAL/Bbox_3.h>
#include <CGAL/Circle_2.h>
#include <CGAL/Iso_rectangle_2.h>
#include <CGAL/Iso_cuboid_3.h>
#include <CGAL/Point_2.h>
#include <CGAL/Point_3.h>
#include <CGAL/Segment_2.h>
#include <CGAL/Segment_3.h>
#include <CGAL/Sphere_3.h>
#include <CGAL/Vector_2.h>
#include <CGAL/Vector_3.h>
#include <CGAL/Weighted_point_2.h>
#include <CGAL/Weighted_point_3.h>
namespace CGAL namespace CGAL
{ {
using boost::hash_value; using boost::hash_value;
template <typename K, typename = void>
inline constexpr bool has_rep_tag_v = false;
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline constexpr bool has_rep_tag_v<K, std::void_t<typename K::Rep_tag>> = true;
template <typename K, typename = void>
struct Rep_tag {
using type = void;
};
template <typename K>
struct Rep_tag<K, std::enable_if_t<has_rep_tag_v<K>>> {
using type = typename K::Rep_tag;
};
template <typename K>
using Rep_tag_t = typename Rep_tag<K>::type;
template <typename K>
inline constexpr bool is_Cartesian_v = std::is_same<Rep_tag_t<K>, Cartesian_tag>::value;
template <typename K, typename = void>
struct Is_kernel_hashable : public std::false_type {};
template <typename K>
struct Is_kernel_hashable<K, std::void_t<decltype(hash_value(std::declval<typename K::FT>()))>> : public std::true_type {};
template <typename K>
inline constexpr bool is_kernel_hashable_v = Is_kernel_hashable<K>::value;
template <typename K, typename T>
using enable_if_Cartesian_and_hashable_t =
std::enable_if_t<is_Cartesian_v<K> && is_kernel_hashable_v<K>, T>;
template <typename K>
inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Aff_transformation_2<K>& transform) hash_value (const Aff_transformation_2<K>& transform)
{ {
std::size_t result = hash_value(transform.cartesian(0,0)); std::size_t result = hash_value(transform.cartesian(0,0));
for(int i=0; i < 3; ++i) for(int i=0; i < 3; ++i)
for(int j = 0; j < 3; ++j) for(int j=0; j < 3; ++j)
// Skip (0,0) as it was already used to initialize the hash
if (!(i == 0 && j == 0)) if (!(i == 0 && j == 0))
boost::hash_combine(result, hash_value(transform.cartesian(i,j))); boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
return result; return result;
@ -44,7 +101,7 @@ hash_value (const Bbox_2& bbox)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Circle_2<K>& circle) hash_value (const Circle_2<K>& circle)
{ {
std::size_t result = hash_value(circle.center()); std::size_t result = hash_value(circle.center());
@ -54,7 +111,7 @@ hash_value (const Circle_2<K>& circle)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Iso_rectangle_2<K>& iso_rectangle) hash_value (const Iso_rectangle_2<K>& iso_rectangle)
{ {
std::size_t result = hash_value((iso_rectangle.min)()); std::size_t result = hash_value((iso_rectangle.min)());
@ -63,7 +120,7 @@ hash_value (const Iso_rectangle_2<K>& iso_rectangle)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Point_2<K>& point) hash_value (const Point_2<K>& point)
{ {
std::size_t result = hash_value(point.x()); std::size_t result = hash_value(point.x());
@ -72,7 +129,7 @@ hash_value (const Point_2<K>& point)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Segment_2<K>& segment) hash_value (const Segment_2<K>& segment)
{ {
std::size_t result = hash_value(segment.source()); std::size_t result = hash_value(segment.source());
@ -81,7 +138,7 @@ hash_value (const Segment_2<K>& segment)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Vector_2<K>& vector) hash_value (const Vector_2<K>& vector)
{ {
std::size_t result = hash_value(vector.x()); std::size_t result = hash_value(vector.x());
@ -90,7 +147,7 @@ hash_value (const Vector_2<K>& vector)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Weighted_point_2<K>& weighed_point) hash_value (const Weighted_point_2<K>& weighed_point)
{ {
std::size_t result = hash_value(weighed_point.point()); std::size_t result = hash_value(weighed_point.point());
@ -99,14 +156,13 @@ hash_value (const Weighted_point_2<K>& weighed_point)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Aff_transformation_3<K>& transform) hash_value (const Aff_transformation_3<K>& transform)
{ {
std::size_t result = hash_value(transform.cartesian(0,0)); std::size_t result = hash_value(transform.cartesian(0,0));
for(int i = 0; i < 3; ++i) for(int i = 0; i < 3; ++i)
for(int j = 0; j < 4; ++j) for(int j = (i == 0 ? 1 : 0); j < 4; ++j)
if (!(i == 0 && j == 0)) boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
boost::hash_combine(result, hash_value(transform.cartesian(i,j)));
return result; return result;
} }
@ -123,7 +179,7 @@ hash_value (const Bbox_3& bbox)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Iso_cuboid_3<K>& iso_cuboid) hash_value (const Iso_cuboid_3<K>& iso_cuboid)
{ {
std::size_t result = hash_value((iso_cuboid.min)()); std::size_t result = hash_value((iso_cuboid.min)());
@ -132,7 +188,7 @@ hash_value (const Iso_cuboid_3<K>& iso_cuboid)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Point_3<K>& point) hash_value (const Point_3<K>& point)
{ {
std::size_t result = hash_value(point.x()); std::size_t result = hash_value(point.x());
@ -142,7 +198,7 @@ hash_value (const Point_3<K>& point)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Segment_3<K>& segment) hash_value (const Segment_3<K>& segment)
{ {
std::size_t result = hash_value(segment.source()); std::size_t result = hash_value(segment.source());
@ -151,7 +207,7 @@ hash_value (const Segment_3<K>& segment)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Sphere_3<K>& sphere) hash_value (const Sphere_3<K>& sphere)
{ {
std::size_t result = hash_value(sphere.center()); std::size_t result = hash_value(sphere.center());
@ -161,7 +217,7 @@ hash_value (const Sphere_3<K>& sphere)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Vector_3<K>& vector) hash_value (const Vector_3<K>& vector)
{ {
std::size_t result = hash_value(vector.x()); std::size_t result = hash_value(vector.x());
@ -171,7 +227,7 @@ hash_value (const Vector_3<K>& vector)
} }
template <typename K> template <typename K>
inline std::enable_if_t<std::is_same<typename K::Rep_tag, Cartesian_tag>::value, std::size_t> inline enable_if_Cartesian_and_hashable_t<K, std::size_t>
hash_value (const Weighted_point_3<K>& weighed_point) hash_value (const Weighted_point_3<K>& weighed_point)
{ {
std::size_t result = hash_value(weighed_point.point()); std::size_t result = hash_value(weighed_point.point());
@ -179,93 +235,46 @@ hash_value (const Weighted_point_3<K>& weighed_point)
return result; return result;
} }
struct Forward_to_hash_value {
template <typename T>
std::size_t operator()(T&& t) const {
using boost::hash_value;
return hash_value(std::forward<T>(t));
}
};
template <typename K, typename = void>
struct Maybe_forward_to_hash_value {
Maybe_forward_to_hash_value() = delete;
Maybe_forward_to_hash_value(const Maybe_forward_to_hash_value&) = delete;
};
template <typename K>
struct Maybe_forward_to_hash_value<K, std::enable_if_t<is_kernel_hashable_v<K>>>
: public Forward_to_hash_value {};
} //namespace CGAL } //namespace CGAL
// overloads of std::hash used for using std::unordered_[set/map] on CGAL Kernel objects // overloads of std::hash used for using std::unordered_[set/map] on CGAL Kernel objects
namespace std namespace std {
{ template <typename K> struct hash<CGAL::Aff_transformation_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Circle_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Iso_rectangle_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Point_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Segment_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Vector_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Weighted_point_2<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <> struct hash<CGAL::Bbox_2> : CGAL::Forward_to_hash_value {};
template <typename K> struct hash<CGAL::Aff_transformation_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Iso_cuboid_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Point_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Segment_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Sphere_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Vector_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <typename K> struct hash<CGAL::Weighted_point_3<K>> : CGAL::Maybe_forward_to_hash_value<K> {};
template <> struct hash<CGAL::Bbox_3> : CGAL::Forward_to_hash_value {};
} // namespace std
template <typename K> struct hash<CGAL::Aff_transformation_2<K> > {
std::size_t operator() (const CGAL::Aff_transformation_2<K>& transform) const {
return CGAL::hash_value<K> (transform);
}
};
template <> struct hash<CGAL::Bbox_2> {
std::size_t operator() (const CGAL::Bbox_2& bbox) const {
return CGAL::hash_value (bbox);
}
};
template <typename K> struct hash<CGAL::Circle_2<K> > {
std::size_t operator() (const CGAL::Circle_2<K>& circle) const {
return CGAL::hash_value<K> (circle);
}
};
template <typename K> struct hash<CGAL::Iso_rectangle_2<K> > {
std::size_t operator() (const CGAL::Iso_rectangle_2<K>& iso_rectangle) const {
return CGAL::hash_value<K> (iso_rectangle);
}
};
template <typename K> struct hash<CGAL::Point_2<K> > {
std::size_t operator() (const CGAL::Point_2<K>& point) const {
return CGAL::hash_value<K> (point);
}
};
template <typename K> struct hash<CGAL::Segment_2<K> > {
std::size_t operator() (const CGAL::Segment_2<K>& segment) const {
return CGAL::hash_value<K> (segment);
}
};
template <typename K> struct hash<CGAL::Vector_2<K> > {
std::size_t operator() (const CGAL::Vector_2<K>& vector) const {
return CGAL::hash_value<K> (vector);
}
};
template <typename K> struct hash<CGAL::Weighted_point_2<K> > {
std::size_t operator() (const CGAL::Weighted_point_2<K>& weighted_point) const {
return CGAL::hash_value<K> (weighted_point);
}
};
template <typename K> struct hash<CGAL::Aff_transformation_3<K> > {
std::size_t operator() (const CGAL::Aff_transformation_3<K>& transform) const {
return CGAL::hash_value<K> (transform);
}
};
template <> struct hash<CGAL::Bbox_3> {
std::size_t operator() (const CGAL::Bbox_3& bbox) const {
return CGAL::hash_value (bbox);
}
};
template <typename K> struct hash<CGAL::Iso_cuboid_3<K> > {
std::size_t operator() (const CGAL::Iso_cuboid_3<K>& iso_cuboid) const {
return CGAL::hash_value<K> (iso_cuboid);
}
};
template <typename K> struct hash<CGAL::Point_3<K> > {
std::size_t operator() (const CGAL::Point_3<K>& point) const {
return CGAL::hash_value<K> (point);
}
};
template <typename K> struct hash<CGAL::Segment_3<K> > {
std::size_t operator() (const CGAL::Segment_3<K>& segment) const {
return CGAL::hash_value<K> (segment);
}
};
template <typename K> struct hash<CGAL::Sphere_3<K> > {
std::size_t operator() (const CGAL::Sphere_3<K>& sphere) const {
return CGAL::hash_value<K> (sphere);
}
};
template <typename K> struct hash<CGAL::Vector_3<K> > {
std::size_t operator() (const CGAL::Vector_3<K>& vector) const {
return CGAL::hash_value<K> (vector);
}
};
template <typename K> struct hash<CGAL::Weighted_point_3<K> > {
std::size_t operator() (const CGAL::Weighted_point_3<K>& weighted_point) const {
return CGAL::hash_value<K> (weighted_point);
}
};
}
#endif // CGAL_KERNEL_HASH_FUNCTIONS_H #endif // CGAL_KERNEL_HASH_FUNCTIONS_H

View File

@ -1,13 +1,18 @@
// test partially generated by Github Copilot
#include <unordered_set> #include <unordered_set>
#include <CGAL/Simple_cartesian.h> #include <CGAL/Simple_cartesian.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Bbox_2.h> #include <CGAL/Bbox_2.h>
#include <CGAL/Bbox_3.h>
typedef CGAL::Simple_cartesian<double> SC; typedef CGAL::Simple_cartesian<double> SC;
typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick; typedef CGAL::Exact_predicates_inexact_constructions_kernel Epick;
static_assert(CGAL::is_kernel_hashable_v<SC>);
static_assert(CGAL::is_kernel_hashable_v<Epick>);
template <typename Object> template <typename Object>
void test (const Object& obj) void test (const Object& obj)
{ {
@ -67,5 +72,3 @@ int main()
return 0; return 0;
} }

View File

@ -78,6 +78,9 @@ pushd Triangulation_on_sphere_2_Demo_with_dlls; zip -r ../triangulation_on_spher
pushd Lab_Demo_with_dlls; zip -r ../CGALlab.zip *; popd pushd Lab_Demo_with_dlls; zip -r ../CGALlab.zip *; popd
pushd Arrangement_on_surface_2_earth_Demo_with_dlls; zip -r ../arrangements_2_earth.zip *; popd pushd Arrangement_on_surface_2_earth_Demo_with_dlls; zip -r ../arrangements_2_earth.zip *; popd
# CGAL-6.1
pushd Triangulation_on_hyperbolic_surface_2_Demo_with_dlls; zip -r ../triangulation_on_hyperbolic_surface_2.zip *; popd
# check # check
echo CHECK now. The following lines should be empty. echo CHECK now. The following lines should be empty.
for f in *zip; do unzip -qql $f; done | awk '{print $4}' >| done for f in *zip; do unzip -qql $f; done | awk '{print $4}' >| done

View File

@ -11,6 +11,11 @@
#ifndef CGAL_NT_WRAPPER_H #ifndef CGAL_NT_WRAPPER_H
#define CGAL_NT_WRAPPER_H #define CGAL_NT_WRAPPER_H
#include <CGAL/config.h>
#if __cpp_lib_source_location
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> #include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h> #include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <CGAL/Coercion_traits.h> #include <CGAL/Coercion_traits.h>
@ -184,4 +189,6 @@ struct Wrapped_epeck
} // namespace CGAL } // namespace CGAL
#endif // __cpp_lib_source_location
#endif // CGAL_NT_WRAPPER_H #endif // CGAL_NT_WRAPPER_H

View File

@ -1366,7 +1366,7 @@ preprocess_bounded_error_squared_Hausdorff_distance_impl(const TriangleMesh1& tm
if(is_one_sided_distance) // one-sided distance if(is_one_sided_distance) // one-sided distance
{ {
if(tm1_only.size() > 0) // create TM1 and and full TM2 if(tm1_only.size() > 0) // create TM1 and full TM2
{ {
tm1_tree.insert(tm1_only.begin(), tm1_only.end(), tm1, vpm1); tm1_tree.insert(tm1_only.begin(), tm1_only.end(), tm1, vpm1);
tm2_tree.insert(faces2.begin(), faces2.end(), tm2, vpm2); tm2_tree.insert(faces2.begin(), faces2.end(), tm2, vpm2);

View File

@ -76,35 +76,6 @@ struct is_convertible_without_narrowing : details::is_convertible_without_narrow
template <typename From, typename To> template <typename From, typename To>
inline constexpr bool is_convertible_without_narrowing_v = is_convertible_without_narrowing<From, To>::value; inline constexpr bool is_convertible_without_narrowing_v = is_convertible_without_narrowing<From, To>::value;
#if 0
namespace is_complete_internals
{
template<class T>
std::enable_if_t<sizeof(T) != 0, std::true_type>
check(T(*)());
std::false_type check(...);
};
template<class T, class Base = decltype(is_complete_internals::check(typename std::enable_if<true, T(*)()>::type()))>
struct is_complete : Base { };
template <class T>
inline constexpr bool is_complete_v = is_complete<T>::value;
namespace is_complete_testsuite
{
struct S1;
static_assert(!is_complete<S1>::value, "error");
struct S2
{
static_assert(!is_complete<S2>::value, "error");
};
struct S3 {};
static_assert(is_complete<S3>::value, "error");
}
#endif
} // end namespace CGAL } // end namespace CGAL

View File

@ -38,6 +38,24 @@
namespace CGAL { namespace CGAL {
namespace internal_is_hashable {
using boost::hash_value;
template <typename T, typename = void>
struct Has_hash_value : std::false_type {};
template <typename T>
using hash_value_type = decltype(hash_value(std::declval<T>()));
template <typename T>
struct Has_hash_value<T, std::void_t<hash_value_type<T>>>
: std::is_convertible<hash_value_type<T>, std::size_t>
{};
}
template <typename T>
inline constexpr bool is_hashable_v =
internal_is_hashable::Has_hash_value<T>::value && std::is_default_constructible_v<std::hash<T>>;
template < template <
typename Key, typename Key,
typename T, typename T,

View File

@ -28,6 +28,7 @@ create_single_source_cgal_program("test_dispatch_output.cpp")
create_single_source_cgal_program("test_Flattening_iterator.cpp") create_single_source_cgal_program("test_Flattening_iterator.cpp")
create_single_source_cgal_program("test_Handle_with_policy.cpp") create_single_source_cgal_program("test_Handle_with_policy.cpp")
create_single_source_cgal_program("test_In_place_list.cpp") create_single_source_cgal_program("test_In_place_list.cpp")
create_single_source_cgal_program("test_is_hashable.cpp")
create_single_source_cgal_program("test_is_iterator.cpp") create_single_source_cgal_program("test_is_iterator.cpp")
create_single_source_cgal_program("test_is_streamable.cpp") create_single_source_cgal_program("test_is_streamable.cpp")
create_single_source_cgal_program("test_lexcompare_outputrange.cpp") create_single_source_cgal_program("test_lexcompare_outputrange.cpp")

View File

@ -0,0 +1,86 @@
// test partially generated by Github Copilot
#include <CGAL/unordered_flat_map.h>
#include <CGAL/Point_2.h>
#include <CGAL/Point_3.h>
#include <CGAL/Vector_2.h>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
#include <CGAL/Exact_predicates_exact_constructions_kernel.h>
#include <string>
#include <utility> // std::pair
// Test types without hash support
struct No_hash {};
struct No_default_constructible_hash {};
// Provide boost::hash_value for No_default_constructible_hash
namespace boost {
std::size_t hash_value(const No_default_constructible_hash&) { return 42; }
}
// But make std::hash not default constructible
namespace std {
template <>
struct hash<No_default_constructible_hash> {
hash() = delete; // Not default constructible
std::size_t operator()(const No_default_constructible_hash&) const { return 42; }
};
}
int main() {
using CGAL::is_hashable_v;
using SC = CGAL::Simple_cartesian<double>;
using Epick = CGAL::Exact_predicates_inexact_constructions_kernel;
using Epeck = CGAL::Exact_predicates_exact_constructions_kernel;
// Built-in types should be hashable
static_assert(is_hashable_v<int>);
static_assert(is_hashable_v<double>);
static_assert(is_hashable_v<float>);
static_assert(is_hashable_v<long>);
static_assert(is_hashable_v<std::string>);
// Types without hash support should not be hashable
static_assert(!is_hashable_v<No_hash>);
// Types with hash_value but non-default-constructible std::hash should not be hashable
static_assert(!is_hashable_v<No_default_constructible_hash>);
// CGAL kernel objects should be hashable (with Cartesian kernels)
static_assert(is_hashable_v<SC::Point_2>);
static_assert(is_hashable_v<SC::Point_3>);
static_assert(is_hashable_v<SC::Vector_2>);
static_assert(is_hashable_v<SC::Vector_3>);
static_assert(is_hashable_v<SC::Segment_2>);
static_assert(is_hashable_v<SC::Segment_3>);
static_assert(is_hashable_v<SC::Aff_transformation_2>);
static_assert(is_hashable_v<SC::Aff_transformation_3>);
static_assert(is_hashable_v<SC::Circle_2>);
static_assert(is_hashable_v<SC::Sphere_3>);
static_assert(is_hashable_v<SC::Iso_rectangle_2>);
static_assert(is_hashable_v<SC::Iso_cuboid_3>);
static_assert(is_hashable_v<SC::Weighted_point_2>);
static_assert(is_hashable_v<SC::Weighted_point_3>);
// Test with Epick kernel
static_assert(is_hashable_v<Epick::Point_2>);
static_assert(is_hashable_v<Epick::Point_3>);
static_assert(is_hashable_v<Epick::Vector_2>);
static_assert(is_hashable_v<Epick::Vector_3>);
// Test with Epeck kernel
static_assert(!is_hashable_v<Epeck::Point_2>);
static_assert(!is_hashable_v<Epeck::Point_3>);
static_assert(!is_hashable_v<Epeck::Vector_2>);
static_assert(!is_hashable_v<Epeck::Vector_3>);
// Bbox types should be hashable
static_assert(is_hashable_v<CGAL::Bbox_2>);
static_assert(is_hashable_v<CGAL::Bbox_3>);
// std::pair should not be hashable (no std::hash specialization in standard)
static_assert(!is_hashable_v<std::pair<int, int>>);
return 0;
}

View File

@ -29,7 +29,7 @@
\cgalPkgDependsOn{\ref PkgCombinatorialMaps} \cgalPkgDependsOn{\ref PkgCombinatorialMaps}
\cgalPkgBib{cgal:ddpt-thss} \cgalPkgBib{cgal:ddpt-thss}
\cgalPkgLicense{\ref licensesGPL "GPL"} \cgalPkgLicense{\ref licensesGPL "GPL"}
\cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,nofilefornow.zip} \cgalPkgDemo{2D Triangulations on Hyperbolic Surfaces,triangulation_on_hyperbolic_surface_2.zip}
\cgalPkgShortInfoEnd \cgalPkgShortInfoEnd
\cgalPkgDescriptionEnd \cgalPkgDescriptionEnd