From 2434b2437be01a6fe675edefee855e3765da1cef Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 4 May 2023 09:54:40 +0200 Subject: [PATCH 01/60] fix an UBSAN report when `ch` is null --- TDS_3/include/CGAL/Triangulation_simplex_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TDS_3/include/CGAL/Triangulation_simplex_3.h b/TDS_3/include/CGAL/Triangulation_simplex_3.h index aa2109b89ced..8bb4188f4420 100644 --- a/TDS_3/include/CGAL/Triangulation_simplex_3.h +++ b/TDS_3/include/CGAL/Triangulation_simplex_3.h @@ -180,7 +180,7 @@ operator==(Triangulation_simplex_3 s0, } return false; case (3): - return (&(*s0.ch) == &(*s1.ch)); + return s0.ch.operator->() == s1.ch.operator->(); } CGAL_error(); return false; From dd738bf0297ceff9bd71186360661ff0a0891094 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 4 May 2023 09:55:10 +0200 Subject: [PATCH 02/60] bug fix for the simplex traverser --- .../Triangulation_segment_traverser_3_impl.h | 1 + .../CGAL/Triangulation_segment_traverser_3.h | 13 ++++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 663032162a4d..f7411f652e8f 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -241,6 +241,7 @@ walk_to_next() { // The target is inside the cell. _prev = Simplex( cell(), Tr::VERTEX, ti, -1 ); cell() = Cell_handle(); + lt() = Locate_type::VERTEX; return; } diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 76b0f7572e30..49ba25ccd3e3 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -228,6 +228,8 @@ class Triangulation_segment_cell_iterator_3 */ const Point& target() const { return _target; } + Vertex_handle target_vertex() const { return _t_vertex; } + // gives a handle to the current cell. /* By invariance, this cell is intersected by the segment * between `source()` and `target()`. @@ -809,7 +811,7 @@ class Triangulation_segment_simplex_iterator_3 else ch = _cell_iterator.previous(); - Cell_handle chnext = Cell_handle(_cell_iterator); + const Cell_handle chnext = Cell_handle(_cell_iterator); //_cell_iterator is one step forward _curr_simplex CGAL_assertion(ch != chnext); @@ -834,8 +836,13 @@ class Triangulation_segment_simplex_iterator_3 { if (prev == ch && ltprev == Locate_type::VERTEX) { - CGAL_assertion(prev->vertex(liprev) == get_vertex()); - _curr_simplex = ch; + const auto current_vertex = get_vertex(); + if(current_vertex == _cell_iterator.target_vertex()) { + _curr_simplex = Simplex_3(); + } else { + CGAL_assertion(prev->vertex(liprev) == _cell_iterator.target_vertex()); + _curr_simplex = ch; + } } else { From 5893f7f4c43af42a12fb4c5e483d253ef8b26088 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 20 Jan 2023 13:54:29 +0100 Subject: [PATCH 03/60] Introduce Base_with_time_stamp --- .../include/CGAL/Base_with_time_stamp.h | 48 +++++++++++++++++++ .../test/Triangulation_2/issue_4405.cpp | 31 +----------- .../test_cdt_degenerate_case.cpp | 31 +----------- 3 files changed, 52 insertions(+), 58 deletions(-) create mode 100644 STL_Extension/include/CGAL/Base_with_time_stamp.h diff --git a/STL_Extension/include/CGAL/Base_with_time_stamp.h b/STL_Extension/include/CGAL/Base_with_time_stamp.h new file mode 100644 index 000000000000..1e2dbeff0881 --- /dev/null +++ b/STL_Extension/include/CGAL/Base_with_time_stamp.h @@ -0,0 +1,48 @@ +// Copyright (c) 2023 GeometryFactory Sarl (France). +// All rights reserved. +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Laurent Rineau + +#ifndef CGAL_BASE_WITH_TIME_STAMP_H +#define CGAL_BASE_WITH_TIME_STAMP_H + +#include // for Tag_true +#include // for std::size_t +#include // for std::forward + +namespace CGAL { + +template +class Base_with_time_stamp : public Base { + std::size_t time_stamp_ = -1; +public: + using Base::Base; + + Base_with_time_stamp(const Base_with_time_stamp& other) : + Base(other), + time_stamp_(other.time_stamp_) + {} + + typedef CGAL::Tag_true Has_timestamp; + + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + template < class TDS > + struct Rebind_TDS { + typedef typename Base::template Rebind_TDS::Other Base2; + typedef Base_with_time_stamp Other; + }; +}; + +} // namespace CGAL + +#endif // CGAL_BASE_WITH_TIME_STAMP_H diff --git a/Triangulation_2/test/Triangulation_2/issue_4405.cpp b/Triangulation_2/test/Triangulation_2/issue_4405.cpp index 770cd6c761c4..d01f3f7a2342 100644 --- a/Triangulation_2/test/Triangulation_2/issue_4405.cpp +++ b/Triangulation_2/test/Triangulation_2/issue_4405.cpp @@ -4,47 +4,20 @@ #include #include #include +#include typedef CGAL::Epick Kernel; typedef Kernel::FT FieldNumberType; typedef Kernel::Point_2 Point2; typedef Kernel::Point_3 Point3; -template -class My_vertex_base : public Vb { - std::size_t time_stamp_; -public: - My_vertex_base() : Vb(), time_stamp_(-1) { - } - - My_vertex_base(const My_vertex_base& other) : - Vb(other), - time_stamp_(other.time_stamp_) - {} - - typedef CGAL::Tag_true Has_timestamp; - - std::size_t time_stamp() const { - return time_stamp_; - } - void set_time_stamp(const std::size_t& ts) { - time_stamp_ = ts; - } - - template < class TDS > - struct Rebind_TDS { - typedef typename Vb::template Rebind_TDS::Other Vb2; - typedef My_vertex_base Other; - }; -}; - struct FaceInfo2 { unsigned long long m_id; }; typedef CGAL::Projection_traits_xy_3 TriangulationTraits; typedef CGAL::Triangulation_vertex_base_with_id_2 VertexBaseWithId; -typedef My_vertex_base Vb2; +typedef CGAL::Base_with_time_stamp Vb2; typedef CGAL::Triangulation_vertex_base_2 VertexBase; typedef CGAL::Triangulation_face_base_with_info_2 FaceBaseWithInfo; typedef CGAL::Constrained_triangulation_face_base_2 FaceBase; diff --git a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp index b4de0e1e0f72..3c2bcf48f3ff 100644 --- a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp +++ b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp @@ -2,41 +2,14 @@ #include #include #include +#include #include typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC; typedef EPIC::Point_2 Point_2; -template -class My_vertex_base : public Vb { - std::size_t time_stamp_; -public: - My_vertex_base() : Vb(), time_stamp_(-1) { - } - - My_vertex_base(const My_vertex_base& other) : - Vb(other), - time_stamp_(other.time_stamp_) - {} - - typedef CGAL::Tag_true Has_timestamp; - - std::size_t time_stamp() const { - return time_stamp_; - } - void set_time_stamp(const std::size_t& ts) { - time_stamp_ = ts; - } - - template < class TDS > - struct Rebind_TDS { - typedef typename Vb::template Rebind_TDS::Other Vb2; - typedef My_vertex_base Other; - }; -}; - #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS -typedef My_vertex_base > Vb; +typedef CGAL::Base_with_time_stamp > Vb; #else typedef CGAL::Triangulation_vertex_base_2 Vb; #endif From 36b349167236e53ab4c4d5a23c85c7534f2c2b92 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 5 May 2023 15:30:43 +0200 Subject: [PATCH 04/60] add a new test case vfefv for the simplex traverser For the moment, that new test fails. --- STL_Extension/include/CGAL/Iterator_range.h | 7 + .../test_segment_simplex_traverser_3.cpp | 201 ++++++++++++++---- 2 files changed, 169 insertions(+), 39 deletions(-) diff --git a/STL_Extension/include/CGAL/Iterator_range.h b/STL_Extension/include/CGAL/Iterator_range.h index e1d41818d5a7..e42441e98588 100644 --- a/STL_Extension/include/CGAL/Iterator_range.h +++ b/STL_Extension/include/CGAL/Iterator_range.h @@ -78,6 +78,13 @@ namespace CGAL { { return std::tuple{this->first, this->second}; } + + template class Container> + auto to() const + { + using V = std::remove_cv_t>; + return Container(begin(), end()); + } }; template diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index eb1fa780be49..eae0282b2af5 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -17,14 +19,162 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef Kernel::Point_3 Point_3; // Define the structure. -typedef CGAL::Delaunay_triangulation_3 DT; +typedef CGAL::Base_with_time_stamp> Vb; +typedef CGAL::Delaunay_triangulation_cell_base_3 Cb; +typedef CGAL::Triangulation_data_structure_3 Tds; +typedef CGAL::Delaunay_triangulation_3 DT; typedef DT::Cell_handle Cell_handle; +typedef DT::Edge Edge; +typedef DT::Facet Facet; +typedef DT::Vertex_handle Vertex_handle; typedef DT::Segment_simplex_iterator Segment_simplex_iterator; +// a function to insert without spatial sorting +template +void insert(DT& dt, Point_it first, Point_it end) { + for(; first != end; ++first) { + dt.insert(*first); + } +} +// trick to avoid a conflict with CGAL-5.6 +// -> specialization of Output_rep for `CC_iterator` *and* `My` +struct My {}; +template +class CGAL::Output_rep, My > { +protected: + using CC_iterator = CGAL::internal::CC_iterator; + using Compact_container = typename CC_iterator::CC; + using Time_stamper = typename Compact_container::Time_stamper; + CC_iterator it; +public: + Output_rep( const CC_iterator it) : it(it) {} + std::ostream& operator()( std::ostream& out) const { + return out << '#' << it->time_stamp(); + } +}; +auto display_vert(Vertex_handle v) { + std::stringstream os; + os.precision(17); + os << CGAL::IO::oformat(v, My()) << "=(" << v->point() << ")"; + return os.str(); +}; +template +struct Debug_simplex { + Simplex simplex; + + template + friend + std::basic_ostream& + operator<<(std::basic_ostream& os, const Debug_simplex& d) { + auto&& simplex = d.simplex; + switch(simplex.dimension()) { + case 0: { + os << " vertex " << display_vert(static_cast(simplex)); + break; + } + case 1: { + const auto [c, index1, index2] = static_cast(simplex); + os << " egde " + << display_vert(c->vertex(index1)) << " - " + << display_vert(c->vertex(index2)); + break; + } + case 2: { + const auto [c, index] = static_cast(simplex); + os << " facet " + << display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - " + << display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - " + << display_vert(c->vertex(DT::vertex_triple_index(index, 2))); + break; + } + case 3: { + const auto c = static_cast(simplex); + os << " cell " + << display_vert(c->vertex(0)) << " - " + << display_vert(c->vertex(1)) << " - " + << display_vert(c->vertex(2)) << " - " + << display_vert(c->vertex(3)); + break; + } + default: CGAL_assume(false); + } + return os; + }; +}; +template +auto debug_simplex(Simplex simplex) { + return Debug_simplex{simplex}; +} + +DT dt; +std::string result_string; + +auto visit_simplex = [](auto s) { + auto d = s.dimension(); + if(3 == d && dt.is_infinite(static_cast(s))) { + result_string += 'I'; + } else { + result_string += std::to_string(d); + } + std::cout << debug_simplex(s) << '\n'; +}; + +bool test_vfefv(bool with_bbox = false) +{ + std::cerr << "## test_vfefv(" << std::boolalpha << with_bbox << ")\n"; + result_string.clear(); + static const std::vector points = + { + { -1, 0, 0 }, + { 0, 1, 0 }, + { 0, -1, 0 }, + { 5, 0, 0 }, + { 6, 2, 2 }, + { 6, -2, -2 }, + }; + + static const std::vector bbox_points = + { + { -10, -10, -10 }, + { -10, 10, -10 }, + { 10, 10, -10 }, + { 10, -10, -10 }, + { -10, -10, 10 }, + { -10, 10, 10 }, + { 10, 10, 10 }, + { 10, -10, 10 }, + }; + + dt.clear(); + insert(dt, points.begin(), points.end()); + if(with_bbox) insert(dt, bbox_points.begin(), bbox_points.end()); + + const auto v = dt.finite_vertex_handles().to(); + + Cell_handle c; int i, j, k; + assert(dt.is_facet(v[0], v[1], v[2], c, i, j, k)); + assert(dt.is_facet(v[1], v[2], v[3], c, i, j, k)); + assert(dt.is_cell (v[1], v[2], v[3], v[4], c)); + assert(dt.is_cell (v[1], v[2], v[3], v[5], c)); + + for(auto s: dt.segment_traverser_simplices(v[0], v[3])) { + visit_simplex(s); + } + static const std::string expected_result_string = "02120"; + bool ok = (result_string == expected_result_string); + if(!ok) { + std::cerr << "test_vfefv failed\n"; + std::cerr << " result_string is " << result_string << " instead of " + << expected_result_string << '\n'; + } + return ok; +} + bool test(const DT& dt, const std::pair& query, const std::array& expected_result); + int main(int, char* []) { const std::vector points = { { -2, 0, 0 }, @@ -43,7 +193,7 @@ int main(int, char* []) }; std::vector vertices; vertices.reserve(points.size()); - DT dt; + dt.clear(); for(auto p: points) vertices.push_back(dt.insert(p)); Cell_handle c; assert(dt.is_valid()); @@ -79,6 +229,8 @@ int main(int, char* []) if(!test(dt, queries[i], expected_results[i])) ok = false; } std::cout << "Done (" << queries.size() << " queries)\n"; + ok = test_vfefv() && ok; + ok = test_vfefv(true) && ok; return ok ? EXIT_SUCCESS : EXIT_FAILURE; } @@ -108,46 +260,17 @@ bool test(const DT& dt, else { ++fin; + visit_simplex(*st); + switch (st->dimension()) { - case 2: { - ++nb_facets; - std::cout << "facet " << std::endl; - DT::Facet f = *st; - std::cout << " ( " << f.first->vertex((f.second + 1) & 3)->point() - << " " << f.first->vertex((f.second + 2) & 3)->point() - << " " << f.first->vertex((f.second + 3) & 3)->point() - << " )\n"; - break; - } - case 1: { - ++nb_edges; - std::cout << "edge " << std::endl; - DT::Edge e = *st; - std::cout << " ( " << e.first->vertex(e.second)->point() << " " - << e.first->vertex(e.third)->point() << " )\n"; - break; - } - case 0: { - ++nb_vertex; - std::cout << "vertex " << std::endl; - DT::Vertex_handle v = *st; - std::cout << " ( " << v->point() << " )\n"; - break; - } - case 3: { - ++nb_cells; - std::cout << "cell \n ( "; - DT::Cell_handle ch = *st; - for (int i = 0; i < 4; ++i) - std::cout << ch->vertex(i)->point() << " "; - std::cout << " )\n"; - break; + case 2: ++nb_facets; break; + case 1: ++nb_edges; break; + case 0: ++nb_vertex; break; + case 3: ++nb_cells; break; + default: CGAL_unreachable(); } - default: - CGAL_unreachable(); - } // end switch + } } -} #ifdef CGAL_TRIANGULATION_3_VERBOSE_TRAVERSER_EXAMPLE std::cout << "While traversing from " << st.source() From 2220a1815ad902a416065df79ebba56bd15156e7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 5 May 2023 15:42:43 +0200 Subject: [PATCH 05/60] arg, a trailing whitespace! --- .../test/Triangulation_3/test_segment_simplex_traverser_3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index eae0282b2af5..3b43e1605ed7 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -124,7 +124,7 @@ bool test_vfefv(bool with_bbox = false) std::cerr << "## test_vfefv(" << std::boolalpha << with_bbox << ")\n"; result_string.clear(); static const std::vector points = - { + { { -1, 0, 0 }, { 0, 1, 0 }, { 0, -1, 0 }, From 4a0b1477f9f87240eaec52fff4edc7fbb18f967c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 5 May 2023 16:55:04 +0200 Subject: [PATCH 06/60] new test cases --- .../test/Triangulation_3/CMakeLists.txt | 1 + .../test_segment_simplex_traverser_3.cpp | 81 ++++++++++++++++--- 2 files changed, 70 insertions(+), 12 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/CMakeLists.txt b/Triangulation_3/test/Triangulation_3/CMakeLists.txt index 0cee5c47bfbe..cbeb76d235bc 100644 --- a/Triangulation_3/test/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/test/Triangulation_3/CMakeLists.txt @@ -26,6 +26,7 @@ create_single_source_cgal_program("test_simplex_3.cpp") create_single_source_cgal_program( "test_simplex_iterator_3.cpp" ) create_single_source_cgal_program( "test_segment_cell_traverser_3.cpp" ) create_single_source_cgal_program( "test_segment_simplex_traverser_3.cpp" ) +target_compile_features(test_segment_simplex_traverser_3 PRIVATE cxx_std_17) create_single_source_cgal_program("test_static_filters.cpp") create_single_source_cgal_program("test_triangulation_3.cpp") create_single_source_cgal_program("test_io_triangulation_3.cpp") diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 3b43e1605ed7..efd746544e6f 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -106,6 +106,18 @@ auto debug_simplex(Simplex simplex) { return Debug_simplex{simplex}; } +static const std::vector bbox_points = +{ + { -10.1, -10, -10 }, + { -10.2, 10, -10 }, + { 10.3, 10, -10 }, + { 10.4, -10, -10 }, + { -10.5, -10, 10 }, + { -10.6, 10, 10 }, + { 10.7, 10, 10 }, + { 10.8, -10, 10 }, + }; + DT dt; std::string result_string; @@ -133,18 +145,6 @@ bool test_vfefv(bool with_bbox = false) { 6, -2, -2 }, }; - static const std::vector bbox_points = - { - { -10, -10, -10 }, - { -10, 10, -10 }, - { 10, 10, -10 }, - { 10, -10, -10 }, - { -10, -10, 10 }, - { -10, 10, 10 }, - { 10, 10, 10 }, - { 10, -10, 10 }, - }; - dt.clear(); insert(dt, points.begin(), points.end()); if(with_bbox) insert(dt, bbox_points.begin(), bbox_points.end()); @@ -170,6 +170,62 @@ bool test_vfefv(bool with_bbox = false) return ok; } +bool test_a_simple_tetrahedron() { + std::cerr << "## test_a_simple_tetrahedron()\n"; + bool ok = true; + auto test = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { + bool exception_thrown = false; + dt.clear(); + dt.insert({0, 0, 0}); + dt.insert({1, 0, 0}); + dt.insert({0, 1, 0}); + dt.insert({0, 0, 1}); + if(with_bbox) insert(dt, bbox_points.begin(), bbox_points.end()); + result_string.clear(); + std::cerr << "### Case " << expected_result; + if(with_bbox) std::cerr << " with bbox"; + std::cerr << '\n'; + try { + for(auto s: dt.segment_traverser_simplices(a, b)) { + visit_simplex(s); + } + } catch(const CGAL::Assertion_exception& e) { + CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(), + e.filename().c_str(), + e.line_number(), + e.message().c_str()); + exception_thrown = true; + } + if(result_string != expected_result) { + std::cerr << "test_a_simple_tetrahedron failed\n"; + std::cerr << " result_string is " << result_string << " instead of " + << expected_result << '\n'; + ok = false; + } + if(exception_thrown) { + std::cerr << "test_a_simple_tetrahedron failed\n"; + std::cerr << " exception thrown\n"; + ok = false; + } + }; + + test({ 0, 0, 0}, { 1, 0, 0}, false, "010"); + test({ 0, 0, 0}, { 2, 0, 0}, false, "010I"); + test({-1, 0, 0}, { 2, 0, 0}, false, "I010I"); + test({ 0, 0, 0}, {.5, .5, 0}, false, "021"); + test({ 0, 0, 0}, { 1, 1, 0}, false, "021I"); + test({-1, -1, 0}, { 1, 1, 0}, false, "I021I"); + + test({ 0, 0, 0}, { 1, 0, 0}, true, "010"); + test({ 0, 0, 0}, { 2, 0, 0}, true, "0103"); + test({-1, 0, 0}, { 2, 0, 0}, true, "30103"); + test({ 0, 0, 0}, {.5, .5, 0}, true, "021"); + test({ 0, 0, 0}, { 1, 1, 0}, true, "0213"); + test({-1, -1, 0}, { 1, 1, 0}, true, "30213"); + + return ok; +} + bool test(const DT& dt, const std::pair& query, const std::array& expected_result); @@ -231,6 +287,7 @@ int main(int, char* []) std::cout << "Done (" << queries.size() << " queries)\n"; ok = test_vfefv() && ok; ok = test_vfefv(true) && ok; + ok = test_a_simple_tetrahedron() && ok; return ok ? EXIT_SUCCESS : EXIT_FAILURE; } From 6325190a73f44f4e954cd1851a8c3c6292a824cd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 9 May 2023 12:35:09 +0200 Subject: [PATCH 07/60] even more test cases --- .../test_segment_simplex_traverser_3.cpp | 180 +++++++++++------- 1 file changed, 108 insertions(+), 72 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index efd746544e6f..711d314e5dd6 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -36,26 +36,14 @@ void insert(DT& dt, Point_it first, Point_it end) { dt.insert(*first); } } -// trick to avoid a conflict with CGAL-5.6 -// -> specialization of Output_rep for `CC_iterator` *and* `My` -struct My {}; -template -class CGAL::Output_rep, My > { -protected: - using CC_iterator = CGAL::internal::CC_iterator; - using Compact_container = typename CC_iterator::CC; - using Time_stamper = typename Compact_container::Time_stamper; - CC_iterator it; -public: - Output_rep( const CC_iterator it) : it(it) {} - std::ostream& operator()( std::ostream& out) const { - return out << '#' << it->time_stamp(); - } -}; auto display_vert(Vertex_handle v) { std::stringstream os; os.precision(17); - os << CGAL::IO::oformat(v, My()) << "=(" << v->point() << ")"; + if(v->time_stamp() == 0) { + os << "inf"; + } else { + os << '#' << v->time_stamp() << "=(" << v->point() << ")"; + } return os.str(); }; template @@ -108,14 +96,14 @@ auto debug_simplex(Simplex simplex) { static const std::vector bbox_points = { - { -10.1, -10, -10 }, - { -10.2, 10, -10 }, - { 10.3, 10, -10 }, - { 10.4, -10, -10 }, - { -10.5, -10, 10 }, - { -10.6, 10, 10 }, - { 10.7, 10, 10 }, - { 10.8, -10, 10 }, + { -10.1, -10, -10.08 }, + { -10.2, 10, -10.07 }, + { 10.3, 10, -10.06 }, + { 10.4, -10, -10.05 }, + { -10.5, -10, 10.04 }, + { -10.6, 10, 10.03 }, + { 10.7, 10, 10.02 }, + { 10.8, -10, 10.01 }, }; DT dt; @@ -172,57 +160,105 @@ bool test_vfefv(bool with_bbox = false) bool test_a_simple_tetrahedron() { std::cerr << "## test_a_simple_tetrahedron()\n"; + DT dt2; + dt2.insert({0, 0, 0}); + dt2.insert({1, 0, 0}); + dt2.insert({0, 1, 0}); + dt2.insert({0, 0, 1}); bool ok = true; - auto test = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { - bool exception_thrown = false; - dt.clear(); - dt.insert({0, 0, 0}); - dt.insert({1, 0, 0}); - dt.insert({0, 1, 0}); - dt.insert({0, 0, 1}); - if(with_bbox) insert(dt, bbox_points.begin(), bbox_points.end()); - result_string.clear(); - std::cerr << "### Case " << expected_result; - if(with_bbox) std::cerr << " with bbox"; - std::cerr << '\n'; - try { - for(auto s: dt.segment_traverser_simplices(a, b)) { - visit_simplex(s); + auto test = [&](Point_3 a, Point_3 b, std::string expected_result) { + // This test function calls `do_test` with four configurations: + // - with [ab] and [ba], + // - and with or without a bbox around the central tetrahedron. + dt = dt2; + auto do_test = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { + std::cerr << "### Case " << expected_result; + if(with_bbox) std::cerr << " with bbox"; + std::cerr << '\n'; + std::cerr << "from (" << a << ") to (" << b << ")\n"; + bool exception_thrown = false; + result_string.clear(); + try { + for(auto s: dt.segment_traverser_simplices(a, b)) { + visit_simplex(s); + } + } catch(const CGAL::Assertion_exception& e) { + CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(), + e.filename().c_str(), + e.line_number(), + e.message().c_str()); + exception_thrown = true; } - } catch(const CGAL::Assertion_exception& e) { - CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(), - e.filename().c_str(), - e.line_number(), - e.message().c_str()); - exception_thrown = true; - } - if(result_string != expected_result) { - std::cerr << "test_a_simple_tetrahedron failed\n"; - std::cerr << " result_string is " << result_string << " instead of " - << expected_result << '\n'; - ok = false; - } - if(exception_thrown) { - std::cerr << "test_a_simple_tetrahedron failed\n"; - std::cerr << " exception thrown\n"; - ok = false; - } + if(result_string != expected_result || exception_thrown) { + std::cerr << "test_a_simple_tetrahedron failed on case " << expected_result + << (with_bbox ? " with bbox\n" : "\n"); + ok = false; + } + if(result_string != expected_result) { + std::cerr << " result_string is " << result_string << " instead of " + << expected_result << '\n'; + } + if(exception_thrown) { + std::cerr << " exception thrown\n"; + } + }; + std::string expected_result_reversed{expected_result.rbegin(), expected_result.rend()}; + do_test(a, b, false, expected_result); + do_test(b, a, false, expected_result_reversed); + std::replace(expected_result.begin(), expected_result.end(), 'I', '3'); + std::replace(expected_result_reversed.begin(), expected_result_reversed.end(), 'I', '3'); + insert(dt, bbox_points.begin(), bbox_points.end()); + do_test(a, b, true, expected_result); + do_test(b, a, true, expected_result_reversed); }; - test({ 0, 0, 0}, { 1, 0, 0}, false, "010"); - test({ 0, 0, 0}, { 2, 0, 0}, false, "010I"); - test({-1, 0, 0}, { 2, 0, 0}, false, "I010I"); - test({ 0, 0, 0}, {.5, .5, 0}, false, "021"); - test({ 0, 0, 0}, { 1, 1, 0}, false, "021I"); - test({-1, -1, 0}, { 1, 1, 0}, false, "I021I"); - - test({ 0, 0, 0}, { 1, 0, 0}, true, "010"); - test({ 0, 0, 0}, { 2, 0, 0}, true, "0103"); - test({-1, 0, 0}, { 2, 0, 0}, true, "30103"); - test({ 0, 0, 0}, {.5, .5, 0}, true, "021"); - test({ 0, 0, 0}, { 1, 1, 0}, true, "0213"); - test({-1, -1, 0}, { 1, 1, 0}, true, "30213"); - + // queries entering by a vertex and exiting by a vertex, on the line (x,0,0) + test({ 0, 0, 0}, {.5, 0, 0}, "01"); + test({ 0, 0, 0}, { 1, 0, 0}, "010"); + test({ 0, 0, 0}, { 2, 0, 0}, "010I"); + test({-1, 0, 0}, { 2, 0, 0}, "I010I"); + test({-1, 0, 0}, { 1, 0, 0}, "I010"); + test({-1, 0, 0}, {.5, 0, 0}, "I01"); + + // queries entering by a vertex and exiting by an edge, on the line (x,x,0) (y==x) + test({ 0, 0, 0}, {.2, .2, 0}, "02"); + test({ 0, 0, 0}, {.5, .5, 0}, "021"); + test({ 0, 0, 0}, { 1, 1, 0}, "021I"); + test({-1, -1, 0}, { 1, 1, 0}, "I021I"); + test({-1, -1, 0}, {.5, .5, 0}, "I021"); + test({-1, -1, 0}, {.2, .2, 0}, "I02"); + + // queries entering by a vertex and exiting by a facet, one the line x==y==0.25-0.25z + test({ 0, 0, 1}, { .25, .25, .25}, "03"); + test({ 0, 0, 1}, { .25, .25, 0}, "032"); + test({ 0, 0, 1}, { .5, .5, -1 }, "032I"); + test({-.25,-.25, 2}, { .5, .5, -1 }, "I032I"); + test({-.25,-.25, 2}, { .25, .25, 0}, "I032"); + test({-.25,-.25, 2}, { .05, .05, .8}, "I03"); + + // queries entering by an edge and exiting by an edge, on the line (x,.5,0) + test({ 0, .5, 0}, {.2, .5, 0}, "12"); + test({ 0, .5, 0}, {.5, .5, 0}, "121"); + test({ 0, .5, 0}, { 1, .5, 0}, "121I"); + test({-1, .5, 0}, { 1, .5, 0}, "I121I"); + test({-1, .5, 0}, {.5, .5, 0}, "I121"); + test({-1, .5, 0}, {.2, .5, 0}, "I12"); + + // queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) + test({ 0, .25, 0}, { .20, .05, .20}, "13"); + test({ 0, .25, 0}, { .25, 0, .25}, "132"); + test({ 0, .25, 0}, { .5 ,-.25, .5 }, "132I"); + test({-.5, .75,-.5}, { .5 ,-.25, .5 }, "I132I"); + test({-.5, .75,-.5}, { .25, 0, .25}, "I132"); + test({-.5, .75,-.5}, { .20, .05, .20}, "I13"); + + // queries entering by a facet and exiting by a facet, on the line (x,.5-x,.2) + test({ 0, .5, .2}, {.2, .3, .2}, "23"); + test({ 0, .5, .2}, {.5, 0, .2}, "232"); + test({ 0, .5, .2}, { 1,-.5, .2}, "232I"); + test({-1,1.5, .2}, { 1, .5, .2}, "I232I"); + test({-1,1.5, .2}, {.5, 0, .2}, "I232"); + test({-1,1.5, .2}, {.2, .3, .2}, "I23"); return ok; } From 7a2c543b06e9a9d43a2b40437df399e7b1054a62 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 11:49:57 +0200 Subject: [PATCH 08/60] replace assert(false) by CGAL_unreachable() --- .../Triangulation_segment_traverser_3_impl.h | 19 ++++++++-------- .../CGAL/Triangulation_segment_traverser_3.h | 22 +++++++++---------- 2 files changed, 20 insertions(+), 21 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index f7411f652e8f..4a5304a67571 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -575,7 +575,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre return std::make_pair(prev_after_walk, cur_after_walk); } } - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return std::make_pair(prev, cur); case 1: if(regular_case) @@ -593,10 +593,10 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre return std::make_pair(prev_after_walk, cur_after_walk); } } - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return std::make_pair(prev, cur); default: - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return std::make_pair(prev, cur); } } @@ -626,8 +626,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre prev_after_walk = Simplex( std::get<0>(cur), Tr::VERTEX, pos, -1 ); break; default: - prev_after_walk = Simplex( std::get<0>(cur), Tr::OUTSIDE_AFFINE_HULL, -1, -1 ); - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); } Simplex cur_after_walk(Cell_handle(), Tr::OUTSIDE_AFFINE_HULL, -1, -1); @@ -726,7 +725,7 @@ walk_to_next_3_inf( int inf ) return; } } - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return; case 1: prev_lt() = Tr::VERTEX; @@ -738,10 +737,10 @@ walk_to_next_3_inf( int inf ) return; } } - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return; default: - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return; } } @@ -1007,7 +1006,7 @@ walk_to_next_2() this->li() = cell()->index( prev_cell()->vertex( prev_li() ) ); return; default: - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); return; } } @@ -1018,7 +1017,7 @@ walk_to_next_2() return; } default: - CGAL_triangulation_assertion( false ); + CGAL_unreachable(); } } diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 49ba25ccd3e3..bc00071cb23b 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -625,7 +625,7 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = cell; break; default: - CGAL_assertion(false); + CGAL_unreachable(); }; } @@ -719,7 +719,7 @@ class Triangulation_segment_simplex_iterator_3 break; default: - CGAL_assertion(false); + CGAL_unreachable(); }; break; } @@ -792,7 +792,7 @@ class Triangulation_segment_simplex_iterator_3 break; } default: - CGAL_assertion(false);//should not happen + CGAL_unreachable();//should not happen }; break; } @@ -863,7 +863,7 @@ class Triangulation_segment_simplex_iterator_3 Cell_handle ec; int ei = -1, ej = -1; if (!triangulation()->is_edge(get_vertex(), chnext->vertex(linext), ec, ei, ej)) - CGAL_assertion(false); + CGAL_unreachable(); _curr_simplex = Edge(ec, ei, ej); } } @@ -916,7 +916,7 @@ class Triangulation_segment_simplex_iterator_3 break; default: - CGAL_assertion(false); + CGAL_unreachable(); }; return *this; } @@ -1017,10 +1017,10 @@ class Triangulation_segment_simplex_iterator_3 case 3 ://cell return ch != get_cell(); default: - CGAL_assertion(false); + CGAL_unreachable(); } //should not be reached - CGAL_assertion(false); + CGAL_unreachable(); return false; } @@ -1074,7 +1074,7 @@ class Triangulation_segment_simplex_iterator_3 return v1b; std::cerr << "There is no vertex shared by e1 and e2" << std::endl; - CGAL_assertion(false); + CGAL_unreachable(); return Vertex_handle(); } @@ -1100,7 +1100,7 @@ class Triangulation_segment_simplex_iterator_3 } while (++circ != end); std::cerr << "There is no facet shared by e1 and e2" << std::endl; - CGAL_assertion(false); + CGAL_unreachable(); return Facet(Cell_handle(), 0); } @@ -1118,7 +1118,7 @@ class Triangulation_segment_simplex_iterator_3 } while (++circ != end); std::cerr << "There is no facet shared by e and v" << std::endl; - CGAL_assertion(false); + CGAL_unreachable(); return Facet(Cell_handle(), 0); } @@ -1135,7 +1135,7 @@ class Triangulation_segment_simplex_iterator_3 } while (++circ != end); std::cerr << "There is no cell shared by e and v" << std::endl; - CGAL_assertion(false); + CGAL_unreachable(); return Cell_handle(); } From 59d7a6306b1d15dd472e698b6c33e315ff469339 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 11:53:13 +0200 Subject: [PATCH 09/60] cosmetic changes --- .../CGAL/Triangulation_segment_traverser_3.h | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index bc00071cb23b..0582fd1cb0cb 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -236,7 +236,7 @@ class Triangulation_segment_cell_iterator_3 * \return a handle to the current cell. * \sa `cell()`. */ - Cell_handle handle() + Cell_handle handle() const { return std::get<0>(_cur); } @@ -301,6 +301,10 @@ class Triangulation_segment_cell_iterator_3 { lt = this->lt(); li = this->li(); lj = this->lj(); } + std::tuple entry() const + { + return { lt(), li(), lj() }; + } // gives the simplex through which the previous cell was exited. /* \pre the current cell is not the initial cell. */ @@ -308,6 +312,10 @@ class Triangulation_segment_cell_iterator_3 { lt = prev_lt(); li = prev_li(); lj = prev_lj(); } + std::tuple exit() const + { + return { prev_lt(), prev_li(), prev_lj() }; + } // gives the past-the-end iterator associated with this iterator. SCI end() const; @@ -588,18 +596,17 @@ class Triangulation_segment_simplex_iterator_3 { Locate_type lt; int li, lj; - Cell_handle cell; + Cell_handle cell = Cell_handle(_cell_iterator); //check what is the entry type of _cell_iterator - if (Cell_handle(_cell_iterator) == Cell_handle()) + if (cell == Cell_handle()) { - //where did the segment std::get out from previous cell + //where did the segment get out from previous cell cell = _cell_iterator.previous(); _cell_iterator.exit(lt, li, lj); } else { - cell = Cell_handle(_cell_iterator); _cell_iterator.entry(lt, li, lj); } From 5a9d6d4998225375f5839ba3b3a66ea34449ca29 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 15:04:46 +0200 Subject: [PATCH 10/60] cosmetic changes --- .../test_segment_simplex_traverser_3.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 711d314e5dd6..a42d0f2fb60d 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -27,6 +27,7 @@ typedef DT::Cell_handle Cell_handle; typedef DT::Edge Edge; typedef DT::Facet Facet; typedef DT::Vertex_handle Vertex_handle; +typedef DT::Simplex Simplex; typedef DT::Segment_simplex_iterator Segment_simplex_iterator; // a function to insert without spatial sorting @@ -46,7 +47,7 @@ auto display_vert(Vertex_handle v) { } return os.str(); }; -template + struct Debug_simplex { Simplex simplex; @@ -57,19 +58,19 @@ struct Debug_simplex { auto&& simplex = d.simplex; switch(simplex.dimension()) { case 0: { - os << " vertex " << display_vert(static_cast(simplex)); + os << " - vertex " << display_vert(static_cast(simplex)); break; } case 1: { const auto [c, index1, index2] = static_cast(simplex); - os << " egde " + os << " - egde " << display_vert(c->vertex(index1)) << " - " << display_vert(c->vertex(index2)); break; } case 2: { const auto [c, index] = static_cast(simplex); - os << " facet " + os << " - facet " << display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - " << display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - " << display_vert(c->vertex(DT::vertex_triple_index(index, 2))); @@ -77,7 +78,7 @@ struct Debug_simplex { } case 3: { const auto c = static_cast(simplex); - os << " cell " + os << " - cell " << display_vert(c->vertex(0)) << " - " << display_vert(c->vertex(1)) << " - " << display_vert(c->vertex(2)) << " - " @@ -89,9 +90,8 @@ struct Debug_simplex { return os; }; }; -template auto debug_simplex(Simplex simplex) { - return Debug_simplex{simplex}; + return Debug_simplex{simplex}; } static const std::vector bbox_points = From 152f0038fbca979a60f177de2d952c1df4a8641f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 15:06:27 +0200 Subject: [PATCH 11/60] improve the test process - call the API with two vertex handles, when possible, - add a check that the reported simplices intersect the query segment, - add a chech that two consecutive simplices are incident. --- .../test_segment_simplex_traverser_3.cpp | 194 ++++++++++++++---- 1 file changed, 157 insertions(+), 37 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index a42d0f2fb60d..af2441cfa692 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -17,6 +17,9 @@ // Define the kernel. typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; typedef Kernel::Point_3 Point_3; +typedef Kernel::Segment_3 Segment_3; +typedef Kernel::Triangle_3 Triangle_3; +typedef Kernel::Tetrahedron_3 Tetrahedron_3; // Define the structure. typedef CGAL::Base_with_time_stamp> Vb; @@ -109,7 +112,74 @@ static const std::vector bbox_points = DT dt; std::string result_string; -auto visit_simplex = [](auto s) { +bool reverse_sort_vertex_handles(Vertex_handle v1, Vertex_handle v2) { + return v1.operator->() > v2.operator->(); +}; + +auto vertices_of_simplex(Simplex simplex) -> std::array { + std::array vertices = { Vertex_handle{}, Vertex_handle{}, Vertex_handle{}, Vertex_handle{} }; + switch(simplex.dimension()) { + case 0: { + vertices[0] = static_cast(simplex); + break; + } + case 1: { + const auto [c, index1, index2] = static_cast(simplex); + vertices[0] = c->vertex(index1); + vertices[1] = c->vertex(index2); + break; + } + case 2: { + const auto [c, index] = static_cast(simplex); + vertices[0] = c->vertex(DT::vertex_triple_index(index, 0)); + vertices[1] = c->vertex(DT::vertex_triple_index(index, 1)); + vertices[2] = c->vertex(DT::vertex_triple_index(index, 2)); + break; + } + case 3: { + const auto c = static_cast(simplex); + vertices[0] = c->vertex(0); + vertices[1] = c->vertex(1); + vertices[2] = c->vertex(2); + vertices[3] = c->vertex(3); + break; + } + default: CGAL_unreachable(); + } + std::sort(vertices.begin(), vertices.end(), reverse_sort_vertex_handles); + for(int i = 0; i < 4; ++i) { + assert((i <= simplex.dimension()) == (vertices[i] != Vertex_handle{})); + } + return vertices; +} + +std::variant get_simplex_geometry(Simplex simplex) { + switch(simplex.dimension()) { + case 0: { + return static_cast(simplex)->point(); + } + case 1: { + const auto [c, index1, index2] = static_cast(simplex); + return Segment_3(c->vertex(index1)->point(), c->vertex(index2)->point()); + } + case 2: { + const auto [c, index] = static_cast(simplex); + return Triangle_3(c->vertex(DT::vertex_triple_index(index, 0))->point(), + c->vertex(DT::vertex_triple_index(index, 1))->point(), + c->vertex(DT::vertex_triple_index(index, 2))->point()); + } + case 3: { + const auto c = static_cast(simplex); + return Tetrahedron_3(c->vertex(0)->point(), + c->vertex(1)->point(), + c->vertex(2)->point(), + c->vertex(3)->point()); + } + default: CGAL_unreachable(); + } +} + +void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional previous_simplex_optional) { auto d = s.dimension(); if(3 == d && dt.is_infinite(static_cast(s))) { result_string += 'I'; @@ -117,6 +187,29 @@ auto visit_simplex = [](auto s) { result_string += std::to_string(d); } std::cout << debug_simplex(s) << '\n'; + if(previous_simplex_optional) { + // this block checks that consecutive simplices are incident + using Set = std::array; + Set prev_vertices = vertices_of_simplex(*previous_simplex_optional); + Set s_vertices = vertices_of_simplex(s); + if(previous_simplex_optional->dimension() < s.dimension()) { + std::swap(prev_vertices, s_vertices); + std::swap(*previous_simplex_optional, s); + } + if(!std::includes( + prev_vertices.begin(), prev_vertices.begin() + 1 + previous_simplex_optional->dimension(), + s_vertices.begin(), s_vertices.begin() + 1 + s.dimension(), + reverse_sort_vertex_handles)) + { + CGAL_error_msg("consecutive simplices are not incident"); + } + const bool does_intersect_ab = std::visit( + [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, + get_simplex_geometry(s)); + if(!does_intersect_ab) { + CGAL_error_msg("the simplex does not intersect the query segment"); + } + } }; bool test_vfefv(bool with_bbox = false) @@ -145,8 +238,10 @@ bool test_vfefv(bool with_bbox = false) assert(dt.is_cell (v[1], v[2], v[3], v[4], c)); assert(dt.is_cell (v[1], v[2], v[3], v[5], c)); + std::optional previous{}; for(auto s: dt.segment_traverser_simplices(v[0], v[3])) { - visit_simplex(s); + visit_simplex(points[0], points[3], s, previous); + previous = s; } static const std::string expected_result_string = "02120"; bool ok = (result_string == expected_result_string); @@ -171,46 +266,66 @@ bool test_a_simple_tetrahedron() { // - with [ab] and [ba], // - and with or without a bbox around the central tetrahedron. dt = dt2; - auto do_test = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { + auto do_with_or_without_bbox = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { std::cerr << "### Case " << expected_result; if(with_bbox) std::cerr << " with bbox"; std::cerr << '\n'; - std::cerr << "from (" << a << ") to (" << b << ")\n"; - bool exception_thrown = false; - result_string.clear(); - try { - for(auto s: dt.segment_traverser_simplices(a, b)) { - visit_simplex(s); + auto do_it = [&](auto from, auto to) { + bool exception_thrown = false; + result_string.clear(); + try { + std::optional previous_simplex; + for(auto s: dt.segment_traverser_simplices(from, to)) { + visit_simplex(a, b, s, previous_simplex); + previous_simplex = s; + } + } catch(const CGAL::Assertion_exception& e) { + CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(), + e.filename().c_str(), + e.line_number(), + e.message().c_str()); + exception_thrown = true; } - } catch(const CGAL::Assertion_exception& e) { - CGAL::get_static_warning_handler()("Assertion", e.expression().c_str(), - e.filename().c_str(), - e.line_number(), - e.message().c_str()); - exception_thrown = true; - } - if(result_string != expected_result || exception_thrown) { - std::cerr << "test_a_simple_tetrahedron failed on case " << expected_result - << (with_bbox ? " with bbox\n" : "\n"); - ok = false; - } - if(result_string != expected_result) { - std::cerr << " result_string is " << result_string << " instead of " - << expected_result << '\n'; - } - if(exception_thrown) { - std::cerr << " exception thrown\n"; - } - }; + if(result_string != expected_result || exception_thrown) { + std::cerr << "test_a_simple_tetrahedron failed on case " << expected_result + << (with_bbox ? " with bbox\n" : "\n"); + ok = false; + } + if(result_string != expected_result) { + std::cerr << " result_string is " << result_string << " instead of " + << expected_result << '\n'; + } + if(exception_thrown) { + std::cerr << " exception thrown\n"; + } + }; // end do_it + + std::cerr << "from (" << a << ") to (" << b << ")\n"; + do_it(a, b); + + // then re-test using vertex handles, if possible + Vertex_handle va{}; + Vertex_handle vb{}; + DT::Locate_type lt; + int i, j; + auto c = dt.locate(a, lt, i, j); + if(lt == DT::VERTEX) va = c->vertex(i); + c = dt.locate(b, lt, i, j); + if(lt == DT::VERTEX) vb = c->vertex(i); + if(va != Vertex_handle{} && vb != Vertex_handle{}) { + std::cerr << "from vertex" << display_vert(va) << " to vertex" << display_vert(vb) << ")\n"; + do_it(va, vb); + }; + }; // end do_with_or_without_bbox std::string expected_result_reversed{expected_result.rbegin(), expected_result.rend()}; - do_test(a, b, false, expected_result); - do_test(b, a, false, expected_result_reversed); + do_with_or_without_bbox(a, b, false, expected_result); + do_with_or_without_bbox(b, a, false, expected_result_reversed); std::replace(expected_result.begin(), expected_result.end(), 'I', '3'); std::replace(expected_result_reversed.begin(), expected_result_reversed.end(), 'I', '3'); insert(dt, bbox_points.begin(), bbox_points.end()); - do_test(a, b, true, expected_result); - do_test(b, a, true, expected_result_reversed); - }; + do_with_or_without_bbox(a, b, true, expected_result); + do_with_or_without_bbox(b, a, true, expected_result_reversed); + }; // end test() lambda // queries entering by a vertex and exiting by a vertex, on the line (x,0,0) test({ 0, 0, 0}, {.5, 0, 0}, "01"); @@ -317,13 +432,16 @@ int main(int, char* []) }; bool ok = true; + ok = test_a_simple_tetrahedron() && ok; + for(std::size_t i=0; i previous; for (; st != stend; ++st) { if (st->dimension() == 3 @@ -353,7 +472,8 @@ bool test(const DT& dt, else { ++fin; - visit_simplex(*st); + visit_simplex(p1, p2, *st, previous); + previous = *st; switch (st->dimension()) { case 2: ++nb_facets; break; From 6f22c113dfc147ac76c71437c9794d803a3f0a95 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 15:13:16 +0200 Subject: [PATCH 12/60] WIP on the Triangulation_segment_cell_iterator_3 --- .../Triangulation_segment_traverser_3_impl.h | 156 ++++++++++++------ 1 file changed, 104 insertions(+), 52 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 4a5304a67571..d70cfd9202e5 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -333,104 +333,154 @@ std::pair::Simplex, Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& prev, const Simplex& cur) const { + const auto cur_cell = std::get<0>(cur); std::array vert - = {&(std::get<0>(cur)->vertex(0)->point()), - &(std::get<0>(cur)->vertex(1)->point()), - &(std::get<0>(cur)->vertex(2)->point()), - &(std::get<0>(cur)->vertex(3)->point()) }; + = {&(cur_cell->vertex(0)->point()), + &(cur_cell->vertex(1)->point()), + &(cur_cell->vertex(2)->point()), + &(cur_cell->vertex(3)->point()) }; int inside=0,outside=0,regular_case=0,degenerate=0; Cell_handle nnext; if (std::get<1>(cur) == Tr::FACET) { + Simplex prev_after_walk; + Simplex cur_after_walk; + + auto case_target_is_inside_cur_cell = [&](int case_nb) { + inside = case_nb; + prev_after_walk = { cur_cell, Tr::CELL, -1, -1 }; + cur_after_walk = { {}, Tr::OUTSIDE_AFFINE_HULL, -1, -1 }; + }; + auto case_segment_exits_cur_cell_by = [&](int facet_nb) { + outside = facet_nb; + prev_after_walk = { cur_cell, Tr::FACET, facet_nb, -1 }; + cur_after_walk = { nnext, Tr::FACET, nnext->index(cur_cell), -1 }; + }; regular_case = 1; - int i = std::get<2>(cur); - int j0 = Tr::vertex_triple_index(i, 0); - int j1 = Tr::vertex_triple_index(i, 1); - int j2 = Tr::vertex_triple_index(i, 2); + const int i = std::get<2>(cur); + const int j0 = Tr::vertex_triple_index(i, 0); + const int j1 = Tr::vertex_triple_index(i, 1); + const int j2 = Tr::vertex_triple_index(i, 2); Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target); if (o0 == POSITIVE) { Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); if (o1 != POSITIVE) { - if (_tr->orientation(*vert[i], *vert[j0], *vert[j1], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j2); - outside = j2; + Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); + if (oi01 == POSITIVE) { + nnext = cur_cell->neighbor(j2); + case_segment_exits_cur_cell_by(j2); if (o1 == ZERO) degenerate = 1; //EDGE i j1 } - else - inside = 1; + else { + case_target_is_inside_cur_cell(1); // o0 > 0, o1 <= 0, oi01 <= 0 + if(oi01 == ZERO) { // on FACET i j0 j1 + if(o1 == ZERO) { // on EDGE i j1 + if(_tr->equal(_target, cur_cell->vertex(i)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } + else if(_tr->equal(_target, cur_cell->vertex(j1)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, j1, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } + else { + prev_after_walk = { cur_cell, Tr::EDGE, i, j1}; + cur_after_walk = { {}, Tr::EDGE, -1, -1}; + } + } else { // o0 > 0, o1 < 0, oi01 == 0 + //on FACET j2 (i-j0-j1) but not edge i-j1, or i-j0 + Orientation o012 = _tr->orientation(*vert[j0], *vert[j1], *vert[j2], _target); + CGAL_assertion(o012 != NEGATIVE); + if(o012 == ZERO) { // on edge j0-j1 + prev_after_walk = { cur_cell, Tr::EDGE, j0, j1}; + cur_after_walk = { {}, Tr::EDGE, -1, -1}; + } else { // on facet j2 + prev_after_walk = { cur_cell, Tr::FACET, j2, -1}; + cur_after_walk = { {}, Tr::FACET, -1, -1}; + } + } + } + } } else { if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j0); - outside = j0; + nnext = cur_cell->neighbor(j0); + case_segment_exits_cur_cell_by(j0); } else - inside = 2; + case_target_is_inside_cur_cell(2); } } else if (o0 == ZERO) { + // target is on plane (source, vert[i], vert[j0]) Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); if (o1 == NEGATIVE) { - if (_tr->orientation(*vert[i], *vert[j0], *vert[j1], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j2); //EDGE i j0 + Orientation oi12 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); + if (oi12 == POSITIVE) { + nnext = cur_cell->neighbor(j2); //EDGE i j0 degenerate = 2; - outside = 44; + case_segment_exits_cur_cell_by(44); + } + else { + case_target_is_inside_cur_cell(3); + if(oi12 == ZERO) { // target is *on* EDGE i j0 + if(_tr->equal(_target, cur_cell->vertex(i)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } else if(_tr->equal(_target, cur_cell->vertex(j0)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, j0, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } else { + prev_after_walk = { cur_cell, Tr::EDGE, i, j0 }; + cur_after_walk = { {}, Tr::EDGE, -1, -1 }; + } + } } - else - inside = 3; } else if (o1 == ZERO) { + // o0 == o1 == 0 -> target is on line source-vert[i] if (_tr->orientation(*vert[i], *vert[j0], *vert[j2], _target) == POSITIVE) - inside = 55; + case_target_is_inside_cur_cell(55); else { - nnext = std::get<0>(cur)->neighbor(j2); //VERTEX i + nnext = cur_cell->neighbor(j2); //VERTEX i degenerate = 3; - outside = 5; + case_segment_exits_cur_cell_by(5); } } - else { + else { // o0 == 0, o1 > 0 if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j0); - outside = j0; + nnext = cur_cell->neighbor(j0); + case_segment_exits_cur_cell_by(j0); } else - inside = 4; + case_target_is_inside_cur_cell(4); } } else { Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); if (o2 != NEGATIVE) { if (_tr->orientation(*vert[i], *vert[j2], *vert[j0], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j1); - outside = j1; + nnext = cur_cell->neighbor(j1); + case_segment_exits_cur_cell_by(j1); if (o2 == ZERO) degenerate = 4; // EDGE i j2 } else - inside = 5; + case_target_is_inside_cur_cell(5); } else { if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = std::get<0>(cur)->neighbor(j0); - outside = j0; + nnext = cur_cell->neighbor(j0); + case_segment_exits_cur_cell_by(j0); } else - inside = 6; + case_target_is_inside_cur_cell(6); } } - if ((!degenerate) && (!inside)) - { - Simplex prev_after_walk(std::get<0>(cur), Tr::FACET, outside, -1); - Simplex cur_after_walk( nnext, Tr::FACET, nnext->index(std::get<0>(cur)), -1); - return std::make_pair(prev_after_walk, cur_after_walk); - } - - if ((!degenerate) && inside) + if (!degenerate) { - Simplex prev_after_walk(std::get<0>(cur), Tr::CELL, -1, -1); - Simplex cur_after_walk(Cell_handle(), Tr::OUTSIDE_AFFINE_HULL, -1, -1); return std::make_pair(prev_after_walk, cur_after_walk); } } @@ -468,7 +518,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre for( int k = 0; k < 4; ++k, ++li ) { // Skip the previous cell. - Cell_handle next = std::get<0>(cur)->neighbor(li); + Cell_handle next = cur_cell->neighbor(li); if( next == std::get<0>(prev) ) { op[li] = POSITIVE; @@ -537,7 +587,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre Simplex prev_after_walk; Simplex cur_after_walk; - std::get<0>(prev_after_walk) = std::get<0>(cur); + std::get<0>(prev_after_walk) = cur_cell; std::get<0>(cur_after_walk) = next; switch( Or ) { case 3: @@ -607,23 +657,23 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre switch( op[0] + op[1] + op[2] + op[3] ) { case 4: CGAL_triangulation_assertion( pos == 6 ); - prev_after_walk = Simplex( std::get<0>(cur), Tr::CELL, -1, -1 ); + prev_after_walk = Simplex( cur_cell, Tr::CELL, -1, -1 ); CGAL_triangulation_assertion( (! regular_case) || inside ); break; case 3: - prev_after_walk = Simplex( std::get<0>(cur), Tr::FACET, 6-pos, -1 ); + prev_after_walk = Simplex( cur_cell, Tr::FACET, 6-pos, -1 ); break; case 2: if( pos < 3 ) - prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 0, pos+1 ); + prev_after_walk = Simplex( cur_cell, Tr::EDGE, 0, pos+1 ); else if( pos < 5 ) - prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 1, pos-1 ); + prev_after_walk = Simplex( cur_cell, Tr::EDGE, 1, pos-1 ); else - prev_after_walk = Simplex( std::get<0>(cur), Tr::EDGE, 2, 3 ); + prev_after_walk = Simplex( cur_cell, Tr::EDGE, 2, 3 ); break; case 1: - prev_after_walk = Simplex( std::get<0>(cur), Tr::VERTEX, pos, -1 ); + prev_after_walk = Simplex( cur_cell, Tr::VERTEX, pos, -1 ); break; default: CGAL_unreachable(); @@ -643,7 +693,9 @@ walk_to_next_3_inf( int inf ) Cell_handle fin = cell()->neighbor(inf); if( fin == prev_cell() ) { _prev = _cur; + prev_lt() = Tr::CELL; cell() = Cell_handle(); + lt() = Tr::CELL; return; } From 7260a9497ce8ffa0d97eb1088eaea19c97f0fc3e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 16:00:28 +0200 Subject: [PATCH 13/60] Add debug tool Protected by the macro CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 --- .../CGAL/Triangulation_segment_traverser_3.h | 71 +++++++++++++++++-- .../test_segment_simplex_traverser_3.cpp | 9 +-- 2 files changed, 72 insertions(+), 8 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 0582fd1cb0cb..3fe2d83c691d 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -127,6 +127,55 @@ class Triangulation_segment_cell_iterator_3 template < class Tr2, class Inc2 > struct Rebind { typedef Triangulation_segment_cell_iterator_3 Other; }; +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + static auto display_vert(Vertex_handle v) + { + std::stringstream os; + os.precision(17); + if(v->time_stamp() == 0) { + os << "inf"; + } else { + os << '#' << v->time_stamp() << "=(" << v->point() << ")"; + } + return os.str(); + }; + + static auto display_lt(Locate_type lt) { + std::stringstream os; + switch(lt) { + case Locate_type::VERTEX: os << " VERTEX"; break; + case Locate_type::EDGE: os << " EDGE"; break; + case Locate_type::FACET: os << " FACET"; break; + case Locate_type::CELL: os << " CELL"; break; + case Locate_type::OUTSIDE_CONVEX_HULL: os << " OUTSIDE_CONVEX_HULL"; break; + case Locate_type::OUTSIDE_AFFINE_HULL: os << " OUTSIDE_AFFINE_HULL"; break; + } + return os.str(); + } + + static auto debug_simplex(Simplex s) { + std::stringstream os; + os.precision(17); + const auto [c, lt, i, j] = s; + if(c == Cell_handle{}) { + os << "end()"; + } else { + os << display_vert(c->vertex(0)) << " - " << display_vert(c->vertex(1)) << " - " + << display_vert(c->vertex(2)) << " - " << display_vert(c->vertex(3)); + } + os << display_lt(lt) << " " << i << " " << j; + return os.str(); + } + + auto debug_iterator() const + { + std::stringstream os; + os.precision(17); + os << " cur: " << debug_simplex(_cur) << "\n prev: " << debug_simplex(_prev); + return os.str(); + } +#endif // CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + private: typedef Segment_cell_iterator SCI; @@ -594,6 +643,10 @@ class Triangulation_segment_simplex_iterator_3 private: void set_curr_simplex_to_entry() { +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << "cell iterator is:\n" << _cell_iterator.debug_iterator() << std::endl; +#endif // #if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + Locate_type lt; int li, lj; Cell_handle cell = Cell_handle(_cell_iterator); @@ -646,6 +699,16 @@ class Triangulation_segment_simplex_iterator_3 // provides the increment postfix operator. Simplex_iterator& operator++() { + auto increment_cell_iterator = [&]() + { +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << "increment cell iterator from:\n" << _cell_iterator.debug_iterator(); +#endif + ++_cell_iterator; +#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 + std::cerr << "\n > to:\n" << _cell_iterator.debug_iterator() << std::endl; +#endif + }; CGAL_assertion(_curr_simplex.incident_cell() != Cell_handle()); switch(_curr_simplex.dimension()) @@ -664,7 +727,7 @@ class Triangulation_segment_simplex_iterator_3 else { if (!cell_iterator_is_ahead()) - ++_cell_iterator; + increment_cell_iterator(); set_curr_simplex_to_entry(); } break; @@ -678,7 +741,7 @@ class Triangulation_segment_simplex_iterator_3 //we cannot be in any of the degenerate cases, only detected by //taking cell_iterator one step forward CGAL_assertion(cell_has_facet(Cell_handle(_cell_iterator), get_facet())); - ++_cell_iterator; + increment_cell_iterator(); if (Cell_handle(_cell_iterator) == Cell_handle()) { _curr_simplex = _cell_iterator.previous(); @@ -744,7 +807,7 @@ class Triangulation_segment_simplex_iterator_3 if (!cell_iterator_is_ahead()) { - ++_cell_iterator;//cell_iterator needs to be ahead to detect degeneracies + increment_cell_iterator();//cell_iterator needs to be ahead to detect degeneracies if (Cell_handle(_cell_iterator) == Cell_handle()) { _curr_simplex = _cell_iterator.previous(); @@ -813,7 +876,7 @@ class Triangulation_segment_simplex_iterator_3 } if (!cell_iterator_is_ahead()) //_curr_simplex does contain v { - ++_cell_iterator;//cell_iterator needs to be ahead to detect degeneracies + increment_cell_iterator();//cell_iterator needs to be ahead to detect degeneracies } else ch = _cell_iterator.previous(); diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index af2441cfa692..30028a5d5651 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -1,3 +1,4 @@ +#define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1 #include #include #include @@ -61,19 +62,19 @@ struct Debug_simplex { auto&& simplex = d.simplex; switch(simplex.dimension()) { case 0: { - os << " - vertex " << display_vert(static_cast(simplex)); + os << "- vertex " << display_vert(static_cast(simplex)); break; } case 1: { const auto [c, index1, index2] = static_cast(simplex); - os << " - egde " + os << "- egde " << display_vert(c->vertex(index1)) << " - " << display_vert(c->vertex(index2)); break; } case 2: { const auto [c, index] = static_cast(simplex); - os << " - facet " + os << "- facet " << display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - " << display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - " << display_vert(c->vertex(DT::vertex_triple_index(index, 2))); @@ -81,7 +82,7 @@ struct Debug_simplex { } case 3: { const auto c = static_cast(simplex); - os << " - cell " + os << "- cell " << display_vert(c->vertex(0)) << " - " << display_vert(c->vertex(1)) << " - " << display_vert(c->vertex(2)) << " - " From 2b94f06f573226401b902b8f98e06973db5796a6 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 11 May 2023 16:32:34 +0200 Subject: [PATCH 14/60] Remove trailing whitespces --- .../internal/Triangulation_segment_traverser_3_impl.h | 2 +- .../Triangulation_3/test_segment_simplex_traverser_3.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index d70cfd9202e5..25e904faa2a5 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -422,7 +422,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre degenerate = 2; case_segment_exits_cur_cell_by(44); } - else { + else { case_target_is_inside_cur_cell(3); if(oi12 == ZERO) { // target is *on* EDGE i j0 if(_tr->equal(_target, cur_cell->vertex(i)->point())) { diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 30028a5d5651..9c56c7681a70 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -434,15 +434,15 @@ int main(int, char* []) bool ok = true; ok = test_a_simple_tetrahedron() && ok; - + for(std::size_t i=0; i Date: Thu, 11 May 2023 18:08:16 +0200 Subject: [PATCH 15/60] additional bug-fix --- .../include/CGAL/Triangulation_segment_traverser_3.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 3fe2d83c691d..b011ff85e7f8 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -959,7 +959,12 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = Simplex_3(); } else if (ltprev == Locate_type::EDGE)//vertex-facet-edge-outside - _curr_simplex = Facet(prev, prev->index(get_vertex())); + { + if(prev->vertex(liprev) != get_vertex() && prev->vertex(ljprev) != get_vertex()) + _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); + else + _curr_simplex = Edge(prev, liprev, ljprev); + } else if (ltprev == Locate_type::FACET) //vertex-facet-outside { if(prev->vertex(liprev) != get_vertex()) //vertex-facet-outside From 087492b72d5cfd6ba6256dc1577161199d9de441 Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Fri, 12 May 2023 16:13:30 +0200 Subject: [PATCH 16/60] replace dealing with OUTSIDE_AFFINE_HULL with tests on cell_iterator == end() --- .../CGAL/Triangulation_segment_traverser_3.h | 106 +++++++++--------- 1 file changed, 56 insertions(+), 50 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index b011ff85e7f8..ace5492353fb 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -752,6 +752,12 @@ class Triangulation_segment_simplex_iterator_3 ch = _cell_iterator.previous(); Cell_handle chnext = Cell_handle(_cell_iterator); + if (chnext == Cell_handle()) + { + _curr_simplex = Simplex_3(); + break; + } + Locate_type ltnext; int linext, ljnext; _cell_iterator.entry(ltnext, linext, ljnext); @@ -784,10 +790,6 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = ch; break; - case Locate_type::OUTSIDE_AFFINE_HULL: - _curr_simplex = Simplex_3(); - break; - default: CGAL_unreachable(); }; @@ -816,6 +818,20 @@ class Triangulation_segment_simplex_iterator_3 } Cell_handle chnext = Cell_handle(_cell_iterator); + if (chnext == Cell_handle()) + { + Cell_handle chprev = _cell_iterator.previous(); + Locate_type ltprev; + int liprev, ljprev; + _cell_iterator.exit(ltprev, liprev, ljprev); + + if (ltprev == Locate_type::VERTEX) //edge-vertex-outside + _curr_simplex = chprev->vertex(liprev); + else + _curr_simplex = Simplex_3(); //edge-outside + break; + } + Locate_type ltnext; int linext, ljnext; _cell_iterator.entry(ltnext, linext, ljnext); @@ -848,19 +864,6 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = Cell_handle(_cell_iterator);//query goes through the cell break; - case Locate_type::OUTSIDE_AFFINE_HULL: - { - Cell_handle chprev = _cell_iterator.previous(); - Locate_type ltprev; - int liprev, ljprev; - _cell_iterator.exit(ltprev, liprev, ljprev); - - if (ltprev == Locate_type::VERTEX) //edge-vertex-outside - _curr_simplex = chprev->vertex(liprev); - else - _curr_simplex = Simplex_3(); //edge-outside - break; - } default: CGAL_unreachable();//should not happen }; @@ -895,6 +898,38 @@ class Triangulation_segment_simplex_iterator_3 prev = _cell_iterator.previous(); _cell_iterator.exit(ltprev, liprev, ljprev); + if (chnext == Cell_handle()) + { + CGAL_assertion(_cell_iterator == _cell_iterator.end()); + if (ltprev == Locate_type::VERTEX) //vertex-edge-vertex-outside + { + if (prev->vertex(liprev) != get_vertex())//avoid infinite loop edge-vertex-same edge-... + _curr_simplex = Edge(prev, liprev, prev->index(get_vertex())); + else + _curr_simplex = Simplex_3(); + } + else if (ltprev == Locate_type::EDGE)//vertex-facet-edge-outside + { + if (prev->vertex(liprev) != get_vertex() && prev->vertex(ljprev) != get_vertex()) + _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); + else + _curr_simplex = Edge(prev, liprev, ljprev); + } + else if (ltprev == Locate_type::FACET) //vertex-facet-outside + { + if (prev->vertex(liprev) != get_vertex()) //vertex-facet-outside + _curr_simplex = Facet(prev, liprev); + else //vertex-cell-facet-outside + _curr_simplex = prev; + } + else + { + CGAL_assertion(ltprev == Locate_type::CELL);//vertex-cell-outside + _curr_simplex = prev; + } + break; + } + switch (ltnext) { case Locate_type::VERTEX: @@ -948,44 +983,15 @@ class Triangulation_segment_simplex_iterator_3 break; } - case Locate_type::OUTSIDE_AFFINE_HULL: - { - CGAL_assertion(_cell_iterator == _cell_iterator.end()); - if (ltprev == Locate_type::VERTEX) //vertex-edge-vertex-outside - { - if(prev->vertex(liprev) != get_vertex())//avoid infinite loop edge-vertex-same edge-... - _curr_simplex = Edge(prev, liprev, prev->index(get_vertex())); - else - _curr_simplex = Simplex_3(); - } - else if (ltprev == Locate_type::EDGE)//vertex-facet-edge-outside - { - if(prev->vertex(liprev) != get_vertex() && prev->vertex(ljprev) != get_vertex()) - _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); - else - _curr_simplex = Edge(prev, liprev, ljprev); - } - else if (ltprev == Locate_type::FACET) //vertex-facet-outside - { - if(prev->vertex(liprev) != get_vertex()) //vertex-facet-outside - _curr_simplex = Facet(prev, liprev); - else //vertex-cell-facet-outside - _curr_simplex = prev; - } - else - { - CGAL_assertion(ltprev == Locate_type::CELL);//vertex-cell-outside - _curr_simplex = prev; - } - break; - } - - default://FACET + case Locate_type::FACET : if (chnext == Cell_handle()) _curr_simplex = Simplex_3(); else _curr_simplex = shared_cell(Facet(chnext, linext), get_vertex()); break; + + default: + CGAL_unreachable(); }; } break; From 4e14700ab43df37381e6bfa1f0d90b56fb533ba7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 12 May 2023 16:57:25 +0200 Subject: [PATCH 17/60] Remove cases of OUTSIDE_AFFINE_HULL --- .../internal/Triangulation_segment_traverser_3_impl.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 25e904faa2a5..3b115a49aa4e 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -350,7 +350,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre auto case_target_is_inside_cur_cell = [&](int case_nb) { inside = case_nb; prev_after_walk = { cur_cell, Tr::CELL, -1, -1 }; - cur_after_walk = { {}, Tr::OUTSIDE_AFFINE_HULL, -1, -1 }; + cur_after_walk = { {}, Tr::CELL, -1, -1 }; }; auto case_segment_exits_cur_cell_by = [&](int facet_nb) { outside = facet_nb; @@ -679,7 +679,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre CGAL_unreachable(); } - Simplex cur_after_walk(Cell_handle(), Tr::OUTSIDE_AFFINE_HULL, -1, -1); + Simplex cur_after_walk(Cell_handle(), std::get<1>(prev_after_walk), -1, -1); return std::make_pair(prev_after_walk, cur_after_walk); } @@ -854,7 +854,7 @@ walk_to_next_2() return; default: // The current vertex is the target. - CGAL_triangulation_assertion(false); + CGAL_unreachable(); return; } } @@ -881,8 +881,7 @@ walk_to_next_2() _prev = Simplex( cell(), Tr::VERTEX, li(), -1 ); break; case 0: - CGAL_triangulation_assertion(false); - _prev = Simplex( cell(), Tr::OUTSIDE_AFFINE_HULL, -1, -1 ); + CGAL_unreachable(); break; } cell() = Cell_handle(); @@ -1190,7 +1189,7 @@ Triangulation_segment_cell_iterator_3::opposite_edge( case 5: return Edge(c, 2, 3); } - CGAL_triangulation_assertion(false); + CGAL_unreachable(); return Edge(); } From 4bf7c45c8b348bb28d53026dc51802f7d12107ab Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Mon, 15 May 2023 13:06:37 +0200 Subject: [PATCH 18/60] replace std::tuple Simplex with a struct and then avoid all std std::get(simplex), hard to read --- .../Triangulation_segment_traverser_3_impl.h | 192 +++++++++--------- .../CGAL/Triangulation_segment_traverser_3.h | 54 ++--- 2 files changed, 126 insertions(+), 120 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 3b115a49aa4e..a45d65263601 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -36,7 +36,7 @@ Triangulation_segment_cell_iterator_3( const Tr* tr, Vertex_handle s, Vertex_han if( c->has_vertex( _tr->infinite_vertex(), inf ) ) c = c->neighbor(inf); - _cur = Simplex( c, Tr::VERTEX, c->index(s), -1 ); + _cur = Simplex{ c, Tr::VERTEX, c->index(s), -1 }; jump_to_intersecting_cell(); } @@ -62,7 +62,7 @@ Triangulation_segment_cell_iterator_3( const Tr* tr, Vertex_handle s, const Poin if( c->has_vertex( _tr->infinite_vertex(), inf ) ) c = c->neighbor(inf); - _cur = Simplex( c, Tr::VERTEX, c->index(s), -1 ); + _cur = Simplex{ c, Tr::VERTEX, c->index(s), -1 }; jump_to_intersecting_cell(); } @@ -124,7 +124,7 @@ template < class Tr, class Inc > Triangulation_segment_cell_iterator_3 Triangulation_segment_cell_iterator_3::end() const { SCI sci(_tr); - std::get<0>(sci._cur) = Cell_handle(); + sci._cur.cell = Cell_handle(); return sci; } @@ -239,7 +239,7 @@ walk_to_next() { int ti; if( cell()->has_vertex( _t_vertex, ti ) ) { // The target is inside the cell. - _prev = Simplex( cell(), Tr::VERTEX, ti, -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, ti, -1 }; cell() = Cell_handle(); lt() = Locate_type::VERTEX; return; @@ -303,24 +303,24 @@ bool Triangulation_segment_cell_iterator_3:: have_same_entry(const Simplex& s1, const Simplex& s2) const { //type - if (std::get<1>(s1) != std::get<1>(s2)) + if (s1.lt != s2.lt) return false; - switch (std::get<1>(s1)) + switch (s1.lt) { case Locate_type::VERTEX: - return std::get<0>(s1)->vertex(std::get<2>(s1)) == std::get<0>(s2)->vertex(std::get<2>(s2)); + return s1.cell->vertex(s1.li) == s2.cell->vertex(s2.li); case Locate_type::EDGE: { - Vertex_handle v1a = std::get<0>(s1)->vertex(std::get<2>(s1)); - Vertex_handle v1b = std::get<0>(s1)->vertex(std::get<3>(s1)); - Vertex_handle v2a = std::get<0>(s2)->vertex(std::get<2>(s2)); - Vertex_handle v2b = std::get<0>(s2)->vertex(std::get<3>(s2)); + Vertex_handle v1a = s1.cell->vertex(s1.li); + Vertex_handle v1b = s1.cell->vertex(s1.lj); + Vertex_handle v2a = s2.cell->vertex(s2.li); + Vertex_handle v2b = s2.cell->vertex(s2.lj); return (v1a == v2a && v1b == v2b) || (v1a == v2b && v1b == v2a); } case Locate_type::FACET: - return triangulation()->are_equal(Facet(std::get<0>(s1), std::get<2>(s1)), - Facet(std::get<0>(s2), std::get<2>(s2))); + return triangulation()->are_equal(Facet(s1.cell, s1.li), + Facet(s2.cell, s2.li)); default: CGAL_assertion(false); }; @@ -333,7 +333,7 @@ std::pair::Simplex, Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& prev, const Simplex& cur) const { - const auto cur_cell = std::get<0>(cur); + const auto cur_cell = cur.cell; std::array vert = {&(cur_cell->vertex(0)->point()), &(cur_cell->vertex(1)->point()), @@ -343,7 +343,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre int inside=0,outside=0,regular_case=0,degenerate=0; Cell_handle nnext; - if (std::get<1>(cur) == Tr::FACET) { + if (cur.lt == Tr::FACET) { Simplex prev_after_walk; Simplex cur_after_walk; @@ -358,7 +358,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre cur_after_walk = { nnext, Tr::FACET, nnext->index(cur_cell), -1 }; }; regular_case = 1; - const int i = std::get<2>(cur); + const int i = cur.li; const int j0 = Tr::vertex_triple_index(i, 0); const int j1 = Tr::vertex_triple_index(i, 1); const int j2 = Tr::vertex_triple_index(i, 2); @@ -495,19 +495,19 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre // We keep track of which orientations are calculated. bool calc[6] = { false, false, false, false, false, false }; - if( std::get<1>(cur) == Tr::VERTEX ) { + if( cur.lt == Tr::VERTEX ) { // The three planes through the vertex are set to coplanar. for( int j = 0; j < 4; ++j ) { - if( std::get<2>(cur) != j ) { - int ij = edgeIndex( std::get<2>(cur), j ); + if( cur.li != j ) { + int ij = edgeIndex( cur.li, j ); o[ij] = COPLANAR; calc[ij] = true; } } } - else if( std::get<1>(cur) == Tr::EDGE ) { + else if( cur.lt == Tr::EDGE ) { // The plane through the edge is set to coplanar. - int ij = edgeIndex( std::get<2>(cur), std::get<3>(cur) ); + int ij = edgeIndex( cur.li, cur.lj ); o[ij] = COPLANAR; calc[ij] = true; } @@ -519,7 +519,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre { // Skip the previous cell. Cell_handle next = cur_cell->neighbor(li); - if( next == std::get<0>(prev) ) + if( next == prev.cell ) { op[li] = POSITIVE; pos += li; @@ -587,18 +587,18 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre Simplex prev_after_walk; Simplex cur_after_walk; - std::get<0>(prev_after_walk) = cur_cell; - std::get<0>(cur_after_walk) = next; + prev_after_walk.cell = cur_cell; + cur_after_walk.cell = next; switch( Or ) { case 3: - std::get<1>(prev_after_walk) = Tr::FACET; - std::get<2>(prev_after_walk) = li; - std::get<1>(cur_after_walk) = Tr::FACET; - std::get<2>(cur_after_walk) = std::get<0>(cur_after_walk)->index(std::get<0>(prev_after_walk)); + prev_after_walk.lt = Tr::FACET; + prev_after_walk.li = li; + cur_after_walk.lt = Tr::FACET; + cur_after_walk.li = cur_after_walk.cell->index(prev_after_walk.cell); if(regular_case) { - CGAL_triangulation_assertion( std::get<0>(cur_after_walk)==nnext ); + CGAL_triangulation_assertion( cur_after_walk.cell==nnext ); CGAL_triangulation_assertion( li==outside ); CGAL_triangulation_assertion( ! inside ); } @@ -608,19 +608,19 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if(regular_case) CGAL_triangulation_assertion(degenerate ); - std::get<1>(prev_after_walk) = Tr::EDGE; - std::get<1>(cur_after_walk) = Tr::EDGE; + prev_after_walk.lt = Tr::EDGE; + cur_after_walk.lt = Tr::EDGE; for( int j = 0; j < 4; ++j ) { if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) { - Edge opp = opposite_edge( std::get<0>(prev), li, j ); - std::get<2>(prev_after_walk) = opp.second; - std::get<3>(prev_after_walk) = opp.third; - std::get<2>(cur_after_walk) - = std::get<0>(cur_after_walk)->index( - std::get<0>(prev_after_walk)->vertex( std::get<2>(prev_after_walk) ) ); - std::get<3>(cur_after_walk) - = std::get<0>(cur_after_walk)->index( - std::get<0>(prev_after_walk)->vertex( std::get<3>(prev_after_walk) ) ); + Edge opp = opposite_edge( prev.cell, li, j ); + prev_after_walk.li = opp.second; + prev_after_walk.lj = opp.third; + cur_after_walk.li + = cur_after_walk.cell->index( + prev_after_walk.cell->vertex( prev_after_walk.li ) ); + cur_after_walk.lj + = cur_after_walk.cell->index( + prev_after_walk.cell->vertex( prev_after_walk.lj ) ); return std::make_pair(prev_after_walk, cur_after_walk); } @@ -631,14 +631,14 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if(regular_case) CGAL_triangulation_assertion(degenerate ); - std::get<1>(prev_after_walk) = Tr::VERTEX; - std::get<1>(cur_after_walk) = Tr::VERTEX; + prev_after_walk.lt = Tr::VERTEX; + cur_after_walk.lt = Tr::VERTEX; for( int j = 0; j < 4; ++j ) { if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) { - std::get<2>(prev_after_walk) = j; - std::get<2>(cur_after_walk) - = std::get<0>(cur_after_walk)->index( - std::get<0>(prev_after_walk)->vertex(j) ); + prev_after_walk.li = j; + cur_after_walk.li + = cur_after_walk.cell->index( + prev_after_walk.cell->vertex(j) ); return std::make_pair(prev_after_walk, cur_after_walk); } @@ -657,29 +657,29 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre switch( op[0] + op[1] + op[2] + op[3] ) { case 4: CGAL_triangulation_assertion( pos == 6 ); - prev_after_walk = Simplex( cur_cell, Tr::CELL, -1, -1 ); + prev_after_walk = Simplex{ cur_cell, Tr::CELL, -1, -1 }; CGAL_triangulation_assertion( (! regular_case) || inside ); break; case 3: - prev_after_walk = Simplex( cur_cell, Tr::FACET, 6-pos, -1 ); + prev_after_walk = Simplex{ cur_cell, Tr::FACET, 6 - pos, -1 }; break; case 2: if( pos < 3 ) - prev_after_walk = Simplex( cur_cell, Tr::EDGE, 0, pos+1 ); + prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 0, pos+1 }; else if( pos < 5 ) - prev_after_walk = Simplex( cur_cell, Tr::EDGE, 1, pos-1 ); + prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 1, pos-1 }; else - prev_after_walk = Simplex( cur_cell, Tr::EDGE, 2, 3 ); + prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 2, 3 }; break; case 1: - prev_after_walk = Simplex( cur_cell, Tr::VERTEX, pos, -1 ); + prev_after_walk = Simplex{ cur_cell, Tr::VERTEX, pos, -1 }; break; default: CGAL_unreachable(); } - Simplex cur_after_walk(Cell_handle(), std::get<1>(prev_after_walk), -1, -1); + Simplex cur_after_walk{ Cell_handle(), prev_after_walk.lt, -1, -1 }; return std::make_pair(prev_after_walk, cur_after_walk); } @@ -710,7 +710,7 @@ walk_to_next_3_inf( int inf ) if( _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ) == POSITIVE ) { // The target lies in an infinite cell. // Note that we do not traverse to other infinite cells. - _prev = Simplex( cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 ); + _prev = Simplex{ cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 }; cell() = Cell_handle(); return; } @@ -747,8 +747,8 @@ walk_to_next_3_inf( int inf ) // The target lies behind the plane through the source and two finite vertices. // Traverse to the incident infinite cell. CGAL_triangulation_assertion( _tr->is_infinite( next ) ); - _prev = Simplex( cell(), Tr::FACET, li, -1 ); - _cur = Simplex( next, Tr::FACET, next->index( prev_cell() ), -1 ); + _prev = Simplex{ cell(), Tr::FACET, li, -1 }; + _cur = Simplex{ next, Tr::FACET, next->index(prev_cell()), -1 }; return; } @@ -862,23 +862,23 @@ walk_to_next_2() // The target lies in this cell. switch( ocw+occw+op ) { case 3: - _prev = Simplex( cell(), Tr::FACET, 3, -1 ); - break; + _prev = Simplex{ cell(), Tr::FACET, 3, -1 }; + break; case 2: if( ocw == 0 ) - _prev = Simplex( cell(), Tr::EDGE, _tr->ccw(li()), -1 ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(li()), -1 }; else if( occw == 0 ) - _prev = Simplex( cell(), Tr::EDGE, _tr->cw(li()), -1 ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->cw(li()), -1 }; else - _prev = Simplex( cell(), Tr::EDGE, li(), -1 ); + _prev = Simplex{ cell(), Tr::EDGE, li(), -1 }; break; case 1: if( ocw == 1 ) - _prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(li()), -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(li()), -1 }; else if( occw == 1 ) - _prev = Simplex( cell(), Tr::VERTEX, _tr->cw(li()), -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(li()), -1 }; else - _prev = Simplex( cell(), Tr::VERTEX, li(), -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, li(), -1 }; break; case 0: CGAL_unreachable(); @@ -978,19 +978,19 @@ walk_to_next_2() // The target lies in this cell. if( op == POSITIVE ) - _prev = Simplex( cell(), Tr::FACET, 3, -1 ); + _prev = Simplex{ cell(), Tr::FACET, 3, -1 }; else { CGAL_triangulation_assertion( op == ZERO ); switch( o ) { case POSITIVE: - _prev = Simplex( cell(), Tr::EDGE, li(), lk ); - break; + _prev = Simplex{ cell(), Tr::EDGE, li(), lk }; + break; case NEGATIVE: - _prev = Simplex( cell(), Tr::EDGE, lj(), lk ); - break; + _prev = Simplex{ cell(), Tr::EDGE, lj(), lk }; + break; case ZERO: - _prev = Simplex( cell(), Tr::VERTEX, lk, -1 ); - break; + _prev = Simplex{ cell(), Tr::VERTEX, lk, -1 }; + break; } } cell() = Cell_handle(); @@ -1020,7 +1020,7 @@ walk_to_next_2() if( o[_tr->ccw(li)] == NEGATIVE ) continue; else if( op == COLLINEAR && o[_tr->ccw(li)] == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(li), -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(li), -1 }; cell() = Cell_handle(); return; } @@ -1032,7 +1032,7 @@ walk_to_next_2() if( o[_tr->cw(li)] == POSITIVE ) continue; else if( op == COLLINEAR && o[_tr->cw(li)] == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->cw(li), -1 ); + _prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(li), -1 }; cell() = Cell_handle(); return; } @@ -1063,7 +1063,7 @@ walk_to_next_2() } // The target lies in this cell. - _prev = Simplex( cell(), Tr::FACET, 3, -1 ); + _prev = Simplex{ cell(), Tr::FACET, 3, -1 }; cell() = Cell_handle(); return; } @@ -1097,8 +1097,8 @@ walk_to_next_2_inf( int inf ) _target ); if( occw == NEGATIVE ) { Cell_handle tmp = cell()->neighbor(_tr->cw(inf)); - _prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), inf ); - _cur = Simplex( tmp, Tr::EDGE, tmp->index( prev_cell()->vertex( prev_li() ) ), tmp->index( prev_cell()->vertex( prev_lj() ) ) ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), inf }; + _cur = Simplex{ tmp, Tr::EDGE, tmp->index(prev_cell()->vertex(prev_li())), tmp->index(prev_cell()->vertex(prev_lj())) }; return; } Orientation ocw = coplanar_orientation( _source, @@ -1107,8 +1107,8 @@ walk_to_next_2_inf( int inf ) _target ); if( ocw == NEGATIVE ) { Cell_handle tmp = cell()->neighbor(_tr->ccw(inf)); - _prev = Simplex( cell(), Tr::EDGE, _tr->cw(inf), inf ); - _cur = Simplex( tmp, Tr::EDGE, tmp->index( prev_cell()->vertex( prev_li() ) ), tmp->index( prev_cell()->vertex( prev_lj() ) ) ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->cw(inf), inf }; + _cur = Simplex{ tmp, Tr::EDGE, tmp->index(prev_cell()->vertex(prev_li())), tmp->index(prev_cell()->vertex(prev_lj())) }; return; } Orientation op = coplanar_orientation( @@ -1118,37 +1118,37 @@ walk_to_next_2_inf( int inf ) switch( op ) { case NEGATIVE: if( occw == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(inf), -1 ); - _cur = Simplex( fin, Tr::VERTEX, fin->index( prev_cell()->vertex( prev_li() ) ), -1 ); - return; + _prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(inf), -1 }; + _cur = Simplex{ fin, Tr::VERTEX, fin->index(prev_cell()->vertex(prev_li())), -1 }; + return; } if( ocw == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->cw(inf), -1 ); - _cur = Simplex( fin, Tr::VERTEX, fin->index( prev_cell()->vertex( prev_li() ) ), -1 ); - return; + _prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(inf), -1 }; + _cur = Simplex{ fin, Tr::VERTEX, fin->index(prev_cell()->vertex(prev_li())), -1 }; + return; } - _prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) ); - _cur = Simplex( fin, Tr::EDGE, fin->index( prev_cell()->vertex( prev_li() ) ), fin->index( prev_cell()->vertex( prev_lj() ) ) ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) }; + _cur = Simplex{ fin, Tr::EDGE, fin->index(prev_cell()->vertex(prev_li())), fin->index(prev_cell()->vertex(prev_lj())) }; return; case COLLINEAR: if( occw == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->ccw(inf), -1 ); - cell() = Cell_handle(); - return; + _prev = Simplex{ cell(), Tr::VERTEX, _tr->ccw(inf), -1 }; + cell() = Cell_handle(); + return; } if( ocw == COLLINEAR ) { - _prev = Simplex( cell(), Tr::VERTEX, _tr->cw(inf), -1 ); - cell() = Cell_handle(); - return; + _prev = Simplex{ cell(), Tr::VERTEX, _tr->cw(inf), -1 }; + cell() = Cell_handle(); + return; } - _prev = Simplex( cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) ); + _prev = Simplex{ cell(), Tr::EDGE, _tr->ccw(inf), _tr->cw(inf) }; cell() = Cell_handle(); return; case POSITIVE: // The tarstd::std::get lies in this infinite cell. - _prev = Simplex( cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 ); - cell() = Cell_handle(); - return; + _prev = Simplex{ cell(), Tr::OUTSIDE_CONVEX_HULL, -1, -1 }; + cell() = Cell_handle(); + return; } } diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index ace5492353fb..09dd5c3029fc 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -113,7 +112,13 @@ class Triangulation_segment_cell_iterator_3 typedef typename Tr::Locate_type Locate_type; //< defines the simplex type returned from location. - typedef std::tuple Simplex; //< defines the simplex type. + struct Simplex //< defines the simplex type + { + Cell_handle cell; + Locate_type lt; + int li; + int lj; + }; typedef Cell value_type; //< defines the value type the iterator refers to. typedef Cell& reference; //< defines the reference type of the iterator. @@ -287,7 +292,7 @@ class Triangulation_segment_cell_iterator_3 */ Cell_handle handle() const { - return std::get<0>(_cur); + return _cur.cell; } // gives the previous cell. @@ -308,7 +313,7 @@ class Triangulation_segment_cell_iterator_3 */ Cell* operator->() { - return &*std::get<0>(_cur); + return &*(_cur.cell); } // provides an indirection operator. @@ -316,7 +321,7 @@ class Triangulation_segment_cell_iterator_3 */ Cell& operator*() { - return *std::get<0>(_cur); + return *(_cur.cell); } // provides a conversion operator. @@ -324,7 +329,7 @@ class Triangulation_segment_cell_iterator_3 */ operator Cell_handle() const { - return std::get<0>(_cur); + return _cur.cell; } // provides a conversion operator. @@ -423,7 +428,7 @@ class Triangulation_segment_cell_iterator_3 */ bool operator==( const Cell_handle& ch ) const { - return ch == std::get<0>(_cur); + return ch == _cur.cell; } // compares the current cell with `ch`. @@ -434,7 +439,7 @@ class Triangulation_segment_cell_iterator_3 */ bool operator!=( const Cell_handle& ch ) const { - return ch != std::get<0>(_cur); + return ch != _cur.cell; } // \} @@ -498,32 +503,33 @@ class Triangulation_segment_cell_iterator_3 Edge opposite_edge(Cell_handle c, int li, int lj) const; Edge opposite_edge(const Edge& e) const; +protected: // ref-accessors to the simplex, for use in internal code // access _cur - Cell_handle& cell() { return std::get<0>(_cur); } - Cell_handle const& cell() const { return std::get<0>(_cur); } + Cell_handle& cell() { return _cur.cell; } + Cell_handle const& cell() const { return _cur.cell; } - Locate_type& lt() { return std::get<1>(_cur); } - Locate_type const& lt() const { return std::get<1>(_cur); } + Locate_type& lt() { return _cur.lt; } + Locate_type const& lt() const { return _cur.lt; } - int& li() { return std::get<2>(_cur); } - int const& li() const { return std::get<2>(_cur); } + int& li() { return _cur.li; } + int const& li() const { return _cur.li; } - int& lj() { return std::get<3>(_cur); } - int const& lj() const { return std::get<3>(_cur); } + int& lj() { return _cur.lj; } + int const& lj() const { return _cur.lj; } // access _prev - Cell_handle& prev_cell() { return std::get<0>(_prev); } - Cell_handle const& prev_cell() const { return std::get<0>(_prev); } + Cell_handle& prev_cell() { return _prev.cell; } + Cell_handle const& prev_cell() const { return _prev.cell; } - Locate_type& prev_lt() { return std::get<1>(_prev); } - Locate_type const& prev_lt() const { return std::get<1>(_prev); } + Locate_type& prev_lt() { return _prev.lt; } + Locate_type const& prev_lt() const { return _prev.lt; } - int& prev_li() { return std::get<2>(_prev); } - int const& prev_li() const { return std::get<2>(_prev); } + int& prev_li() { return _prev.li; } + int const& prev_li() const { return _prev.li; } - int& prev_lj() { return std::get<3>(_prev); } - int const& prev_lj() const { return std::get<3>(_prev); } + int& prev_lj() { return _prev.lj; } + int const& prev_lj() const { return _prev.lj; } }; // class Triangulation_segment_cell_iterator_3 From c7f75a90306e487b449970c80bf5244aa3aa656e Mon Sep 17 00:00:00 2001 From: Jane Tournois Date: Tue, 16 May 2023 18:35:54 +0200 Subject: [PATCH 19/60] wip fixes for simplex traverser * test_segment_simplex_traverser_3 first failing test is now "032" * the geometric intersection test fails because of doubles --- .../CGAL/Triangulation_segment_traverser_3.h | 128 +++++++++++------- .../test_segment_simplex_traverser_3.cpp | 14 +- 2 files changed, 83 insertions(+), 59 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 09dd5c3029fc..3f2ebf774b8e 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -748,37 +748,59 @@ class Triangulation_segment_simplex_iterator_3 //taking cell_iterator one step forward CGAL_assertion(cell_has_facet(Cell_handle(_cell_iterator), get_facet())); increment_cell_iterator(); - if (Cell_handle(_cell_iterator) == Cell_handle()) - { - _curr_simplex = _cell_iterator.previous(); - break; - } } else ch = _cell_iterator.previous(); Cell_handle chnext = Cell_handle(_cell_iterator); + Locate_type lt; + int li, lj; + _cell_iterator.exit(lt, li, lj); + if (chnext == Cell_handle()) { - _curr_simplex = Simplex_3(); + CGAL_assertion(_cell_iterator == _cell_iterator.end()); + Cell_handle prev = _cell_iterator.previous(); + if (lt == Locate_type::VERTEX) //facet-cell?-vertex-outside + { + int i; + if (triangulation()->has_vertex(get_facet(), prev->vertex(li), i)) + _curr_simplex = prev->vertex(li); + else + _curr_simplex = prev; + } + else if (lt == Locate_type::EDGE)//facet-cell?-edge-outside + { + int i, j; + if ( triangulation()->has_vertex(get_facet(), prev->vertex(li), i) + && triangulation()->has_vertex(get_facet(), prev->vertex(lj), j)) + _curr_simplex = Edge(prev, li, lj); + else + _curr_simplex = prev; + } + else if (lt == Locate_type::FACET) //facet-cell-facet-outside + { + if (Facet(prev, li) == get_facet() + || triangulation()->mirror_facet(Facet(prev, li)) == get_facet()) + _curr_simplex = Simplex_3(); + else + _curr_simplex = prev; + } + else + { + CGAL_assertion(lt == Locate_type::CELL); + _curr_simplex = Simplex_3(); + } break; } - Locate_type ltnext; - int linext, ljnext; - _cell_iterator.entry(ltnext, linext, ljnext); - switch (ltnext)//entry simplex in next cell + switch (lt)//entry simplex in next cell is exit simplex in current cell { case Locate_type::VERTEX: { - if (_cell_iterator == _cell_iterator.end()) - { - _curr_simplex = Simplex_3(); - break; - } //if the entry vertex is a vertex of current facet int i; - if (triangulation()->has_vertex(get_facet(), chnext->vertex(linext), i)) + if (triangulation()->has_vertex(get_facet(), ch->vertex(li), i)) set_curr_simplex_to_entry(); else _curr_simplex = ch; @@ -786,7 +808,7 @@ class Triangulation_segment_simplex_iterator_3 } case Locate_type::EDGE: - if (facet_has_edge(get_facet(), Edge(chnext, linext, ljnext))) + if (facet_has_edge(get_facet(), Edge(ch, li, lj))) set_curr_simplex_to_entry(); else _curr_simplex = ch; @@ -809,18 +831,9 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = Simplex_3(); break; } - Locate_type lt; - int li, lj; - _cell_iterator.entry(lt, li, lj); - if (!cell_iterator_is_ahead()) { increment_cell_iterator();//cell_iterator needs to be ahead to detect degeneracies - if (Cell_handle(_cell_iterator) == Cell_handle()) - { - _curr_simplex = _cell_iterator.previous(); - break; - } } Cell_handle chnext = Cell_handle(_cell_iterator); @@ -832,37 +845,47 @@ class Triangulation_segment_simplex_iterator_3 _cell_iterator.exit(ltprev, liprev, ljprev); if (ltprev == Locate_type::VERTEX) //edge-vertex-outside - _curr_simplex = chprev->vertex(liprev); + { + if(edge_has_vertex(get_edge(), chprev->vertex(liprev))) + _curr_simplex = chprev->vertex(liprev); + else + _curr_simplex = shared_facet(get_edge(), chprev->vertex(liprev)); + } + else if(ltprev == Locate_type::CELL) + _curr_simplex = ch; //edge-cell-outside else _curr_simplex = Simplex_3(); //edge-outside break; } - Locate_type ltnext; - int linext, ljnext; - _cell_iterator.entry(ltnext, linext, ljnext); - switch (ltnext)//entry simplex in next cell + ch = _cell_iterator.previous(); + Locate_type lt_exit; + int li_exit, lj_exit; + _cell_iterator.exit(lt_exit, li_exit, lj_exit); + switch (lt_exit)//entry simplex in next cell is exit simplex in current cell { case Locate_type::VERTEX: - if (edge_has_vertex(get_edge(), chnext->vertex(linext))) - _curr_simplex = chnext->vertex(linext); + { + const Vertex_handle v_exit = ch->vertex(li_exit); + if (edge_has_vertex(get_edge(), v_exit)) + _curr_simplex = v_exit; else - _curr_simplex = shared_facet(get_edge(), chnext->vertex(linext)); + _curr_simplex = shared_facet(get_edge(), v_exit); break; - + } case Locate_type::EDGE: { + const Edge e_exit(ch, li_exit, lj_exit); CGAL_assertion(_cell_iterator == _cell_iterator.end() || triangulation()->is_infinite(chnext) - || _curr_simplex != Simplex_3(Edge(chnext, linext, ljnext))); + || _curr_simplex != Simplex_3(e_exit)); if (_cell_iterator == _cell_iterator.end()) - _curr_simplex = Simplex_3(); - else if (triangulation()->is_infinite(chnext) - && _curr_simplex == Simplex_3(Edge(chnext, linext, ljnext))) + _curr_simplex = Simplex_3();//should not be reached + else if (triangulation()->is_infinite(chnext) && is_same_edge(get_edge(), e_exit)) _curr_simplex = chnext; else - _curr_simplex = shared_facet(get_edge(), Edge(chnext, linext, ljnext)); + _curr_simplex = shared_facet(get_edge(), e_exit); break; } @@ -894,14 +917,9 @@ class Triangulation_segment_simplex_iterator_3 //_cell_iterator is one step forward _curr_simplex CGAL_assertion(ch != chnext); - Locate_type ltnext; - int linext, ljnext; - _cell_iterator.entry(ltnext, linext, ljnext); - - Cell_handle prev; + Cell_handle prev = _cell_iterator.previous(); Locate_type ltprev; int liprev, ljprev; - prev = _cell_iterator.previous(); _cell_iterator.exit(ltprev, liprev, ljprev); if (chnext == Cell_handle()) @@ -936,12 +954,12 @@ class Triangulation_segment_simplex_iterator_3 break; } - switch (ltnext) + switch (ltprev) { case Locate_type::VERTEX: { CGAL_assertion(_cell_iterator == _cell_iterator.end() - || get_vertex() != chnext->vertex(linext) + || get_vertex() != prev->vertex(liprev) || triangulation()->is_infinite(chnext)); if (_cell_iterator == _cell_iterator.end()) { @@ -967,13 +985,13 @@ class Triangulation_segment_simplex_iterator_3 } else { - if (triangulation()->is_infinite(chnext) && get_vertex() == chnext->vertex(linext)) + if (triangulation()->is_infinite(chnext) && get_vertex() == prev->vertex(liprev)) _curr_simplex = chnext; else { Cell_handle ec; int ei = -1, ej = -1; - if (!triangulation()->is_edge(get_vertex(), chnext->vertex(linext), ec, ei, ej)) + if (!triangulation()->is_edge(get_vertex(), prev->vertex(liprev), ec, ei, ej)) CGAL_unreachable(); _curr_simplex = Edge(ec, ei, ej); } @@ -985,7 +1003,7 @@ class Triangulation_segment_simplex_iterator_3 { //facet shared by get_vertex() and the edge //none of ch and chnext is certainly shared by both endpoints - _curr_simplex = shared_facet(Edge(chnext, linext, ljnext), get_vertex()); + _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); break; } @@ -993,7 +1011,7 @@ class Triangulation_segment_simplex_iterator_3 if (chnext == Cell_handle()) _curr_simplex = Simplex_3(); else - _curr_simplex = shared_cell(Facet(chnext, linext), get_vertex()); + _curr_simplex = shared_cell(Facet(prev, liprev), get_vertex()); break; default: @@ -1148,6 +1166,12 @@ class Triangulation_segment_simplex_iterator_3 || e.first->vertex(e.third) == v; } + bool is_same_edge(const Edge& e1, const Edge& e2) const + { + return edge_has_vertex(e1, e2.first->vertex(e2.second)) + && edge_has_vertex(e1, e2.first->vertex(e2.third)); + } + Vertex_handle shared_vertex(const Edge& e1, const Edge& e2) const { Vertex_handle v1a = e1.first->vertex(e1.second); diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 9c56c7681a70..c588f83272fc 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -67,7 +67,7 @@ struct Debug_simplex { } case 1: { const auto [c, index1, index2] = static_cast(simplex); - os << "- egde " + os << "- edge " << display_vert(c->vertex(index1)) << " - " << display_vert(c->vertex(index2)); break; @@ -204,12 +204,12 @@ void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional previ { CGAL_error_msg("consecutive simplices are not incident"); } - const bool does_intersect_ab = std::visit( - [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, - get_simplex_geometry(s)); - if(!does_intersect_ab) { - CGAL_error_msg("the simplex does not intersect the query segment"); - } +// const bool does_intersect_ab = std::visit( +// [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, +// get_simplex_geometry(s)); +// if(!does_intersect_ab) { +// CGAL_error_msg("the simplex does not intersect the query segment"); +// } } }; From d6f6096518067375a187bae0e9d5c2eec89c07cd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 12 Jun 2023 16:38:42 +0200 Subject: [PATCH 20/60] test intersection before the other lines that may swap simplices --- .../test_segment_simplex_traverser_3.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index c588f83272fc..1335e04286cd 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -188,6 +188,13 @@ void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional previ result_string += std::to_string(d); } std::cout << debug_simplex(s) << '\n'; + const bool does_intersect_ab = (3 == d && dt.is_infinite(static_cast(s))) || + std::visit( + [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, + get_simplex_geometry(s)); + if(!does_intersect_ab) { + CGAL_error_msg("the simplex does not intersect the query segment"); + } if(previous_simplex_optional) { // this block checks that consecutive simplices are incident using Set = std::array; @@ -204,12 +211,6 @@ void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional previ { CGAL_error_msg("consecutive simplices are not incident"); } -// const bool does_intersect_ab = std::visit( -// [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, -// get_simplex_geometry(s)); -// if(!does_intersect_ab) { -// CGAL_error_msg("the simplex does not intersect the query segment"); -// } } }; From 5dceac54ef641f67e6ddd29cc27f83bac9d62cd7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 12 Jun 2023 16:43:51 +0200 Subject: [PATCH 21/60] cosmetic changes --- .../Triangulation_segment_traverser_3_impl.h | 160 +++++++----------- 1 file changed, 64 insertions(+), 96 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index a45d65263601..75f56b666a8c 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -341,7 +341,6 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre &(cur_cell->vertex(3)->point()) }; int inside=0,outside=0,regular_case=0,degenerate=0; - Cell_handle nnext; if (cur.lt == Tr::FACET) { Simplex prev_after_walk; @@ -352,7 +351,11 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre prev_after_walk = { cur_cell, Tr::CELL, -1, -1 }; cur_after_walk = { {}, Tr::CELL, -1, -1 }; }; - auto case_segment_exits_cur_cell_by = [&](int facet_nb) { + auto case_segment_exits_cur_cell_by = [&](int facet_nb, + Cell_handle nnext = {}) { + if(nnext == Cell_handle{}) { + nnext = cur_cell->neighbor(facet_nb); + } outside = facet_nb; prev_after_walk = { cur_cell, Tr::FACET, facet_nb, -1 }; cur_after_walk = { nnext, Tr::FACET, nnext->index(cur_cell), -1 }; @@ -368,7 +371,6 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if (o1 != POSITIVE) { Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); if (oi01 == POSITIVE) { - nnext = cur_cell->neighbor(j2); case_segment_exits_cur_cell_by(j2); if (o1 == ZERO) degenerate = 1; //EDGE i j1 } @@ -405,7 +407,6 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } else { if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = cur_cell->neighbor(j0); case_segment_exits_cur_cell_by(j0); } else @@ -418,9 +419,8 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if (o1 == NEGATIVE) { Orientation oi12 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); if (oi12 == POSITIVE) { - nnext = cur_cell->neighbor(j2); //EDGE i j0 degenerate = 2; - case_segment_exits_cur_cell_by(44); + case_segment_exits_cur_cell_by(44, cur_cell->neighbor(j2)); //EDGE i j0 } else { case_target_is_inside_cur_cell(3); @@ -444,14 +444,12 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre case_target_is_inside_cur_cell(55); else { - nnext = cur_cell->neighbor(j2); //VERTEX i degenerate = 3; - case_segment_exits_cur_cell_by(5); + case_segment_exits_cur_cell_by(5, cur_cell->neighbor(j2)); //VERTEX i } } else { // o0 == 0, o1 > 0 if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = cur_cell->neighbor(j0); case_segment_exits_cur_cell_by(j0); } else @@ -462,7 +460,6 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); if (o2 != NEGATIVE) { if (_tr->orientation(*vert[i], *vert[j2], *vert[j0], _target) == POSITIVE) { - nnext = cur_cell->neighbor(j1); case_segment_exits_cur_cell_by(j1); if (o2 == ZERO) degenerate = 4; // EDGE i j2 } @@ -471,7 +468,6 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } else { if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { - nnext = cur_cell->neighbor(j0); case_segment_exits_cur_cell_by(j0); } else @@ -481,7 +477,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if (!degenerate) { - return std::make_pair(prev_after_walk, cur_after_walk); + return { prev_after_walk, cur_after_walk }; } } @@ -489,8 +485,8 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre // We check in which direction the target lies // by comparing its position relative to the planes through the // source and the edges of the cell. - Orientation o[6]; - Orientation op[4]; + std::array o; + std::array op; int pos = 0; // We keep track of which orientations are calculated. bool calc[6] = { false, false, false, false, false, false }; @@ -513,9 +509,8 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } // For the remembering stochastic walk, we start trying with a random facet. - int li = 0; CGAL_triangulation_assertion_code( bool incell = true; ) - for( int k = 0; k < 4; ++k, ++li ) + for( int li = 0; li < 4; ++li) { // Skip the previous cell. Cell_handle next = cur_cell->neighbor(li); @@ -525,48 +520,42 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre pos += li; continue; } - const Point* backup = vert[li]; - vert[li] = &_target; + const Point* const backup_vert_li = std::exchange(vert[li], &_target); // Check if the target is on the opposite side of the supporting plane. op[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ); if( op[li] == POSITIVE ) pos += li; if( op[li] != NEGATIVE ) { - vert[li] = backup; + vert[li] = backup_vert_li; continue; } CGAL_triangulation_assertion_code( incell = false; ) // Check if the target is inside the 3-wedge with // the source as apex and the facet as an intersection. - int lj = 0; int Or = 0; - for( int l = 0; l < 4; ++l, ++lj ) { + for( int lj = 0; lj < 4; ++lj ) { if( li == lj ) continue; // We check the orientation of the target compared to the plane // Through the source and the edge opposite of ij. - int oij = 5 - edgeIndex( li, lj ); + const int oij = 5 - edgeIndex( li, lj ); if( !calc[oij] ) { - const Point* backup2 = vert[lj]; - vert[lj] = &_source; + const Point* const backup_vert_lj = std::exchange(vert[lj], &_source); o[oij] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ); - vert[lj] = backup2; + vert[lj] = backup_vert_lj; calc[oij] = true; } if( o[oij] == POSITIVE ) { // The target is not inside the pyramid. // Invert the planes. - // This can be safely done because either - // they were not calculated yet, - // or they will no longer be used. for( int j = 0; j < 4; ++j ) { if( li == j ) continue; int oij = 5 - edgeIndex( li, j ); - o[oij] = -o[oij]; + if(calc[oij]) o[oij] = -o[oij]; } Or = 0; break; @@ -578,69 +567,47 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if( Or == 0 ) { // Either the target is not inside the pyramid, // or the pyramid is degenerate. - vert[li] = backup; + vert[li] = backup_vert_li; continue; } // The target is inside the pyramid. - - Simplex prev_after_walk; - Simplex cur_after_walk; - - prev_after_walk.cell = cur_cell; - cur_after_walk.cell = next; switch( Or ) { - case 3: - prev_after_walk.lt = Tr::FACET; - prev_after_walk.li = li; - cur_after_walk.lt = Tr::FACET; - cur_after_walk.li = cur_after_walk.cell->index(prev_after_walk.cell); - + case 3: { if(regular_case) { - CGAL_triangulation_assertion( cur_after_walk.cell==nnext ); CGAL_triangulation_assertion( li==outside ); CGAL_triangulation_assertion( ! inside ); } - return std::make_pair(prev_after_walk, cur_after_walk); - - case 2: + return { {cur_cell, Tr::FACET, li}, + {next, Tr::FACET, next->index(cur_cell)} }; + } + case 2: { if(regular_case) CGAL_triangulation_assertion(degenerate ); - prev_after_walk.lt = Tr::EDGE; - cur_after_walk.lt = Tr::EDGE; for( int j = 0; j < 4; ++j ) { if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) { Edge opp = opposite_edge( prev.cell, li, j ); - prev_after_walk.li = opp.second; - prev_after_walk.lj = opp.third; - cur_after_walk.li - = cur_after_walk.cell->index( - prev_after_walk.cell->vertex( prev_after_walk.li ) ); - cur_after_walk.lj - = cur_after_walk.cell->index( - prev_after_walk.cell->vertex( prev_after_walk.lj ) ); - - return std::make_pair(prev_after_walk, cur_after_walk); + return { {cur_cell, Tr::EDGE, opp.second, opp.third}, + {next, Tr::EDGE, + next->index(cur_cell->vertex( opp.second )), + next->index(cur_cell->vertex( opp.third )) + } + }; } } CGAL_unreachable(); return std::make_pair(prev, cur); + } case 1: if(regular_case) CGAL_triangulation_assertion(degenerate ); - prev_after_walk.lt = Tr::VERTEX; - cur_after_walk.lt = Tr::VERTEX; for( int j = 0; j < 4; ++j ) { if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) { - prev_after_walk.li = j; - cur_after_walk.li - = cur_after_walk.cell->index( - prev_after_walk.cell->vertex(j) ); - - return std::make_pair(prev_after_walk, cur_after_walk); + return { {cur_cell, Tr::VERTEX, j}, + {next, Tr::VERTEX, next->index(cur_cell->vertex(j))} }; } } CGAL_unreachable(); @@ -649,38 +616,39 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre CGAL_unreachable(); return std::make_pair(prev, cur); } + CGAL_unreachable(); } // The target lies inside this cell. - Simplex prev_after_walk; CGAL_triangulation_assertion( incell ); - switch( op[0] + op[1] + op[2] + op[3] ) { - case 4: - CGAL_triangulation_assertion( pos == 6 ); - prev_after_walk = Simplex{ cur_cell, Tr::CELL, -1, -1 }; - CGAL_triangulation_assertion( (! regular_case) || inside ); - break; - - case 3: - prev_after_walk = Simplex{ cur_cell, Tr::FACET, 6 - pos, -1 }; - break; - case 2: - if( pos < 3 ) - prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 0, pos+1 }; - else if( pos < 5 ) - prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 1, pos-1 }; - else - prev_after_walk = Simplex{ cur_cell, Tr::EDGE, 2, 3 }; - break; - case 1: - prev_after_walk = Simplex{ cur_cell, Tr::VERTEX, pos, -1 }; - break; - default: - CGAL_unreachable(); - } - - Simplex cur_after_walk{ Cell_handle(), prev_after_walk.lt, -1, -1 }; - return std::make_pair(prev_after_walk, cur_after_walk); + return { + [&]() -> Simplex { + switch( op[0] + op[1] + op[2] + op[3] ) { + case 4: + CGAL_triangulation_assertion( pos == 6 ); + CGAL_triangulation_assertion( (! regular_case) || inside ); + return { cur_cell, Tr::CELL }; + break; + case 3: + return { cur_cell, Tr::FACET, 6 - pos }; + break; + case 2: + if( pos < 3 ) + return { cur_cell, Tr::EDGE, 0, pos+1 }; + else if( pos < 5 ) + return { cur_cell, Tr::EDGE, 1, pos-1 }; + else + return { cur_cell, Tr::EDGE, 2, 3 }; + break; + case 1: + return { cur_cell, Tr::VERTEX, pos }; + break; + default: + CGAL_unreachable(); + } + }(), + { Cell_handle() } + }; } template < class Tr, class Inc > @@ -735,12 +703,12 @@ walk_to_next_3_inf( int inf ) continue; } - Point* backup = vert[li]; + Point* backup_vert_li = vert[li]; vert[li] = &(_target); o[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ); if( o[li] != NEGATIVE ) { - vert[li] = backup; + vert[li] = backup_vert_li; continue; } From 5048eb960d3ba9d51f2cfa55cae610a1e7a59224 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 12 Jun 2023 16:45:16 +0200 Subject: [PATCH 22/60] bug-fix!! I have been working on that issue for a few days. Eventually I found the bug. --- .../internal/Triangulation_segment_traverser_3_impl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 75f56b666a8c..ed9160c9445f 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -634,7 +634,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre break; case 2: if( pos < 3 ) - return { cur_cell, Tr::EDGE, 0, pos+1 }; + return { cur_cell, Tr::EDGE, 0, pos }; else if( pos < 5 ) return { cur_cell, Tr::EDGE, 1, pos-1 }; else From 67b2d1c77084ab6fd57aae90e36ceaa5a0cdd800 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 12 Jun 2023 18:06:40 +0200 Subject: [PATCH 23/60] bug-fix of case "230 with bbox" --- .../internal/Triangulation_segment_traverser_3_impl.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index ed9160c9445f..8b8b27e4aae4 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -342,7 +342,10 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre int inside=0,outside=0,regular_case=0,degenerate=0; - if (cur.lt == Tr::FACET) { + if (cur.lt == Tr::FACET && prev.cell != Cell_handle()) { + // [source, target] entered the cell `cur` via a facet. + // Note that, if prev.cell == Cell_handle(), that means `source` is *on* + // the facet, and the block of this `if` cannot be applied. Simplex prev_after_walk; Simplex cur_after_walk; From d5f5a6e2cdd56b5d338baf212f4d197f456411e2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 13 Jun 2023 17:19:03 +0200 Subject: [PATCH 24/60] buf-fix for case 032I --- .../include/CGAL/Triangulation_segment_traverser_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 3f2ebf774b8e..14ff9f769ad8 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -786,10 +786,10 @@ class Triangulation_segment_simplex_iterator_3 else _curr_simplex = prev; } - else + else // facet-cell then end { CGAL_assertion(lt == Locate_type::CELL); - _curr_simplex = Simplex_3(); + _curr_simplex = prev; } break; } From 311b04a0a70fa497870e94726f0a5b09b89efb1e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 13 Jun 2023 17:32:29 +0200 Subject: [PATCH 25/60] bug-fix for case "0323 with bbox" The test-case was wrong. --- .../test/Triangulation_3/test_segment_simplex_traverser_3.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 1335e04286cd..6d3dda171aec 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -348,8 +348,8 @@ bool test_a_simple_tetrahedron() { // queries entering by a vertex and exiting by a facet, one the line x==y==0.25-0.25z test({ 0, 0, 1}, { .25, .25, .25}, "03"); test({ 0, 0, 1}, { .25, .25, 0}, "032"); - test({ 0, 0, 1}, { .5, .5, -1 }, "032I"); - test({-.25,-.25, 2}, { .5, .5, -1 }, "I032I"); + test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); + test({-.25,-.25, 2}, { .5, .5, -.1 }, "I032I"); test({-.25,-.25, 2}, { .25, .25, 0}, "I032"); test({-.25,-.25, 2}, { .05, .05, .8}, "I03"); From 7b039e3761ec01a2ea6b4e01c6a33336fcfb784e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 14 Jun 2023 17:57:50 +0200 Subject: [PATCH 26/60] fix test cases for I032I, and I03 `-.1`, and `.8` are not floating point values. I have used `.125` (1/8) and `.5` instead. --- .../test_segment_simplex_traverser_3.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 6d3dda171aec..139a68552a2a 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -345,13 +345,13 @@ bool test_a_simple_tetrahedron() { test({-1, -1, 0}, {.5, .5, 0}, "I021"); test({-1, -1, 0}, {.2, .2, 0}, "I02"); - // queries entering by a vertex and exiting by a facet, one the line x==y==0.25-0.25z + // queries entering by a vertex and exiting by a facet, on the line x==y==0.25-0.25z test({ 0, 0, 1}, { .25, .25, .25}, "03"); - test({ 0, 0, 1}, { .25, .25, 0}, "032"); - test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); - test({-.25,-.25, 2}, { .5, .5, -.1 }, "I032I"); - test({-.25,-.25, 2}, { .25, .25, 0}, "I032"); - test({-.25,-.25, 2}, { .05, .05, .8}, "I03"); + test({ 0, 0, 1}, { .25, .25, 0 }, "032"); + test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); + test({-.25,-.25, 2}, { .28125, .28125, -.125}, "I032I"); + test({-.25,-.25, 2}, { .25, .25, 0 }, "I032"); + test({-.25,-.25, 2}, { .125, .125, .5 }, "I03"); // queries entering by an edge and exiting by an edge, on the line (x,.5,0) test({ 0, .5, 0}, {.2, .5, 0}, "12"); @@ -386,6 +386,8 @@ bool test(const DT& dt, int main(int, char* []) { + std::cerr.precision(17); + std::cout.precision(17); const std::vector points = { { -2, 0, 0 }, { 2, 0, 0 }, { 0, 1, -1 }, @@ -409,8 +411,6 @@ int main(int, char* []) assert(dt.is_cell(vertices[0], vertices[2], vertices[3], vertices[4], c)); assert(dt.is_cell(vertices[1], vertices[2], vertices[3], vertices[4], c)); - std::cerr << dt.number_of_finite_cells() << '\n'; - const std::vector < std::pair> queries = { {{-1, 0, 0}, { 1, 0, 0}}, // CFC {{-1, 0, 0}, { 2, 0, 0}}, // CFCV From b9eea8ec0d02a3231e9e0feb7c833ed988ed4594 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 14 Jun 2023 21:12:15 +0200 Subject: [PATCH 27/60] bug-fix test case 121 --- .../CGAL/Triangulation_segment_traverser_3.h | 33 ++++++++++++++++--- 1 file changed, 29 insertions(+), 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 14ff9f769ad8..02a29f092a4a 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -844,17 +844,42 @@ class Triangulation_segment_simplex_iterator_3 int liprev, ljprev; _cell_iterator.exit(ltprev, liprev, ljprev); - if (ltprev == Locate_type::VERTEX) //edge-vertex-outside - { + switch(ltprev) { + case Locate_type::VERTEX: { //edge-vertex-outside if(edge_has_vertex(get_edge(), chprev->vertex(liprev))) _curr_simplex = chprev->vertex(liprev); else _curr_simplex = shared_facet(get_edge(), chprev->vertex(liprev)); + break; + } + case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside + const Vertex_handle vi = chprev->vertex(liprev); + const Vertex_handle vj = chprev->vertex(ljprev); + const bool vi_is_vertex_of_edge = edge_has_vertex(get_edge(), vi); + const bool vj_is_vertex_of_edge = edge_has_vertex(get_edge(), vj); + if(vi_is_vertex_of_edge && vj_is_vertex_of_edge) { + _curr_simplex = Simplex_3(); + } else if(vi_is_vertex_of_edge && !vj_is_vertex_of_edge) { + _curr_simplex = shared_facet(get_edge(), vj); + } else if(vj_is_vertex_of_edge && !vi_is_vertex_of_edge) { + _curr_simplex = shared_facet(get_edge(), vi); + } else { + CGAL_assertion(!vi_is_vertex_of_edge && !vj_is_vertex_of_edge); + Facet f = shared_facet(get_edge(), vi); + _curr_simplex = shared_cell(f, vj); + } + break; } - else if(ltprev == Locate_type::CELL) + case Locate_type::FACET: + _curr_simplex = chprev; //query goes through the cell + break; + case Locate_type::CELL: _curr_simplex = ch; //edge-cell-outside - else + break; + default: _curr_simplex = Simplex_3(); //edge-outside + break; + } break; } From a26351455b7afeea9bad33ba91088d87c0a9341f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 10:23:01 +0200 Subject: [PATCH 28/60] Add comments about missing cases --- .../test_segment_simplex_traverser_3.cpp | 31 ++++++++++++------- 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 139a68552a2a..b14d64da2836 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -329,7 +329,7 @@ bool test_a_simple_tetrahedron() { do_with_or_without_bbox(b, a, true, expected_result_reversed); }; // end test() lambda - // queries entering by a vertex and exiting by a vertex, on the line (x,0,0) + // [010] queries entering by a vertex and exiting by a vertex, on the line (x,0,0) test({ 0, 0, 0}, {.5, 0, 0}, "01"); test({ 0, 0, 0}, { 1, 0, 0}, "010"); test({ 0, 0, 0}, { 2, 0, 0}, "010I"); @@ -337,7 +337,7 @@ bool test_a_simple_tetrahedron() { test({-1, 0, 0}, { 1, 0, 0}, "I010"); test({-1, 0, 0}, {.5, 0, 0}, "I01"); - // queries entering by a vertex and exiting by an edge, on the line (x,x,0) (y==x) + // [021] queries entering by a vertex and exiting by an edge, on the line (x,x,0) (y==x) test({ 0, 0, 0}, {.2, .2, 0}, "02"); test({ 0, 0, 0}, {.5, .5, 0}, "021"); test({ 0, 0, 0}, { 1, 1, 0}, "021I"); @@ -345,7 +345,7 @@ bool test_a_simple_tetrahedron() { test({-1, -1, 0}, {.5, .5, 0}, "I021"); test({-1, -1, 0}, {.2, .2, 0}, "I02"); - // queries entering by a vertex and exiting by a facet, on the line x==y==0.25-0.25z + // [032] queries entering by a vertex and exiting by a facet, on the line x==y==0.25-0.25z test({ 0, 0, 1}, { .25, .25, .25}, "03"); test({ 0, 0, 1}, { .25, .25, 0 }, "032"); test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); @@ -353,15 +353,22 @@ bool test_a_simple_tetrahedron() { test({-.25,-.25, 2}, { .25, .25, 0 }, "I032"); test({-.25,-.25, 2}, { .125, .125, .5 }, "I03"); - // queries entering by an edge and exiting by an edge, on the line (x,.5,0) - test({ 0, .5, 0}, {.2, .5, 0}, "12"); - test({ 0, .5, 0}, {.5, .5, 0}, "121"); - test({ 0, .5, 0}, { 1, .5, 0}, "121I"); - test({-1, .5, 0}, { 1, .5, 0}, "I121I"); - test({-1, .5, 0}, {.5, .5, 0}, "I121"); - test({-1, .5, 0}, {.2, .5, 0}, "I12"); + // TODO: case [031] + // TODO: case [030] - // queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) + // [121] queries entering by an edge and exiting by an edge, on the line (x,.5,0) + test({0, .5, 0}, {.2, .5, 0}, "12"); + test({0, .5, 0}, {.5 , .5, 0}, "121"); + test({0, .5, 0}, {.6 , .5, 0}, "121I"); + test({-.1, .5, 0}, {.6 , .5, 0}, "I121I"); + test({-.1, .5, 0}, {.5 , .5, 0}, "I121"); + test({-.1, .5, 0}, {.25, .5, 0}, "I12"); + + + // TODO: case 130 + // TODO: case 131 (entering by and edge into a cell, and exiting by the opposite edge in the cell) + + // [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) test({ 0, .25, 0}, { .20, .05, .20}, "13"); test({ 0, .25, 0}, { .25, 0, .25}, "132"); test({ 0, .25, 0}, { .5 ,-.25, .5 }, "132I"); @@ -369,7 +376,7 @@ bool test_a_simple_tetrahedron() { test({-.5, .75,-.5}, { .25, 0, .25}, "I132"); test({-.5, .75,-.5}, { .20, .05, .20}, "I13"); - // queries entering by a facet and exiting by a facet, on the line (x,.5-x,.2) + // [232] queries entering by a facet and exiting by a facet, on the line (x,.5-x,.2) test({ 0, .5, .2}, {.2, .3, .2}, "23"); test({ 0, .5, .2}, {.5, 0, .2}, "232"); test({ 0, .5, .2}, { 1,-.5, .2}, "232I"); From 9cd8f0e8e14cc2a2d3127467afa2d636369fb96c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 11:32:41 +0200 Subject: [PATCH 29/60] fix case 12 --- .../CGAL/Triangulation_segment_traverser_3.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 02a29f092a4a..0860eaeee56f 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -870,9 +870,13 @@ class Triangulation_segment_simplex_iterator_3 } break; } - case Locate_type::FACET: - _curr_simplex = chprev; //query goes through the cell + case Locate_type::FACET: { + if(facet_has_edge(Facet(chprev, liprev), get_edge())) + _curr_simplex = Facet(chprev, liprev); //edge-facet-outside + else + _curr_simplex = chprev; //query goes through the cell break; + } case Locate_type::CELL: _curr_simplex = ch; //edge-cell-outside break; @@ -915,7 +919,10 @@ class Triangulation_segment_simplex_iterator_3 } case Locate_type::FACET: - _curr_simplex = Cell_handle(_cell_iterator);//query goes through the cell + if(facet_has_edge(Facet(ch, li_exit), get_edge())) + _curr_simplex = Facet(ch, li_exit); //edge-facet-outside + else + _curr_simplex = Cell_handle(_cell_iterator);//query goes through the cell break; default: From e574a3a191eccc30b013c23b3ed30542b7813196 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 12:32:35 +0200 Subject: [PATCH 30/60] fix case 132I --- .../include/CGAL/Triangulation_segment_traverser_3.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 0860eaeee56f..9933b570330c 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -919,10 +919,10 @@ class Triangulation_segment_simplex_iterator_3 } case Locate_type::FACET: - if(facet_has_edge(Facet(ch, li_exit), get_edge())) - _curr_simplex = Facet(ch, li_exit); //edge-facet-outside - else - _curr_simplex = Cell_handle(_cell_iterator);//query goes through the cell + if(facet_has_edge(Facet(ch, li_exit), get_edge())) + _curr_simplex = Facet(ch, li_exit); //edge-facet-outside + else + _curr_simplex = ch;//query goes through the cell break; default: From 00aa91967be99d6be11554dbc0776100ff1668a2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 12:33:00 +0200 Subject: [PATCH 31/60] `prev` then `cur` is more logic --- .../include/CGAL/Triangulation_segment_traverser_3.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 9933b570330c..013511ae32a6 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -176,7 +176,7 @@ class Triangulation_segment_cell_iterator_3 { std::stringstream os; os.precision(17); - os << " cur: " << debug_simplex(_cur) << "\n prev: " << debug_simplex(_prev); + os << " prev: " << debug_simplex(_prev) << "\n cur: " << debug_simplex(_cur); return os.str(); } #endif // CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 From 9f4b8d57856ce1af64ede808e3e7af1326f04daf Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 13:16:28 +0200 Subject: [PATCH 32/60] fix case I232 --- .../Triangulation_segment_traverser_3_impl.h | 34 +++++++++++++++++-- 1 file changed, 31 insertions(+), 3 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 8b8b27e4aae4..90f2b3b66a14 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -379,7 +379,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } else { case_target_is_inside_cur_cell(1); // o0 > 0, o1 <= 0, oi01 <= 0 - if(oi01 == ZERO) { // on FACET i j0 j1 + if(oi01 == ZERO) { // on FACET j2 (i, j0, j1) if(o1 == ZERO) { // on EDGE i j1 if(_tr->equal(_target, cur_cell->vertex(i)->point())) { prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; @@ -462,12 +462,40 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre else { Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); if (o2 != NEGATIVE) { - if (_tr->orientation(*vert[i], *vert[j2], *vert[j0], _target) == POSITIVE) { + // o2 >= 0 + Orientation oi20 = _tr->orientation(*vert[i], *vert[j2], *vert[j0], _target); + if ( oi20 == POSITIVE) { case_segment_exits_cur_cell_by(j1); if (o2 == ZERO) degenerate = 4; // EDGE i j2 } - else + else { case_target_is_inside_cur_cell(5); + if(oi20 == ZERO) { // on FACET j1 (i, j2, j0) + if(o2 == ZERO) { // one edge i j2 + if(_tr->equal(_target, cur_cell->vertex(i)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } else if(_tr->equal(_target, cur_cell->vertex(j2)->point())) { + prev_after_walk = { cur_cell, Tr::VERTEX, j2, -1 }; + cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; + } else { + prev_after_walk = { cur_cell, Tr::EDGE, i, j2 }; + cur_after_walk = { {}, Tr::EDGE, -1, -1 }; + } + } else { // o0 < 0, o2 > 0 + // on FACET j1 (i, j2, j0) but not on edges i-j0 or i-j2 + Orientation o012 = _tr->orientation(*vert[j0], *vert[j1], *vert[j2], _target); + CGAL_assertion(o012 != NEGATIVE); + if(o012 == ZERO) { // on edge j1-j2 + prev_after_walk = { cur_cell, Tr::EDGE, j1, j2}; + cur_after_walk = { {}, Tr::EDGE, -1, -1}; + } else { // on facet j1 (i, j2, j0) + prev_after_walk = { cur_cell, Tr::FACET, j1, -1}; + cur_after_walk = { {}, Tr::FACET, -1, -1}; + } + } + } + } } else { if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { From 6525e46d5894d47d00f4b9ab12c3265325abcaea Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 13:17:05 +0200 Subject: [PATCH 33/60] fix test case 232I the test case was wrong --- .../test_segment_simplex_traverser_3.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index b14d64da2836..599134aa8e34 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -377,12 +377,12 @@ bool test_a_simple_tetrahedron() { test({-.5, .75,-.5}, { .20, .05, .20}, "I13"); // [232] queries entering by a facet and exiting by a facet, on the line (x,.5-x,.2) - test({ 0, .5, .2}, {.2, .3, .2}, "23"); - test({ 0, .5, .2}, {.5, 0, .2}, "232"); - test({ 0, .5, .2}, { 1,-.5, .2}, "232I"); - test({-1,1.5, .2}, { 1, .5, .2}, "I232I"); - test({-1,1.5, .2}, {.5, 0, .2}, "I232"); - test({-1,1.5, .2}, {.2, .3, .2}, "I23"); + test({ 0, .5, .2}, {.2, .3, .2}, "23"); + test({ 0, .5, .2}, {.5, 0, .2}, "232"); + test({ 0, .5, .2}, {.55, -.05, .2}, "232I"); + test({-.05, .45, .2}, {.55, -.05, .2}, "I232I"); + test({-.05, .45, .2}, {.5, 0, .2}, "I232"); + test({-.05, .45, .2}, {.2, .3, .2}, "I23"); return ok; } From f75f642b211d976880a890fb74d990a6693bfc83 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 13:21:11 +0200 Subject: [PATCH 34/60] all test cases pass!! (this commit is a cosmetic change) All test cases pass, but: - there are TODOs (missing cases 031, 030, 130, and 131. - we should test with permutations of the four vertices --- .../test/Triangulation_3/test_segment_simplex_traverser_3.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 599134aa8e34..a90c57c2ecda 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -383,6 +383,7 @@ bool test_a_simple_tetrahedron() { test({-.05, .45, .2}, {.55, -.05, .2}, "I232I"); test({-.05, .45, .2}, {.5, 0, .2}, "I232"); test({-.05, .45, .2}, {.2, .3, .2}, "I23"); + return ok; } From bec374fc863387f19725f4f1b43b790bdc30f85e Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 14:28:02 +0200 Subject: [PATCH 35/60] add comments: actually only one missing case --- .../test_segment_simplex_traverser_3.cpp | 41 ++++++++++++------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index a90c57c2ecda..097e3bc38167 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -329,7 +329,8 @@ bool test_a_simple_tetrahedron() { do_with_or_without_bbox(b, a, true, expected_result_reversed); }; // end test() lambda - // [010] queries entering by a vertex and exiting by a vertex, on the line (x,0,0) + // [010] queries entering by a vertex and exiting by the other vertex of an incident edge, + // on the line (x,0,0) test({ 0, 0, 0}, {.5, 0, 0}, "01"); test({ 0, 0, 0}, { 1, 0, 0}, "010"); test({ 0, 0, 0}, { 2, 0, 0}, "010I"); @@ -337,7 +338,10 @@ bool test_a_simple_tetrahedron() { test({-1, 0, 0}, { 1, 0, 0}, "I010"); test({-1, 0, 0}, {.5, 0, 0}, "I01"); - // [021] queries entering by a vertex and exiting by an edge, on the line (x,x,0) (y==x) + // x [020] is not possible, because that would have passed through the edge -> see [010] + + // [021] queries entering by a vertex and exiting by the opposite edge of a same face, + // on the line (x,x,0) (y==x) test({ 0, 0, 0}, {.2, .2, 0}, "02"); test({ 0, 0, 0}, {.5, .5, 0}, "021"); test({ 0, 0, 0}, { 1, 1, 0}, "021I"); @@ -345,19 +349,24 @@ bool test_a_simple_tetrahedron() { test({-1, -1, 0}, {.5, .5, 0}, "I021"); test({-1, -1, 0}, {.2, .2, 0}, "I02"); - // [032] queries entering by a vertex and exiting by a facet, on the line x==y==0.25-0.25z - test({ 0, 0, 1}, { .25, .25, .25}, "03"); - test({ 0, 0, 1}, { .25, .25, 0 }, "032"); - test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); - test({-.25,-.25, 2}, { .28125, .28125, -.125}, "I032I"); - test({-.25,-.25, 2}, { .25, .25, 0 }, "I032"); - test({-.25,-.25, 2}, { .125, .125, .5 }, "I03"); + // x [030] (entering by a vertex and exiting by a non-adjacent vertex) is not possible + // because that would have passed by the common edge -> see [010] - // TODO: case [031] - // TODO: case [030] + // x [031] (entering by a vertex and exiting by a non-incident edge), is not possible + // because that would have passed by the face -> see [021] - // [121] queries entering by an edge and exiting by an edge, on the line (x,.5,0) - test({0, .5, 0}, {.2, .5, 0}, "12"); + // [032] queries entering by a vertex and exiting by the opposite facet, + // on the line x==y==0.25-0.25z + test({ 0, 0, 1}, { .25, .25, .25 }, "03"); + test({ 0, 0, 1}, { .25, .25, 0 }, "032"); + test({ 0, 0, 1}, { .5, .5, -.1 }, "032I"); + test({-.25,-.25, 2}, { .28125, .28125, -.125}, "I032I"); + test({-.25,-.25, 2}, { .25, .25, 0 }, "I032"); + test({-.25,-.25, 2}, { .125, .125, .5 }, "I03"); + + // [121] queries entering by an edge and exiting by an edge of the same face, + // on the line (x,.5,0) + test({0, .5, 0}, {.2, .5, 0}, "12"); test({0, .5, 0}, {.5 , .5, 0}, "121"); test({0, .5, 0}, {.6 , .5, 0}, "121I"); test({-.1, .5, 0}, {.6 , .5, 0}, "I121I"); @@ -365,8 +374,10 @@ bool test_a_simple_tetrahedron() { test({-.1, .5, 0}, {.25, .5, 0}, "I12"); - // TODO: case 130 - // TODO: case 131 (entering by and edge into a cell, and exiting by the opposite edge in the cell) + // x [130] (entering by an edge and exiting by a non-incident vertex) is not possible + // because that would have passed by the common face -> see [120] ([021] in reverse) + + // TODO: case [131] (entering by an edge and exiting by the opposite edge in the cell) // [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) test({ 0, .25, 0}, { .20, .05, .20}, "13"); From 4f20dc0f44afd7366b5caa08dd02f0dc7470b5c2 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 15:50:51 +0200 Subject: [PATCH 36/60] fix case 31 --- .../internal/Triangulation_segment_traverser_3_impl.h | 10 +++++++--- .../test_segment_simplex_traverser_3.cpp | 9 ++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 90f2b3b66a14..d451611e8c51 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -664,10 +664,14 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre return { cur_cell, Tr::FACET, 6 - pos }; break; case 2: - if( pos < 3 ) + if( pos < 3 ) // first is 0 return { cur_cell, Tr::EDGE, 0, pos }; - else if( pos < 5 ) - return { cur_cell, Tr::EDGE, 1, pos-1 }; + else if( pos < 5 ) { // could be (0, pos), or (1, pos-1) + if(op[0] == POSITIVE) + return { cur_cell, Tr::EDGE, 0, pos }; + else + return { cur_cell, Tr::EDGE, 1, pos-1 }; + } else return { cur_cell, Tr::EDGE, 2, 3 }; break; diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 097e3bc38167..111eb35907c4 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -377,7 +377,14 @@ bool test_a_simple_tetrahedron() { // x [130] (entering by an edge and exiting by a non-incident vertex) is not possible // because that would have passed by the common face -> see [120] ([021] in reverse) - // TODO: case [131] (entering by an edge and exiting by the opposite edge in the cell) + // [131] entering by an edge and exiting by the opposite edge in the cell, + // on the line x==y==0.5-z, also known as (.5-z, .5-z, z) + test({ 0, 0, .5 }, { .25, .25, .25}, "13"); + test({ 0, 0, .5 }, { .5, .5, 0 }, "131"); + test({ 0, 0, .5 }, { .55, .55, -.05}, "131I"); + test({ -.05, -.05, .55}, { .55, .55, -.05}, "I131I"); + test({ -.05, -.05, .55}, { .5 , .5 , 0 }, "I131"); + test({ -.05, -.05, .55}, { .2 , .2 , .3 }, "I13"); // [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) test({ 0, .25, 0}, { .20, .05, .20}, "13"); From c7130e0c585650698448a764f0f443de74ec6be5 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 16:41:07 +0200 Subject: [PATCH 37/60] fix test case 131I --- .../CGAL/Triangulation_segment_traverser_3.h | 31 ++++++++++++------- .../test_segment_simplex_traverser_3.cpp | 13 ++++---- 2 files changed, 25 insertions(+), 19 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 013511ae32a6..8e08e2f0447b 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -26,6 +26,7 @@ #include #include +#include // If defined, type casting is done statically, // reducing type-safety overhead. @@ -913,8 +914,11 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = Simplex_3();//should not be reached else if (triangulation()->is_infinite(chnext) && is_same_edge(get_edge(), e_exit)) _curr_simplex = chnext; - else - _curr_simplex = shared_facet(get_edge(), e_exit); + else { + auto facet_opt = shared_facet(get_edge(), e_exit); + if(static_cast(facet_opt)) _curr_simplex = *facet_opt; + else _curr_simplex = shared_cell(get_edge(), e_exit); + } break; } @@ -1204,7 +1208,7 @@ class Triangulation_segment_simplex_iterator_3 && edge_has_vertex(e1, e2.first->vertex(e2.third)); } - Vertex_handle shared_vertex(const Edge& e1, const Edge& e2) const + std::optional shared_vertex(const Edge& e1, const Edge& e2) const { Vertex_handle v1a = e1.first->vertex(e1.second); Vertex_handle v1b = e1.first->vertex(e1.third); @@ -1215,18 +1219,18 @@ class Triangulation_segment_simplex_iterator_3 return v1a; else if (v1b == v2a || v1b == v2b) return v1b; - - std::cerr << "There is no vertex shared by e1 and e2" << std::endl; - CGAL_unreachable(); - return Vertex_handle(); + else + return {}; } - Facet shared_facet(const Edge& e1, const Edge& e2) const + std::optional shared_facet(const Edge& e1, const Edge& e2) const { Vertex_handle v2a = e2.first->vertex(e2.second); Vertex_handle v2b = e2.first->vertex(e2.third); - Vertex_handle sv = shared_vertex(e1, e2); + auto sv_opt = shared_vertex(e1, e2); + if(!sv_opt) return {}; + Vertex_handle sv = *sv_opt; Vertex_handle nsv2 = (sv == v2a) ? v2b : v2a; typename Tr::Facet_circulator circ @@ -1242,9 +1246,7 @@ class Triangulation_segment_simplex_iterator_3 } } while (++circ != end); - std::cerr << "There is no facet shared by e1 and e2" << std::endl; - CGAL_unreachable(); - return Facet(Cell_handle(), 0); + return {}; } Facet shared_facet(const Edge& e, const Vertex_handle v) const @@ -1295,6 +1297,11 @@ class Triangulation_segment_simplex_iterator_3 } } + Cell_handle shared_cell(const Edge e1, const Edge e2) const { + auto facet = shared_facet(e1, e2.first->vertex(e2.second)); + return shared_cell(facet, e2.first->vertex(e2.third)); + } + };//class Triangulation_segment_simplex_iterator_3 } // namespace CGAL diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 111eb35907c4..d491066a4e8c 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -373,18 +373,17 @@ bool test_a_simple_tetrahedron() { test({-.1, .5, 0}, {.5 , .5, 0}, "I121"); test({-.1, .5, 0}, {.25, .5, 0}, "I12"); - // x [130] (entering by an edge and exiting by a non-incident vertex) is not possible // because that would have passed by the common face -> see [120] ([021] in reverse) // [131] entering by an edge and exiting by the opposite edge in the cell, // on the line x==y==0.5-z, also known as (.5-z, .5-z, z) - test({ 0, 0, .5 }, { .25, .25, .25}, "13"); - test({ 0, 0, .5 }, { .5, .5, 0 }, "131"); - test({ 0, 0, .5 }, { .55, .55, -.05}, "131I"); - test({ -.05, -.05, .55}, { .55, .55, -.05}, "I131I"); - test({ -.05, -.05, .55}, { .5 , .5 , 0 }, "I131"); - test({ -.05, -.05, .55}, { .2 , .2 , .3 }, "I13"); + test({ 0, 0, .5 }, { .25, .25, .25 }, "13"); + test({ 0, 0, .5 }, { .5, .5, 0 }, "131"); + test({ 0, 0, .5 }, { .625, .625, -.125}, "131I"); + test({ -.05, -.05, .55}, { .625, .625, -.125}, "I131I"); + test({ -.05, -.05, .55}, { .5 , .5 , 0 }, "I131"); + test({ -.05, -.05, .55}, { .25, .25, .25 }, "I13"); // [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) test({ 0, .25, 0}, { .20, .05, .20}, "13"); From 8e7460108f503e0677ab57dab8edd36d580727e4 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 17:05:04 +0200 Subject: [PATCH 38/60] fix case I131I The test case was wrong, because of non-exact floating points values, in decimal. All implemented test cases pass, now. And we do not expect missing test cases. Now, I should implement permutations of the four vertices of the tet. --- .../test_segment_simplex_traverser_3.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index d491066a4e8c..899bbfc742c6 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -378,12 +378,12 @@ bool test_a_simple_tetrahedron() { // [131] entering by an edge and exiting by the opposite edge in the cell, // on the line x==y==0.5-z, also known as (.5-z, .5-z, z) - test({ 0, 0, .5 }, { .25, .25, .25 }, "13"); - test({ 0, 0, .5 }, { .5, .5, 0 }, "131"); - test({ 0, 0, .5 }, { .625, .625, -.125}, "131I"); - test({ -.05, -.05, .55}, { .625, .625, -.125}, "I131I"); - test({ -.05, -.05, .55}, { .5 , .5 , 0 }, "I131"); - test({ -.05, -.05, .55}, { .25, .25, .25 }, "I13"); + test({ 0, 0, .5 }, { .25, .25, .25 }, "13"); + test({ 0, 0, .5 }, { .5, .5, 0 }, "131"); + test({ 0, 0, .5 }, { .625, .625, -.125}, "131I"); + test({ -.125, -.125, .625}, { .625, .625, -.125}, "I131I"); + test({ -.125, -.125, .625}, { .5 , .5 , 0 }, "I131"); + test({ -.125, -.125, .625}, { .25, .25, .25 }, "I13"); // [132] queries entering by an edge and exiting by a facet, on the line (x, .25-x, x) test({ 0, .25, 0}, { .20, .05, .20}, "13"); From a4a1e51e02b02e989077248f5fd5f36ed4e8935a Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 17:25:16 +0200 Subject: [PATCH 39/60] implementation permutations... and tests fail! --- .../test_segment_simplex_traverser_3.cpp | 31 +++++++++++++++---- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 899bbfc742c6..6940b5b5ff1b 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -255,13 +255,11 @@ bool test_vfefv(bool with_bbox = false) return ok; } -bool test_a_simple_tetrahedron() { - std::cerr << "## test_a_simple_tetrahedron()\n"; +bool test_a_simple_tetrahedron(const std::vector& points) { + DT dt2; - dt2.insert({0, 0, 0}); - dt2.insert({1, 0, 0}); - dt2.insert({0, 1, 0}); - dt2.insert({0, 0, 1}); + for(const auto& p: points) dt2.insert(p); + bool ok = true; auto test = [&](Point_3 a, Point_3 b, std::string expected_result) { // This test function calls `do_test` with four configurations: @@ -404,6 +402,27 @@ bool test_a_simple_tetrahedron() { return ok; } +bool test_a_simple_tetrahedron() { + bool ok = true; + std::cerr << "## test_a_simple_tetrahedron()\n"; + + std::vector points = { + {0., 0., 0.}, + {1., 0., 0.}, + {0., 1., 0.}, + {0., 0., 1.}, + }; + std::sort(points.begin(), points.end()); + do { + std::cerr << "### new permutation of the four points\n"; + for(const auto& p: points) std::cout << " " << p << '\n'; + std::cerr << '\n'; + ok = test_a_simple_tetrahedron(points) && ok; + } + while (std::next_permutation(points.begin(), points.end())); + return ok; +} + bool test(const DT& dt, const std::pair& query, const std::array& expected_result); From 8207105503a2ca49afa82f6e67b4721b349d0c47 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 15 Jun 2023 18:07:52 +0200 Subject: [PATCH 40/60] fix accidental use of std::optional (boost:: instead) --- .../include/CGAL/Triangulation_segment_traverser_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 8e08e2f0447b..fe2f4e969928 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -1208,7 +1208,7 @@ class Triangulation_segment_simplex_iterator_3 && edge_has_vertex(e1, e2.first->vertex(e2.third)); } - std::optional shared_vertex(const Edge& e1, const Edge& e2) const + boost::optional shared_vertex(const Edge& e1, const Edge& e2) const { Vertex_handle v1a = e1.first->vertex(e1.second); Vertex_handle v1b = e1.first->vertex(e1.third); @@ -1223,7 +1223,7 @@ class Triangulation_segment_simplex_iterator_3 return {}; } - std::optional shared_facet(const Edge& e1, const Edge& e2) const + boost::optional shared_facet(const Edge& e1, const Edge& e2) const { Vertex_handle v2a = e2.first->vertex(e2.second); Vertex_handle v2b = e2.first->vertex(e2.third); From 42f8b92c1d0234e077d93337a3c4141b4b872418 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 11:50:20 +0200 Subject: [PATCH 41/60] add comments --- .../Triangulation_segment_traverser_3_impl.h | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index d451611e8c51..770d56a47e71 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -369,16 +369,16 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre const int j1 = Tr::vertex_triple_index(i, 1); const int j2 = Tr::vertex_triple_index(i, 2); Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target); - if (o0 == POSITIVE) { + if (o0 == POSITIVE) { // o0 > 0 Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); - if (o1 != POSITIVE) { + if (o1 != POSITIVE) { // o1 <= 0 Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); if (oi01 == POSITIVE) { case_segment_exits_cur_cell_by(j2); if (o1 == ZERO) degenerate = 1; //EDGE i j1 } - else { - case_target_is_inside_cur_cell(1); // o0 > 0, o1 <= 0, oi01 <= 0 + else { // o0 > 0, o1 <= 0, oi01 <= 0 + case_target_is_inside_cur_cell(1); if(oi01 == ZERO) { // on FACET j2 (i, j0, j1) if(o1 == ZERO) { // on EDGE i j1 if(_tr->equal(_target, cur_cell->vertex(i)->point())) { @@ -405,17 +405,18 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre cur_after_walk = { {}, Tr::FACET, -1, -1}; } } - } + } // end oi01 == ZERO } - } - else { - if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { + } // end o1 <= 0 + else { // o1 > 0 + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if ( oi12 == POSITIVE) { case_segment_exits_cur_cell_by(j0); } else case_target_is_inside_cur_cell(2); } - } + } // end o0 > 0 else if (o0 == ZERO) { // target is on plane (source, vert[i], vert[j0]) Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); @@ -458,8 +459,8 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre else case_target_is_inside_cur_cell(4); } - } - else { + } // end o0 == 0 + else { // o0 < 0 Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); if (o2 != NEGATIVE) { // o2 >= 0 From 169985ea962ddda1b433cf9b6b562cb96b530f50 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 12:37:08 +0200 Subject: [PATCH 42/60] fix remaining cases even with permutations Now I am quite confident that the code is correct. --- .../Triangulation_segment_traverser_3_impl.h | 85 +++++-------------- 1 file changed, 22 insertions(+), 63 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 770d56a47e71..99b9db1aeda6 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -380,31 +380,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre else { // o0 > 0, o1 <= 0, oi01 <= 0 case_target_is_inside_cur_cell(1); if(oi01 == ZERO) { // on FACET j2 (i, j0, j1) - if(o1 == ZERO) { // on EDGE i j1 - if(_tr->equal(_target, cur_cell->vertex(i)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } - else if(_tr->equal(_target, cur_cell->vertex(j1)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, j1, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } - else { - prev_after_walk = { cur_cell, Tr::EDGE, i, j1}; - cur_after_walk = { {}, Tr::EDGE, -1, -1}; - } - } else { // o0 > 0, o1 < 0, oi01 == 0 - //on FACET j2 (i-j0-j1) but not edge i-j1, or i-j0 - Orientation o012 = _tr->orientation(*vert[j0], *vert[j1], *vert[j2], _target); - CGAL_assertion(o012 != NEGATIVE); - if(o012 == ZERO) { // on edge j0-j1 - prev_after_walk = { cur_cell, Tr::EDGE, j0, j1}; - cur_after_walk = { {}, Tr::EDGE, -1, -1}; - } else { // on facet j2 - prev_after_walk = { cur_cell, Tr::FACET, j2, -1}; - cur_after_walk = { {}, Tr::FACET, -1, -1}; - } - } + degenerate = 1; } // end oi01 == ZERO } } // end o1 <= 0 @@ -413,8 +389,12 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre if ( oi12 == POSITIVE) { case_segment_exits_cur_cell_by(j0); } - else + else { // o0 > 0, o1 > 0, oi12 <= 0 case_target_is_inside_cur_cell(2); + if( oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; + } // end oi12 == ZERO + } } } // end o0 > 0 else if (o0 == ZERO) { @@ -429,16 +409,7 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre else { case_target_is_inside_cur_cell(3); if(oi12 == ZERO) { // target is *on* EDGE i j0 - if(_tr->equal(_target, cur_cell->vertex(i)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } else if(_tr->equal(_target, cur_cell->vertex(j0)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, j0, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } else { - prev_after_walk = { cur_cell, Tr::EDGE, i, j0 }; - cur_after_walk = { {}, Tr::EDGE, -1, -1 }; - } + degenerate = 1; } } } @@ -453,11 +424,16 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre } } else { // o0 == 0, o1 > 0 - if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if (oi12 == POSITIVE) { case_segment_exits_cur_cell_by(j0); } - else + else { case_target_is_inside_cur_cell(4); + if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; + } // end oi12 == ZERO + } } } // end o0 == 0 else { // o0 < 0 @@ -472,38 +448,21 @@ Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& pre else { case_target_is_inside_cur_cell(5); if(oi20 == ZERO) { // on FACET j1 (i, j2, j0) - if(o2 == ZERO) { // one edge i j2 - if(_tr->equal(_target, cur_cell->vertex(i)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, i, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } else if(_tr->equal(_target, cur_cell->vertex(j2)->point())) { - prev_after_walk = { cur_cell, Tr::VERTEX, j2, -1 }; - cur_after_walk = { {}, Tr::VERTEX, -1, -1 }; - } else { - prev_after_walk = { cur_cell, Tr::EDGE, i, j2 }; - cur_after_walk = { {}, Tr::EDGE, -1, -1 }; - } - } else { // o0 < 0, o2 > 0 - // on FACET j1 (i, j2, j0) but not on edges i-j0 or i-j2 - Orientation o012 = _tr->orientation(*vert[j0], *vert[j1], *vert[j2], _target); - CGAL_assertion(o012 != NEGATIVE); - if(o012 == ZERO) { // on edge j1-j2 - prev_after_walk = { cur_cell, Tr::EDGE, j1, j2}; - cur_after_walk = { {}, Tr::EDGE, -1, -1}; - } else { // on facet j1 (i, j2, j0) - prev_after_walk = { cur_cell, Tr::FACET, j1, -1}; - cur_after_walk = { {}, Tr::FACET, -1, -1}; - } - } + degenerate = 1; } } } else { - if (_tr->orientation(*vert[i], *vert[j1], *vert[j2], _target) == POSITIVE) { + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if (oi12 == POSITIVE) { case_segment_exits_cur_cell_by(j0); } - else + else { case_target_is_inside_cur_cell(6); + if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; + } + } } } From a2a736d074bdea362c86fd90262000665f2860e0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 12:48:39 +0200 Subject: [PATCH 43/60] fix last bug in the test file --- .../Triangulation_3/test_segment_simplex_traverser_3.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 6940b5b5ff1b..3200f326f5b3 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -432,6 +432,10 @@ int main(int, char* []) { std::cerr.precision(17); std::cout.precision(17); + + bool ok = true; + ok = test_a_simple_tetrahedron() && ok; + const std::vector points = { { -2, 0, 0 }, { 2, 0, 0 }, { 0, 1, -1 }, @@ -477,9 +481,6 @@ int main(int, char* []) {2, 1, 1, 0} // reverse case: FVEV }; - bool ok = true; - ok = test_a_simple_tetrahedron() && ok; - for(std::size_t i=0; i Date: Fri, 16 Jun 2023 15:00:29 +0200 Subject: [PATCH 44/60] change the display of the test file --- .../test_segment_simplex_traverser_3.cpp | 44 ++++++++++++++----- 1 file changed, 34 insertions(+), 10 deletions(-) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 3200f326f5b3..fdd66b150e25 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -187,7 +187,7 @@ void visit_simplex(Point_3 a, Point_3 b, Simplex s, std::optional previ } else { result_string += std::to_string(d); } - std::cout << debug_simplex(s) << '\n'; + std::clog << debug_simplex(s) << '\n'; const bool does_intersect_ab = (3 == d && dt.is_infinite(static_cast(s))) || std::visit( [&](auto geometry) { return CGAL::do_intersect(Segment_3(a, b), geometry); }, @@ -267,9 +267,6 @@ bool test_a_simple_tetrahedron(const std::vector& points) { // - and with or without a bbox around the central tetrahedron. dt = dt2; auto do_with_or_without_bbox = [&](Point_3 a, Point_3 b, bool with_bbox, std::string expected_result) { - std::cerr << "### Case " << expected_result; - if(with_bbox) std::cerr << " with bbox"; - std::cerr << '\n'; auto do_it = [&](auto from, auto to) { bool exception_thrown = false; result_string.clear(); @@ -300,7 +297,10 @@ bool test_a_simple_tetrahedron(const std::vector& points) { } }; // end do_it - std::cerr << "from (" << a << ") to (" << b << ")\n"; + std::clog << "### Case " << expected_result; + if(with_bbox) std::clog << " with bbox"; + std::clog << '\n'; + std::clog << "from (" << a << ") to (" << b << ")\n"; do_it(a, b); // then re-test using vertex handles, if possible @@ -313,7 +313,7 @@ bool test_a_simple_tetrahedron(const std::vector& points) { c = dt.locate(b, lt, i, j); if(lt == DT::VERTEX) vb = c->vertex(i); if(va != Vertex_handle{} && vb != Vertex_handle{}) { - std::cerr << "from vertex" << display_vert(va) << " to vertex" << display_vert(vb) << ")\n"; + std::clog << "from vertex" << display_vert(va) << " to vertex" << display_vert(vb) << ")\n"; do_it(va, vb); }; }; // end do_with_or_without_bbox @@ -404,8 +404,31 @@ bool test_a_simple_tetrahedron(const std::vector& points) { bool test_a_simple_tetrahedron() { bool ok = true; - std::cerr << "## test_a_simple_tetrahedron()\n"; - + std::cout << "## test_a_simple_tetrahedron()\n" + << R"#( +This test uses with a trivial tetrahedron, and is launched with all the +24 permutations of the four vertices. There are 7 test cases, and for each of +them 6 different segments are tested: +- The segment starts at the incoming boundary of the tetrahedron and ends + inside. +- The segment starts at the incoming boundary of the tetrahedron and ends + at the outgoing boundary. +- The segment starts at the incoming boundary of the tetrahedron, goes out + and beyond. +- The segment starts before the tetrahedron, goes through it, and comes out. +- The segment starts before the tetrahedron and ends at the outgoing boundary. +- The segment starts before the tetrahedron and ends inside. + +For each of those query segments, 4 tests are performed: + - with/without 8 extra vertices in the triangulation, forming a bounding + box, + - and in the direct and reverse direction. + +In total, 4032 tests are performed... + + +)#"; + std::cout.flush(); std::vector points = { {0., 0., 0.}, {1., 0., 0.}, @@ -414,9 +437,9 @@ bool test_a_simple_tetrahedron() { }; std::sort(points.begin(), points.end()); do { - std::cerr << "### new permutation of the four points\n"; + std::cout << "### new permutation of the four points\n"; for(const auto& p: points) std::cout << " " << p << '\n'; - std::cerr << '\n'; + std::cout << std::endl; ok = test_a_simple_tetrahedron(points) && ok; } while (std::next_permutation(points.begin(), points.end())); @@ -431,6 +454,7 @@ bool test(const DT& dt, int main(int, char* []) { std::cerr.precision(17); + std::clog.precision(17); std::cout.precision(17); bool ok = true; From 80a4064350d1f14fc5f849c1edd9332e2ad8faea Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 15:23:11 +0200 Subject: [PATCH 45/60] chprev/chnext --- .../CGAL/Triangulation_segment_traverser_3.h | 38 +++++++++---------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index fe2f4e969928..9edf15c563c8 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -741,7 +741,6 @@ class Triangulation_segment_simplex_iterator_3 } case 2 :/*Facet*/ { - Cell_handle ch = Cell_handle(_cell_iterator); if (!cell_iterator_is_ahead()) { //cell_iterator is not ahead. get_facet() is part of cell_iterator @@ -750,9 +749,7 @@ class Triangulation_segment_simplex_iterator_3 CGAL_assertion(cell_has_facet(Cell_handle(_cell_iterator), get_facet())); increment_cell_iterator(); } - else - ch = _cell_iterator.previous(); - + Cell_handle chprev = _cell_iterator.previous(); Cell_handle chnext = Cell_handle(_cell_iterator); Locate_type lt; int li, lj; @@ -761,36 +758,35 @@ class Triangulation_segment_simplex_iterator_3 if (chnext == Cell_handle()) { CGAL_assertion(_cell_iterator == _cell_iterator.end()); - Cell_handle prev = _cell_iterator.previous(); if (lt == Locate_type::VERTEX) //facet-cell?-vertex-outside { int i; - if (triangulation()->has_vertex(get_facet(), prev->vertex(li), i)) - _curr_simplex = prev->vertex(li); + if (triangulation()->has_vertex(get_facet(), chprev->vertex(li), i)) + _curr_simplex = chprev->vertex(li); else - _curr_simplex = prev; + _curr_simplex = chprev; } else if (lt == Locate_type::EDGE)//facet-cell?-edge-outside { int i, j; - if ( triangulation()->has_vertex(get_facet(), prev->vertex(li), i) - && triangulation()->has_vertex(get_facet(), prev->vertex(lj), j)) - _curr_simplex = Edge(prev, li, lj); + if ( triangulation()->has_vertex(get_facet(), chprev->vertex(li), i) + && triangulation()->has_vertex(get_facet(), chprev->vertex(lj), j)) + _curr_simplex = Edge(chprev, li, lj); else - _curr_simplex = prev; + _curr_simplex = chprev; } else if (lt == Locate_type::FACET) //facet-cell-facet-outside { - if (Facet(prev, li) == get_facet() - || triangulation()->mirror_facet(Facet(prev, li)) == get_facet()) + if (Facet(chprev, li) == get_facet() + || triangulation()->mirror_facet(Facet(chprev, li)) == get_facet()) _curr_simplex = Simplex_3(); else - _curr_simplex = prev; + _curr_simplex = chprev; } else // facet-cell then end { CGAL_assertion(lt == Locate_type::CELL); - _curr_simplex = prev; + _curr_simplex = chprev; } break; } @@ -801,22 +797,22 @@ class Triangulation_segment_simplex_iterator_3 { //if the entry vertex is a vertex of current facet int i; - if (triangulation()->has_vertex(get_facet(), ch->vertex(li), i)) + if (triangulation()->has_vertex(get_facet(), chprev->vertex(li), i)) set_curr_simplex_to_entry(); else - _curr_simplex = ch; + _curr_simplex = chprev; break; } case Locate_type::EDGE: - if (facet_has_edge(get_facet(), Edge(ch, li, lj))) + if (facet_has_edge(get_facet(), Edge(chprev, li, lj))) set_curr_simplex_to_entry(); else - _curr_simplex = ch; + _curr_simplex = chprev; break; case Locate_type::FACET: - _curr_simplex = ch; + _curr_simplex = chprev; break; default: From 5c81b975aefd92d11a0e1bef48e68dc265aaaffa Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 15:33:02 +0200 Subject: [PATCH 46/60] triangulation() is now a reference --- .../CGAL/Triangulation_segment_traverser_3.h | 32 +++++++++---------- .../test_segment_simplex_traverser_3.cpp | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 9edf15c563c8..9e14888d41c0 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -638,7 +638,7 @@ class Triangulation_segment_simplex_iterator_3 const Point& source() const { return _cell_iterator.source(); } const Point& target() const { return _cell_iterator.target(); } - const Tr* triangulation() const { return _cell_iterator.triangulation(); } + const Tr& triangulation() const { return *_cell_iterator.triangulation(); } private: Triangulation_segment_simplex_iterator_3 @@ -725,7 +725,7 @@ class Triangulation_segment_simplex_iterator_3 Cell_handle ch = Cell_handle(_cell_iterator); if (ch == Cell_handle()) { - if(!triangulation()->is_infinite(Cell_handle(_curr_simplex))) + if(!triangulation().is_infinite(Cell_handle(_curr_simplex))) set_curr_simplex_to_entry(); else _curr_simplex = Simplex_3(); @@ -761,7 +761,7 @@ class Triangulation_segment_simplex_iterator_3 if (lt == Locate_type::VERTEX) //facet-cell?-vertex-outside { int i; - if (triangulation()->has_vertex(get_facet(), chprev->vertex(li), i)) + if (triangulation().has_vertex(get_facet(), chprev->vertex(li), i)) _curr_simplex = chprev->vertex(li); else _curr_simplex = chprev; @@ -769,8 +769,8 @@ class Triangulation_segment_simplex_iterator_3 else if (lt == Locate_type::EDGE)//facet-cell?-edge-outside { int i, j; - if ( triangulation()->has_vertex(get_facet(), chprev->vertex(li), i) - && triangulation()->has_vertex(get_facet(), chprev->vertex(lj), j)) + if ( triangulation().has_vertex(get_facet(), chprev->vertex(li), i) + && triangulation().has_vertex(get_facet(), chprev->vertex(lj), j)) _curr_simplex = Edge(chprev, li, lj); else _curr_simplex = chprev; @@ -778,7 +778,7 @@ class Triangulation_segment_simplex_iterator_3 else if (lt == Locate_type::FACET) //facet-cell-facet-outside { if (Facet(chprev, li) == get_facet() - || triangulation()->mirror_facet(Facet(chprev, li)) == get_facet()) + || triangulation().mirror_facet(Facet(chprev, li)) == get_facet()) _curr_simplex = Simplex_3(); else _curr_simplex = chprev; @@ -797,7 +797,7 @@ class Triangulation_segment_simplex_iterator_3 { //if the entry vertex is a vertex of current facet int i; - if (triangulation()->has_vertex(get_facet(), chprev->vertex(li), i)) + if (triangulation().has_vertex(get_facet(), chprev->vertex(li), i)) set_curr_simplex_to_entry(); else _curr_simplex = chprev; @@ -903,12 +903,12 @@ class Triangulation_segment_simplex_iterator_3 { const Edge e_exit(ch, li_exit, lj_exit); CGAL_assertion(_cell_iterator == _cell_iterator.end() - || triangulation()->is_infinite(chnext) + || triangulation().is_infinite(chnext) || _curr_simplex != Simplex_3(e_exit)); if (_cell_iterator == _cell_iterator.end()) _curr_simplex = Simplex_3();//should not be reached - else if (triangulation()->is_infinite(chnext) && is_same_edge(get_edge(), e_exit)) + else if (triangulation().is_infinite(chnext) && is_same_edge(get_edge(), e_exit)) _curr_simplex = chnext; else { auto facet_opt = shared_facet(get_edge(), e_exit); @@ -992,7 +992,7 @@ class Triangulation_segment_simplex_iterator_3 { CGAL_assertion(_cell_iterator == _cell_iterator.end() || get_vertex() != prev->vertex(liprev) - || triangulation()->is_infinite(chnext)); + || triangulation().is_infinite(chnext)); if (_cell_iterator == _cell_iterator.end()) { if (prev == ch && ltprev == Locate_type::VERTEX) @@ -1017,13 +1017,13 @@ class Triangulation_segment_simplex_iterator_3 } else { - if (triangulation()->is_infinite(chnext) && get_vertex() == prev->vertex(liprev)) + if (triangulation().is_infinite(chnext) && get_vertex() == prev->vertex(liprev)) _curr_simplex = chnext; else { Cell_handle ec; int ei = -1, ej = -1; - if (!triangulation()->is_edge(get_vertex(), prev->vertex(liprev), ec, ei, ej)) + if (!triangulation().is_edge(get_vertex(), prev->vertex(liprev), ec, ei, ej)) CGAL_unreachable(); _curr_simplex = Edge(ec, ei, ej); } @@ -1230,7 +1230,7 @@ class Triangulation_segment_simplex_iterator_3 Vertex_handle nsv2 = (sv == v2a) ? v2b : v2a; typename Tr::Facet_circulator circ - = triangulation()->incident_facets(e1); + = triangulation().incident_facets(e1); typename Tr::Facet_circulator end = circ; do { @@ -1248,13 +1248,13 @@ class Triangulation_segment_simplex_iterator_3 Facet shared_facet(const Edge& e, const Vertex_handle v) const { typename Tr::Facet_circulator circ - = triangulation()->incident_facets(e); + = triangulation().incident_facets(e); typename Tr::Facet_circulator end = circ; do { Facet f = *circ; int i; - if (triangulation()->has_vertex(f, v, i)) + if (triangulation().has_vertex(f, v, i)) return f; } while (++circ != end); @@ -1266,7 +1266,7 @@ class Triangulation_segment_simplex_iterator_3 Cell_handle shared_cell(const Edge& e, const Vertex_handle v) const { typename Tr::Cell_circulator circ - = triangulation()->incident_cells(e); + = triangulation().incident_cells(e); typename Tr::Cell_circulator end = circ; do { diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index fdd66b150e25..5b940f07fde8 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -1,4 +1,4 @@ -#define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1 +//#define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1 #include #include #include From 6b835a17999d46d78c8512ea31ad87e668929ec0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 15:35:18 +0200 Subject: [PATCH 47/60] use triangulation().tds().has_vertex to avoid dummies --- .../CGAL/Triangulation_segment_traverser_3.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 9e14888d41c0..9c291bf480fe 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -760,17 +760,15 @@ class Triangulation_segment_simplex_iterator_3 CGAL_assertion(_cell_iterator == _cell_iterator.end()); if (lt == Locate_type::VERTEX) //facet-cell?-vertex-outside { - int i; - if (triangulation().has_vertex(get_facet(), chprev->vertex(li), i)) + if (triangulation().tds().has_vertex(get_facet(), chprev->vertex(li))) _curr_simplex = chprev->vertex(li); else _curr_simplex = chprev; } else if (lt == Locate_type::EDGE)//facet-cell?-edge-outside { - int i, j; - if ( triangulation().has_vertex(get_facet(), chprev->vertex(li), i) - && triangulation().has_vertex(get_facet(), chprev->vertex(lj), j)) + if ( triangulation().tds().has_vertex(get_facet(), chprev->vertex(li)) + && triangulation().tds().has_vertex(get_facet(), chprev->vertex(lj))) _curr_simplex = Edge(chprev, li, lj); else _curr_simplex = chprev; @@ -796,8 +794,7 @@ class Triangulation_segment_simplex_iterator_3 case Locate_type::VERTEX: { //if the entry vertex is a vertex of current facet - int i; - if (triangulation().has_vertex(get_facet(), chprev->vertex(li), i)) + if (triangulation().tds().has_vertex(get_facet(), chprev->vertex(li))) set_curr_simplex_to_entry(); else _curr_simplex = chprev; @@ -1253,8 +1250,7 @@ class Triangulation_segment_simplex_iterator_3 do { Facet f = *circ; - int i; - if (triangulation().has_vertex(f, v, i)) + if (triangulation().tds().has_vertex(f, v)) return f; } while (++circ != end); From 5a0c09d667f26eb7963f0dc74d76b49b6a79b524 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 15:48:33 +0200 Subject: [PATCH 48/60] factorize/reformat the code The cases `chnext == {}` and `chnext != {}` were actually very similar. --- .../CGAL/Triangulation_segment_traverser_3.h | 381 +++++------------- .../test_segment_simplex_traverser_3.cpp | 9 +- 2 files changed, 99 insertions(+), 291 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 9c291bf480fe..2c00da85bc9a 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -706,8 +706,7 @@ class Triangulation_segment_simplex_iterator_3 // provides the increment postfix operator. Simplex_iterator& operator++() { - auto increment_cell_iterator = [&]() - { + auto increment_cell_iterator = [&]() { #if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 std::cerr << "increment cell iterator from:\n" << _cell_iterator.debug_iterator(); #endif @@ -718,12 +717,20 @@ class Triangulation_segment_simplex_iterator_3 }; CGAL_assertion(_curr_simplex.incident_cell() != Cell_handle()); - switch(_curr_simplex.dimension()) - { + if(!cell_iterator_is_ahead()) { + increment_cell_iterator(); // cell_iterator needs to be ahead + } + + Cell_handle ch_next = Cell_handle(_cell_iterator); + Cell_handle ch_prev = _cell_iterator.previous(); + Locate_type lt_prev; + int li_prev, lj_prev; + _cell_iterator.exit(lt_prev, li_prev, lj_prev); + + switch(_curr_simplex.dimension()) { case 3 :/*Cell_handle*/ { - Cell_handle ch = Cell_handle(_cell_iterator); - if (ch == Cell_handle()) + if (ch_next == Cell_handle()) { if(!triangulation().is_infinite(Cell_handle(_curr_simplex))) set_curr_simplex_to_entry(); @@ -741,319 +748,115 @@ class Triangulation_segment_simplex_iterator_3 } case 2 :/*Facet*/ { - if (!cell_iterator_is_ahead()) - { - //cell_iterator is not ahead. get_facet() is part of cell_iterator - //we cannot be in any of the degenerate cases, only detected by - //taking cell_iterator one step forward - CGAL_assertion(cell_has_facet(Cell_handle(_cell_iterator), get_facet())); - increment_cell_iterator(); - } - Cell_handle chprev = _cell_iterator.previous(); - Cell_handle chnext = Cell_handle(_cell_iterator); - Locate_type lt; - int li, lj; - _cell_iterator.exit(lt, li, lj); - - if (chnext == Cell_handle()) - { - CGAL_assertion(_cell_iterator == _cell_iterator.end()); - if (lt == Locate_type::VERTEX) //facet-cell?-vertex-outside - { - if (triangulation().tds().has_vertex(get_facet(), chprev->vertex(li))) - _curr_simplex = chprev->vertex(li); - else - _curr_simplex = chprev; - } - else if (lt == Locate_type::EDGE)//facet-cell?-edge-outside - { - if ( triangulation().tds().has_vertex(get_facet(), chprev->vertex(li)) - && triangulation().tds().has_vertex(get_facet(), chprev->vertex(lj))) - _curr_simplex = Edge(chprev, li, lj); - else - _curr_simplex = chprev; - } - else if (lt == Locate_type::FACET) //facet-cell-facet-outside - { - if (Facet(chprev, li) == get_facet() - || triangulation().mirror_facet(Facet(chprev, li)) == get_facet()) - _curr_simplex = Simplex_3(); - else - _curr_simplex = chprev; - } - else // facet-cell then end - { - CGAL_assertion(lt == Locate_type::CELL); - _curr_simplex = chprev; - } - break; - } + CGAL_assertion((ch_next == Cell_handle()) == (_cell_iterator == _cell_iterator.end())); - switch (lt)//entry simplex in next cell is exit simplex in current cell - { - case Locate_type::VERTEX: - { - //if the entry vertex is a vertex of current facet - if (triangulation().tds().has_vertex(get_facet(), chprev->vertex(li))) - set_curr_simplex_to_entry(); + switch(lt_prev) { + case Locate_type::VERTEX: { // facet-cell?-vertex-outside + Vertex_handle v_prev{ch_prev->vertex(li_prev)}; + if(triangulation().tds().has_vertex(get_facet(), v_prev)) + _curr_simplex = v_prev; else - _curr_simplex = chprev; - break; - } - - case Locate_type::EDGE: - if (facet_has_edge(get_facet(), Edge(chprev, li, lj))) - set_curr_simplex_to_entry(); + _curr_simplex = ch_prev; + } break; + case Locate_type::EDGE: { // facet-cell?-edge-outside + Edge edge_prev{ch_prev, li_prev, lj_prev}; + if(facet_has_edge(get_facet(), edge_prev)) + _curr_simplex = edge_prev; else - _curr_simplex = chprev; - break; - - case Locate_type::FACET: - _curr_simplex = chprev; - break; - + _curr_simplex = ch_prev; + } break; + case Locate_type::FACET: { // facet-cell-facet-outside + if(ch_next == Cell_handle() && + (Facet(ch_prev, li_prev) == get_facet() || triangulation().mirror_facet(Facet(ch_prev, li_prev)) == get_facet())) + _curr_simplex = Simplex_3(); + else + _curr_simplex = ch_prev; + } break; + case Locate_type::CELL: { // facet-cell then end + CGAL_assertion(ch_next == Cell_handle()); + _curr_simplex = ch_prev; + } break; default: CGAL_unreachable(); - }; + } break; } case 1:/*Edge*/ { - Cell_handle ch = Cell_handle(_cell_iterator); - if (ch == _cell_iterator.previous()) - { - _curr_simplex = Simplex_3(); - break; - } - if (!cell_iterator_is_ahead()) - { - increment_cell_iterator();//cell_iterator needs to be ahead to detect degeneracies - } - - Cell_handle chnext = Cell_handle(_cell_iterator); - if (chnext == Cell_handle()) - { - Cell_handle chprev = _cell_iterator.previous(); - Locate_type ltprev; - int liprev, ljprev; - _cell_iterator.exit(ltprev, liprev, ljprev); - - switch(ltprev) { - case Locate_type::VERTEX: { //edge-vertex-outside - if(edge_has_vertex(get_edge(), chprev->vertex(liprev))) - _curr_simplex = chprev->vertex(liprev); - else - _curr_simplex = shared_facet(get_edge(), chprev->vertex(liprev)); - break; - } - case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside - const Vertex_handle vi = chprev->vertex(liprev); - const Vertex_handle vj = chprev->vertex(ljprev); - const bool vi_is_vertex_of_edge = edge_has_vertex(get_edge(), vi); - const bool vj_is_vertex_of_edge = edge_has_vertex(get_edge(), vj); - if(vi_is_vertex_of_edge && vj_is_vertex_of_edge) { - _curr_simplex = Simplex_3(); - } else if(vi_is_vertex_of_edge && !vj_is_vertex_of_edge) { - _curr_simplex = shared_facet(get_edge(), vj); - } else if(vj_is_vertex_of_edge && !vi_is_vertex_of_edge) { - _curr_simplex = shared_facet(get_edge(), vi); - } else { - CGAL_assertion(!vi_is_vertex_of_edge && !vj_is_vertex_of_edge); - Facet f = shared_facet(get_edge(), vi); - _curr_simplex = shared_cell(f, vj); - } - break; - } - case Locate_type::FACET: { - if(facet_has_edge(Facet(chprev, liprev), get_edge())) - _curr_simplex = Facet(chprev, liprev); //edge-facet-outside - else - _curr_simplex = chprev; //query goes through the cell - break; - } - case Locate_type::CELL: - _curr_simplex = ch; //edge-cell-outside - break; - default: - _curr_simplex = Simplex_3(); //edge-outside - break; - } - break; - } - - ch = _cell_iterator.previous(); - Locate_type lt_exit; - int li_exit, lj_exit; - _cell_iterator.exit(lt_exit, li_exit, lj_exit); - switch (lt_exit)//entry simplex in next cell is exit simplex in current cell - { - case Locate_type::VERTEX: - { - const Vertex_handle v_exit = ch->vertex(li_exit); - if (edge_has_vertex(get_edge(), v_exit)) - _curr_simplex = v_exit; + switch(lt_prev) { + case Locate_type::VERTEX: { //edge-vertex-outside + if(edge_has_vertex(get_edge(), ch_prev->vertex(li_prev))) + _curr_simplex = ch_prev->vertex(li_prev); else - _curr_simplex = shared_facet(get_edge(), v_exit); - break; - } - case Locate_type::EDGE: - { - const Edge e_exit(ch, li_exit, lj_exit); + _curr_simplex = shared_facet(get_edge(), ch_prev->vertex(li_prev)); + } break; + case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside + const Edge e_prev(ch_prev, li_prev, lj_prev); CGAL_assertion(_cell_iterator == _cell_iterator.end() - || triangulation().is_infinite(chnext) - || _curr_simplex != Simplex_3(e_exit)); - - if (_cell_iterator == _cell_iterator.end()) - _curr_simplex = Simplex_3();//should not be reached - else if (triangulation().is_infinite(chnext) && is_same_edge(get_edge(), e_exit)) - _curr_simplex = chnext; - else { - auto facet_opt = shared_facet(get_edge(), e_exit); - if(static_cast(facet_opt)) _curr_simplex = *facet_opt; - else _curr_simplex = shared_cell(get_edge(), e_exit); + || triangulation().is_infinite(ch_next) + || _curr_simplex != Simplex_3(e_prev)); + if(is_same_edge(get_edge(), e_prev)) { + _curr_simplex = Simplex_3(); + } else { + auto facet_opt = shared_facet(get_edge(), e_prev); + if(static_cast(facet_opt)) { + _curr_simplex = *facet_opt; + } + else { + _curr_simplex = shared_cell(get_edge(), e_prev); + } } - break; - } - - case Locate_type::FACET: - if(facet_has_edge(Facet(ch, li_exit), get_edge())) - _curr_simplex = Facet(ch, li_exit); //edge-facet-outside + } break; + case Locate_type::FACET: { + if(facet_has_edge(Facet(ch_prev, li_prev), get_edge())) + _curr_simplex = Facet(ch_prev, li_prev); //edge-facet-outside else - _curr_simplex = ch;//query goes through the cell + _curr_simplex = ch_prev; //query goes through the cell + } break; + case Locate_type::CELL: + CGAL_assertion(ch_next == Cell_handle()); + _curr_simplex = ch_prev; //edge-cell-outside break; - default: - CGAL_unreachable();//should not happen - }; + CGAL_unreachable(); + } break; } case 0 :/*Vertex_handle*/ { - Cell_handle ch = Cell_handle(_cell_iterator); - if (ch == _cell_iterator.previous()) - { - _curr_simplex = Simplex_3(); - break; - } - if (!cell_iterator_is_ahead()) //_curr_simplex does contain v - { - increment_cell_iterator();//cell_iterator needs to be ahead to detect degeneracies - } - else - ch = _cell_iterator.previous(); - - const Cell_handle chnext = Cell_handle(_cell_iterator); - //_cell_iterator is one step forward _curr_simplex - CGAL_assertion(ch != chnext); - - Cell_handle prev = _cell_iterator.previous(); - Locate_type ltprev; - int liprev, ljprev; - _cell_iterator.exit(ltprev, liprev, ljprev); - - if (chnext == Cell_handle()) - { - CGAL_assertion(_cell_iterator == _cell_iterator.end()); - if (ltprev == Locate_type::VERTEX) //vertex-edge-vertex-outside - { - if (prev->vertex(liprev) != get_vertex())//avoid infinite loop edge-vertex-same edge-... - _curr_simplex = Edge(prev, liprev, prev->index(get_vertex())); - else - _curr_simplex = Simplex_3(); - } - else if (ltprev == Locate_type::EDGE)//vertex-facet-edge-outside - { - if (prev->vertex(liprev) != get_vertex() && prev->vertex(ljprev) != get_vertex()) - _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); - else - _curr_simplex = Edge(prev, liprev, ljprev); - } - else if (ltprev == Locate_type::FACET) //vertex-facet-outside - { - if (prev->vertex(liprev) != get_vertex()) //vertex-facet-outside - _curr_simplex = Facet(prev, liprev); - else //vertex-cell-facet-outside - _curr_simplex = prev; - } - else - { - CGAL_assertion(ltprev == Locate_type::CELL);//vertex-cell-outside - _curr_simplex = prev; - } - break; - } - - switch (ltprev) - { - case Locate_type::VERTEX: - { - CGAL_assertion(_cell_iterator == _cell_iterator.end() - || get_vertex() != prev->vertex(liprev) - || triangulation().is_infinite(chnext)); - if (_cell_iterator == _cell_iterator.end()) - { - if (prev == ch && ltprev == Locate_type::VERTEX) - { - const auto current_vertex = get_vertex(); - if(current_vertex == _cell_iterator.target_vertex()) { - _curr_simplex = Simplex_3(); - } else { - CGAL_assertion(prev->vertex(liprev) == _cell_iterator.target_vertex()); - _curr_simplex = ch; - } - } - else - { - if(ltprev == Locate_type::FACET) - _curr_simplex = Facet(prev, liprev); - else if(ltprev == Locate_type::EDGE) - _curr_simplex = Edge(prev, liprev, ljprev); - else - CGAL_assertion(false); - } - } + switch(lt_prev) { + case Locate_type::VERTEX: { + if(ch_prev->vertex(li_prev) != get_vertex()) // avoid infinite loop edge-vertex-same edge-... + _curr_simplex = Edge(ch_prev, li_prev, ch_prev->index(get_vertex())); else - { - if (triangulation().is_infinite(chnext) && get_vertex() == prev->vertex(liprev)) - _curr_simplex = chnext; - else - { - Cell_handle ec; - int ei = -1, ej = -1; - if (!triangulation().is_edge(get_vertex(), prev->vertex(liprev), ec, ei, ej)) - CGAL_unreachable(); - _curr_simplex = Edge(ec, ei, ej); - } - } - break; - } - - case Locate_type::EDGE: - { - //facet shared by get_vertex() and the edge - //none of ch and chnext is certainly shared by both endpoints - _curr_simplex = shared_facet(Edge(prev, liprev, ljprev), get_vertex()); - break; - } - - case Locate_type::FACET : - if (chnext == Cell_handle()) _curr_simplex = Simplex_3(); + } break; + case Locate_type::EDGE: { + if(ch_prev->vertex(li_prev) != get_vertex() && ch_prev->vertex(lj_prev) != get_vertex()) + _curr_simplex = shared_facet(Edge(ch_prev, li_prev, lj_prev), get_vertex()); else - _curr_simplex = shared_cell(Facet(prev, liprev), get_vertex()); - break; - + _curr_simplex = Edge(ch_prev, li_prev, lj_prev); + } break; + case Locate_type::FACET: { + if(ch_prev->vertex(li_prev) != get_vertex()) // vertex-facet-outside + _curr_simplex = Facet(ch_prev, li_prev); + else // vertex-cell-facet-outside + _curr_simplex = ch_prev; + } break; + case Locate_type::CELL: { + _curr_simplex = ch_prev; + } break; default: CGAL_unreachable(); - }; + } + break; } - break; - default: CGAL_unreachable(); }; return *this; } + // provides the increment prefix operator. Simplex_iterator operator++(int) { diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 5b940f07fde8..7e7640527068 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -512,8 +512,13 @@ int main(int, char* []) ok = test_vfefv() && ok; ok = test_vfefv(true) && ok; - - return ok ? EXIT_SUCCESS : EXIT_FAILURE; + if(ok) { + std::cout << "All tests passed\n"; + return EXIT_SUCCESS; + } else { + std::cout << "Some tests failed\n"; + return EXIT_FAILURE; + } } bool test(const DT& dt, From dcfd78395376158feb0dc12d60ea4f46d9e74bcf Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 18:07:22 +0200 Subject: [PATCH 49/60] change/fix some oddities in the code --- .../CGAL/Triangulation_segment_traverser_3.h | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 2c00da85bc9a..0ddc090627bc 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -728,26 +728,19 @@ class Triangulation_segment_simplex_iterator_3 _cell_iterator.exit(lt_prev, li_prev, lj_prev); switch(_curr_simplex.dimension()) { - case 3 :/*Cell_handle*/ - { - if (ch_next == Cell_handle()) - { + case 3: { /*Cell_handle*/ + if (ch_next == Cell_handle()) { if(!triangulation().is_infinite(Cell_handle(_curr_simplex))) set_curr_simplex_to_entry(); else _curr_simplex = Simplex_3(); - break; - } - else - { + } else { if (!cell_iterator_is_ahead()) increment_cell_iterator(); set_curr_simplex_to_entry(); } - break; - } - case 2 :/*Facet*/ - { + } break; + case 2: { /*Facet*/ CGAL_assertion((ch_next == Cell_handle()) == (_cell_iterator == _cell_iterator.end())); switch(lt_prev) { @@ -766,10 +759,11 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = ch_prev; } break; case Locate_type::FACET: { // facet-cell-facet-outside - if(ch_next == Cell_handle() && - (Facet(ch_prev, li_prev) == get_facet() || triangulation().mirror_facet(Facet(ch_prev, li_prev)) == get_facet())) + if(ch_next == Cell_handle() && (Facet(ch_prev, li_prev) == get_facet() || + triangulation().mirror_facet(Facet(ch_prev, li_prev)) == get_facet())) + { _curr_simplex = Simplex_3(); - else + } else _curr_simplex = ch_prev; } break; case Locate_type::CELL: { // facet-cell then end @@ -779,10 +773,8 @@ class Triangulation_segment_simplex_iterator_3 default: CGAL_unreachable(); } - break; - } - case 1:/*Edge*/ - { + } break; + case 1: {/*Edge*/ switch(lt_prev) { case Locate_type::VERTEX: { //edge-vertex-outside if(edge_has_vertex(get_edge(), ch_prev->vertex(li_prev))) @@ -792,9 +784,6 @@ class Triangulation_segment_simplex_iterator_3 } break; case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside const Edge e_prev(ch_prev, li_prev, lj_prev); - CGAL_assertion(_cell_iterator == _cell_iterator.end() - || triangulation().is_infinite(ch_next) - || _curr_simplex != Simplex_3(e_prev)); if(is_same_edge(get_edge(), e_prev)) { _curr_simplex = Simplex_3(); } else { @@ -820,8 +809,7 @@ class Triangulation_segment_simplex_iterator_3 default: CGAL_unreachable(); } - break; - } + } break; case 0 :/*Vertex_handle*/ { switch(lt_prev) { @@ -844,13 +832,13 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = ch_prev; } break; case Locate_type::CELL: { + CGAL_assertion(ch_next == Cell_handle()); _curr_simplex = ch_prev; } break; default: CGAL_unreachable(); } - break; - } + } break; default: CGAL_unreachable(); }; From f193744e66b99db2234a42892d6df2e2bf267cb0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 16 Jun 2023 18:10:19 +0200 Subject: [PATCH 50/60] walk_to_next_3: reformat to indentation by 2 space --- .../Triangulation_segment_traverser_3_impl.h | 541 +++++++++--------- 1 file changed, 260 insertions(+), 281 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index 99b9db1aeda6..a6d7e58df96d 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -333,317 +333,296 @@ std::pair::Simplex, Triangulation_segment_cell_iterator_3::walk_to_next_3(const Simplex& prev, const Simplex& cur) const { - const auto cur_cell = cur.cell; - std::array vert - = {&(cur_cell->vertex(0)->point()), - &(cur_cell->vertex(1)->point()), - &(cur_cell->vertex(2)->point()), - &(cur_cell->vertex(3)->point()) }; - - int inside=0,outside=0,regular_case=0,degenerate=0; - - if (cur.lt == Tr::FACET && prev.cell != Cell_handle()) { - // [source, target] entered the cell `cur` via a facet. - // Note that, if prev.cell == Cell_handle(), that means `source` is *on* - // the facet, and the block of this `if` cannot be applied. - Simplex prev_after_walk; - Simplex cur_after_walk; - - auto case_target_is_inside_cur_cell = [&](int case_nb) { - inside = case_nb; - prev_after_walk = { cur_cell, Tr::CELL, -1, -1 }; - cur_after_walk = { {}, Tr::CELL, -1, -1 }; - }; - auto case_segment_exits_cur_cell_by = [&](int facet_nb, - Cell_handle nnext = {}) { - if(nnext == Cell_handle{}) { - nnext = cur_cell->neighbor(facet_nb); + const auto cur_cell = cur.cell; + std::array vert = {&(cur_cell->vertex(0)->point()), &(cur_cell->vertex(1)->point()), + &(cur_cell->vertex(2)->point()), &(cur_cell->vertex(3)->point())}; + + int inside = 0, outside = 0, regular_case = 0, degenerate = 0; + + if(cur.lt == Tr::FACET && prev.cell != Cell_handle()) { + // [source, target] entered the cell `cur` via a facet. + // Note that, if prev.cell == Cell_handle(), that means `source` is *on* + // the facet, and the block of this `if` cannot be applied. + Simplex prev_after_walk; + Simplex cur_after_walk; + + auto case_target_is_inside_cur_cell = [&](int case_nb) { + inside = case_nb; + prev_after_walk = {cur_cell, Tr::CELL, -1, -1}; + cur_after_walk = {{}, Tr::CELL, -1, -1}; + }; + auto case_segment_exits_cur_cell_by = [&](int facet_nb, Cell_handle nnext = {}) { + if(nnext == Cell_handle{}) { + nnext = cur_cell->neighbor(facet_nb); + } + outside = facet_nb; + prev_after_walk = {cur_cell, Tr::FACET, facet_nb, -1}; + cur_after_walk = {nnext, Tr::FACET, nnext->index(cur_cell), -1}; + }; + regular_case = 1; + const int i = cur.li; + const int j0 = Tr::vertex_triple_index(i, 0); + const int j1 = Tr::vertex_triple_index(i, 1); + const int j2 = Tr::vertex_triple_index(i, 2); + Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target); + if(o0 == POSITIVE) { // o0 > 0 + Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); + if(o1 != POSITIVE) { // o1 <= 0 + Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); + if(oi01 == POSITIVE) { + case_segment_exits_cur_cell_by(j2); + if(o1 == ZERO) + degenerate = 1; // EDGE i j1 + } else { // o0 > 0, o1 <= 0, oi01 <= 0 + case_target_is_inside_cur_cell(1); + if(oi01 == ZERO) { // on FACET j2 (i, j0, j1) + degenerate = 1; + } // end oi01 == ZERO } - outside = facet_nb; - prev_after_walk = { cur_cell, Tr::FACET, facet_nb, -1 }; - cur_after_walk = { nnext, Tr::FACET, nnext->index(cur_cell), -1 }; - }; - regular_case = 1; - const int i = cur.li; - const int j0 = Tr::vertex_triple_index(i, 0); - const int j1 = Tr::vertex_triple_index(i, 1); - const int j2 = Tr::vertex_triple_index(i, 2); - Orientation o0 = _tr->orientation(_source, *vert[i], *vert[j0], _target); - if (o0 == POSITIVE) { // o0 > 0 - Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); - if (o1 != POSITIVE) { // o1 <= 0 - Orientation oi01 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); - if (oi01 == POSITIVE) { - case_segment_exits_cur_cell_by(j2); - if (o1 == ZERO) degenerate = 1; //EDGE i j1 - } - else { // o0 > 0, o1 <= 0, oi01 <= 0 - case_target_is_inside_cur_cell(1); - if(oi01 == ZERO) { // on FACET j2 (i, j0, j1) - degenerate = 1; - } // end oi01 == ZERO - } - } // end o1 <= 0 - else { // o1 > 0 - Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); - if ( oi12 == POSITIVE) { - case_segment_exits_cur_cell_by(j0); - } - else { // o0 > 0, o1 > 0, oi12 <= 0 - case_target_is_inside_cur_cell(2); - if( oi12 == ZERO) { // on FACET j0 (i, j1, j2) - degenerate = 1; - } // end oi12 == ZERO - } + } // end o1 <= 0 + else + { // o1 > 0 + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if(oi12 == POSITIVE) { + case_segment_exits_cur_cell_by(j0); + } else { // o0 > 0, o1 > 0, oi12 <= 0 + case_target_is_inside_cur_cell(2); + if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; + } // end oi12 == ZERO } - } // end o0 > 0 - else if (o0 == ZERO) { - // target is on plane (source, vert[i], vert[j0]) - Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); - if (o1 == NEGATIVE) { - Orientation oi12 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); - if (oi12 == POSITIVE) { - degenerate = 2; - case_segment_exits_cur_cell_by(44, cur_cell->neighbor(j2)); //EDGE i j0 - } - else { - case_target_is_inside_cur_cell(3); - if(oi12 == ZERO) { // target is *on* EDGE i j0 - degenerate = 1; - } + } + } // end o0 > 0 + else if(o0 == ZERO) + { + // target is on plane (source, vert[i], vert[j0]) + Orientation o1 = _tr->orientation(_source, *vert[i], *vert[j1], _target); + if(o1 == NEGATIVE) { + Orientation oi12 = _tr->orientation(*vert[i], *vert[j0], *vert[j1], _target); + if(oi12 == POSITIVE) { + degenerate = 2; + case_segment_exits_cur_cell_by(44, cur_cell->neighbor(j2)); // EDGE i j0 + } else { + case_target_is_inside_cur_cell(3); + if(oi12 == ZERO) { // target is *on* EDGE i j0 + degenerate = 1; } } - else if (o1 == ZERO) { - // o0 == o1 == 0 -> target is on line source-vert[i] - if (_tr->orientation(*vert[i], *vert[j0], *vert[j2], _target) == POSITIVE) - case_target_is_inside_cur_cell(55); - else - { - degenerate = 3; - case_segment_exits_cur_cell_by(5, cur_cell->neighbor(j2)); //VERTEX i - } + } else if(o1 == ZERO) { + // o0 == o1 == 0 -> target is on line source-vert[i] + if(_tr->orientation(*vert[i], *vert[j0], *vert[j2], _target) == POSITIVE) + case_target_is_inside_cur_cell(55); + else { + degenerate = 3; + case_segment_exits_cur_cell_by(5, cur_cell->neighbor(j2)); // VERTEX i } - else { // o0 == 0, o1 > 0 - Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); - if (oi12 == POSITIVE) { - case_segment_exits_cur_cell_by(j0); - } - else { - case_target_is_inside_cur_cell(4); - if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) - degenerate = 1; - } // end oi12 == ZERO - } + } else { // o0 == 0, o1 > 0 + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if(oi12 == POSITIVE) { + case_segment_exits_cur_cell_by(j0); + } else { + case_target_is_inside_cur_cell(4); + if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; + } // end oi12 == ZERO } - } // end o0 == 0 - else { // o0 < 0 - Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); - if (o2 != NEGATIVE) { - // o2 >= 0 - Orientation oi20 = _tr->orientation(*vert[i], *vert[j2], *vert[j0], _target); - if ( oi20 == POSITIVE) { - case_segment_exits_cur_cell_by(j1); - if (o2 == ZERO) degenerate = 4; // EDGE i j2 - } - else { - case_target_is_inside_cur_cell(5); - if(oi20 == ZERO) { // on FACET j1 (i, j2, j0) - degenerate = 1; - } + } + } // end o0 == 0 + else + { // o0 < 0 + Orientation o2 = _tr->orientation(_source, *vert[i], *vert[j2], _target); + if(o2 != NEGATIVE) { + // o2 >= 0 + Orientation oi20 = _tr->orientation(*vert[i], *vert[j2], *vert[j0], _target); + if(oi20 == POSITIVE) { + case_segment_exits_cur_cell_by(j1); + if(o2 == ZERO) + degenerate = 4; // EDGE i j2 + } else { + case_target_is_inside_cur_cell(5); + if(oi20 == ZERO) { // on FACET j1 (i, j2, j0) + degenerate = 1; } } - else { - Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); - if (oi12 == POSITIVE) { - case_segment_exits_cur_cell_by(j0); - } - else { - case_target_is_inside_cur_cell(6); - if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) - degenerate = 1; - } + } else { + Orientation oi12 = _tr->orientation(*vert[i], *vert[j1], *vert[j2], _target); + if(oi12 == POSITIVE) { + case_segment_exits_cur_cell_by(j0); + } else { + case_target_is_inside_cur_cell(6); + if(oi12 == ZERO) { // on FACET j0 (i, j1, j2) + degenerate = 1; } } } - - if (!degenerate) - { - return { prev_after_walk, cur_after_walk }; - } } + if(!degenerate) { + return {prev_after_walk, cur_after_walk}; + } + } - // We check in which direction the target lies - // by comparing its position relative to the planes through the - // source and the edges of the cell. - std::array o; - std::array op; - int pos = 0; - // We keep track of which orientations are calculated. - bool calc[6] = { false, false, false, false, false, false }; - - if( cur.lt == Tr::VERTEX ) { - // The three planes through the vertex are set to coplanar. - for( int j = 0; j < 4; ++j ) { - if( cur.li != j ) { - int ij = edgeIndex( cur.li, j ); - o[ij] = COPLANAR; - calc[ij] = true; - } + // We check in which direction the target lies + // by comparing its position relative to the planes through the + // source and the edges of the cell. + std::array o; + std::array op; + int pos = 0; + // We keep track of which orientations are calculated. + bool calc[6] = {false, false, false, false, false, false}; + + if(cur.lt == Tr::VERTEX) { + // The three planes through the vertex are set to coplanar. + for(int j = 0; j < 4; ++j) { + if(cur.li != j) { + int ij = edgeIndex(cur.li, j); + o[ij] = COPLANAR; + calc[ij] = true; } } - else if( cur.lt == Tr::EDGE ) { - // The plane through the edge is set to coplanar. - int ij = edgeIndex( cur.li, cur.lj ); - o[ij] = COPLANAR; - calc[ij] = true; - } + } else if(cur.lt == Tr::EDGE) { + // The plane through the edge is set to coplanar. + int ij = edgeIndex(cur.li, cur.lj); + o[ij] = COPLANAR; + calc[ij] = true; + } - // For the remembering stochastic walk, we start trying with a random facet. - CGAL_triangulation_assertion_code( bool incell = true; ) - for( int li = 0; li < 4; ++li) - { - // Skip the previous cell. - Cell_handle next = cur_cell->neighbor(li); - if( next == prev.cell ) - { - op[li] = POSITIVE; - pos += li; - continue; - } - const Point* const backup_vert_li = std::exchange(vert[li], &_target); + // For the remembering stochastic walk, we start trying with a random facet. + CGAL_triangulation_assertion_code(bool incell = true;) - // Check if the target is on the opposite side of the supporting plane. - op[li] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ); - if( op[li] == POSITIVE ) - pos += li; - if( op[li] != NEGATIVE ) { - vert[li] = backup_vert_li; + for(int li = 0; li < 4; ++li) + { + // Skip the previous cell. + Cell_handle next = cur_cell->neighbor(li); + if(next == prev.cell) { + op[li] = POSITIVE; + pos += li; + continue; + } + const Point* const backup_vert_li = std::exchange(vert[li], &_target); + + // Check if the target is on the opposite side of the supporting plane. + op[li] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); + if(op[li] == POSITIVE) + pos += li; + if(op[li] != NEGATIVE) { + vert[li] = backup_vert_li; + continue; + } + CGAL_triangulation_assertion_code(incell = false;) + + // Check if the target is inside the 3-wedge with + // the source as apex and the facet as an intersection. + int Or = 0; + for(int lj = 0; lj < 4; ++lj) { + if(li == lj) + continue; + // We check the orientation of the target compared to the plane + // Through the source and the edge opposite of ij. + const int oij = 5 - edgeIndex(li, lj); + if(!calc[oij]) { + const Point* const backup_vert_lj = std::exchange(vert[lj], &_source); + o[oij] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); + vert[lj] = backup_vert_lj; + calc[oij] = true; + } + if(o[oij] == POSITIVE) { + // The target is not inside the pyramid. + // Invert the planes. + for(int j = 0; j < 4; ++j) { + if(li == j) continue; + int oij = 5 - edgeIndex(li, j); + if(calc[oij]) + o[oij] = -o[oij]; } - CGAL_triangulation_assertion_code( incell = false; ) - - // Check if the target is inside the 3-wedge with - // the source as apex and the facet as an intersection. - int Or = 0; - for( int lj = 0; lj < 4; ++lj ) { - if( li == lj ) - continue; - - // We check the orientation of the target compared to the plane - // Through the source and the edge opposite of ij. - const int oij = 5 - edgeIndex( li, lj ); - if( !calc[oij] ) { - const Point* const backup_vert_lj = std::exchange(vert[lj], &_source); - o[oij] = _tr->orientation( *vert[0], *vert[1], *vert[2], *vert[3] ); - vert[lj] = backup_vert_lj; - calc[oij] = true; - } + Or = 0; + break; + } else + Or -= o[oij]; + } - if( o[oij] == POSITIVE ) { - // The target is not inside the pyramid. - // Invert the planes. - for( int j = 0; j < 4; ++j ) { - if( li == j ) continue; - int oij = 5 - edgeIndex( li, j ); - if(calc[oij]) o[oij] = -o[oij]; - } - Or = 0; - break; - } - else - Or -= o[oij]; - } + if(Or == 0) { + // Either the target is not inside the pyramid, + // or the pyramid is degenerate. + vert[li] = backup_vert_li; + continue; + } - if( Or == 0 ) { - // Either the target is not inside the pyramid, - // or the pyramid is degenerate. - vert[li] = backup_vert_li; - continue; + // The target is inside the pyramid. + switch(Or) { + case 3: { + if(regular_case) { + CGAL_triangulation_assertion(li == outside); + CGAL_triangulation_assertion(!inside); + } + return {{cur_cell, Tr::FACET, li}, {next, Tr::FACET, next->index(cur_cell)}}; + } + case 2: { + if(regular_case) + CGAL_triangulation_assertion(degenerate); + for(int j = 0; j < 4; ++j) { + if(li != j && o[5 - edgeIndex(li, j)] == COPLANAR) { + Edge opp = opposite_edge(prev.cell, li, j); + return { + {cur_cell, Tr::EDGE, opp.second, opp.third}, + {next, Tr::EDGE, next->index(cur_cell->vertex(opp.second)), next->index(cur_cell->vertex(opp.third))}}; } - - // The target is inside the pyramid. - switch( Or ) { - case 3: { - if(regular_case) - { - CGAL_triangulation_assertion( li==outside ); - CGAL_triangulation_assertion( ! inside ); - } - return { {cur_cell, Tr::FACET, li}, - {next, Tr::FACET, next->index(cur_cell)} }; - } - case 2: { - if(regular_case) - CGAL_triangulation_assertion(degenerate ); - - for( int j = 0; j < 4; ++j ) { - if( li != j && o[ 5 - edgeIndex(li, j) ] == COPLANAR) { - Edge opp = opposite_edge( prev.cell, li, j ); - return { {cur_cell, Tr::EDGE, opp.second, opp.third}, - {next, Tr::EDGE, - next->index(cur_cell->vertex( opp.second )), - next->index(cur_cell->vertex( opp.third )) - } - }; - } - } - CGAL_unreachable(); - return std::make_pair(prev, cur); - } - case 1: - if(regular_case) - CGAL_triangulation_assertion(degenerate ); - - for( int j = 0; j < 4; ++j ) { - if( li != j && o[ 5 - edgeIndex(li, j) ] == NEGATIVE ) { - return { {cur_cell, Tr::VERTEX, j}, - {next, Tr::VERTEX, next->index(cur_cell->vertex(j))} }; - } - } - CGAL_unreachable(); - return std::make_pair(prev, cur); - default: - CGAL_unreachable(); - return std::make_pair(prev, cur); + } + CGAL_unreachable(); + return std::make_pair(prev, cur); + } + case 1: + if(regular_case) + CGAL_triangulation_assertion(degenerate); + for(int j = 0; j < 4; ++j) { + if(li != j && o[5 - edgeIndex(li, j)] == NEGATIVE) { + return {{cur_cell, Tr::VERTEX, j}, {next, Tr::VERTEX, next->index(cur_cell->vertex(j))}}; } + } + CGAL_unreachable(); + return std::make_pair(prev, cur); + default: CGAL_unreachable(); + return std::make_pair(prev, cur); } + CGAL_unreachable(); + } - // The target lies inside this cell. - CGAL_triangulation_assertion( incell ); - return { - [&]() -> Simplex { - switch( op[0] + op[1] + op[2] + op[3] ) { - case 4: - CGAL_triangulation_assertion( pos == 6 ); - CGAL_triangulation_assertion( (! regular_case) || inside ); - return { cur_cell, Tr::CELL }; - break; - case 3: - return { cur_cell, Tr::FACET, 6 - pos }; - break; - case 2: - if( pos < 3 ) // first is 0 + // The target lies inside this cell. + CGAL_triangulation_assertion( incell ); + return { + [&]() -> Simplex { + switch( op[0] + op[1] + op[2] + op[3] ) { + case 4: + CGAL_triangulation_assertion( pos == 6 ); + CGAL_triangulation_assertion( (! regular_case) || inside ); + return { cur_cell, Tr::CELL }; + break; + case 3: + return { cur_cell, Tr::FACET, 6 - pos }; + break; + case 2: + if( pos < 3 ) // first is 0 + return { cur_cell, Tr::EDGE, 0, pos }; + else if( pos < 5 ) { // could be (0, pos), or (1, pos-1) + if(op[0] == POSITIVE) return { cur_cell, Tr::EDGE, 0, pos }; - else if( pos < 5 ) { // could be (0, pos), or (1, pos-1) - if(op[0] == POSITIVE) - return { cur_cell, Tr::EDGE, 0, pos }; - else - return { cur_cell, Tr::EDGE, 1, pos-1 }; - } else - return { cur_cell, Tr::EDGE, 2, 3 }; - break; - case 1: - return { cur_cell, Tr::VERTEX, pos }; - break; - default: - CGAL_unreachable(); + return { cur_cell, Tr::EDGE, 1, pos-1 }; } - }(), - { Cell_handle() } - }; + else + return { cur_cell, Tr::EDGE, 2, 3 }; + break; + case 1: + return { cur_cell, Tr::VERTEX, pos }; + break; + default: + CGAL_unreachable(); + } + }(), + { Cell_handle() } + }; } template < class Tr, class Inc > From e936fcb36bd7dccad9c9744ffb44e738e032fd75 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Sun, 18 Jun 2023 21:20:19 +0200 Subject: [PATCH 51/60] factorize the debug function helpers --- .../test_segment_simplex_traverser_3.cpp | 58 +--------------- .../test_simplex_iterator_3.cpp | 14 +++- .../test_triangulation_simplex_3_debug.h | 68 +++++++++++++++++++ 3 files changed, 81 insertions(+), 59 deletions(-) create mode 100644 Triangulation_3/test/Triangulation_3/test_triangulation_simplex_3_debug.h diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index 7e7640527068..a6b53e4cf5e9 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -34,6 +34,8 @@ typedef DT::Vertex_handle Vertex_handle; typedef DT::Simplex Simplex; typedef DT::Segment_simplex_iterator Segment_simplex_iterator; +#include "test_triangulation_simplex_3_debug.h" + // a function to insert without spatial sorting template void insert(DT& dt, Point_it first, Point_it end) { @@ -41,62 +43,6 @@ void insert(DT& dt, Point_it first, Point_it end) { dt.insert(*first); } } -auto display_vert(Vertex_handle v) { - std::stringstream os; - os.precision(17); - if(v->time_stamp() == 0) { - os << "inf"; - } else { - os << '#' << v->time_stamp() << "=(" << v->point() << ")"; - } - return os.str(); -}; - -struct Debug_simplex { - Simplex simplex; - - template - friend - std::basic_ostream& - operator<<(std::basic_ostream& os, const Debug_simplex& d) { - auto&& simplex = d.simplex; - switch(simplex.dimension()) { - case 0: { - os << "- vertex " << display_vert(static_cast(simplex)); - break; - } - case 1: { - const auto [c, index1, index2] = static_cast(simplex); - os << "- edge " - << display_vert(c->vertex(index1)) << " - " - << display_vert(c->vertex(index2)); - break; - } - case 2: { - const auto [c, index] = static_cast(simplex); - os << "- facet " - << display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - " - << display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - " - << display_vert(c->vertex(DT::vertex_triple_index(index, 2))); - break; - } - case 3: { - const auto c = static_cast(simplex); - os << "- cell " - << display_vert(c->vertex(0)) << " - " - << display_vert(c->vertex(1)) << " - " - << display_vert(c->vertex(2)) << " - " - << display_vert(c->vertex(3)); - break; - } - default: CGAL_assume(false); - } - return os; - }; -}; -auto debug_simplex(Simplex simplex) { - return Debug_simplex{simplex}; -} static const std::vector bbox_points = { diff --git a/Triangulation_3/test/Triangulation_3/test_simplex_iterator_3.cpp b/Triangulation_3/test/Triangulation_3/test_simplex_iterator_3.cpp index 048581c0d906..506fd81022cf 100644 --- a/Triangulation_3/test/Triangulation_3/test_simplex_iterator_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_simplex_iterator_3.cpp @@ -1,5 +1,7 @@ +// #define CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 1 #include #include +#include #include #include @@ -17,14 +19,20 @@ typedef Kernel::Vector_3 Vector_3; typedef Kernel::Segment_3 Segment_3; // Define the structure. -typedef CGAL::Delaunay_triangulation_3< Kernel > DT; +typedef CGAL::Base_with_time_stamp> Vb; +typedef CGAL::Delaunay_triangulation_cell_base_3 Cb; +typedef CGAL::Triangulation_data_structure_3 Tds; +typedef CGAL::Delaunay_triangulation_3< Kernel, Tds > DT; typedef DT::Vertex_handle Vertex_handle; typedef DT::Cell_handle Cell_handle; typedef DT::Edge Edge; typedef DT::Facet Facet; +typedef DT::Simplex Simplex; typedef DT::Segment_simplex_iterator Segment_simplex_iterator; +#include "test_triangulation_simplex_3_debug.h" + void test_vertex_edge_vertex(const DT& dt, const std::size_t& nb_tests) { std::cout << "* test_vertex_edge_vertex *" << std::endl; @@ -299,8 +307,8 @@ void test_triangulation_on_a_grid() unsigned int nb_facets = 0, nb_edges = 0, nb_vertex = 0; for (; st != st.end(); ++st) { - std::cout << st->dimension() << " "; - std::cout.flush(); + std::cerr << st->dimension() << " "; + std::cerr << debug_simplex(*st) <<'\n'; if (st->dimension() == 3) { if (dt.is_infinite(Cell_handle(*st))) ++inf; diff --git a/Triangulation_3/test/Triangulation_3/test_triangulation_simplex_3_debug.h b/Triangulation_3/test/Triangulation_3/test_triangulation_simplex_3_debug.h new file mode 100644 index 000000000000..5ea79279b1cb --- /dev/null +++ b/Triangulation_3/test/Triangulation_3/test_triangulation_simplex_3_debug.h @@ -0,0 +1,68 @@ +template +auto display_vert(Vertex_handle v) { + std::stringstream os; + os.precision(17); + if(v->time_stamp() == 0) { + os << "inf"; + } else { + os << '#' << v->time_stamp() << "=(" << v->point() << ")"; + } + return os.str(); +}; + +template +struct Debug_simplex { + using Cell_handle = typename DT::Cell_handle; + using Edge = typename DT::Edge; + using Facet = typename DT::Facet; + using Vertex_handle = typename DT::Vertex_handle; + using Simplex = typename DT::Simplex; + + Simplex simplex; + + template + friend + std::basic_ostream& + operator<<(std::basic_ostream& os, const Debug_simplex
& d) { + auto&& simplex = d.simplex; + switch(simplex.dimension()) { + case 0: { + os << "- vertex " << display_vert(static_cast(simplex)); + break; + } + case 1: { + const auto [c, index1, index2] = static_cast(simplex); + os << "- edge " + << display_vert(c->vertex(index1)) << " - " + << display_vert(c->vertex(index2)); + break; + } + case 2: { + const auto [c, index] = static_cast(simplex); + os << "- facet " + << display_vert(c->vertex(DT::vertex_triple_index(index, 0))) << " - " + << display_vert(c->vertex(DT::vertex_triple_index(index, 1))) << " - " + << display_vert(c->vertex(DT::vertex_triple_index(index, 2))); + break; + } + case 3: { + const auto c = static_cast(simplex); + os << "- cell " + << display_vert(c->vertex(0)) << " - " + << display_vert(c->vertex(1)) << " - " + << display_vert(c->vertex(2)) << " - " + << display_vert(c->vertex(3)); + break; + } + default: CGAL_assume(false); + } + return os; + }; +}; + +#include + +template +auto debug_simplex(CGAL::Triangulation_simplex_3 simplex) { + return Debug_simplex{simplex}; +} From 8a6f8f2c06406aaaba583c3683f63b1225e7e489 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Sun, 18 Jun 2023 21:20:56 +0200 Subject: [PATCH 52/60] fix dimension() of a singular simplex --- TDS_3/include/CGAL/Triangulation_simplex_3.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/TDS_3/include/CGAL/Triangulation_simplex_3.h b/TDS_3/include/CGAL/Triangulation_simplex_3.h index 8bb4188f4420..0754fb021c59 100644 --- a/TDS_3/include/CGAL/Triangulation_simplex_3.h +++ b/TDS_3/include/CGAL/Triangulation_simplex_3.h @@ -96,8 +96,10 @@ class Triangulation_simplex_3 { // returns the dimension of the simplex int dimension () const { - return (ref & 3); + if(ref == -1) return -1; + else return (ref & 3); } + // returns an incident cell: Cell_handle incident_cell() { return ch; @@ -161,6 +163,7 @@ operator==(Triangulation_simplex_3 s0, typename Sim::Cell_handle neighbor; switch (s0.dimension()) { + case -1: return s1.dimension() == -1; case (0): // Vertex return (s0.ch->vertex(s0.index(0)) == s1.ch->vertex(s1.index(0))); case (1): // Edge From 14ff8c6af57d8a016602e639d6bf5761d52516ae Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 19 Jun 2023 17:06:10 +0200 Subject: [PATCH 53/60] fix bugs --- .../CGAL/Triangulation_segment_traverser_3.h | 64 +++++++++++-------- 1 file changed, 38 insertions(+), 26 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 0ddc090627bc..bb987c3ef996 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -729,16 +729,7 @@ class Triangulation_segment_simplex_iterator_3 switch(_curr_simplex.dimension()) { case 3: { /*Cell_handle*/ - if (ch_next == Cell_handle()) { - if(!triangulation().is_infinite(Cell_handle(_curr_simplex))) - set_curr_simplex_to_entry(); - else - _curr_simplex = Simplex_3(); - } else { - if (!cell_iterator_is_ahead()) - increment_cell_iterator(); - set_curr_simplex_to_entry(); - } + set_curr_simplex_to_entry(); } break; case 2: { /*Facet*/ CGAL_assertion((ch_next == Cell_handle()) == (_cell_iterator == _cell_iterator.end())); @@ -746,7 +737,7 @@ class Triangulation_segment_simplex_iterator_3 switch(lt_prev) { case Locate_type::VERTEX: { // facet-cell?-vertex-outside Vertex_handle v_prev{ch_prev->vertex(li_prev)}; - if(triangulation().tds().has_vertex(get_facet(), v_prev)) + if(facet_has_vertex(get_facet(), v_prev)) _curr_simplex = v_prev; else _curr_simplex = ch_prev; @@ -759,10 +750,12 @@ class Triangulation_segment_simplex_iterator_3 _curr_simplex = ch_prev; } break; case Locate_type::FACET: { // facet-cell-facet-outside - if(ch_next == Cell_handle() && (Facet(ch_prev, li_prev) == get_facet() || - triangulation().mirror_facet(Facet(ch_prev, li_prev)) == get_facet())) - { - _curr_simplex = Simplex_3(); + Facet f_prev{ch_prev, li_prev}; + if(is_same_facet(f_prev, get_facet())) { + if(ch_next == Cell_handle()) + _curr_simplex = Simplex_3(); + else + _curr_simplex = ch_next; } else _curr_simplex = ch_prev; } break; @@ -777,15 +770,20 @@ class Triangulation_segment_simplex_iterator_3 case 1: {/*Edge*/ switch(lt_prev) { case Locate_type::VERTEX: { //edge-vertex-outside - if(edge_has_vertex(get_edge(), ch_prev->vertex(li_prev))) - _curr_simplex = ch_prev->vertex(li_prev); + Vertex_handle v_prev{ch_prev->vertex(li_prev)}; + if(edge_has_vertex(get_edge(), v_prev)) + _curr_simplex = v_prev; else - _curr_simplex = shared_facet(get_edge(), ch_prev->vertex(li_prev)); + _curr_simplex = shared_facet(get_edge(), v_prev); } break; case Locate_type::EDGE: { //edge-outside or edge-cell-edge-outside const Edge e_prev(ch_prev, li_prev, lj_prev); if(is_same_edge(get_edge(), e_prev)) { - _curr_simplex = Simplex_3(); + if(ch_next == Cell_handle()) { + _curr_simplex = Simplex_3(); + } else { + _curr_simplex = ch_next; + } } else { auto facet_opt = shared_facet(get_edge(), e_prev); if(static_cast(facet_opt)) { @@ -797,8 +795,9 @@ class Triangulation_segment_simplex_iterator_3 } } break; case Locate_type::FACET: { - if(facet_has_edge(Facet(ch_prev, li_prev), get_edge())) - _curr_simplex = Facet(ch_prev, li_prev); //edge-facet-outside + Facet f_prev{ch_prev, li_prev}; + if(facet_has_edge(f_prev, get_edge())) + _curr_simplex = f_prev; //edge-facet-outside else _curr_simplex = ch_prev; //query goes through the cell } break; @@ -816,14 +815,17 @@ class Triangulation_segment_simplex_iterator_3 case Locate_type::VERTEX: { if(ch_prev->vertex(li_prev) != get_vertex()) // avoid infinite loop edge-vertex-same edge-... _curr_simplex = Edge(ch_prev, li_prev, ch_prev->index(get_vertex())); - else + else { + CGAL_assertion(ch_next == Cell_handle()); _curr_simplex = Simplex_3(); + } } break; case Locate_type::EDGE: { - if(ch_prev->vertex(li_prev) != get_vertex() && ch_prev->vertex(lj_prev) != get_vertex()) - _curr_simplex = shared_facet(Edge(ch_prev, li_prev, lj_prev), get_vertex()); + const Edge e_prev(ch_prev, li_prev, lj_prev); + if(edge_has_vertex(e_prev, get_vertex())) + _curr_simplex = e_prev; else - _curr_simplex = Edge(ch_prev, li_prev, lj_prev); + _curr_simplex = shared_facet(Edge(ch_prev, li_prev, lj_prev), get_vertex()); } break; case Locate_type::FACET: { if(ch_prev->vertex(li_prev) != get_vertex()) // vertex-facet-outside @@ -980,6 +982,11 @@ class Triangulation_segment_simplex_iterator_3 return false; } + bool facet_has_vertex(const Facet& f, const Vertex_handle v) const + { + return triangulation().tds().has_vertex(f, v); + } + bool edge_has_vertex(const Edge& e, const Vertex_handle v) const { return e.first->vertex(e.second) == v @@ -992,6 +999,11 @@ class Triangulation_segment_simplex_iterator_3 && edge_has_vertex(e1, e2.first->vertex(e2.third)); } + bool is_same_facet(const Facet& f1, const Facet& f2) const + { + return f1 == f2 || triangulation().mirror_facet(f1) == f2; + } + boost::optional shared_vertex(const Edge& e1, const Edge& e2) const { Vertex_handle v1a = e1.first->vertex(e1.second); @@ -1041,7 +1053,7 @@ class Triangulation_segment_simplex_iterator_3 do { Facet f = *circ; - if (triangulation().tds().has_vertex(f, v)) + if (facet_has_vertex(f, v)) return f; } while (++circ != end); From 94a1d7efdb954e69a8a20d049b6425bec3ae81b5 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 19 Jun 2023 17:06:31 +0200 Subject: [PATCH 54/60] add special test cases --- .../Triangulation_3/test_segment_simplex_traverser_3.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp index a6b53e4cf5e9..45e4f46c318d 100644 --- a/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp +++ b/Triangulation_3/test/Triangulation_3/test_segment_simplex_traverser_3.cpp @@ -345,6 +345,12 @@ bool test_a_simple_tetrahedron(const std::vector& points) { test({-.05, .45, .2}, {.5, 0, .2}, "I232"); test({-.05, .45, .2}, {.2, .3, .2}, "I23"); + // special case: queries stay in a single simplex + test({ -.125, -.125, .625}, { -.125, -.125, .6251}, "I"); + test({ .25, .25, .25}, { .20, .25, .25}, "3"); + test({ 0, .5, .2}, { 0, .4, .2}, "2"); + test({ 0, .5, .0}, { 0, .6, .0}, "1"); + return ok; } From 6edb602729f35fd3d869f29e39fd8e4cf603fcfc Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 19 Jun 2023 17:11:19 +0200 Subject: [PATCH 55/60] factorize code when cells are traversed --- .../CGAL/Triangulation_segment_traverser_3.h | 25 ++++++++----------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index bb987c3ef996..f27ab9f757cf 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -727,10 +727,17 @@ class Triangulation_segment_simplex_iterator_3 int li_prev, lj_prev; _cell_iterator.exit(lt_prev, li_prev, lj_prev); - switch(_curr_simplex.dimension()) { - case 3: { /*Cell_handle*/ + if(_curr_simplex.dimension() == 3) { set_curr_simplex_to_entry(); - } break; + return *this; + } + if(lt_prev == Locate_type::CELL) { + CGAL_assertion(ch_next == Cell_handle()); + _curr_simplex = ch_prev; + return *this; + } + + switch(_curr_simplex.dimension()) { case 2: { /*Facet*/ CGAL_assertion((ch_next == Cell_handle()) == (_cell_iterator == _cell_iterator.end())); @@ -759,10 +766,6 @@ class Triangulation_segment_simplex_iterator_3 } else _curr_simplex = ch_prev; } break; - case Locate_type::CELL: { // facet-cell then end - CGAL_assertion(ch_next == Cell_handle()); - _curr_simplex = ch_prev; - } break; default: CGAL_unreachable(); } @@ -801,10 +804,6 @@ class Triangulation_segment_simplex_iterator_3 else _curr_simplex = ch_prev; //query goes through the cell } break; - case Locate_type::CELL: - CGAL_assertion(ch_next == Cell_handle()); - _curr_simplex = ch_prev; //edge-cell-outside - break; default: CGAL_unreachable(); } @@ -833,10 +832,6 @@ class Triangulation_segment_simplex_iterator_3 else // vertex-cell-facet-outside _curr_simplex = ch_prev; } break; - case Locate_type::CELL: { - CGAL_assertion(ch_next == Cell_handle()); - _curr_simplex = ch_prev; - } break; default: CGAL_unreachable(); } From 4f94c70740a8ed8e18cea97b2564038095b80ce7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 19 Jun 2023 17:15:42 +0200 Subject: [PATCH 56/60] typos --- .../include/CGAL/Triangulation_segment_traverser_3.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index f27ab9f757cf..d30395ef0411 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -278,7 +278,7 @@ class Triangulation_segment_cell_iterator_3 */ const Point& source() const { return _source; } - // gives the target point of the segment follwoed. + // gives the target point of the segment followed. /* \return the target point. */ const Point& target() const { return _target; } @@ -334,7 +334,7 @@ class Triangulation_segment_cell_iterator_3 } // provides a conversion operator. - /* \return the simplex through wich the current cell was entered. + /* \return the simplex through which the current cell was entered. */ operator Simplex() const { return _cur; } From fe0dc127a39227505c932976c36623fb18bb7bbf Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 20 Jun 2023 15:14:01 +0200 Subject: [PATCH 57/60] if-guard about C++17 --- Triangulation_3/test/Triangulation_3/CMakeLists.txt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Triangulation_3/test/Triangulation_3/CMakeLists.txt b/Triangulation_3/test/Triangulation_3/CMakeLists.txt index 4b0ca5adcf70..d5156f0d1e63 100644 --- a/Triangulation_3/test/Triangulation_3/CMakeLists.txt +++ b/Triangulation_3/test/Triangulation_3/CMakeLists.txt @@ -26,7 +26,14 @@ create_single_source_cgal_program("test_simplex_3.cpp") create_single_source_cgal_program( "test_simplex_iterator_3.cpp" ) create_single_source_cgal_program( "test_segment_cell_traverser_3.cpp" ) create_single_source_cgal_program( "test_segment_simplex_traverser_3.cpp" ) -target_compile_features(test_segment_simplex_traverser_3 PRIVATE cxx_std_17) +if(cxx_std_17 IN_LIST CMAKE_CXX_COMPILE_FEATURES) + target_compile_features(test_segment_simplex_traverser_3 PRIVATE cxx_std_17) +else() + message( + STATUS + "NOTICE: test_segment_simplex_traverser_3.cpp requires C++17 and will not be compiled." +) +endif() create_single_source_cgal_program("test_static_filters.cpp") create_single_source_cgal_program("test_triangulation_3.cpp") create_single_source_cgal_program("test_io_triangulation_3.cpp") From 4a7f9269dc55aacb33d7c39a40c35c0a9460014d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 20 Jun 2023 17:31:13 +0200 Subject: [PATCH 58/60] another bug fix?! --- .../include/CGAL/Triangulation_segment_traverser_3.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index d30395ef0411..a43ef0d42fd8 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -731,7 +731,10 @@ class Triangulation_segment_simplex_iterator_3 set_curr_simplex_to_entry(); return *this; } - if(lt_prev == Locate_type::CELL) { + if(lt_prev == Locate_type::CELL || + lt_prev == Locate_type::OUTSIDE_CONVEX_HULL || + lt_prev == Locate_type::OUTSIDE_AFFINE_HULL) + { CGAL_assertion(ch_next == Cell_handle()); _curr_simplex = ch_prev; return *this; From d5f521c78c0a69aeb11db689b1c489582ab04bef Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 20 Jun 2023 18:28:36 +0200 Subject: [PATCH 59/60] commit improvement to debugging code --- .../include/CGAL/Triangulation_segment_traverser_3.h | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index 830b2cd52158..919e2d0f5bac 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -168,8 +168,8 @@ class Triangulation_segment_cell_iterator_3 } else { os << display_vert(c->vertex(0)) << " - " << display_vert(c->vertex(1)) << " - " << display_vert(c->vertex(2)) << " - " << display_vert(c->vertex(3)); + os << display_lt(lt) << " " << i << " " << j; } - os << display_lt(lt) << " " << i << " " << j; return os.str(); } @@ -707,12 +707,9 @@ class Triangulation_segment_simplex_iterator_3 Simplex_iterator& operator++() { auto increment_cell_iterator = [&]() { -#if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 - std::cerr << "increment cell iterator from:\n" << _cell_iterator.debug_iterator(); -#endif ++_cell_iterator; #if CGAL_DEBUG_TRIANGULATION_SEGMENT_TRAVERSER_3 - std::cerr << "\n > to:\n" << _cell_iterator.debug_iterator() << std::endl; + std::cerr << "increment cell iterator to:\n" << _cell_iterator.debug_iterator() << '\n'; #endif }; CGAL_assertion(_curr_simplex.incident_cell() != Cell_handle()); From 28ab0b7c3eee97eadc2fea5446773a48967a027d Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 21 Jun 2023 10:16:22 +0200 Subject: [PATCH 60/60] another bug-fix Jane and I thought that case vertex-vertex with `ch_next != Cell_handle()` was not possible. Let's patch that. --- .../include/CGAL/Triangulation_segment_traverser_3.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index a43ef0d42fd8..abc9944ae254 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -818,8 +818,11 @@ class Triangulation_segment_simplex_iterator_3 if(ch_prev->vertex(li_prev) != get_vertex()) // avoid infinite loop edge-vertex-same edge-... _curr_simplex = Edge(ch_prev, li_prev, ch_prev->index(get_vertex())); else { - CGAL_assertion(ch_next == Cell_handle()); - _curr_simplex = Simplex_3(); + if(ch_next == Cell_handle()) { + _curr_simplex = Simplex_3(); + } else { + _curr_simplex = ch_next; + } } } break; case Locate_type::EDGE: {