final fix for `is_edge` with the hash set

This commit is contained in:
Laurent Rineau 2024-04-05 16:39:26 +02:00
parent 9077dec742
commit ce3daa342b
3 changed files with 56 additions and 30 deletions

View File

@ -466,7 +466,7 @@ public:
}
bool use_finite_edges_map() const {
return debug_flags[static_cast<int>(Debug_flags::use_finite_edges_map)];
return update_all_finite_edges_ && debug_flags[static_cast<int>(Debug_flags::use_finite_edges_map)];
}
void use_finite_edges_map(bool b) {
@ -497,13 +497,32 @@ public:
return id;
}
bool is_edge(Vertex_handle va, Vertex_handle vb) const {
const bool is_edge_v1 =
((debug_finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr.tds().is_edge(va, vb);
const bool is_edge_v2 =
use_finite_edges_map() && all_finite_edges.find(make_sorted_pair(va, vb)) != all_finite_edges.end();
if(debug_finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) {
std::cerr << "!! Inconsistent edge status\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_v2 ? "is" : "is not") << " in all_finite_edges\n";
debug_dump("bug-inconsistent-edge-status");
CGAL_error();
}
const bool is_edge = use_finite_edges_map() ? is_edge_v2 : is_edge_v1;
return is_edge;
}
using T_3::is_edge;
bool is_conforming() const {
return std::all_of(constraint_hierarchy.sc_begin(),
constraint_hierarchy.sc_end(),
[this](const auto &sc) {
const auto va = sc.first.first;
const auto vb = sc.first.second;
const auto is_edge = this->tr.tds().is_edge(va, vb);
const auto is_edge = this->is_edge(va, vb);
#if CGAL_DEBUG_CDT_3 & 128 && __has_include(<format>)
std::cerr << std::format("is_conforming>> Edge is 3D: {} ({} , {})\n",
is_edge,
@ -592,7 +611,7 @@ public:
std::for_each(
constraint_hierarchy.sc_begin(), constraint_hierarchy.sc_end(),
[this, &out, &any_missing_segment](const auto &sc) {
if (!tr.tds().is_edge(sc.first.first, sc.first.second)) {
if (!this->is_edge(sc.first.first, sc.first.second)) {
const auto v0 = sc.first.first;
const auto v1 = sc.first.second;
out << "2 " << this->tr.point(v0) << " " << this->tr.point(v1)
@ -639,6 +658,7 @@ protected:
template <typename Visitor>
void restore_Delaunay(Visitor& visitor) {
update_all_finite_edges();
while(!subconstraints_to_conform.empty()) {
const auto [subconstraint, constraint_id] = subconstraints_to_conform.top();
subconstraints_to_conform.pop();
@ -685,20 +705,7 @@ protected:
const Vertex_handle va = subconstraint.first;
const Vertex_handle vb = subconstraint.second;
CGAL_assertion(va != vb);
const bool is_edge_v1 =
((debug_finite_edges_map() && use_finite_edges_map()) || !use_finite_edges_map()) && tr.tds().is_edge(va, vb);
const bool is_edge_v2 =
use_finite_edges_map() && all_finite_edges.find(make_sorted_pair(va, vb)) != all_finite_edges.end();
if(debug_finite_edges_map() && use_finite_edges_map() && is_edge_v1 != is_edge_v2) {
std::cerr << "!! Inconsistent edge status\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_v2 ? "is" : "is not") << " in all_finite_edges\n";
debug_dump("bug-inconsistent-edge-status");
CGAL_error();
}
const bool is_edge = use_finite_edges_map() ? is_edge_v2 : is_edge_v1;
if(!is_edge) {
if(!this->is_edge(va, vb)) {
const auto& [steiner_pt, hint, ref_vertex] = construct_Steiner_point(constraint, subconstraint);
[[maybe_unused]] const auto v =
insert_Steiner_point_on_subconstraint(steiner_pt, hint, subconstraint, constraint, visitor);
@ -1015,6 +1022,20 @@ protected:
using Hash = boost::hash<Pair_of_vertex_handles>;
std::unordered_set<Pair_of_vertex_handles, Hash> all_finite_edges;
bool update_all_finite_edges_ = false;
void update_all_finite_edges() {
if(!update_all_finite_edges_) {
update_all_finite_edges_ = true;
if(use_finite_edges_map()) {
all_finite_edges.clear();
all_finite_edges.reserve(tr.number_of_finite_edges());
for(auto e: tr.all_edges()) {
new_edge(e);
}
}
}
}
enum class Debug_flags {
Steiner_points = 0,

View File

@ -1296,7 +1296,7 @@ private:
CGAL_assertion(!cdt_2.is_edge(vb, vd));
const auto vb_3d = vb->info().vertex_handle_3d;
const auto vd_3d = vd->info().vertex_handle_3d;
if(tr.tds().is_edge(vb_3d, vd_3d)) {
if(this->is_edge(vb_3d, vd_3d)) {
// let's insert the diagonal [bd] in the CDT_2
cdt_2.insert_constraint(vb, vd);
#if CGAL_DEBUG_CDT_3 & 64
@ -2178,12 +2178,12 @@ private:
("NOTE: diagonal: {:.6} {:.6} {} in tr\n",
IO::oformat(*diagonal.begin(), with_point),
IO::oformat(*std::next(diagonal.begin()), with_point),
tr.tds().is_edge(*diagonal.begin(), *std::next(diagonal.begin())) ? "IS" : "is NOT");
this->is_edge(*diagonal.begin(), *std::next(diagonal.begin())) ? "IS" : "is NOT");
std::cerr << std::format(
"NOTE: the other diagonal: {:.6} {:.6} {} in tr\n",
IO::oformat(*other_diagonal.begin(), with_point),
IO::oformat(*std::next(other_diagonal.begin()), with_point),
tr.tds().is_edge(*other_diagonal.begin(), *std::next(other_diagonal.begin())) ? "IS" : "is NOT");
this->is_edge(*other_diagonal.begin(), *std::next(other_diagonal.begin())) ? "IS" : "is NOT");
if(cdt_2.geom_traits().side_of_oriented_circle_2_object()(
(*region_border_vertices.begin())->point(), (*std::next(region_border_vertices.begin()))->point(),
(*std::next(region_border_vertices.begin(), 2))->point(),
@ -2979,7 +2979,7 @@ private:
const auto i = edge.second;
const auto va_3d = fh->vertex(cdt_2.cw(i))->info().vertex_handle_3d;
const auto vb_3d = fh->vertex(cdt_2.ccw(i))->info().vertex_handle_3d;
const bool is_3d = this->tds().is_edge(va_3d, vb_3d);
const bool is_3d = this->is_edge(va_3d, vb_3d);
#if CGAL_CDT_3_CAN_USE_CXX20_FORMAT
if(this->debug_copy_triangulation_into_hole()) {
std::cerr << std::format("Edge is 3D: {:6} ({} , {})\n",
@ -3150,7 +3150,7 @@ public:
<< " != number_of_finite_edges() = " << this->number_of_finite_edges() << std::endl;
}
for(auto e: this->all_finite_edges) {
test = this->tds().is_edge(e.first, e.second);
test = this->is_edge(e.first, e.second);
result = result && test;
if(!test && verbose) {
std::cerr << "edge (" << IO::oformat(e.first, with_point_and_info) << ", "

View File

@ -54,8 +54,8 @@ using K = CGAL::Exact_predicates_inexact_constructions_kernel;
#endif // use Epick
using Vb = CGAL::Constrained_Delaunay_triangulation_vertex_base_3<K>;
using Cb = CGAL::Constrained_Delaunay_triangulation_cell_base_3<K>;
struct Vb : public CGAL::Constrained_Delaunay_triangulation_vertex_base_3<K> {};
struct Cb : public CGAL::Constrained_Delaunay_triangulation_cell_base_3<K> {};
using Tds = CGAL::Triangulation_data_structure_3<Vb, Cb>;
using Delaunay = CGAL::Delaunay_triangulation_3<K, Tds>;
using CDT = CGAL::Constrained_Delaunay_triangulation_3<Delaunay>;
@ -81,6 +81,7 @@ struct CDT_options
bool debug_validity = false;
bool debug_finite_edges_map = false;
bool use_finite_edges_map = false;
bool call_is_valid = true;
double ratio = 0.1;
double vertex_vertex_epsilon = 1e-14;
double segment_vertex_epsilon = 1e-14;
@ -196,6 +197,8 @@ int main(int argc, char* argv[])
options.coplanar_polygon_max_distance = std::stod(argv[++i]);
} else if(arg == "--quiet") {
options.quiet = true;
} else if(arg == "--no-is-valid") {
options.call_is_valid = false;
} else if(arg == "--debug-missing-regions") {
options.debug_missing_regions = true;
} else if(arg == "--debug-regions") {
@ -545,9 +548,11 @@ int go(Mesh mesh, CDT_options options) {
CGAL_CDT_3_TASK_BEGIN(insert_vertices_task_handle);
auto start_time = std::chrono::high_resolution_clock::now();
CDT::Cell_handle hint{};
for(auto v: vertices(mesh)) {
if(options.merge_facets && false == get(v_selected_map, v)) continue;
auto vh = cdt.insert(get(pmap, v));
auto vh = cdt.insert(get(pmap, v), hint, false);
hint = vh->cell();
put(tr_vertex_pmap, v, vh);
}
if(!options.quiet) {
@ -776,9 +781,9 @@ int go(Mesh mesh, CDT_options options) {
std::cerr << "Number of vertices after conforming: " << cdt.number_of_vertices() << "\n\n";
}
CGAL_CDT_3_TASK_BEGIN(validation_task_handle);
CGAL_assertion(cdt.Delaunay::is_valid(true));
CGAL_assertion(cdt.is_valid(true));
CGAL_assertion(cdt.is_conforming());
CGAL_assertion(!options.call_is_valid || cdt.Delaunay::is_valid(true));
CGAL_assertion(!options.call_is_valid || cdt.is_valid(true));
CGAL_assertion(!options.call_is_valid || cdt.is_conforming());
CGAL_CDT_3_TASK_END(validation_task_handle);
if(exit_code == EXIT_SUCCESS) {
try {
@ -802,8 +807,8 @@ int go(Mesh mesh, CDT_options options) {
finally();
CGAL_CDT_3_TASK_BEGIN(validation_task_handle);
CGAL_assertion(cdt.is_conforming());
CGAL_assertion(cdt.is_valid(true));
CGAL_assertion(!options.call_is_valid || cdt.is_conforming());
CGAL_assertion(!options.call_is_valid || cdt.is_valid(true));
CGAL_CDT_3_TASK_END(validation_task_handle);
return exit_code;