mirror of https://github.com/CGAL/cgal
refactor debug API so that cdt_3_from_off can use the official API
This commit is contained in:
parent
b068e62ffb
commit
edbc32959d
|
|
@ -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
|
||||||
...
|
...
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,96 @@
|
||||||
|
|
||||||
namespace CGAL {
|
namespace CGAL {
|
||||||
|
|
||||||
namespace CDT_3::internal {
|
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() {
|
auto& tasks_manager() {
|
||||||
struct Tasks_manager {
|
struct Tasks_manager {
|
||||||
|
|
@ -80,6 +169,12 @@ auto& tasks_manager() {
|
||||||
__itt_task_begin(instance->cdt_3_domain, __itt_null, __itt_null, instance->task_handles[task_id]);
|
__itt_task_begin(instance->cdt_3_domain, __itt_null, __itt_null, instance->task_handles[task_id]);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
auto time() const {
|
||||||
|
return instance->timers[task_id].time();
|
||||||
|
}
|
||||||
|
auto time_ms() const {
|
||||||
|
return instance->timers[task_id].time() / 1000.;
|
||||||
|
}
|
||||||
~Scope_guard() {
|
~Scope_guard() {
|
||||||
instance->timers[task_id].stop();
|
instance->timers[task_id].stop();
|
||||||
#if CGAL_USE_ITT
|
#if CGAL_USE_ITT
|
||||||
|
|
@ -107,7 +202,9 @@ auto& tasks_manager() {
|
||||||
return instance;
|
return instance;
|
||||||
} // end auto& tasks_manager()
|
} // end auto& tasks_manager()
|
||||||
|
|
||||||
} // end namespace CDT_3::internal
|
} // end namespace internal
|
||||||
|
|
||||||
|
} // end namespace CDT_3
|
||||||
|
|
||||||
inline auto CDT_3_READ_INPUT_TASK_guard() {
|
inline auto CDT_3_READ_INPUT_TASK_guard() {
|
||||||
return CDT_3::internal::tasks_manager().READ_INPUT_TASK_guard();
|
return CDT_3::internal::tasks_manager().READ_INPUT_TASK_guard();
|
||||||
|
|
@ -155,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)
|
||||||
|
|
@ -215,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)));
|
||||||
}
|
}
|
||||||
|
|
@ -274,7 +371,7 @@ 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(debug_subconstraints_to_conform()) {
|
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";
|
||||||
}
|
}
|
||||||
|
|
@ -321,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));
|
||||||
}
|
}
|
||||||
|
|
@ -372,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);
|
||||||
}
|
}
|
||||||
|
|
@ -408,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();
|
||||||
|
|
@ -421,137 +518,15 @@ public:
|
||||||
segment_vertex_epsilon = epsilon;
|
segment_vertex_epsilon = epsilon;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool debug_Steiner_points() const {
|
CDT_3::Debug_options& debug() { return debug_options_; }
|
||||||
return debug_flags[static_cast<int>(Debug_flags::Steiner_points)];
|
const CDT_3::Debug_options& debug() const { return debug_options_; }
|
||||||
}
|
|
||||||
|
|
||||||
void debug_Steiner_points(bool b) {
|
// Backward compatibility wrappers (deprecated, use debug().method() instead)
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::Steiner_points), b);
|
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); }
|
||||||
bool debug_input_faces() const {
|
bool use_finite_edges_map() const { return update_all_finite_edges_ && debug_options_.use_finite_edges_map_flag(); }
|
||||||
return debug_flags[static_cast<int>(Debug_flags::input_faces)];
|
void use_finite_edges_map(bool b) { debug_options_.use_finite_edges_map(b); }
|
||||||
}
|
|
||||||
|
|
||||||
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 debug_subconstraints_to_conform() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_subconstraints_to_conform)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_subconstraints_to_conform(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_subconstraints_to_conform), 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_verbose_special_cases() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::verbose_special_cases)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_verbose_special_cases(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::verbose_special_cases), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_encroaching_vertices() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_encroaching_vertices)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_encroaching_vertices(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_encroaching_vertices), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_conforming_validation() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_conforming_validation)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_conforming_validation(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_conforming_validation), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_constraint_hierarchy() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_constraint_hierarchy)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_constraint_hierarchy(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_constraint_hierarchy), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_geometric_errors() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_geometric_errors)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_geometric_errors(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_geometric_errors), b);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool debug_polygon_insertion() const {
|
|
||||||
return debug_flags[static_cast<int>(Debug_flags::debug_polygon_insertion)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void debug_polygon_insertion(bool b) {
|
|
||||||
debug_flags.set(static_cast<int>(Debug_flags::debug_polygon_insertion), 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)
|
||||||
|
|
@ -579,14 +554,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";
|
||||||
|
|
@ -606,7 +581,7 @@ 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 constexpr (cdt_3_can_use_cxx20_format()) if(debug_conforming_validation()) {
|
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),
|
||||||
|
|
@ -622,7 +597,7 @@ public:
|
||||||
Vertex_handle vb,
|
Vertex_handle vb,
|
||||||
Vertex_handle min_vertex,
|
Vertex_handle min_vertex,
|
||||||
double min_dist,
|
double min_dist,
|
||||||
Check_distance distance_type)
|
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();
|
||||||
|
|
@ -643,6 +618,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());
|
||||||
|
|
@ -748,7 +743,7 @@ protected:
|
||||||
if(!constraint_hierarchy.is_subconstraint(va, vb)) {
|
if(!constraint_hierarchy.is_subconstraint(va, vb)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if(debug_subconstraints_to_conform()) {
|
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";
|
||||||
}
|
}
|
||||||
|
|
@ -794,7 +789,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) << " ] ";
|
||||||
|
|
@ -830,7 +825,7 @@ 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(debug_constraint_hierarchy()) {
|
if(debug().constraint_hierarchy()) {
|
||||||
std::cerr << "constraint " << static_cast<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";
|
||||||
}
|
}
|
||||||
|
|
@ -891,7 +886,7 @@ protected:
|
||||||
encroaching_vertices.insert(v);
|
encroaching_vertices.insert(v);
|
||||||
};
|
};
|
||||||
auto fill_encroaching_vertices = [&](const auto simplex) {
|
auto fill_encroaching_vertices = [&](const auto simplex) {
|
||||||
if(debug_encroaching_vertices()) {
|
if(debug().encroaching_vertices()) {
|
||||||
std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n';
|
std::cerr << " - " << IO::oformat(simplex, With_point_tag{}) << '\n';
|
||||||
}
|
}
|
||||||
auto visit_cell = [&](Cell_handle cell) {
|
auto visit_cell = [&](Cell_handle cell) {
|
||||||
|
|
@ -937,7 +932,7 @@ 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(debug_geometric_errors()) {
|
if(debug().geometric_errors()) {
|
||||||
debug_dump("bug-through-vertex");
|
debug_dump("bug-through-vertex");
|
||||||
}
|
}
|
||||||
CGAL_error();
|
CGAL_error();
|
||||||
|
|
@ -949,7 +944,7 @@ 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(debug_encroaching_vertices()) {
|
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(),
|
||||||
|
|
@ -965,7 +960,7 @@ protected:
|
||||||
this->tr().point(v),
|
this->tr().point(v),
|
||||||
pb) == ACUTE;
|
pb) == ACUTE;
|
||||||
});
|
});
|
||||||
if(debug_encroaching_vertices()) {
|
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)
|
||||||
|
|
@ -1001,7 +996,7 @@ protected:
|
||||||
return {midpoint_functor(pa, pb), va->cell(), va};
|
return {midpoint_functor(pa, pb), va->cell(), va};
|
||||||
}
|
}
|
||||||
|
|
||||||
if(debug_encroaching_vertices()) {
|
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";
|
||||||
}
|
}
|
||||||
|
|
@ -1102,7 +1097,7 @@ protected:
|
||||||
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;
|
double segment_vertex_epsilon = 1e-8;
|
||||||
std::optional<double> max_bbox_edge_length;
|
mutable 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};
|
||||||
|
|
@ -1134,27 +1129,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,
|
|
||||||
debug_subconstraints_to_conform,
|
|
||||||
verbose_special_cases,
|
|
||||||
debug_encroaching_vertices,
|
|
||||||
debug_conforming_validation,
|
|
||||||
debug_constraint_hierarchy,
|
|
||||||
debug_geometric_errors,
|
|
||||||
debug_polygon_insertion,
|
|
||||||
nb_of_flags
|
|
||||||
};
|
|
||||||
std::bitset<static_cast<int>(Debug_flags::nb_of_flags)> debug_flags{};
|
|
||||||
bool is_Delaunay = true;
|
bool is_Delaunay = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1162,6 +1137,5 @@ protected:
|
||||||
|
|
||||||
#endif // not DOXYGEN_RUNNING
|
#endif // not DOXYGEN_RUNNING
|
||||||
|
|
||||||
#
|
|
||||||
|
|
||||||
#endif // CGAL_CONFORMING_DELAUNAY_TRIANGULATION_3_H
|
#endif // CGAL_CONFORMING_DELAUNAY_TRIANGULATION_3_H
|
||||||
|
|
|
||||||
|
|
@ -9,8 +9,8 @@
|
||||||
//
|
//
|
||||||
// Author(s) : Laurent Rineau
|
// Author(s) : Laurent Rineau
|
||||||
|
|
||||||
#ifndef CGAL_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
#ifndef CGAL_CONFORMING_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
||||||
#define CGAL_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
#define CGAL_CONFORMING_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
||||||
|
|
||||||
#include <CGAL/license/Constrained_triangulation_3.h>
|
#include <CGAL/license/Constrained_triangulation_3.h>
|
||||||
|
|
||||||
|
|
@ -66,6 +66,7 @@
|
||||||
#include <boost/container/map.hpp>
|
#include <boost/container/map.hpp>
|
||||||
#include <boost/container/small_vector.hpp>
|
#include <boost/container/small_vector.hpp>
|
||||||
#include <boost/dynamic_bitset.hpp>
|
#include <boost/dynamic_bitset.hpp>
|
||||||
|
#include <boost/graph/adjacency_list.hpp>
|
||||||
#include <boost/graph/breadth_first_search.hpp>
|
#include <boost/graph/breadth_first_search.hpp>
|
||||||
#include <boost/graph/filtered_graph.hpp>
|
#include <boost/graph/filtered_graph.hpp>
|
||||||
#include <boost/iterator/filter_iterator.hpp>
|
#include <boost/iterator/filter_iterator.hpp>
|
||||||
|
|
@ -79,6 +80,7 @@
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <map>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
@ -578,6 +580,9 @@ public:
|
||||||
#endif // not DOXYGEN_RUNNING
|
#endif // not DOXYGEN_RUNNING
|
||||||
using size_type = typename Triangulation::size_type;
|
using size_type = typename Triangulation::size_type;
|
||||||
|
|
||||||
|
/// \cond SKIP_IN_MANUAL
|
||||||
|
CDT_3_impl& impl() { return cdt_impl; }
|
||||||
|
/// /endcond
|
||||||
public:
|
public:
|
||||||
/** \name Constructors
|
/** \name Constructors
|
||||||
@{
|
@{
|
||||||
|
|
@ -647,6 +652,7 @@ public:
|
||||||
|
|
||||||
auto mesh_vp_map = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
auto mesh_vp_map = choose_parameter(get_parameter(np, internal_np::vertex_point),
|
||||||
get_const_property_map(vertex_point, mesh));
|
get_const_property_map(vertex_point, mesh));
|
||||||
|
this->debug() = choose_parameter(get_parameter(np, internal_np::debug), CDT_3::Debug_options{});
|
||||||
|
|
||||||
using graph_traits = boost::graph_traits<PolygonMesh>;
|
using graph_traits = boost::graph_traits<PolygonMesh>;
|
||||||
using vertex_descriptor = typename graph_traits::vertex_descriptor;
|
using vertex_descriptor = typename graph_traits::vertex_descriptor;
|
||||||
|
|
@ -779,6 +785,11 @@ public:
|
||||||
|
|
||||||
cdt_impl.insert_vertices_range(vertices(mesh), mesh_vp_map, tr_vertex_pmap,
|
cdt_impl.insert_vertices_range(vertices(mesh), mesh_vp_map, tr_vertex_pmap,
|
||||||
p::vertex_is_constrained_map(v_selected_map));
|
p::vertex_is_constrained_map(v_selected_map));
|
||||||
|
|
||||||
|
cdt_impl.template validate_distances_and_report<has_plc_face_id>(mesh, patch_edges, tr_vertex_pmap);
|
||||||
|
|
||||||
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_CONFORMING_TASK_guard();
|
||||||
for(auto&& edges : patch_edges) {
|
for(auto&& edges : patch_edges) {
|
||||||
auto index = &edges - &patch_edges[0];
|
auto index = &edges - &patch_edges[0];
|
||||||
auto face_index_opt =
|
auto face_index_opt =
|
||||||
|
|
@ -787,19 +798,44 @@ public:
|
||||||
auto vh = get(tr_vertex_pmap, vd);
|
auto vh = get(tr_vertex_pmap, vd);
|
||||||
cdt_impl.mark_vertex_as_isolated_in_a_constrained_face(vh, face_index_opt);
|
cdt_impl.mark_vertex_as_isolated_in_a_constrained_face(vh, face_index_opt);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
cdt_impl.insert_vertices_range(vertices(mesh), mesh_vp_map, tr_vertex_pmap);
|
cdt_impl.insert_vertices_range(vertices(mesh), mesh_vp_map, tr_vertex_pmap);
|
||||||
|
cdt_impl.template validate_distances_and_report<has_plc_face_id>(mesh, patch_edges, tr_vertex_pmap);
|
||||||
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_CONFORMING_TASK_guard();
|
||||||
|
|
||||||
for(auto f : faces(mesh)) {
|
for(auto f : faces(mesh)) {
|
||||||
auto face_vertices = vertices_around_face(halfedge(f, mesh), mesh);
|
auto face_vertices = vertices_around_face(halfedge(f, mesh), mesh);
|
||||||
auto range_of_vertices = CGAL::make_transform_range_from_property_map(face_vertices, tr_vertex_pmap);
|
auto range_of_vertices = CGAL::make_transform_range_from_property_map(face_vertices, tr_vertex_pmap);
|
||||||
cdt_impl.insert_constrained_face(range_of_vertices, false);
|
cdt_impl.insert_constrained_face(range_of_vertices, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_CONFORMING_TASK_guard();
|
||||||
cdt_impl.restore_Delaunay();
|
cdt_impl.restore_Delaunay();
|
||||||
|
if(cdt_impl.debug().display_statistics()) {
|
||||||
|
std::cout << "[timings] restored Delaunay in " << task_guard.time_ms() << " ms\n";
|
||||||
|
std::cout << "Number of vertices after Delaunay: " << cdt_impl.number_of_vertices() << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto& visitor = parameters::get_parameter(np, internal_np::visitor);
|
||||||
|
if constexpr (!std::is_same_v<CGAL::cpp20::remove_cvref_t<decltype(visitor)>, internal_np::Param_not_found>) {
|
||||||
|
visitor(*this);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_CDT_TASK_guard();
|
||||||
cdt_impl.restore_constrained_Delaunay();
|
cdt_impl.restore_constrained_Delaunay();
|
||||||
|
if(cdt_impl.debug().display_statistics()) {
|
||||||
|
std::cout << "[timings] restored constrained Delaunay in " << task_guard.time_ms() << " ms\n";
|
||||||
|
std::cout << "Number of vertices after CDT: " << cdt_impl.number_of_vertices() << "\n\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// std::cerr << cdt_3_format("cdt_impl: {} vertices, {} cells\n", cdt_impl.number_of_vertices(),
|
// std::cerr << cdt_3_format("cdt_impl: {} vertices, {} cells\n", cdt_impl.number_of_vertices(),
|
||||||
// cdt_impl.number_of_cells());
|
// cdt_impl.number_of_cells());
|
||||||
}
|
}
|
||||||
|
|
@ -1042,15 +1078,58 @@ public:
|
||||||
/// \name Checking
|
/// \name Checking
|
||||||
/// These methods are mainly a debugging help for the users of advanced features.
|
/// These methods are mainly a debugging help for the users of advanced features.
|
||||||
/// @{
|
/// @{
|
||||||
|
/// @}
|
||||||
|
|
||||||
/*!
|
// -----------------------
|
||||||
\brief returns whether the triangulation is valid.
|
// Debug and advanced control
|
||||||
When `verbose` is set to `true`, messages describing the first invalidity encountered are
|
// -----------------------
|
||||||
printed.
|
public:
|
||||||
|
/**
|
||||||
|
* \brief Access debug options.
|
||||||
|
*
|
||||||
|
* Returns a reference to the debug options object that controls various debugging
|
||||||
|
* and algorithmic behaviors. Use this to configure debug flags:
|
||||||
|
*
|
||||||
|
* \code
|
||||||
|
* ccdt.debug().Steiner_points(true);
|
||||||
|
* ccdt.debug().input_faces(true);
|
||||||
|
* \endcode
|
||||||
*/
|
*/
|
||||||
|
CDT_3::Debug_options& debug() { return cdt_impl.debug(); }
|
||||||
|
const CDT_3::Debug_options& debug() const { return cdt_impl.debug(); }
|
||||||
|
|
||||||
|
// Algorithmic switches and tolerances
|
||||||
|
void use_older_cavity_algorithm(bool b) { cdt_impl.use_older_cavity_algorithm(b); }
|
||||||
|
void use_finite_edges_map(bool b) { cdt_impl.use_finite_edges_map(b); }
|
||||||
|
void set_segment_vertex_epsilon(double eps) { cdt_impl.set_segment_vertex_epsilon(eps); }
|
||||||
|
|
||||||
|
// Validation helpers
|
||||||
|
bool is_conforming() const { return cdt_impl.is_conforming(); }
|
||||||
bool is_valid(bool verbose = false) const { return cdt_impl.is_valid(verbose); }
|
bool is_valid(bool verbose = false) const { return cdt_impl.is_valid(verbose); }
|
||||||
|
|
||||||
/// @}
|
// IO helpers for debugging
|
||||||
|
bool write_missing_segments_file(std::ostream& out) { return cdt_impl.write_missing_segments_file(out); }
|
||||||
|
void write_all_segments_file(std::ostream& out) { cdt_impl.write_all_segments_file(out); }
|
||||||
|
|
||||||
|
// Lightweight accessors used by tests/tools
|
||||||
|
size_type number_of_vertices() const { return static_cast<size_type>(cdt_impl.number_of_vertices()); }
|
||||||
|
size_type number_of_cells() const { return triangulation().number_of_cells(); }
|
||||||
|
|
||||||
|
// Ranges and utilities for post-processing (e.g., dumping Steiner vertices)
|
||||||
|
auto finite_vertex_handles() const { return cdt_impl.finite_vertex_handles(); }
|
||||||
|
auto finite_cell_handles() const { return triangulation().finite_cell_handles(); }
|
||||||
|
auto all_cell_handles() const { return triangulation().all_cell_handles(); }
|
||||||
|
auto finite_facets() const { return triangulation().finite_facets(); }
|
||||||
|
typename Triangulation::Cell_handle infinite_cell() const { return triangulation().infinite_cell(); }
|
||||||
|
|
||||||
|
auto ancestors_of_Steiner_vertex_on_edge(Vertex_handle v) const
|
||||||
|
{ return cdt_impl.ancestors_of_Steiner_vertex_on_edge(v); }
|
||||||
|
|
||||||
|
// Write facets (for debugging/output)
|
||||||
|
template<typename CDT, typename FacetRange>
|
||||||
|
void write_facets(std::ostream& out, const CDT& cdt, FacetRange&& facets) const {
|
||||||
|
cdt_impl.write_facets(out, cdt, std::forward<FacetRange>(facets));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef DOXYGEN_RUNNING
|
#ifndef DOXYGEN_RUNNING
|
||||||
|
|
@ -1423,7 +1502,7 @@ public:
|
||||||
|
|
||||||
this->new_vertex(p_vh);
|
this->new_vertex(p_vh);
|
||||||
|
|
||||||
CGAL_assume(!this->debug_validity() || this->is_valid(true));
|
CGAL_assume(!this->debug().validity() || this->is_valid(true));
|
||||||
|
|
||||||
return p_vh;
|
return p_vh;
|
||||||
}
|
}
|
||||||
|
|
@ -1471,6 +1550,8 @@ public:
|
||||||
VertexHandleMap tr_vertex_pmap,
|
VertexHandleMap tr_vertex_pmap,
|
||||||
const NamedParameters& np = parameters::default_values())
|
const NamedParameters& np = parameters::default_values())
|
||||||
{
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_INSERT_VERTICES_TASK_guard();
|
||||||
|
|
||||||
using parameters::get_parameter;
|
using parameters::get_parameter;
|
||||||
using parameters::is_default_parameter;
|
using parameters::is_default_parameter;
|
||||||
|
|
||||||
|
|
@ -1495,6 +1576,13 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
add_bbox_points_if_not_dimension_3();
|
add_bbox_points_if_not_dimension_3();
|
||||||
|
|
||||||
|
if(this->debug().display_statistics()) {
|
||||||
|
|
||||||
|
std::cout << "[timings] inserted vertices in "
|
||||||
|
<< task_guard.time_ms() << " ms\n";
|
||||||
|
std::cout << "Number of vertices: " << this->number_of_vertices() << "\n\n";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1663,7 +1751,7 @@ public:
|
||||||
|
|
||||||
restore_Delaunay = false;
|
restore_Delaunay = false;
|
||||||
|
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
std::cerr << "insert_constrained_face (" << std::size(vertex_handles) << " vertices):\n";
|
std::cerr << "insert_constrained_face (" << std::size(vertex_handles) << " vertices):\n";
|
||||||
for(auto v: vertex_handles) {
|
for(auto v: vertex_handles) {
|
||||||
std::cerr << " - " << this->display_vert(v) << '\n';
|
std::cerr << " - " << this->display_vert(v) << '\n';
|
||||||
|
|
@ -1703,7 +1791,7 @@ public:
|
||||||
}
|
}
|
||||||
} while(circ != circ_end);
|
} while(circ != circ_end);
|
||||||
|
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
std::stringstream filename;
|
std::stringstream filename;
|
||||||
filename << "dump-input-face-" << polygon_contraint_id << "_polygon_" << borders.size() - 1 << ".polylines.txt";
|
filename << "dump-input-face-" << polygon_contraint_id << "_polygon_" << borders.size() - 1 << ".polylines.txt";
|
||||||
std::ofstream os(filename.str());
|
std::ofstream os(filename.str());
|
||||||
|
|
@ -1748,7 +1836,7 @@ public:
|
||||||
face_constraint_misses_subfaces.resize(face_cdt_2.size());
|
face_constraint_misses_subfaces.resize(face_cdt_2.size());
|
||||||
extra_isolated_vertices.resize(face_cdt_2.size());
|
extra_isolated_vertices.resize(face_cdt_2.size());
|
||||||
}
|
}
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
std::cerr << "insert_constrained_face return the polygon_contraint_id: " << polygon_contraint_id << '\n';
|
std::cerr << "insert_constrained_face return the polygon_contraint_id: " << polygon_contraint_id << '\n';
|
||||||
}
|
}
|
||||||
return polygon_contraint_id;
|
return polygon_contraint_id;
|
||||||
|
|
@ -1817,10 +1905,181 @@ public:
|
||||||
extra_isolated_vertices[face_index].insert(vh);
|
extra_isolated_vertices[face_index].insert(vh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Min_distance_result {
|
||||||
|
double min_distance;
|
||||||
|
std::array<Vertex_handle, 2> vertices_of_min_edge;
|
||||||
|
};
|
||||||
|
|
||||||
|
Min_distance_result compute_minimum_vertex_distance() const {
|
||||||
|
const auto& tr = *this;
|
||||||
|
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
||||||
|
auto [min_sq_distance, min_edge] =
|
||||||
|
(std::ranges::min)(tr.finite_edges() | std::views::transform([&](auto edge) {
|
||||||
|
return std::make_pair(tr.segment(edge).squared_length(), edge);
|
||||||
|
}));
|
||||||
|
#else
|
||||||
|
auto transform_fct = [&](auto edge) { return std::make_pair(tr.segment(edge).squared_length(), edge); };
|
||||||
|
auto min_p = transform_fct(*tr.finite_edges_begin());
|
||||||
|
for (auto ite=tr.finite_edges_begin(); ite!=tr.finite_edges_end(); ++ite)
|
||||||
|
{
|
||||||
|
auto p = transform_fct(*ite);
|
||||||
|
if (p < min_p)
|
||||||
|
p = min_p;
|
||||||
|
}
|
||||||
|
auto [min_sq_distance, min_edge] = min_p;
|
||||||
|
#endif
|
||||||
|
auto min_distance = CGAL::to_double(CGAL::approximate_sqrt(min_sq_distance));
|
||||||
|
auto vertices_of_min_edge = this->vertices(min_edge);
|
||||||
|
|
||||||
|
return {min_distance, vertices_of_min_edge};
|
||||||
|
}
|
||||||
|
|
||||||
|
static void print_minimum_distance_info(const Min_distance_result& min_dist) {
|
||||||
|
std::cout << "Min distance between vertices: " << min_dist.min_distance << '\n'
|
||||||
|
<< " between vertices: : "
|
||||||
|
<< CGAL::IO::oformat(min_dist.vertices_of_min_edge[0], CGAL::With_point_tag{}) << " "
|
||||||
|
<< CGAL::IO::oformat(min_dist.vertices_of_min_edge[1], CGAL::With_point_tag{}) << "\n\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Constraint_distance_result {
|
||||||
|
double min_distance;
|
||||||
|
Vertex_handle min_va, min_vb, min_vertex;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename BordersOfPatches, typename VertexPointMap>
|
||||||
|
Constraint_distance_result
|
||||||
|
compute_constraint_vertex_distances_from_patches_borders(const BordersOfPatches& patch_edges,
|
||||||
|
const VertexPointMap& tr_vertex_pmap) const
|
||||||
|
{
|
||||||
|
|
||||||
|
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
||||||
|
auto edge_results = patch_edges
|
||||||
|
| std::views::join
|
||||||
|
| std::views::transform([&](const auto& edge_pair) {
|
||||||
|
auto [vda, vdb] = edge_pair;
|
||||||
|
auto va = get(tr_vertex_pmap, vda);
|
||||||
|
auto vb = get(tr_vertex_pmap, vdb);
|
||||||
|
auto [min_dist, min_v] = this->min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
|
return std::make_tuple(CGAL::to_double(min_dist), va, vb, min_v);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto min_result = std::ranges::min_element(edge_results, {}, [](const auto& tuple) {
|
||||||
|
return std::get<0>(tuple);
|
||||||
|
});
|
||||||
|
|
||||||
|
auto [min_distance, min_va, min_vb, min_vertex] = *min_result;
|
||||||
|
#else
|
||||||
|
double min_distance = (std::numeric_limits<double>::max)();
|
||||||
|
Vertex_handle min_va, min_vb, min_vertex;
|
||||||
|
|
||||||
|
for(const auto& edges : patch_edges) {
|
||||||
|
for(auto [vda, vdb]: edges) {
|
||||||
|
auto va = get(tr_vertex_pmap, vda);
|
||||||
|
auto vb = get(tr_vertex_pmap, vdb);
|
||||||
|
auto [min_dist, min_v] = this->min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
|
if(min_dist < min_distance) {
|
||||||
|
min_distance = CGAL::to_double(min_dist);
|
||||||
|
min_va = va;
|
||||||
|
min_vb = vb;
|
||||||
|
min_vertex = min_v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return {min_distance, min_va, min_vb, min_vertex};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Mesh, typename VertexPointMap>
|
||||||
|
Constraint_distance_result
|
||||||
|
compute_constraint_vertex_distances_from_faces(const Mesh& mesh, const VertexPointMap& tr_vertex_pmap) const {
|
||||||
|
double min_distance = (std::numeric_limits<double>::max)();
|
||||||
|
Vertex_handle min_va, min_vb, min_vertex;
|
||||||
|
|
||||||
|
for(auto face_descriptor : faces(mesh)) {
|
||||||
|
auto he = halfedge(face_descriptor, mesh);
|
||||||
|
const auto end = he;
|
||||||
|
do {
|
||||||
|
auto va = get(tr_vertex_pmap, source(he, mesh));
|
||||||
|
auto vb = get(tr_vertex_pmap, target(he, mesh));
|
||||||
|
auto [min_dist, min_v] = this->min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
||||||
|
if(min_dist < min_distance) {
|
||||||
|
min_distance = CGAL::to_double(min_dist);
|
||||||
|
min_va = va;
|
||||||
|
min_vb = vb;
|
||||||
|
min_vertex = min_v;
|
||||||
|
}
|
||||||
|
he = next(he, mesh);
|
||||||
|
} while((he = next(he, mesh)) != end);
|
||||||
|
}
|
||||||
|
|
||||||
|
return {min_distance, min_va, min_vb, min_vertex};
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool merged_facets, typename Mesh, typename BordersOfPatches, typename VertexPointMap>
|
||||||
|
void validate_constraint_vertex_distances_or_throw(const Mesh& mesh,
|
||||||
|
const BordersOfPatches& patch_edges,
|
||||||
|
const VertexPointMap& tr_vertex_pmap)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto [min_distance, min_va, min_vb, min_vertex] =
|
||||||
|
merged_facets ? compute_constraint_vertex_distances_from_patches_borders(patch_edges, tr_vertex_pmap)
|
||||||
|
: compute_constraint_vertex_distances_from_faces(mesh, tr_vertex_pmap);
|
||||||
|
|
||||||
|
if(this->debug().display_statistics()) {
|
||||||
|
std::cout << "Min distance between constraint segment and vertex: " << min_distance << '\n'
|
||||||
|
<< " between segment : "
|
||||||
|
<< CGAL::IO::oformat(min_va, CGAL::With_point_tag{}) << " "
|
||||||
|
<< CGAL::IO::oformat(min_vb, CGAL::With_point_tag{}) << '\n'
|
||||||
|
<< " and vertex : "
|
||||||
|
<< CGAL::IO::oformat(min_vertex, CGAL::With_point_tag{}) << "\n\n";
|
||||||
|
}
|
||||||
|
this->check_segment_vertex_distance_or_throw(min_va, min_vb, min_vertex, min_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool merged_facets, typename Mesh, typename BordersOfPatches, typename VertexPointMap>
|
||||||
|
void validate_vertex_vertex_distances_or_throw([[maybe_unused]] const Mesh& mesh,
|
||||||
|
[[maybe_unused]] const BordersOfPatches& patch_edges,
|
||||||
|
[[maybe_unused]] const VertexPointMap& tr_vertex_pmap)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto result = this->compute_minimum_vertex_distance();
|
||||||
|
|
||||||
|
if(this->debug().display_statistics()) {
|
||||||
|
std::cout << "Min distance between vertices: " << result.min_distance << '\n'
|
||||||
|
<< " between vertices : "
|
||||||
|
<< CGAL::IO::oformat(result.vertices_of_min_edge[0], CGAL::With_point_tag{}) << " "
|
||||||
|
<< CGAL::IO::oformat(result.vertices_of_min_edge[1], CGAL::With_point_tag{}) << "\n\n";
|
||||||
|
}
|
||||||
|
this->check_vertex_vertex_distance_or_throw(result.vertices_of_min_edge[0],
|
||||||
|
result.vertices_of_min_edge[1],
|
||||||
|
result.min_distance);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <bool merged_facets, typename Mesh, typename BordersOfPatches, typename VertexPointMap>
|
||||||
|
void validate_distances_and_report(const Mesh& mesh,
|
||||||
|
const BordersOfPatches& patch_edges,
|
||||||
|
const VertexPointMap& tr_vertex_pmap)
|
||||||
|
{
|
||||||
|
auto task_guard = CGAL::CDT_3_COMPUTE_DISTANCES_TASK_guard();
|
||||||
|
if(this->debug().segment_vertex_epsilon() > 0) {
|
||||||
|
this->validate_constraint_vertex_distances_or_throw<merged_facets>(mesh, patch_edges, tr_vertex_pmap);
|
||||||
|
}
|
||||||
|
if(this->debug().vertex_vertex_epsilon() > 0) {
|
||||||
|
this->validate_vertex_vertex_distances_or_throw<merged_facets>(mesh, patch_edges, tr_vertex_pmap);
|
||||||
|
}
|
||||||
|
if(this->debug().display_statistics()) {
|
||||||
|
std::cout << "[timings] compute distances in "
|
||||||
|
<< task_guard.time_ms() << " ms\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void set_mark(Vertex_handle v, Vertex_marker m) {
|
void set_mark(Vertex_handle v, Vertex_marker m) {
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << " set_mark(" << this->display_vert(v) << ", ";
|
std::cerr << " set_mark(" << this->display_vert(v) << ", ";
|
||||||
switch(m) {
|
switch(m) {
|
||||||
case Vertex_marker::CLEAR: std::cerr << "CLEAR"; break;
|
case Vertex_marker::CLEAR: std::cerr << "CLEAR"; break;
|
||||||
|
|
@ -1900,7 +2159,7 @@ private:
|
||||||
return vec_of_handles;
|
return vec_of_handles;
|
||||||
});
|
});
|
||||||
|
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
std::cerr << "Polygon #" << polygon_contraint_id << " normal is: " << cdt_2.geom_traits().normal() << '\n';
|
std::cerr << "Polygon #" << polygon_contraint_id << " normal is: " << cdt_2.geom_traits().normal() << '\n';
|
||||||
auto filename = "dump_cdt_2_polygons_" + std::to_string(polygon_contraint_id) + ".polylines.txt";
|
auto filename = "dump_cdt_2_polygons_" + std::to_string(polygon_contraint_id) + ".polylines.txt";
|
||||||
std::cerr << " dumping it to \"" << filename << "\".\n";
|
std::cerr << " dumping it to \"" << filename << "\".\n";
|
||||||
|
|
@ -1917,7 +2176,7 @@ private:
|
||||||
// create and fill the 2D triangulation
|
// create and fill the 2D triangulation
|
||||||
{
|
{
|
||||||
auto insert_constraint_in_cdt_2 = [&](const auto& va, const auto& vb) {
|
auto insert_constraint_in_cdt_2 = [&](const auto& va, const auto& vb) {
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
std::cerr << "cdt_2.insert_constraint ("
|
std::cerr << "cdt_2.insert_constraint ("
|
||||||
<< tr().point(va->info().vertex_handle_3d)
|
<< tr().point(va->info().vertex_handle_3d)
|
||||||
<< " , "
|
<< " , "
|
||||||
|
|
@ -2032,7 +2291,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // end of marking inside/outside
|
} // end of marking inside/outside
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
int counter = 0;
|
int counter = 0;
|
||||||
for(const auto fh: cdt_2.finite_face_handles()) {
|
for(const auto fh: cdt_2.finite_face_handles()) {
|
||||||
if(!fh->info().is_outside_the_face) ++counter;
|
if(!fh->info().is_outside_the_face) ++counter;
|
||||||
|
|
@ -2066,7 +2325,7 @@ private:
|
||||||
if(this->is_edge(vb_3d, vd_3d)) {
|
if(this->is_edge(vb_3d, vd_3d)) {
|
||||||
// let's insert the diagonal [bd] in the CDT_2
|
// let's insert the diagonal [bd] in the CDT_2
|
||||||
cdt_2.insert_constraint(vb, vd);
|
cdt_2.insert_constraint(vb, vd);
|
||||||
if(this->debug_verbose_special_cases()) {
|
if(this->debug().verbose_special_cases()) {
|
||||||
std::cerr << "NOTE: CDT_2 has 4 vertices. Flip the diagonal\n";
|
std::cerr << "NOTE: CDT_2 has 4 vertices. Flip the diagonal\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2146,7 +2405,7 @@ private:
|
||||||
border_edges.emplace_back(c, i, j);
|
border_edges.emplace_back(c, i, j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "region size is: " << fh_region.size() << "\n";
|
std::cerr << "region size is: " << fh_region.size() << "\n";
|
||||||
std::cerr << "region border size is: " << border_edges.size() << "\n";
|
std::cerr << "region border size is: " << border_edges.size() << "\n";
|
||||||
}
|
}
|
||||||
|
|
@ -2292,7 +2551,7 @@ private:
|
||||||
|
|
||||||
std::set<std::pair<Vertex_handle, Vertex_handle>> non_intersecting_edges_set;
|
std::set<std::pair<Vertex_handle, Vertex_handle>> non_intersecting_edges_set;
|
||||||
|
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
expensive_debug_dump_tetrahedra_intersect_region(face_index, region_index, cdt_2, fh_region);
|
expensive_debug_dump_tetrahedra_intersect_region(face_index, region_index, cdt_2, fh_region);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2334,7 +2593,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "...use edges of the border facets to unify sets\n";
|
std::cerr << "...use edges of the border facets to unify sets\n";
|
||||||
}
|
}
|
||||||
for(auto facet: facets_of_border) {
|
for(auto facet: facets_of_border) {
|
||||||
|
|
@ -2350,7 +2609,7 @@ private:
|
||||||
}
|
}
|
||||||
|
|
||||||
if(vertices_of_cavity_union_find.number_of_sets() > 2) {
|
if(vertices_of_cavity_union_find.number_of_sets() > 2) {
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "...use non-intersecting edges to unify sets, until we have at most 2 sets\n";
|
std::cerr << "...use non-intersecting edges to unify sets, until we have at most 2 sets\n";
|
||||||
}
|
}
|
||||||
for(auto c : cr_intersecting_cells) {
|
for(auto c : cr_intersecting_cells) {
|
||||||
|
|
@ -2400,13 +2659,13 @@ private:
|
||||||
return std::make_pair(Vertex_handle{}, Facet{});
|
return std::make_pair(Vertex_handle{}, Facet{});
|
||||||
});
|
});
|
||||||
CGAL_assume(vertex_above != Vertex_handle{});
|
CGAL_assume(vertex_above != Vertex_handle{});
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "The vertex above the region is " << IO::oformat(vertex_above, with_point_and_info) << "\n";
|
std::cerr << "The vertex above the region is " << IO::oformat(vertex_above, with_point_and_info) << "\n";
|
||||||
}
|
}
|
||||||
// if there are still more than 2 sets, we need to propagate the information
|
// if there are still more than 2 sets, we need to propagate the information
|
||||||
// using a DFS on the border facets
|
// using a DFS on the border facets
|
||||||
if(vertices_of_cavity_union_find.number_of_sets() > 2) {
|
if(vertices_of_cavity_union_find.number_of_sets() > 2) {
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "...propagate the information using a DFS on the border facets\n";
|
std::cerr << "...propagate the information using a DFS on the border facets\n";
|
||||||
}
|
}
|
||||||
const auto border_edges_set = std::invoke([&] {
|
const auto border_edges_set = std::invoke([&] {
|
||||||
|
|
@ -2561,7 +2820,7 @@ private:
|
||||||
|
|
||||||
// classify the facets of the border of the cavity
|
// classify the facets of the border of the cavity
|
||||||
for(auto facet: facets_of_border) {
|
for(auto facet: facets_of_border) {
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
debug_output_facet_vertices({facet});
|
debug_output_facet_vertices({facet});
|
||||||
}
|
}
|
||||||
for(auto v: tr().vertices(facet)) {
|
for(auto v: tr().vertices(facet)) {
|
||||||
|
|
@ -2579,7 +2838,7 @@ private:
|
||||||
clear_marks(vertices_of_lower_cavity, Vertex_marker::CAVITY_BELOW);
|
clear_marks(vertices_of_lower_cavity, Vertex_marker::CAVITY_BELOW);
|
||||||
} // new algorithm
|
} // new algorithm
|
||||||
|
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
debug_dump_cavity_outputs(face_index, region_index, intersecting_edges, facets_of_border, facets_of_upper_cavity, facets_of_lower_cavity);
|
debug_dump_cavity_outputs(face_index, region_index, intersecting_edges, facets_of_border, facets_of_upper_cavity, facets_of_lower_cavity);
|
||||||
for(auto edge : intersecting_edges) {
|
for(auto edge : intersecting_edges) {
|
||||||
auto [v1, v2] = tr().vertices(edge);
|
auto [v1, v2] = tr().vertices(edge);
|
||||||
|
|
@ -2617,7 +2876,7 @@ private:
|
||||||
void restore_subface_region(CDT_3_signed_index face_index, int region_index,
|
void restore_subface_region(CDT_3_signed_index face_index, int region_index,
|
||||||
CDT_2& non_const_cdt_2, Fh_region& non_const_fh_region)
|
CDT_2& non_const_cdt_2, Fh_region& non_const_fh_region)
|
||||||
{
|
{
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "restore_subface_region face index: " << face_index << ", region #" << region_index << "\n";
|
std::cerr << "restore_subface_region face index: " << face_index << ", region #" << region_index << "\n";
|
||||||
}
|
}
|
||||||
const auto& cdt_2 = non_const_cdt_2;
|
const auto& cdt_2 = non_const_cdt_2;
|
||||||
|
|
@ -2640,7 +2899,7 @@ private:
|
||||||
}
|
}
|
||||||
return vertices;
|
return vertices;
|
||||||
});
|
});
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
std::cerr << "region_border_vertices.size() = " << region_border_vertices.size() << "\n";
|
std::cerr << "region_border_vertices.size() = " << region_border_vertices.size() << "\n";
|
||||||
for(auto v : region_border_vertices) {
|
for(auto v : region_border_vertices) {
|
||||||
std::cerr << cdt_3_format(" {}\n", IO::oformat(v, with_point));
|
std::cerr << cdt_3_format(" {}\n", IO::oformat(v, with_point));
|
||||||
|
|
@ -2685,7 +2944,7 @@ private:
|
||||||
if(cdt_2.orientation(v0->point(), v1->point(), v3->point()) == CGAL::POSITIVE &&
|
if(cdt_2.orientation(v0->point(), v1->point(), v3->point()) == CGAL::POSITIVE &&
|
||||||
cdt_2.orientation(v0->point(), v3->point(), v2->point()) == CGAL::POSITIVE)
|
cdt_2.orientation(v0->point(), v3->point(), v2->point()) == CGAL::POSITIVE)
|
||||||
{
|
{
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "NOTE: the other diagonal is in the 3D triangulation: flip the edge\n";
|
std::cerr << "NOTE: the other diagonal is in the 3D triangulation: flip the edge\n";
|
||||||
}
|
}
|
||||||
non_const_cdt_2.flip(non_const_fh_region[0], diagonal_index);
|
non_const_cdt_2.flip(non_const_fh_region[0], diagonal_index);
|
||||||
|
|
@ -2705,7 +2964,7 @@ private:
|
||||||
fh->info().missing_subface = false;
|
fh->info().missing_subface = false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if(this->debug_regions()) {
|
} else if(this->debug().regions()) {
|
||||||
std::cerr << "NOTE: the other diagonal is in the 3D triangulation BUT the edge is not flippable!\n";
|
std::cerr << "NOTE: the other diagonal is in the 3D triangulation BUT the edge is not flippable!\n";
|
||||||
std::cerr << " The region " << region_index << " of face #F" << face_index << " has four points:\n";
|
std::cerr << " The region " << region_index << " of face #F" << face_index << " has four points:\n";
|
||||||
std::cerr << " v0: " << v0->point() << '\n';
|
std::cerr << " v0: " << v0->point() << '\n';
|
||||||
|
|
@ -2715,7 +2974,7 @@ private:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
std::cerr << cdt_3_format
|
std::cerr << cdt_3_format
|
||||||
("NOTE: diagonal: {:.6} {:.6} {} in tr\n",
|
("NOTE: diagonal: {:.6} {:.6} {} in tr\n",
|
||||||
IO::oformat(*diagonal.begin(), with_point),
|
IO::oformat(*diagonal.begin(), with_point),
|
||||||
|
|
@ -2786,7 +3045,7 @@ private:
|
||||||
// std::to_string(region_index) + ".binary.cgal");
|
// std::to_string(region_index) + ".binary.cgal");
|
||||||
// CGAL::IO::save_binary_file(dump, *this);
|
// CGAL::IO::save_binary_file(dump, *this);
|
||||||
// }
|
// }
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "ERROR: No first segment found intersecting region " << region_index
|
std::cerr << "ERROR: No first segment found intersecting region " << region_index
|
||||||
<< " of face #" << face_index << "\n";
|
<< " of face #" << face_index << "\n";
|
||||||
dump_region(face_index, region_index, cdt_2);
|
dump_region(face_index, region_index, cdt_2);
|
||||||
|
|
@ -2832,7 +3091,7 @@ private:
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
std::cerr << cdt_3_format("Cavity has {} piercing cells and {} piercing edges, "
|
std::cerr << cdt_3_format("Cavity has {} piercing cells and {} piercing edges, "
|
||||||
"{} vertices in upper cavity and {} in lower, "
|
"{} vertices in upper cavity and {} in lower, "
|
||||||
"{} facets in upper cavity and {} in lower\n",
|
"{} facets in upper cavity and {} in lower\n",
|
||||||
|
|
@ -2845,7 +3104,7 @@ private:
|
||||||
}
|
}
|
||||||
auto register_internal_constrained_facet = [this](Facet f) { this->register_facet_to_be_constrained(f); };
|
auto register_internal_constrained_facet = [this](Facet f) { this->register_facet_to_be_constrained(f); };
|
||||||
|
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "# upper cavity\n";
|
std::cerr << "# upper cavity\n";
|
||||||
}
|
}
|
||||||
[[maybe_unused]] const auto [upper_cavity_triangulation, vertices_of_upper_cavity,
|
[[maybe_unused]] const auto [upper_cavity_triangulation, vertices_of_upper_cavity,
|
||||||
|
|
@ -2855,7 +3114,7 @@ private:
|
||||||
const auto& upper_cavity_triangulation_ = upper_cavity_triangulation;
|
const auto& upper_cavity_triangulation_ = upper_cavity_triangulation;
|
||||||
std::for_each(interior_constrained_faces_upper.begin(), interior_constrained_faces_upper.end(),
|
std::for_each(interior_constrained_faces_upper.begin(), interior_constrained_faces_upper.end(),
|
||||||
register_internal_constrained_facet);
|
register_internal_constrained_facet);
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "# lower cavity\n";
|
std::cerr << "# lower cavity\n";
|
||||||
}
|
}
|
||||||
[[maybe_unused]] const auto [lower_cavity_triangulation, vertices_of_lower_cavity,
|
[[maybe_unused]] const auto [lower_cavity_triangulation, vertices_of_lower_cavity,
|
||||||
|
|
@ -2888,7 +3147,7 @@ private:
|
||||||
<< " )";
|
<< " )";
|
||||||
return s.str();
|
return s.str();
|
||||||
};
|
};
|
||||||
if(this->debug_missing_region()) {
|
if(this->debug().missing_region()) {
|
||||||
if(fail_upper) {
|
if(fail_upper) {
|
||||||
std::cerr << "NOTE: Face " << display_face() << " is not a facet of the upper cavity\n";
|
std::cerr << "NOTE: Face " << display_face() << " is not a facet of the upper cavity\n";
|
||||||
}
|
}
|
||||||
|
|
@ -2900,7 +3159,7 @@ private:
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
})) {
|
})) {
|
||||||
if(this->debug_missing_region()) {
|
if(this->debug().missing_region()) {
|
||||||
// debug_region_size_4();
|
// debug_region_size_4();
|
||||||
dump_region(face_index, region_index, cdt_2);
|
dump_region(face_index, region_index, cdt_2);
|
||||||
std::for_each(fh_region.begin(), fh_region.end(), [](auto fh) { fh->info().is_in_region = 3; });
|
std::for_each(fh_region.begin(), fh_region.end(), [](auto fh) { fh->info().is_in_region = 3; });
|
||||||
|
|
@ -2937,7 +3196,7 @@ private:
|
||||||
insert_in_conflict_visitor.process_cells_in_conflict(cells_of_upper_cavity.begin(), cells_of_upper_cavity.end());
|
insert_in_conflict_visitor.process_cells_in_conflict(cells_of_upper_cavity.begin(), cells_of_upper_cavity.end());
|
||||||
insert_in_conflict_visitor.process_cells_in_conflict(cells_of_lower_cavity.begin(), cells_of_lower_cavity.end());
|
insert_in_conflict_visitor.process_cells_in_conflict(cells_of_lower_cavity.begin(), cells_of_lower_cavity.end());
|
||||||
|
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "# glu the upper triangulation of the cavity\n";
|
std::cerr << "# glu the upper triangulation of the cavity\n";
|
||||||
if(cells_of_lower_cavity.size() > original_intersecting_cells.size() ||
|
if(cells_of_lower_cavity.size() > original_intersecting_cells.size() ||
|
||||||
cells_of_upper_cavity.size() > original_intersecting_cells.size())
|
cells_of_upper_cavity.size() > original_intersecting_cells.size())
|
||||||
|
|
@ -2958,7 +3217,7 @@ private:
|
||||||
outer_map[vt] = f;
|
outer_map[vt] = f;
|
||||||
CGAL_USE(this);
|
CGAL_USE(this);
|
||||||
#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT
|
#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
CGAL_assertion(vt[0] != vt[1]);
|
CGAL_assertion(vt[0] != vt[1]);
|
||||||
CGAL_assertion(vt[0] != vt[2]);
|
CGAL_assertion(vt[0] != vt[2]);
|
||||||
CGAL_assertion(vt[1] != vt[2]);
|
CGAL_assertion(vt[1] != vt[2]);
|
||||||
|
|
@ -2995,7 +3254,7 @@ private:
|
||||||
if(!is_facet)
|
if(!is_facet)
|
||||||
continue; // we might be in a sliver in the plane of the polygon
|
continue; // we might be in a sliver in the plane of the polygon
|
||||||
const auto [fh_2d, reverse_orientation] = *is_facet;
|
const auto [fh_2d, reverse_orientation] = *is_facet;
|
||||||
if(this->debug_regions()) facets_of_polygon.push_back(f);
|
if(this->debug().regions()) facets_of_polygon.push_back(f);
|
||||||
const auto vt_aux = this->make_vertex_triple(f);
|
const auto vt_aux = this->make_vertex_triple(f);
|
||||||
typename T_3::Vertex_triple vt{map_cavity_vertices_to_ambient_vertices[vt_aux[0]],
|
typename T_3::Vertex_triple vt{map_cavity_vertices_to_ambient_vertices[vt_aux[0]],
|
||||||
map_cavity_vertices_to_ambient_vertices[vt_aux[1]],
|
map_cavity_vertices_to_ambient_vertices[vt_aux[1]],
|
||||||
|
|
@ -3010,7 +3269,7 @@ private:
|
||||||
CGAL_assertion(static_cast<bool>(facet_is_facet_of_cdt_2(*this, {new_cell, 3}, cdt_2)));
|
CGAL_assertion(static_cast<bool>(facet_is_facet_of_cdt_2(*this, {new_cell, 3}, cdt_2)));
|
||||||
add_to_outer_map(vt, {new_cell, 3}, "extra ");
|
add_to_outer_map(vt, {new_cell, 3}, "extra ");
|
||||||
}
|
}
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::ofstream out(cdt_3_format("dump_{}_pseudo_cells_region_{}_{}.off", is_upper_cavity ? "upper" : "lower",
|
std::ofstream out(cdt_3_format("dump_{}_pseudo_cells_region_{}_{}.off", is_upper_cavity ? "upper" : "lower",
|
||||||
face_index, region_index));
|
face_index, region_index));
|
||||||
out.precision(17);
|
out.precision(17);
|
||||||
|
|
@ -3025,7 +3284,7 @@ private:
|
||||||
const auto upper_inner_map = tr().create_triangulation_inner_map(
|
const auto upper_inner_map = tr().create_triangulation_inner_map(
|
||||||
upper_cavity_triangulation, map_upper_cavity_vertices_to_ambient_vertices, false);
|
upper_cavity_triangulation, map_upper_cavity_vertices_to_ambient_vertices, false);
|
||||||
|
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_copy_triangulation_into_hole()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "upper_inner_map:\n";
|
std::cerr << "upper_inner_map:\n";
|
||||||
for(auto [vt, _] : upper_inner_map) {
|
for(auto [vt, _] : upper_inner_map) {
|
||||||
std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n",
|
std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n",
|
||||||
|
|
@ -3034,7 +3293,7 @@ private:
|
||||||
IO::oformat(vt[2], with_point));
|
IO::oformat(vt[2], with_point));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "# glu the lower triangulation of the cavity\n";
|
std::cerr << "# glu the lower triangulation of the cavity\n";
|
||||||
}
|
}
|
||||||
this->copy_triangulation_into_hole(map_upper_cavity_vertices_to_ambient_vertices,
|
this->copy_triangulation_into_hole(map_upper_cavity_vertices_to_ambient_vertices,
|
||||||
|
|
@ -3042,7 +3301,7 @@ private:
|
||||||
upper_inner_map,
|
upper_inner_map,
|
||||||
this->new_cells_output_iterator());
|
this->new_cells_output_iterator());
|
||||||
}
|
}
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "# glu the lower triangulation of the cavity\n";
|
std::cerr << "# glu the lower triangulation of the cavity\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3063,7 +3322,7 @@ private:
|
||||||
const auto lower_inner_map = tr().create_triangulation_inner_map(
|
const auto lower_inner_map = tr().create_triangulation_inner_map(
|
||||||
lower_cavity_triangulation, map_lower_cavity_vertices_to_ambient_vertices, false);
|
lower_cavity_triangulation, map_lower_cavity_vertices_to_ambient_vertices, false);
|
||||||
#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT
|
#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT
|
||||||
if(this->debug_copy_triangulation_into_hole()) {
|
if(this->debug().copy_triangulation_into_hole()) {
|
||||||
std::cerr << "outer_map:\n";
|
std::cerr << "outer_map:\n";
|
||||||
for(auto [vt, _] : outer_map) {
|
for(auto [vt, _] : outer_map) {
|
||||||
std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n",
|
std::cerr << cdt_3_format(" {:.6}, {:.6}, {:.6})\n",
|
||||||
|
|
@ -3104,7 +3363,7 @@ private:
|
||||||
set_facet_constrained(f, face_index, f2d);
|
set_facet_constrained(f, face_index, f2d);
|
||||||
f2d->info().missing_subface = false;
|
f2d->info().missing_subface = false;
|
||||||
}
|
}
|
||||||
CGAL_assume(!this->debug_validity() || this->is_valid(true));
|
CGAL_assume(!this->debug().validity() || this->is_valid(true));
|
||||||
};
|
};
|
||||||
|
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
@ -3237,7 +3496,7 @@ private:
|
||||||
tr().is_infinite(v) ? cavity_triangulation.infinite_vertex() : cavity_triangulation.insert(this->point(v));
|
tr().is_infinite(v) ? cavity_triangulation.infinite_vertex() : cavity_triangulation.insert(this->point(v));
|
||||||
map_ambient_vertices_to_cavity_vertices[v] = cavity_v;
|
map_ambient_vertices_to_cavity_vertices[v] = cavity_v;
|
||||||
map_cavity_vertices_to_ambient_vertices[cavity_v] = v;
|
map_cavity_vertices_to_ambient_vertices[cavity_v] = v;
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
std::cerr << cdt_3_format("inserted {}cavity vertex {:.6} -> {:.6}\n",
|
std::cerr << cdt_3_format("inserted {}cavity vertex {:.6} -> {:.6}\n",
|
||||||
extra,
|
extra,
|
||||||
IO::oformat(cavity_v, with_point_and_info),
|
IO::oformat(cavity_v, with_point_and_info),
|
||||||
|
|
@ -3337,7 +3596,7 @@ private:
|
||||||
{
|
{
|
||||||
const auto& cdt_2 = non_const_cdt_2;
|
const auto& cdt_2 = non_const_cdt_2;
|
||||||
auto steiner_pt = CGAL::centroid(cdt_2.triangle(fh_2d));
|
auto steiner_pt = CGAL::centroid(cdt_2.triangle(fh_2d));
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_verbose_special_cases()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().verbose_special_cases()) {
|
||||||
std::cerr << cdt_3_format("Trying to insert Steiner (centroid) point {} in non-coplanar face {}.\n", IO::oformat(steiner_pt),
|
std::cerr << cdt_3_format("Trying to insert Steiner (centroid) point {} in non-coplanar face {}.\n", IO::oformat(steiner_pt),
|
||||||
IO::oformat(cdt_2.triangle(fh_2d)));
|
IO::oformat(cdt_2.triangle(fh_2d)));
|
||||||
}
|
}
|
||||||
|
|
@ -3345,7 +3604,7 @@ private:
|
||||||
if(encroached_edge_opt) {
|
if(encroached_edge_opt) {
|
||||||
return encroached_edge_opt;
|
return encroached_edge_opt;
|
||||||
}
|
}
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_Steiner_points()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) {
|
||||||
std::cerr << cdt_3_format("Inserting Steiner (centroid) point {} in non-coplanar face {}: {}.\n",
|
std::cerr << cdt_3_format("Inserting Steiner (centroid) point {} in non-coplanar face {}: {}.\n",
|
||||||
IO::oformat(steiner_pt), face_index, IO::oformat(cdt_2.triangle(fh_2d)));
|
IO::oformat(steiner_pt), face_index, IO::oformat(cdt_2.triangle(fh_2d)));
|
||||||
}
|
}
|
||||||
|
|
@ -3415,7 +3674,7 @@ private:
|
||||||
const auto v = this->insert_in_cdt_3(steiner_pt, lt, ch, li, lj, insert_in_conflict_visitor);// TODO: use "insert in hole"
|
const auto v = this->insert_in_cdt_3(steiner_pt, lt, ch, li, lj, insert_in_conflict_visitor);// TODO: use "insert in hole"
|
||||||
// this->study_bug = false;
|
// this->study_bug = false;
|
||||||
// assert(is_valid(true));
|
// assert(is_valid(true));
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_Steiner_points()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) {
|
||||||
std::cerr << " -> " << IO::oformat(v, with_offset) << '\n';
|
std::cerr << " -> " << IO::oformat(v, with_offset) << '\n';
|
||||||
}
|
}
|
||||||
v->ccdt_3_data().set_Steiner_vertex_in_face(face_index);
|
v->ccdt_3_data().set_Steiner_vertex_in_face(face_index);
|
||||||
|
|
@ -3438,13 +3697,13 @@ private:
|
||||||
const auto a = this->point(va_3d);
|
const auto a = this->point(va_3d);
|
||||||
const auto b = this->point(vb_3d);
|
const auto b = this->point(vb_3d);
|
||||||
const auto mid = CGAL::midpoint(a, b);
|
const auto mid = CGAL::midpoint(a, b);
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_Steiner_points()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) {
|
||||||
std::cerr << cdt_3_format("Inserting Steiner (midpoint) point {} of constrained edge ({:.6} , {:.6})\n",
|
std::cerr << cdt_3_format("Inserting Steiner (midpoint) point {} of constrained edge ({:.6} , {:.6})\n",
|
||||||
IO::oformat(mid), IO::oformat(va_3d, with_point_and_info),
|
IO::oformat(mid), IO::oformat(va_3d, with_point_and_info),
|
||||||
IO::oformat(vb_3d, with_point_and_info));
|
IO::oformat(vb_3d, with_point_and_info));
|
||||||
}
|
}
|
||||||
auto&& contexts = this->constraint_hierarchy.contexts(va_3d, vb_3d);
|
auto&& contexts = this->constraint_hierarchy.contexts(va_3d, vb_3d);
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_verbose_special_cases()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().verbose_special_cases()) {
|
||||||
if(std::next(contexts.begin()) != contexts.end()) {
|
if(std::next(contexts.begin()) != contexts.end()) {
|
||||||
std::cerr << "ERROR: Edge is constrained by more than one constraint\n";
|
std::cerr << "ERROR: Edge is constrained by more than one constraint\n";
|
||||||
for(const auto& c : contexts) {
|
for(const auto& c : contexts) {
|
||||||
|
|
@ -3472,7 +3731,7 @@ private:
|
||||||
[[maybe_unused]] auto v =
|
[[maybe_unused]] auto v =
|
||||||
this->insert_Steiner_point_on_subconstraint(mid, mid_c, {va_3d, vb_3d},
|
this->insert_Steiner_point_on_subconstraint(mid, mid_c, {va_3d, vb_3d},
|
||||||
constrained_polyline_id, insert_in_conflict_visitor);
|
constrained_polyline_id, insert_in_conflict_visitor);
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_Steiner_points()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().Steiner_points()) {
|
||||||
std::cerr << " -> " << IO::oformat(v, with_offset) << '\n';
|
std::cerr << " -> " << IO::oformat(v, with_offset) << '\n';
|
||||||
}
|
}
|
||||||
// this->study_bug = false;
|
// this->study_bug = false;
|
||||||
|
|
@ -3483,7 +3742,7 @@ private:
|
||||||
CDT_2& non_const_cdt_2 = face_cdt_2[face_index];
|
CDT_2& non_const_cdt_2 = face_cdt_2[face_index];
|
||||||
const CDT_2& cdt_2 = non_const_cdt_2;
|
const CDT_2& cdt_2 = non_const_cdt_2;
|
||||||
if constexpr (cdt_3_can_use_cxx20_format())
|
if constexpr (cdt_3_can_use_cxx20_format())
|
||||||
if(this->debug_copy_triangulation_into_hole() || this->debug_verbose_special_cases()) {
|
if(this->debug().copy_triangulation_into_hole() || this->debug().verbose_special_cases()) {
|
||||||
std::cerr << cdt_3_format("restore_face({}): CDT_2 has {} vertices\n", face_index, cdt_2.number_of_vertices());
|
std::cerr << cdt_3_format("restore_face({}): CDT_2 has {} vertices\n", face_index, cdt_2.number_of_vertices());
|
||||||
}
|
}
|
||||||
for(const auto& edge : cdt_2.finite_edges()) {
|
for(const auto& edge : cdt_2.finite_edges()) {
|
||||||
|
|
@ -3493,7 +3752,7 @@ private:
|
||||||
const auto vb_3d = fh->vertex(cdt_2.ccw(i))->info().vertex_handle_3d;
|
const auto vb_3d = fh->vertex(cdt_2.ccw(i))->info().vertex_handle_3d;
|
||||||
const bool is_3d = this->is_edge(va_3d, vb_3d);
|
const bool is_3d = this->is_edge(va_3d, vb_3d);
|
||||||
if constexpr(cdt_3_can_use_cxx20_format()) {
|
if constexpr(cdt_3_can_use_cxx20_format()) {
|
||||||
if(this->debug_copy_triangulation_into_hole() || this->debug_conforming_validation()) {
|
if(this->debug().copy_triangulation_into_hole() || this->debug().conforming_validation()) {
|
||||||
std::cerr << cdt_3_format("Edge is 3D: {:6} ({} , {})\n", is_3d, IO::oformat(va_3d, with_point_and_info),
|
std::cerr << cdt_3_format("Edge is 3D: {:6} ({} , {})\n", is_3d, IO::oformat(va_3d, with_point_and_info),
|
||||||
IO::oformat(vb_3d, with_point_and_info));
|
IO::oformat(vb_3d, with_point_and_info));
|
||||||
}
|
}
|
||||||
|
|
@ -3529,11 +3788,11 @@ private:
|
||||||
processed_faces.insert(fh_region.begin(), fh_region.end());
|
processed_faces.insert(fh_region.begin(), fh_region.end());
|
||||||
|
|
||||||
auto handle_error_with_region = [&](const char* what, CDT_2_face_handle fh_2d) {
|
auto handle_error_with_region = [&](const char* what, CDT_2_face_handle fh_2d) {
|
||||||
if(this->debug_regions() || this->debug_verbose_special_cases()) {
|
if(this->debug().regions() || this->debug().verbose_special_cases()) {
|
||||||
std::cerr << "NOTE: " << what << " in sub-region " << (region_index - 1)
|
std::cerr << "NOTE: " << what << " in sub-region " << (region_index - 1)
|
||||||
<< " of face #F" << face_index << '\n';
|
<< " of face #F" << face_index << '\n';
|
||||||
}
|
}
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_verbose_special_cases()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().verbose_special_cases()) {
|
||||||
std::cerr << " constrained edges are:\n";
|
std::cerr << " constrained edges are:\n";
|
||||||
for(auto [c, index]: cdt_2.constrained_edges()) {
|
for(auto [c, index]: cdt_2.constrained_edges()) {
|
||||||
const auto va = c->vertex(cdt_2.cw(index));
|
const auto va = c->vertex(cdt_2.cw(index));
|
||||||
|
|
@ -3713,7 +3972,7 @@ public:
|
||||||
fill_cdt_2(cdt_2, i);
|
fill_cdt_2(cdt_2, i);
|
||||||
search_for_missing_subfaces(i);
|
search_for_missing_subfaces(i);
|
||||||
}
|
}
|
||||||
if(this->debug_input_faces()) {
|
if(this->debug().input_faces()) {
|
||||||
for(CDT_3_signed_index i = 0, end = static_cast <CDT_3_signed_index>(face_constraint_misses_subfaces.size()); i < end; ++i) {
|
for(CDT_3_signed_index i = 0, end = static_cast <CDT_3_signed_index>(face_constraint_misses_subfaces.size()); i < end; ++i) {
|
||||||
dump_face(i);
|
dump_face(i);
|
||||||
}
|
}
|
||||||
|
|
@ -3727,7 +3986,7 @@ public:
|
||||||
if(restore_face(static_cast <CDT_3_signed_index>(i))) {
|
if(restore_face(static_cast <CDT_3_signed_index>(i))) {
|
||||||
face_constraint_misses_subfaces_reset(i);
|
face_constraint_misses_subfaces_reset(i);
|
||||||
} else {
|
} else {
|
||||||
if(this->debug_missing_region() || this->debug_Steiner_points()) {
|
if(this->debug().missing_region() || this->debug().Steiner_points()) {
|
||||||
std::cerr << "restore_face(" << i << ") incomplete, back to conforming...\n";
|
std::cerr << "restore_face(" << i << ") incomplete, back to conforming...\n";
|
||||||
}
|
}
|
||||||
Conforming_Dt::restore_Delaunay(insert_in_conflict_visitor);
|
Conforming_Dt::restore_Delaunay(insert_in_conflict_visitor);
|
||||||
|
|
@ -3739,7 +3998,7 @@ public:
|
||||||
i = face_constraint_misses_subfaces_find_next(i);
|
i = face_constraint_misses_subfaces_find_next(i);
|
||||||
if(i == npos) {
|
if(i == npos) {
|
||||||
std::cerr << "ERROR: No more missing face to restore after a PLC error\n";
|
std::cerr << "ERROR: No more missing face to restore after a PLC error\n";
|
||||||
if(this->debug_regions() || this->debug_verbose_special_cases()) {
|
if(this->debug().regions() || this->debug().verbose_special_cases()) {
|
||||||
dump_region(e.face_index, e.region_index);
|
dump_region(e.face_index, e.region_index);
|
||||||
}
|
}
|
||||||
throw;
|
throw;
|
||||||
|
|
@ -3883,7 +4142,7 @@ public:
|
||||||
for(std::size_t i = 0; i < intersecting_edges.size(); ++i) {
|
for(std::size_t i = 0; i < intersecting_edges.size(); ++i) {
|
||||||
const auto intersecting_edge = intersecting_edges[i];
|
const auto intersecting_edge = intersecting_edges[i];
|
||||||
const auto [v_above, v_below] = tr().vertices(intersecting_edge);
|
const auto [v_above, v_below] = tr().vertices(intersecting_edge);
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
debug_dump_edge_region_intersection(face_index, region_index, fh_region, i, v_above, v_below, intersecting_edge);
|
debug_dump_edge_region_intersection(face_index, region_index, fh_region, i, v_above, v_below, intersecting_edge);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3891,7 +4150,7 @@ public:
|
||||||
int expected)
|
int expected)
|
||||||
{
|
{
|
||||||
auto value_returned = [this, v0, v1](bool b, bool not_visited) {
|
auto value_returned = [this, v0, v1](bool b, bool not_visited) {
|
||||||
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug_regions()) {
|
if constexpr (cdt_3_can_use_cxx20_format()) if(this->debug().regions()) {
|
||||||
std::cerr << cdt_3_format(" test_edge {} {} return {} {}\n",
|
std::cerr << cdt_3_format(" test_edge {} {} return {} {}\n",
|
||||||
IO::oformat(v0, with_point_and_info),
|
IO::oformat(v0, with_point_and_info),
|
||||||
IO::oformat(v1, with_point_and_info),
|
IO::oformat(v1, with_point_and_info),
|
||||||
|
|
@ -3952,7 +4211,7 @@ public:
|
||||||
!test_edge(cell, v_below, index_v_below, vc, index_vc, -1) &&
|
!test_edge(cell, v_below, index_v_below, vc, index_vc, -1) &&
|
||||||
this->use_older_cavity_algorithm())
|
this->use_older_cavity_algorithm())
|
||||||
{
|
{
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
dump_triangulation();
|
dump_triangulation();
|
||||||
dump_region(face_index, region_index, cdt_2);
|
dump_region(face_index, region_index, cdt_2);
|
||||||
std::ofstream out(std::string("dump_two_edges_") + std::to_string(face_index) + ".polylines.txt");
|
std::ofstream out(std::string("dump_two_edges_") + std::to_string(face_index) + ".polylines.txt");
|
||||||
|
|
@ -3966,7 +4225,7 @@ public:
|
||||||
} while(++facet_circ != facet_circ_end);
|
} while(++facet_circ != facet_circ_end);
|
||||||
if(this->use_newer_cavity_algorithm() && i + 1 == intersecting_edges.size()) {
|
if(this->use_newer_cavity_algorithm() && i + 1 == intersecting_edges.size()) {
|
||||||
for(auto ch: intersecting_cells) {
|
for(auto ch: intersecting_cells) {
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "tetrahedron #" << ch->time_stamp() << " intersects the region\n";
|
std::cerr << "tetrahedron #" << ch->time_stamp() << " intersects the region\n";
|
||||||
}
|
}
|
||||||
for(int i = 0; i < 4; ++i) {
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
|
@ -3989,10 +4248,10 @@ public:
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
intersecting_cells.insert(n_ch);
|
intersecting_cells.insert(n_ch);
|
||||||
if(this->debug_regions()) {
|
if(this->debug().regions()) {
|
||||||
std::cerr << "new tetrahedron #" << n_ch->time_stamp() << " intersects the region\n";
|
std::cerr << "new tetrahedron #" << n_ch->time_stamp() << " intersects the region\n";
|
||||||
}
|
}
|
||||||
} else if(this->debug_regions()) {
|
} else if(this->debug().regions()) {
|
||||||
std::cerr << "NO, new tetrahedron #" << n_ch->time_stamp() << " does not intersect the region\n";
|
std::cerr << "NO, new tetrahedron #" << n_ch->time_stamp() << " does not intersect the region\n";
|
||||||
}
|
}
|
||||||
for(int i = 0; i < 4; ++i) {
|
for(int i = 0; i < 4; ++i) {
|
||||||
|
|
@ -4570,4 +4829,4 @@ auto get_remeshing_triangulation(Conforming_constrained_Delaunay_triangulation_3
|
||||||
|
|
||||||
} // end CGAL
|
} // end CGAL
|
||||||
|
|
||||||
#endif // CGAL_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
#endif // CGAL_CONFORMING_CONSTRAINED_DELAUNAY_TRIANGULATION_3_H
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
// #define CGAL_CDT_2_DEBUG_INTERSECTIONS 1
|
// #define CGAL_CDT_2_DEBUG_INTERSECTIONS 1
|
||||||
#include <CGAL/Conforming_constrained_Delaunay_triangulation_3.h>
|
#include <CGAL/Conforming_constrained_Delaunay_triangulation_3.h>
|
||||||
#include <CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h>
|
#include <CGAL/Conforming_constrained_Delaunay_triangulation_vertex_base_3.h>
|
||||||
|
#include <CGAL/Conforming_Delaunay_triangulation_3.h>
|
||||||
#include <CGAL/Constrained_triangulation_3/internal/read_polygon_mesh_for_cdt_3.h>
|
#include <CGAL/Constrained_triangulation_3/internal/read_polygon_mesh_for_cdt_3.h>
|
||||||
#include <CGAL/Delaunay_triangulation_3.h>
|
#include <CGAL/Delaunay_triangulation_3.h>
|
||||||
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
#include <CGAL/Exact_predicates_inexact_constructions_kernel.h>
|
||||||
|
|
@ -45,12 +46,8 @@ using K = CGAL::Exact_predicates_inexact_constructions_kernel;
|
||||||
|
|
||||||
#endif // use Epick
|
#endif // use Epick
|
||||||
|
|
||||||
struct Vb : public CGAL::Conforming_constrained_Delaunay_triangulation_vertex_base_3<K> {};
|
using CDT = CGAL::Conforming_constrained_Delaunay_triangulation_3<K>;
|
||||||
struct Cb : public CGAL::Conforming_constrained_Delaunay_triangulation_cell_base_3<K> {};
|
using Point = K::Point_3;
|
||||||
struct Tds: public CGAL::Triangulation_data_structure_3<Vb, Cb> {};
|
|
||||||
using Base_triantulation = CGAL::Delaunay_triangulation_3<K, Tds>;
|
|
||||||
using CDT = CGAL::Conforming_constrained_Delaunay_triangulation_3_impl<Base_triantulation>;
|
|
||||||
using Point = Base_triantulation::Point;
|
|
||||||
using Point_3 = K::Point_3;
|
using Point_3 = K::Point_3;
|
||||||
|
|
||||||
using Mesh = CGAL::Surface_mesh<Point>;
|
using Mesh = CGAL::Surface_mesh<Point>;
|
||||||
|
|
@ -258,35 +255,29 @@ CDT_options::CDT_options(int argc, char* argv[]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NO_TRY_CATCH
|
CGAL::CDT_3::Debug_options cdt_debug_options(const CDT_options& options) {
|
||||||
# define CDT_3_try if (true)
|
CGAL::CDT_3::Debug_options cdt_debug;
|
||||||
# define CDT_3_catch(X) if (false)
|
cdt_debug.Steiner_points(options.verbose_level > 0);
|
||||||
# define CDT_3_throw_exception_again
|
cdt_debug.input_faces(options.debug_input_faces);
|
||||||
#else
|
cdt_debug.missing_region(options.verbose_level > 1 || options.debug_missing_regions);
|
||||||
// Else proceed normally.
|
cdt_debug.regions(options.debug_regions);
|
||||||
# define CDT_3_try try
|
cdt_debug.validity(options.debug_validity);
|
||||||
# define CDT_3_catch(X) catch(X)
|
cdt_debug.finite_edges_map(options.debug_finite_edges_map);
|
||||||
# define CDT_3_throw_exception_again throw
|
cdt_debug.subconstraints_to_conform(options.debug_subconstraints_to_conform);
|
||||||
#endif
|
cdt_debug.verbose_special_cases(options.debug_verbose_special_cases);
|
||||||
|
cdt_debug.encroaching_vertices(options.debug_encroaching_vertices);
|
||||||
|
cdt_debug.conforming_validation(options.debug_conforming_validation);
|
||||||
|
cdt_debug.constraint_hierarchy(options.debug_constraint_hierarchy);
|
||||||
|
cdt_debug.geometric_errors(options.debug_geometric_errors);
|
||||||
|
cdt_debug.polygon_insertion(options.debug_polygon_insertion);
|
||||||
|
cdt_debug.copy_triangulation_into_hole(options.debug_copy_triangulation_into_hole);
|
||||||
|
cdt_debug.use_older_cavity_algorithm(!options.use_new_cavity_algorithm);
|
||||||
|
cdt_debug.use_finite_edges_map(options.use_finite_edges_map);
|
||||||
|
cdt_debug.display_statistics(!options.quiet);
|
||||||
|
cdt_debug.set_segment_vertex_epsilon(options.segment_vertex_epsilon);
|
||||||
|
cdt_debug.set_vertex_vertex_epsilon(options.vertex_vertex_epsilon);
|
||||||
|
|
||||||
void configure_cdt_debug_options(CDT& cdt, const CDT_options& options) {
|
return cdt_debug;
|
||||||
cdt.debug_Steiner_points(options.verbose_level > 0);
|
|
||||||
cdt.debug_input_faces(options.debug_input_faces);
|
|
||||||
cdt.debug_missing_region(options.verbose_level > 1 || options.debug_missing_regions);
|
|
||||||
cdt.debug_regions(options.debug_regions);
|
|
||||||
cdt.debug_validity(options.debug_validity);
|
|
||||||
cdt.debug_finite_edges_map(options.debug_finite_edges_map);
|
|
||||||
cdt.debug_subconstraints_to_conform(options.debug_subconstraints_to_conform);
|
|
||||||
cdt.debug_verbose_special_cases(options.debug_verbose_special_cases);
|
|
||||||
cdt.debug_encroaching_vertices(options.debug_encroaching_vertices);
|
|
||||||
cdt.debug_conforming_validation(options.debug_conforming_validation);
|
|
||||||
cdt.debug_constraint_hierarchy(options.debug_constraint_hierarchy);
|
|
||||||
cdt.debug_geometric_errors(options.debug_geometric_errors);
|
|
||||||
cdt.debug_polygon_insertion(options.debug_polygon_insertion);
|
|
||||||
cdt.debug_copy_triangulation_into_hole(options.debug_copy_triangulation_into_hole);
|
|
||||||
cdt.use_older_cavity_algorithm(!options.use_new_cavity_algorithm);
|
|
||||||
cdt.use_finite_edges_map(options.use_finite_edges_map);
|
|
||||||
cdt.set_segment_vertex_epsilon(options.segment_vertex_epsilon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto compute_bounding_box(const Mesh& mesh, const CDT_options& options) {
|
auto compute_bounding_box(const Mesh& mesh, const CDT_options& options) {
|
||||||
|
|
@ -334,7 +325,7 @@ std::function<void()> create_output_finalizer(const CDT& cdt, const CDT_options&
|
||||||
|
|
||||||
auto& tr = cdt;
|
auto& tr = cdt;
|
||||||
|
|
||||||
std::unordered_map<CDT::Cell_handle, int /*Subdomain_index*/> cells_map;
|
std::unordered_map<CDT::Triangulation::Cell_handle, int /*Subdomain_index*/> cells_map;
|
||||||
for(auto ch : tr.all_cell_handles())
|
for(auto ch : tr.all_cell_handles())
|
||||||
{
|
{
|
||||||
cells_map[ch] = 1;
|
cells_map[ch] = 1;
|
||||||
|
|
@ -380,13 +371,13 @@ std::function<void()> create_output_finalizer(const CDT& cdt, const CDT_options&
|
||||||
std::ofstream dump(options.output_filename);
|
std::ofstream dump(options.output_filename);
|
||||||
dump.precision(17);
|
dump.precision(17);
|
||||||
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
||||||
cdt.write_facets(dump, cdt, std::views::filter(cdt.finite_facets(), [&](auto f) {
|
cdt.write_facets(dump, cdt.triangulation(), std::views::filter(cdt.finite_facets(), [&](auto f) {
|
||||||
return cdt.is_facet_constrained(f);
|
return cdt.is_facet_constrained(f);
|
||||||
}));
|
}));
|
||||||
#else
|
#else
|
||||||
auto is_facet_constrained = [&](auto f) { return cdt.is_facet_constrained(f); };
|
auto is_facet_constrained = [&](auto f) { return cdt.is_facet_constrained(f); };
|
||||||
auto it_end = cdt.finite_facets_end();
|
auto it_end = cdt.finite_facets_end();
|
||||||
cdt.write_facets(dump, cdt,
|
cdt.write_facets(dump, cdt.triangulation(),
|
||||||
CGAL::make_range(
|
CGAL::make_range(
|
||||||
boost::make_filter_iterator(is_facet_constrained,cdt.finite_facets_begin(), it_end),
|
boost::make_filter_iterator(is_facet_constrained,cdt.finite_facets_begin(), it_end),
|
||||||
boost::make_filter_iterator(is_facet_constrained,it_end, it_end)));
|
boost::make_filter_iterator(is_facet_constrained,it_end, it_end)));
|
||||||
|
|
@ -396,155 +387,6 @@ std::function<void()> create_output_finalizer(const CDT& cdt, const CDT_options&
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Min_distance_result {
|
|
||||||
double min_distance;
|
|
||||||
std::array<CDT::Vertex_handle, 2> vertices_of_min_edge;
|
|
||||||
};
|
|
||||||
|
|
||||||
Min_distance_result compute_minimum_vertex_distance(const CDT& cdt) {
|
|
||||||
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
|
||||||
auto [min_sq_distance, min_edge] =
|
|
||||||
(std::ranges::min)(cdt.finite_edges() | std::views::transform([&](auto edge) {
|
|
||||||
return std::make_pair(cdt.segment(edge).squared_length(), edge);
|
|
||||||
}));
|
|
||||||
#else
|
|
||||||
auto transform_fct = [&](auto edge) { return std::make_pair(cdt.segment(edge).squared_length(), edge); };
|
|
||||||
auto min_p = transform_fct(*cdt.finite_edges_begin());
|
|
||||||
for (auto ite=cdt.finite_edges_begin(); ite!=cdt.finite_edges_end(); ++ite)
|
|
||||||
{
|
|
||||||
auto p = transform_fct(*ite);
|
|
||||||
if (p < min_p)
|
|
||||||
p = min_p;
|
|
||||||
}
|
|
||||||
auto [min_sq_distance, min_edge] = min_p;
|
|
||||||
#endif
|
|
||||||
auto min_distance = CGAL::to_double(CGAL::approximate_sqrt(min_sq_distance));
|
|
||||||
auto vertices_of_min_edge = cdt.vertices(min_edge);
|
|
||||||
|
|
||||||
return {min_distance, vertices_of_min_edge};
|
|
||||||
}
|
|
||||||
|
|
||||||
void print_minimum_distance_info(const Min_distance_result& min_dist) {
|
|
||||||
std::cout << "Min distance between vertices: " << min_dist.min_distance << '\n'
|
|
||||||
<< " between vertices: : "
|
|
||||||
<< CGAL::IO::oformat(min_dist.vertices_of_min_edge[0], CGAL::With_point_tag{}) << " "
|
|
||||||
<< CGAL::IO::oformat(min_dist.vertices_of_min_edge[1], CGAL::With_point_tag{}) << "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
int validate_minimum_vertex_distances(const CDT& cdt, double vertex_vertex_min_distance, const CDT_options& options) {
|
|
||||||
auto result = compute_minimum_vertex_distance(cdt);
|
|
||||||
|
|
||||||
if(!options.quiet) {
|
|
||||||
print_minimum_distance_info(result);
|
|
||||||
}
|
|
||||||
if(result.min_distance < vertex_vertex_min_distance) {
|
|
||||||
std::cerr << "ERROR: min distance between vertices is too small\n";
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
return EXIT_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct Constraint_distance_result {
|
|
||||||
double min_distance;
|
|
||||||
CDT::Vertex_handle min_va, min_vb, min_vertex;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename BordersOfPatches, typename VertexPointMap>
|
|
||||||
Constraint_distance_result compute_constraint_vertex_distances_from_patches_borders(
|
|
||||||
CDT& cdt,
|
|
||||||
const BordersOfPatches& patch_edges,
|
|
||||||
const VertexPointMap& tr_vertex_pmap) {
|
|
||||||
|
|
||||||
#if CGAL_CXX20 && __cpp_lib_concepts >= 201806L && __cpp_lib_ranges >= 201911L
|
|
||||||
auto edge_results = patch_edges
|
|
||||||
| std::views::join
|
|
||||||
| std::views::transform([&](const auto& edge_pair) {
|
|
||||||
auto [vda, vdb] = edge_pair;
|
|
||||||
auto va = get(tr_vertex_pmap, vda);
|
|
||||||
auto vb = get(tr_vertex_pmap, vdb);
|
|
||||||
auto [min_dist, min_v] = cdt.min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
|
||||||
return std::make_tuple(CGAL::to_double(min_dist), va, vb, min_v);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto min_result = std::ranges::min_element(edge_results, {}, [](const auto& tuple) {
|
|
||||||
return std::get<0>(tuple);
|
|
||||||
});
|
|
||||||
|
|
||||||
auto [min_distance, min_va, min_vb, min_vertex] = *min_result;
|
|
||||||
#else
|
|
||||||
double min_distance = (std::numeric_limits<double>::max)();
|
|
||||||
CDT::Vertex_handle min_va, min_vb, min_vertex;
|
|
||||||
|
|
||||||
for(const auto& edges : patch_edges) {
|
|
||||||
for(auto [vda, vdb]: edges) {
|
|
||||||
auto va = get(tr_vertex_pmap, vda);
|
|
||||||
auto vb = get(tr_vertex_pmap, vdb);
|
|
||||||
auto [min_dist, min_v] = cdt.min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
|
||||||
if(min_dist < min_distance) {
|
|
||||||
min_distance = CGAL::to_double(min_dist);
|
|
||||||
min_va = va;
|
|
||||||
min_vb = vb;
|
|
||||||
min_vertex = min_v;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return {min_distance, min_va, min_vb, min_vertex};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename VertexPointMap>
|
|
||||||
Constraint_distance_result compute_constraint_vertex_distances_from_faces(
|
|
||||||
CDT& cdt,
|
|
||||||
const Mesh& mesh,
|
|
||||||
const VertexPointMap& tr_vertex_pmap) {
|
|
||||||
|
|
||||||
double min_distance = (std::numeric_limits<double>::max)();
|
|
||||||
CDT::Vertex_handle min_va, min_vb, min_vertex;
|
|
||||||
|
|
||||||
for(auto face_descriptor : faces(mesh)) {
|
|
||||||
auto he = halfedge(face_descriptor, mesh);
|
|
||||||
const auto end = he;
|
|
||||||
do {
|
|
||||||
auto va = get(tr_vertex_pmap, source(he, mesh));
|
|
||||||
auto vb = get(tr_vertex_pmap, target(he, mesh));
|
|
||||||
auto [min_dist, min_v] = cdt.min_distance_and_vertex_between_constraint_and_encroaching_vertex(va, vb);
|
|
||||||
if(min_dist < min_distance) {
|
|
||||||
min_distance = CGAL::to_double(min_dist);
|
|
||||||
min_va = va;
|
|
||||||
min_vb = vb;
|
|
||||||
min_vertex = min_v;
|
|
||||||
}
|
|
||||||
he = next(he, mesh);
|
|
||||||
} while((he = next(he, mesh)) != end);
|
|
||||||
}
|
|
||||||
|
|
||||||
return {min_distance, min_va, min_vb, min_vertex};
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename BordersOfPatches, typename VertexPointMap>
|
|
||||||
void validate_constraint_vertex_distances_or_throw(
|
|
||||||
CDT& cdt,
|
|
||||||
const Mesh& mesh,
|
|
||||||
const CDT_options& options,
|
|
||||||
const BordersOfPatches& patch_edges,
|
|
||||||
const VertexPointMap& tr_vertex_pmap) {
|
|
||||||
|
|
||||||
auto [min_distance, min_va, min_vb, min_vertex] =
|
|
||||||
options.merge_facets ? compute_constraint_vertex_distances_from_patches_borders(cdt, patch_edges, tr_vertex_pmap)
|
|
||||||
: compute_constraint_vertex_distances_from_faces(cdt, mesh, tr_vertex_pmap);
|
|
||||||
|
|
||||||
if(!options.quiet) {
|
|
||||||
std::cout << "Min distance between constraint segment and vertex: " << min_distance << '\n'
|
|
||||||
<< " between segment : "
|
|
||||||
<< CGAL::IO::oformat(min_va, CDT::Conforming_Dt::with_point) << " "
|
|
||||||
<< CGAL::IO::oformat(min_vb, CDT::Conforming_Dt::with_point) << '\n'
|
|
||||||
<< " and vertex : "
|
|
||||||
<< CGAL::IO::oformat(min_vertex, CDT::Conforming_Dt::with_point) << "\n\n";
|
|
||||||
}
|
|
||||||
cdt.check_segment_vertex_distance_or_throw(min_va, min_vb, min_vertex, min_distance,
|
|
||||||
CDT::Check_distance::NON_SQUARED_DISTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename PatchIdMap, typename VertexSelectedMap, typename EdgeBorderMap, typename VertexPointMap>
|
template<typename PatchIdMap, typename VertexSelectedMap, typename EdgeBorderMap, typename VertexPointMap>
|
||||||
struct Mesh_property_maps {
|
struct Mesh_property_maps {
|
||||||
|
|
@ -766,9 +608,9 @@ void dump_patches_borders(const BordersOfPatches& patch_edges,
|
||||||
}
|
}
|
||||||
|
|
||||||
int go(Mesh mesh, CDT_options options) {
|
int go(Mesh mesh, CDT_options options) {
|
||||||
CDT cdt;
|
CGAL::CDT_3::Debug_options cdt_debug = cdt_debug_options(options);
|
||||||
configure_cdt_debug_options(cdt, options);
|
|
||||||
|
|
||||||
|
// Compute bbox (used for distance checks scaling)
|
||||||
auto bbox = compute_bounding_box(mesh, options);
|
auto bbox = compute_bounding_box(mesh, options);
|
||||||
auto bbox_max_span = (std::max)(bbox.x_span(), (std::max)(bbox.y_span(), bbox.z_span()));
|
auto bbox_max_span = (std::max)(bbox.x_span(), (std::max)(bbox.y_span(), bbox.z_span()));
|
||||||
|
|
||||||
|
|
@ -781,99 +623,18 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
dump_patches_borders(patch_edges, pmaps, options.dump_patches_borders_prefix);
|
dump_patches_borders(patch_edges, pmaps, options.dump_patches_borders_prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto mesh_descriptor_to_vertex_handle_pmap = get(CGAL::dynamic_vertex_property_t<CDT::Vertex_handle>(), mesh);
|
auto dump_mesh_with_steiner_points = [&](const auto& cdt) {
|
||||||
|
if(options.dump_after_conforming_filename.empty()) {
|
||||||
{
|
return;
|
||||||
auto _ = CGAL::CDT_3_INSERT_VERTICES_TASK_guard();
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
if(options.merge_facets) {
|
|
||||||
cdt.insert_vertices_range(vertices(mesh), pmaps.mesh_vertex_point_map, mesh_descriptor_to_vertex_handle_pmap,
|
|
||||||
CGAL::parameters::vertex_is_constrained_map(pmaps.v_selected_map));
|
|
||||||
} else {
|
|
||||||
cdt.insert_vertices_range(vertices(mesh), pmaps.mesh_vertex_point_map, mesh_descriptor_to_vertex_handle_pmap);
|
|
||||||
}
|
}
|
||||||
CDT::Cell_handle hint{};
|
|
||||||
for(auto v: vertices(mesh)) {
|
|
||||||
if(options.merge_facets && false == get(pmaps.v_selected_map, v)) continue;
|
|
||||||
auto vh = cdt.insert(get(pmaps.mesh_vertex_point_map, v), hint, false);
|
|
||||||
hint = vh->cell();
|
|
||||||
put(mesh_descriptor_to_vertex_handle_pmap, v, vh);
|
|
||||||
}
|
|
||||||
if(!options.quiet) {
|
|
||||||
auto timing = std::chrono::high_resolution_clock::now() - start_time;
|
|
||||||
std::cout << "[timings] inserted vertices in "
|
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(timing).count() << " ms\n";
|
|
||||||
std::cout << "Number of vertices: " << cdt.number_of_vertices() << "\n\n";
|
|
||||||
}
|
|
||||||
cdt.add_bbox_points_if_not_dimension_3();
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto _ = CGAL::CDT_3_COMPUTE_DISTANCES_TASK_guard();
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
|
|
||||||
auto exit_code = validate_minimum_vertex_distances(cdt, options.vertex_vertex_epsilon * bbox_max_span, options);
|
|
||||||
if(exit_code != EXIT_SUCCESS) {
|
|
||||||
return exit_code;
|
|
||||||
}
|
|
||||||
|
|
||||||
validate_constraint_vertex_distances_or_throw(cdt, mesh, options, patch_edges, mesh_descriptor_to_vertex_handle_pmap);
|
|
||||||
|
|
||||||
if(!options.quiet) {
|
|
||||||
auto timing = std::chrono::high_resolution_clock::now() - start_time;
|
|
||||||
std::cout << "[timings] compute distances on "
|
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(timing).count() << " ms\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto _ = CGAL::CDT_3_CONFORMING_TASK_guard();
|
|
||||||
int poly_id = 0;
|
|
||||||
auto output_on_exit_scope_guard = CGAL::make_scope_exit(create_output_finalizer(cdt, options));
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
if(options.merge_facets) {
|
|
||||||
for(auto& edges: patch_edges) {
|
|
||||||
cdt.insert_constrained_face_defined_by_its_border_edges(std::move(edges), pmaps.mesh_vertex_point_map,
|
|
||||||
mesh_descriptor_to_vertex_handle_pmap);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for(auto face_descriptor : faces(mesh)) {
|
|
||||||
std::vector<Point_3> polygon;
|
|
||||||
const auto he = halfedge(face_descriptor, mesh);
|
|
||||||
for(auto vertex_it : CGAL::vertices_around_face(he, mesh)) {
|
|
||||||
polygon.push_back(get(pmaps.mesh_vertex_point_map, vertex_it));
|
|
||||||
}
|
|
||||||
if(cdt.debug_polygon_insertion()) {
|
|
||||||
std::cerr << "NEW POLYGON #" << poly_id << '\n';
|
|
||||||
}
|
|
||||||
[[maybe_unused]] auto id = cdt.insert_constrained_polygon(polygon, false);
|
|
||||||
assert(id == poly_id);
|
|
||||||
++poly_id;
|
|
||||||
// std::ofstream dump("dump.binary.cgal");
|
|
||||||
// CGAL::Mesh_3::save_binary_file(dump, cdt);
|
|
||||||
}
|
|
||||||
} // not merge_facets
|
|
||||||
if(!options.quiet) {
|
|
||||||
auto timing = std::chrono::high_resolution_clock::now() - start_time;
|
|
||||||
std::cout << "[timings] registered facets in "
|
|
||||||
<< std::chrono::duration_cast<std::chrono::milliseconds>(timing).count() << " ms\n";
|
|
||||||
}
|
|
||||||
start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
cdt.restore_Delaunay();
|
|
||||||
if(!options.quiet) {
|
|
||||||
std::cout << "[timings] restored Delaunay (conforming of facets borders) in " << std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
std::chrono::high_resolution_clock::now() - start_time).count() << " ms\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!options.dump_after_conforming_filename.empty()) {
|
|
||||||
auto _ = CGAL::CDT_3_OUTPUT_TASK_guard();
|
auto _ = CGAL::CDT_3_OUTPUT_TASK_guard();
|
||||||
using Vertex_index = Mesh::Vertex_index;
|
using Vertex_index = Mesh::Vertex_index;
|
||||||
[[maybe_unused]] std::size_t time_stamp_counter = 0u;
|
[[maybe_unused]] std::size_t time_stamp_counter = 0u;
|
||||||
for(auto v: cdt.finite_vertex_handles()) {
|
for(auto v : cdt.finite_vertex_handles()) {
|
||||||
[[maybe_unused]] const auto time_stamp = v->time_stamp();
|
[[maybe_unused]] const auto time_stamp = v->time_stamp();
|
||||||
assert(++time_stamp_counter == time_stamp);
|
assert(++time_stamp_counter == time_stamp);
|
||||||
if(!v->ccdt_3_data().is_Steiner_vertex_on_edge()) continue;
|
if(!v->ccdt_3_data().is_Steiner_vertex_on_edge())
|
||||||
|
continue;
|
||||||
const auto [va, vb] = cdt.ancestors_of_Steiner_vertex_on_edge(v);
|
const auto [va, vb] = cdt.ancestors_of_Steiner_vertex_on_edge(v);
|
||||||
const auto index_va = Vertex_index{static_cast<unsigned>(va->time_stamp() - 1)};
|
const auto index_va = Vertex_index{static_cast<unsigned>(va->time_stamp() - 1)};
|
||||||
const auto index_vb = Vertex_index{static_cast<unsigned>(vb->time_stamp() - 1)};
|
const auto index_vb = Vertex_index{static_cast<unsigned>(vb->time_stamp() - 1)};
|
||||||
|
|
@ -889,36 +650,28 @@ int go(Mesh mesh, CDT_options options) {
|
||||||
out_mesh.precision(17);
|
out_mesh.precision(17);
|
||||||
out_mesh << mesh;
|
out_mesh << mesh;
|
||||||
out_mesh.close();
|
out_mesh.close();
|
||||||
}
|
};
|
||||||
|
|
||||||
|
// Build CDT directly from the polygon mesh using the official API
|
||||||
|
auto build_start = std::chrono::high_resolution_clock::now();
|
||||||
|
CDT cdt{std::invoke([&]() {
|
||||||
|
auto np = CGAL::parameters::debug(cdt_debug).visitor(std::ref(dump_mesh_with_steiner_points));
|
||||||
|
return options.merge_facets ? CDT(mesh, np.plc_face_id(pmaps.patch_id_map)) : CDT(mesh, np);
|
||||||
|
})};
|
||||||
if(!options.quiet) {
|
if(!options.quiet) {
|
||||||
std::cout << "Number of vertices after conforming: " << cdt.number_of_vertices() << "\n\n";
|
auto timing = std::chrono::high_resolution_clock::now() - build_start;
|
||||||
|
std::cout << "[timings] built CDT from mesh in "
|
||||||
|
<< std::chrono::duration_cast<std::chrono::milliseconds>(timing).count() << " ms\n";
|
||||||
|
std::cout << "Number of vertices: " << cdt.number_of_vertices() << "\n\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Validation: check conforming status and validity
|
||||||
{
|
{
|
||||||
auto _ = CGAL::CDT_3_VALIDATION_TASK_guard();
|
auto _ = CGAL::CDT_3_VALIDATION_TASK_guard();
|
||||||
CGAL_assertion(!options.call_is_valid || cdt.Base_triantulation::is_valid(true));
|
|
||||||
CGAL_assertion(!options.call_is_valid || cdt.is_valid(true));
|
CGAL_assertion(!options.call_is_valid || cdt.is_valid(true));
|
||||||
CGAL_assertion(!options.call_is_valid || cdt.is_conforming());
|
CGAL_assertion(!options.call_is_valid || cdt.is_conforming());
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
|
||||||
auto _ = CGAL::CDT_3_CDT_TASK_guard();
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now();
|
|
||||||
cdt.restore_constrained_Delaunay();
|
|
||||||
if(!options.quiet) {
|
|
||||||
std::cout << "[timings] restored constrained Delaunay in " << std::chrono::duration_cast<std::chrono::milliseconds>(
|
|
||||||
std::chrono::high_resolution_clock::now() - start_time).count() << " ms\n";
|
|
||||||
std::cout << "Number of vertices after CDT: " << cdt.number_of_vertices() << "\n\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto _ = CGAL::CDT_3_VALIDATION_TASK_guard();
|
|
||||||
CGAL_assertion(!options.call_is_valid || cdt.is_conforming());
|
|
||||||
CGAL_assertion(!options.call_is_valid || cdt.is_valid(true));
|
|
||||||
}
|
|
||||||
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1008,9 +761,6 @@ int bisect_errors(Mesh mesh, CDT_options options) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
CDT::Conforming_Dt::with_offset.offset = -1;
|
|
||||||
CDT::Conforming_Dt::with_point.offset = -1;
|
|
||||||
CDT::Conforming_Dt::with_point_and_info.offset = -1;
|
|
||||||
std::cerr.precision(17);
|
std::cerr.precision(17);
|
||||||
std::cout.precision(17);
|
std::cout.precision(17);
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue