From c10dcf7daf6ba7fa8b382043a220430618492a9b Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 10 Jun 2024 18:18:59 +0200 Subject: [PATCH 01/20] allow to call save_binary_file on non-C3t3 type (like a CDT_3) --- SMDS_3/include/CGAL/IO/File_binary_mesh_3.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/SMDS_3/include/CGAL/IO/File_binary_mesh_3.h b/SMDS_3/include/CGAL/IO/File_binary_mesh_3.h index e7363047a92..9d3aa0c5d22 100644 --- a/SMDS_3/include/CGAL/IO/File_binary_mesh_3.h +++ b/SMDS_3/include/CGAL/IO/File_binary_mesh_3.h @@ -46,14 +46,13 @@ save_binary_file(std::ostream& os, , bool binary = true) #endif { - typedef typename C3T3::Triangulation::Geom_traits::FT FT; if(binary) os << "binary "; os << "CGAL c3t3 " << CGAL::Get_io_signature()() << "\n"; if(binary) { CGAL::IO::set_binary_mode(os); } else { CGAL::IO::set_ascii_mode(os); - os.precision(std::numeric_limits::digits10+2); + os.precision(std::numeric_limits::max_digits10); } return !!(os << c3t3); // call operator!() twice, because operator bool() is C++11 From 93fd96644c9e2a1aab33433880afada3e4eed02c Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 15 Apr 2024 11:03:20 +0200 Subject: [PATCH 02/20] use boost::unordered_flat_map to optimize Polyline_constraint_hierarchy_2 --- .../Polyline_constraint_hierarchy_2.h | 38 ++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 73a7db231ac..b96752e91fe 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -21,6 +21,15 @@ #include #include #include + +#include +#if BOOST_VERSION >= 108100 +# include +# define CGAL_USE_BOOST_UNORDERED 1 +#else // BOOST before 1.81.0 +# include +#endif + #include #include @@ -134,24 +143,6 @@ class Polyline_constraint_hierarchy_2 } }; - class Pair_compare { - Compare comp; - - public: - Pair_compare(const Compare& comp) : comp(comp) {} - - bool operator()(const Edge& e1, const Edge& e2) const { - if(comp(e1.first, e2.first)) { - return true; - } else if((! comp(e2.first, e1.first)) && // !less(e1,e2) && !less(e2,e1) == equal - comp(e1.second, e2.second)) { - return true; - } else { - return false; - } - } - }; - class Context { friend class Polyline_constraint_hierarchy_2; private: @@ -171,8 +162,11 @@ class Polyline_constraint_hierarchy_2 typedef typename Context_list::iterator Context_iterator; typedef std::set Constraint_set; - typedef std::map Sc_to_c_map; +#if CGAL_USE_BOOST_UNORDERED + typedef boost::unordered_flat_map> Sc_to_c_map; +#else + typedef std::unordered_map> Sc_to_c_map; +#endif typedef typename Constraint_set::iterator C_iterator; typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; @@ -186,7 +180,7 @@ class Polyline_constraint_hierarchy_2 public: Polyline_constraint_hierarchy_2(const Compare& comp) : comp(comp) - , sc_to_c_map(Pair_compare(comp)) + , sc_to_c_map() { } Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch); Polyline_constraint_hierarchy_2(Polyline_constraint_hierarchy_2&&) = default; @@ -290,7 +284,7 @@ template Polyline_constraint_hierarchy_2:: Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch) : comp(ch.comp) - , sc_to_c_map(Pair_compare(comp)) + , sc_to_c_map() { copy(ch); } From 82b53596fd6beaaf6c5accf2182cbdd3553b3365 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 13 Jun 2024 16:31:32 +0200 Subject: [PATCH 03/20] Mesh_2: sort the sequence tr.subconstraints_begin(), tr.subconstraints_end() --- Mesh_2/include/CGAL/Mesh_2/Refine_edges.h | 24 ++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index 852ec07faf0..b2bb3b50b3d 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -346,12 +346,26 @@ class Refine_edges_base : { // with constraint hierarchy - for(typename Tr::Subconstraint_iterator it = tr.subconstraints_begin(); - it != tr.subconstraints_end(); ++it) - { - const Vertex_handle& v1 = it->first.first; - const Vertex_handle& v2 = it->first.second; + // create a vector of pairs of vertex handles, from the subconstraints + // and sort it to ensure the determinism + std::vector> subconstraints_vector(tr.number_of_subconstraints()); + std::transform(tr.subconstraints_begin(), tr.subconstraints_end(), subconstraints_vector.begin(), + [](const auto& sc) { + return std::array{sc.first.first, sc.first.second}; + }); + + auto comp_vh = [&] (Vertex_handle va, Vertex_handle vb) { + return tr.compare_xy(va->point(), vb->point()) == SMALLER; + }; + auto comp_pair_vh = [&] (const auto& e1, const auto& e2) { + return comp_vh(e1[0], e2[0]) || + (!comp_vh(e2[0], e1[0]) && comp_vh(e1[1], e2[1])); + }; + std::sort(subconstraints_vector.begin(), subconstraints_vector.end(), comp_pair_vh); + + for(const auto& [v1, v2] : subconstraints_vector) + { if(!is_locally_conform(tr, v1, v2) ){ add_constrained_edge_to_be_conformed(v1, v2); } From 552685784b6705ea0a3b8f4b0a806de0a8042cc7 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 8 Jan 2025 11:46:23 +0100 Subject: [PATCH 04/20] Add CGAL::unordered_flat_map implementation ...and `refactor Polyline_constraint_hierarchy_2` to use it. `CGAL::unordered_flat_map` will be Boost `unordered_flat_map` if availlable, or the standard `std::unordered_map` otherwise. --- .../include/CGAL/unordered_flat_map.h | 60 +++++++++++++++++++ .../Polyline_constraint_hierarchy_2.h | 15 +---- 2 files changed, 62 insertions(+), 13 deletions(-) create mode 100644 STL_Extension/include/CGAL/unordered_flat_map.h diff --git a/STL_Extension/include/CGAL/unordered_flat_map.h b/STL_Extension/include/CGAL/unordered_flat_map.h new file mode 100644 index 00000000000..45470c04d48 --- /dev/null +++ b/STL_Extension/include/CGAL/unordered_flat_map.h @@ -0,0 +1,60 @@ +// Copyright (c) 2025 GeometryFactory Sarl (France). +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Laurent Rineau + +#ifndef CGAL_UNORDERED_FLAT_MAP_H +#define CGAL_UNORDERED_FLAT_MAP_H + +#include + +#include +#if BOOST_VERSION >= 108100 && !defined(CGAL_USE_BOOST_UNORDERED) +# define CGAL_USE_BOOST_UNORDERED 1 +#endif + +#if CGAL_USE_BARE_STD_MAP // to benchmark with the ordered std::map +# include +#elif CGAL_USE_BOOST_UNORDERED +# include +#else // Boost before 1.81.0, use the C++11 std::unordered_map +# include +#endif + +#if CGAL_USE_BARE_STD_MAP + #include +#endif + +#include + +namespace CGAL { + +template < + typename Key, + typename T, + typename Hash = std::hash, + typename KeyEqual = std::equal_to, + typename Allocator = std::allocator> + > +#if CGAL_USE_BARE_STD_MAP + + using unordered_flat_map = std::map, Allocator>; + +#elif CGAL_USE_BOOST_UNORDERED + + using unordered_flat_map = boost::unordered_flat_map; + +#else // use the C++11 std::unordered_map + + using unordered_flat_map = std::unordered_map; + +#endif + +} // end namespace CGAL + +#endif // CGAL_UNORDERED_FLAT_MAP_H diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index b96752e91fe..6be1e8dd401 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -22,14 +22,7 @@ #include #include -#include -#if BOOST_VERSION >= 108100 -# include -# define CGAL_USE_BOOST_UNORDERED 1 -#else // BOOST before 1.81.0 -# include -#endif - +#include #include #include @@ -162,11 +155,7 @@ class Polyline_constraint_hierarchy_2 typedef typename Context_list::iterator Context_iterator; typedef std::set Constraint_set; -#if CGAL_USE_BOOST_UNORDERED - typedef boost::unordered_flat_map> Sc_to_c_map; -#else - typedef std::unordered_map> Sc_to_c_map; -#endif + typedef CGAL::unordered_flat_map> Sc_to_c_map; typedef typename Constraint_set::iterator C_iterator; typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; From b12625f169854c671ce944804ba7b618b32f6c83 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 8 Jan 2025 21:13:43 +0100 Subject: [PATCH 05/20] fix an error detected by UBSAN --- .../CGAL/Delaunay_mesher_no_edge_refinement_2.h | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/Mesh_2/include/CGAL/Delaunay_mesher_no_edge_refinement_2.h b/Mesh_2/include/CGAL/Delaunay_mesher_no_edge_refinement_2.h index 1729fc795f6..fe316a611e6 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesher_no_edge_refinement_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesher_no_edge_refinement_2.h @@ -63,7 +63,8 @@ class Delaunay_mesher_no_edge_refinement_2 Faces_level faces_level; Seeds seeds; - bool seeds_mark; + bool seeds_mark = false; + bool initialized = false; public: /** \name CONSTRUCTORS */ Delaunay_mesher_no_edge_refinement_2(Tr& tr_, const Criteria& criteria_ = Criteria()) @@ -72,20 +73,18 @@ class Delaunay_mesher_no_edge_refinement_2 null_level(), null_visitor(), edges_level(tr, null_level), - faces_level(tr, criteria, edges_level), - initialized(false) + faces_level(tr, criteria, edges_level) { } Delaunay_mesher_no_edge_refinement_2(Tr& tr_, Edges_level& edges_level_, - const Criteria& criteria_ = Criteria()) + const Criteria& criteria_ = Criteria()) : tr(tr_), criteria(criteria_), null_level(), null_visitor(), edges_level(edges_level_), - faces_level(tr, criteria, edges_level), - initialized(false) + faces_level(tr, criteria, edges_level) { } @@ -101,12 +100,6 @@ class Delaunay_mesher_no_edge_refinement_2 return seeds.end(); } -private: - /** \name INITIALIZED */ - - bool initialized; - -public: /** \name MARKING FUNCTIONS */ /** The value type of \a InputIterator should be `Point`, and represents From ea151ff987730356987964cf5f3616a83d2ee4dd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 8 Jan 2025 21:15:22 +0100 Subject: [PATCH 06/20] fix CGAL_USE_BARE_STD_MAP with Polyline_constraint_hierarchy_2 --- .../include/CGAL/unordered_flat_map.h | 7 ++--- .../Polyline_constraint_hierarchy_2.h | 27 +++++++++++++++++++ 2 files changed, 29 insertions(+), 5 deletions(-) diff --git a/STL_Extension/include/CGAL/unordered_flat_map.h b/STL_Extension/include/CGAL/unordered_flat_map.h index 45470c04d48..8eb3203f87e 100644 --- a/STL_Extension/include/CGAL/unordered_flat_map.h +++ b/STL_Extension/include/CGAL/unordered_flat_map.h @@ -26,11 +26,8 @@ # include #endif -#if CGAL_USE_BARE_STD_MAP - #include -#endif - -#include +#include // for std::hash, std::equal_to +#include // for std::allocator namespace CGAL { diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 6be1e8dd401..037b2368a5c 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -136,6 +136,24 @@ class Polyline_constraint_hierarchy_2 } }; + class Pair_compare { + Compare comp; + + public: + Pair_compare(const Compare& comp) : comp(comp) {} + + bool operator()(const Edge& e1, const Edge& e2) const { + if(comp(e1.first, e2.first)) { + return true; + } else if((! comp(e2.first, e1.first)) && // !less(e1,e2) && !less(e2,e1) == equal + comp(e1.second, e2.second)) { + return true; + } else { + return false; + } + } + }; + class Context { friend class Polyline_constraint_hierarchy_2; private: @@ -155,7 +173,12 @@ class Polyline_constraint_hierarchy_2 typedef typename Context_list::iterator Context_iterator; typedef std::set Constraint_set; +#if CGAL_USE_BARE_STD_MAP + typedef std::map Sc_to_c_map; +#else typedef CGAL::unordered_flat_map> Sc_to_c_map; +#endif typedef typename Constraint_set::iterator C_iterator; typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; @@ -169,7 +192,11 @@ class Polyline_constraint_hierarchy_2 public: Polyline_constraint_hierarchy_2(const Compare& comp) : comp(comp) +#if CGAL_USE_BARE_STD_MAP + , sc_to_c_map(Pair_compare(comp)) +#else , sc_to_c_map() +#endif { } Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch); Polyline_constraint_hierarchy_2(Polyline_constraint_hierarchy_2&&) = default; From bc8c1e659480986b4999c0a7eddaa5f00d0cef9f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 8 Jan 2025 21:53:44 +0100 Subject: [PATCH 07/20] new allocator type, that allocates randomly on purpose To debug non-determinism on Linux platforms. --- .clang-format | 33 +++ Mesh_2/test/Mesh_2/CMakeLists.txt | 4 + Mesh_2/test/Mesh_2/test_meshing.cpp | 5 + STL_Extension/include/CGAL/Random_allocator.h | 191 ++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 .clang-format create mode 100644 STL_Extension/include/CGAL/Random_allocator.h diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000000..ea7a2200d52 --- /dev/null +++ b/.clang-format @@ -0,0 +1,33 @@ +--- +Language: Cpp +BasedOnStyle: LLVM +AccessModifierOffset: -2 +BinPackParameters: false +BreakBeforeBraces: Custom +BraceWrapping: + AfterCaseLabel: false + AfterClass: true + AfterControlStatement: MultiLine + AfterEnum: false + AfterFunction: true + AfterNamespace: false + AfterObjCDeclaration: false + AfterStruct: true + AfterUnion: false + AfterExternBlock: false + BeforeCatch: false + BeforeElse: false + BeforeLambdaBody: false + BeforeWhile: false + IndentBraces: false + SplitEmptyFunction: true + SplitEmptyRecord: true + SplitEmptyNamespace: true +ColumnLimit: 120 +# Force pointers to the type for C++. +DerivePointerAlignment: false +PointerAlignment: Left +# Control the spaces around conditionals +SpacesInConditionalStatement: false +SpaceBeforeParens: false +... diff --git a/Mesh_2/test/Mesh_2/CMakeLists.txt b/Mesh_2/test/Mesh_2/CMakeLists.txt index 9ce291f819a..3501f20ea20 100644 --- a/Mesh_2/test/Mesh_2/CMakeLists.txt +++ b/Mesh_2/test/Mesh_2/CMakeLists.txt @@ -14,3 +14,7 @@ file( foreach(cppfile ${cppfiles}) create_single_source_cgal_program("${cppfile}") endforeach() + +if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES) + target_compile_features(test_meshing PRIVATE cxx_std_20) +endif() diff --git a/Mesh_2/test/Mesh_2/test_meshing.cpp b/Mesh_2/test/Mesh_2/test_meshing.cpp index 48d6ccffaf0..ed6801d28f1 100644 --- a/Mesh_2/test/Mesh_2/test_meshing.cpp +++ b/Mesh_2/test/Mesh_2/test_meshing.cpp @@ -1,5 +1,10 @@ // 154 515 565 #include +#if CGAL_CXX20 +# define CGAL_DEBUG_RANDOM_ALLOCATOR 1 +# include +# define CGAL_ALLOCATOR(T) CGAL::Random_allocator +#endif #include "test_dependencies.h" #include #if CGAL_USE_CORE || CGAL_USE_LEDA diff --git a/STL_Extension/include/CGAL/Random_allocator.h b/STL_Extension/include/CGAL/Random_allocator.h new file mode 100644 index 00000000000..51d36a901fd --- /dev/null +++ b/STL_Extension/include/CGAL/Random_allocator.h @@ -0,0 +1,191 @@ +// Copyright (c) 2025 GeometryFactory Sarl (France). +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Laurent Rineau + +#ifndef CGAL_RANDOM_ALLOCATOR_H +#define CGAL_RANDOM_ALLOCATOR_H + +#include +#include +#include +#include + +// This header requires C++20 or later. +#include +#include +#include +#include + +namespace CGAL { + +// A random allocator that allocates blocks of memory and returns random +// locations. To use only for debugging purposes. That allocator is: +// - not efficient, +// - not thread-safe, +// - and increases memory-fragmentation and non-locality. +template > class Random_allocator +{ + constexpr static std::size_t minimal_block_size = 1024; + constexpr static std::size_t random_size = 64; + + struct Blocks + { + struct Block + { + T* data = nullptr; + boost::dynamic_bitset<> available; + std::size_t maximal_continuous_free_space = 0; + + auto size() const { return available.size(); } + }; + + Upstream_allocator alloc; + std::vector blocks; // List of allocated blocks + + void allocate_new_block(std::size_t block_size = minimal_block_size) + { + auto& block = blocks.emplace_back(nullptr, boost::dynamic_bitset<>(block_size)); + block.data = alloc.allocate(block_size); + block.available.set(); + block.maximal_continuous_free_space = block_size; + } + + Blocks(const Upstream_allocator& alloc) : alloc(alloc) { allocate_new_block(); } + + ~Blocks() + { + for(auto& block : blocks) { + alloc.deallocate(block.data, block.size()); + } + } + }; + using Block = typename Blocks::Block; + using Ptr = std::shared_ptr; + + Ptr ptr_; + std::mt19937 gen; + +public: + using value_type = T; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + using allocator_type = Upstream_allocator; + + Random_allocator(const Upstream_allocator& alloc = {}) noexcept; + + pointer allocate(size_type n, const void* hint = 0); + void deallocate(pointer p, size_type n); + + template void construct(U* p, Args&&... args); + template void destroy(U* p); + + size_type max_size() const noexcept; + + template struct rebind + { + using other_upstream_allocator = std::allocator_traits::template rebind_alloc; + using other = Random_allocator; + }; + + bool operator==(const Random_allocator&) const noexcept; + bool operator!=(const Random_allocator&) const noexcept; +}; + +// Implementation of Random_allocator methods +template +Random_allocator::Random_allocator(const Upstream_allocator& alloc) noexcept + : ptr_(std::make_shared(alloc)), gen(std::random_device()()) +{ +} + +template +typename Random_allocator::pointer +Random_allocator::allocate(size_type n, const void* hint) +{ + boost::container::static_vector, random_size> found_spaces; + for(auto& block : ptr_->blocks | std::views::reverse) { + if(block.maximal_continuous_free_space < n) + continue; + auto& available = block.available; + const auto block_size = block.size(); + size_type found_max_free_space = 0; + auto index = available.find_first(); + while(index != boost::dynamic_bitset<>::npos) { + available.flip(); + const auto end_of_free_block = (std::min)(available.find_next(index), block_size); + available.flip(); + auto free_space = end_of_free_block - index; + found_max_free_space = (std::max)(found_max_free_space, free_space); + while(free_space > n && found_spaces.size() < found_spaces.capacity()) { + found_spaces.push_back({std::addressof(block), index}); + free_space -= n; + index += n; + } + index = block.available.find_next(end_of_free_block); + } + block.maximal_continuous_free_space = found_max_free_space; + if(found_spaces.size() == found_spaces.capacity()) + break; + } + if(!found_spaces.empty()) { + std::uniform_int_distribution<> dis(0, found_spaces.size() - 1); + auto i = dis(gen); + auto [block, index] = found_spaces[i]; + block->available.set(index, n, false); +#if CGAL_DEBUG_RANDOM_ALLOCATOR + std::clog << std::format("CGAL::Random_allocator debug info: n = {}, found_spaces.size() = {}, i = {}," + "block nb = {}, block size = {}, index = {}\n", + n, found_spaces.size(), i, block - ptr_->blocks.data(), block->size(), index); +#endif // CGAL_DEBUG_RANDOM_ALLOCATOR + return block->data + index; + } + size_type block_size = std::max(n * random_size, minimal_block_size); + ptr_->allocate_new_block(block_size); + return allocate(n, hint); +} + +template +void Random_allocator::deallocate(pointer p, size_type n) +{ + for(auto& block : ptr_->blocks) { + if(block.data <= p && p < block.data + block.size()) { + block.available.set(p - block.data, n, true); + return; + } + } +} + +template +template +void Random_allocator::construct(U* p, Args&&... args) +{ + ::new((void*)p) U(std::forward(args)...); +} + +template +template +void Random_allocator::destroy(U* p) +{ + p->~U(); +} + +template +typename Random_allocator::size_type +Random_allocator::max_size() const noexcept +{ + return std::numeric_limits::max() / sizeof(T); +} + +} // namespace CGAL + +#endif // CGAL_RANDOM_ALLOCATOR_H From 364ba1595c87d67ff40bb9d5da05b7d00931d077 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 8 Jan 2025 21:53:53 +0100 Subject: [PATCH 08/20] fix a missing #include --- .../Triangulation_2/internal/Polyline_constraint_hierarchy_2.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 037b2368a5c..0b59735b50e 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -24,6 +24,7 @@ #include #include +#include #include #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS From e5807ca048b57f6849537bff86ea5d4495463e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Loriot?= Date: Fri, 10 Jan 2025 14:45:51 +0100 Subject: [PATCH 09/20] TWS --- Mesh_2/test/Mesh_2/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mesh_2/test/Mesh_2/CMakeLists.txt b/Mesh_2/test/Mesh_2/CMakeLists.txt index 3501f20ea20..877831c292e 100644 --- a/Mesh_2/test/Mesh_2/CMakeLists.txt +++ b/Mesh_2/test/Mesh_2/CMakeLists.txt @@ -15,6 +15,6 @@ foreach(cppfile ${cppfiles}) create_single_source_cgal_program("${cppfile}") endforeach() -if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES) +if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES) target_compile_features(test_meshing PRIVATE cxx_std_20) endif() From 56bb4191ed82c12aa1cd9fd9149450ed0fa34684 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 10 Jan 2025 22:01:18 +0100 Subject: [PATCH 10/20] cleanup existing code --- .clang-format | 10 +- Stream_support/include/CGAL/IO/io.h | 47 +- .../CGAL/Constrained_triangulation_plus_2.h | 66 +- .../Polyline_constraint_hierarchy_2.h | 617 +++++++++--------- .../CGAL/_test_cls_const_triang_plus_2.h | 5 +- 5 files changed, 379 insertions(+), 366 deletions(-) diff --git a/.clang-format b/.clang-format index ea7a2200d52..369aadbb15f 100644 --- a/.clang-format +++ b/.clang-format @@ -2,14 +2,16 @@ Language: Cpp BasedOnStyle: LLVM AccessModifierOffset: -2 +AllowShortFunctionsOnASingleLine: true BinPackParameters: false +BreakConstructorInitializers: BeforeComma BreakBeforeBraces: Custom BraceWrapping: AfterCaseLabel: false AfterClass: true AfterControlStatement: MultiLine AfterEnum: false - AfterFunction: true + AfterFunction: false AfterNamespace: false AfterObjCDeclaration: false AfterStruct: true @@ -20,9 +22,9 @@ BraceWrapping: BeforeLambdaBody: false BeforeWhile: false IndentBraces: false - SplitEmptyFunction: true - SplitEmptyRecord: true - SplitEmptyNamespace: true + SplitEmptyFunction: false + SplitEmptyRecord: false + SplitEmptyNamespace: false ColumnLimit: 120 # Force pointers to the type for C++. DerivePointerAlignment: false diff --git a/Stream_support/include/CGAL/IO/io.h b/Stream_support/include/CGAL/IO/io.h index 74f8dd34bab..3f8202d8325 100644 --- a/Stream_support/include/CGAL/IO/io.h +++ b/Stream_support/include/CGAL/IO/io.h @@ -1004,12 +1004,53 @@ namespace std { template struct formatter, CharT> : public std::formatter> { + using context = std::basic_format_parse_context; + using context_iterator = typename context::iterator; + + constexpr context_iterator parse_non_precision_chars(context_iterator it, context_iterator end) + { + constexpr std::array letters = {CharT('A'), CharT('B'), CharT('P')}; + constexpr std::array modes = {CGAL::IO::ASCII, CGAL::IO::BINARY, CGAL::IO::PRETTY}; + + if(it == end) + throw "it != end is a precondition of `parse_non_precision_chars(it, end)`"; + + if(*it == CharT('}')) + return it; + if(*it == CharT('.')) + return it; + + for(const auto& letter : letters) { + if(*it == letter) { + mode = modes[std::addressof(letter) - letters.data()]; + return ++it; + } + } + + throw std::format_error(R"( +formatter for CGAL::Output_rep only support stream mode and precision, like `{:X.6}` where X is + - `A` (or missing) for ASCII mode, + - `B` for BINARY mode, or + - `P` for PRETTY mode +)"); + } + constexpr auto parse(std::basic_format_parse_context& ctx) { auto it = ctx.begin(); const auto end = ctx.end(); - if(it == end) - return it; + + if(it == end) return it; + + { + auto next = it; + do { + next = parse_non_precision_chars(it, end); + } while(next != it && (it = next) != end); + } + + if(it == end) return it; + if(*it != CharT('.')) { if(*it == CharT('}')) return it; throw std::format_error("formatter for CGAL::Output_rep only support precision, like `{:.6}`"); @@ -1031,12 +1072,14 @@ struct formatter, CharT> : public std::formatter &rep, FormatContext& ctx) const { std::basic_stringstream ss; + CGAL::IO::set_mode(ss, mode); ss.precision(precision); ss << rep; return std::formatter>::format(ss.str(), ctx); } int precision = 17; + CGAL::IO::Mode mode = CGAL::IO::ASCII; }; } // namespace std diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 10cdecc984f..ac3889c5341 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -427,11 +427,11 @@ class Constrained_triangulation_plus_2 hierarchy.swap(cid, aux); remove_constraint(aux, std::back_inserter(fc)); - if(head.vl_ptr()){ + if(head != nullptr){ hierarchy.concatenate2(head, cid); } - if(tail.vl_ptr()){ + if(tail != nullptr){ hierarchy.concatenate(cid, tail); } fc.write_faces(out); @@ -514,7 +514,7 @@ class Constrained_triangulation_plus_2 pos = vertices_in_constraint_begin(aux2); concatenate(aux1, aux2); - if(head.vl_ptr()){ + if(head != nullptr){ //std::cout << "concatenate head" << std::endl; remove_constraint(cid, std::back_inserter(fc)); hierarchy.concatenate(head, aux1); @@ -524,7 +524,7 @@ class Constrained_triangulation_plus_2 head = cid; } - if(tail.vl_ptr()){ + if(tail != nullptr){ //std::cout << "concatenate tail" << std::endl; concatenate(head, tail); } @@ -559,10 +559,8 @@ class Constrained_triangulation_plus_2 insert_subconstraint(vertices[j], vertices[j+1], std::back_inserter(fc)); } } - for(Vertices_in_constraint_iterator vcit = vertices_in_constraint_begin(ca); - vcit != vertices_in_constraint_end(ca); - vcit++){ - insert_incident_faces(vcit, out); + for(auto vh : vertices_in_constraint(ca)) { + out = insert_incident_faces(vh, out); } //AF vertices_in_constraint_begin(ca)->fixed() = true; // Vertices_in_constraint_iterator end = std::prev(vertices_in_constraint_end(ca)); @@ -593,7 +591,7 @@ class Constrained_triangulation_plus_2 std::size_t n = vertices.size(); if(n == 1){ - return nullptr; + return Constraint_id{}; } CGAL_assertion(n >= 2); @@ -628,12 +626,12 @@ class Constrained_triangulation_plus_2 } } - for(Constraint_iterator cit = constraints_begin(); cit != constraints_end(); ++cit){ - os << (*cit).second->all_size(); - for(Vertex_handle vh : vertices_in_constraint(*cit)){ - os << " " << V[vh]; - } - os << std::endl; + for(const auto& cid : constraints()) { + os << cid.size(); + for(Vertex_handle vh : vertices_in_constraint(cid)) { + os << " " << V[vh]; + } + os << std::endl; } } @@ -672,16 +670,14 @@ class Constrained_triangulation_plus_2 { // protects against inserting a zero length constraint if(va == vb){ - return Constraint_id(nullptr); + return Constraint_id(); } // protects against inserting twice the same constraint Constraint_id cid = hierarchy.insert_constraint(va, vb); if (va != vb && (cid != nullptr) ) insert_subconstraint(va,vb,out); - for(Vertices_in_constraint_iterator vcit = vertices_in_constraint_begin(cid); - vcit != vertices_in_constraint_end(cid); - vcit++){ - insert_incident_faces(vcit, out); + for(auto vh : vertices_in_constraint(cid)) { + out = insert_incident_faces(vh, out); } return cid; } @@ -711,14 +707,11 @@ class Constrained_triangulation_plus_2 template void remove_constraint(Constraint_id cid, OutputIterator out) { - std::list vertices(hierarchy.vertices_in_constraint_begin(cid), - hierarchy.vertices_in_constraint_end(cid)); + std::vector vertices(hierarchy.vertices_in_constraint_begin(cid), + hierarchy.vertices_in_constraint_end(cid)); hierarchy.remove_constraint(cid); - for(typename std::list::iterator it = vertices.begin(), - succ = it; - ++succ != vertices.end(); - ++it){ + for(auto it = vertices.begin(), succ = it; ++succ != vertices.end(); ++it){ if(! is_subconstraint(*it, *succ)){ // this checks whether other constraints pass Face_handle fh; int i; @@ -833,29 +826,24 @@ class Constrained_triangulation_plus_2 protected: template - void insert_incident_faces(Vertices_in_constraint_iterator vcit, OutputItertator out) + OutputItertator insert_incident_faces(Vertex_handle vh, OutputItertator out) { - Vertex_handle vh = *vcit; Face_circulator fc = incident_faces(vh), done = fc; - Face_circulator null ; - if ( fc != null ) - { + if(fc != nullptr) { do { Face_handle fh = fc; - out = fh; - out++; - fc++; - }while(fc != done); + *out++ = fh; + } while(++fc != done); } + return out; } - void insert_subconstraint(Vertex_handle vaa, Vertex_handle vbb) - { - insert_subconstraint(vaa,vbb,Emptyset_iterator()); - } +{ + insert_subconstraint(vaa,vbb,Emptyset_iterator()); +} diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 0b59735b50e..761d7f75871 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -47,23 +47,27 @@ class Polyline_constraint_hierarchy_2 typedef std::pair Constraint; typedef std::pair Subconstraint; + using size_type = std::size_t; + private: class Node { public: explicit Node(Vertex_handle vh, bool input = false) - : vertex_(vh), point_(vertex_->point()), input(input) + : vertex_(vh), point_(vertex_->point()), input_(input) {} const Point& point() const { return point_; } Vertex_handle vertex() const { return vertex_; } + bool& input() { return input_; } + const bool& input() const { return input_; } private: Vertex_handle vertex_; Point point_; public: - bool input; + bool input_; }; typedef CGAL::Skiplist Vertex_list; - typedef std::list Constraint_list; + typedef Vertex_list* Vertex_list_ptr; public: // the base line is always @@ -91,51 +95,75 @@ class Polyline_constraint_hierarchy_2 , std::bidirectional_iterator_tag , Vertex_handle> { + typedef typename Vertex_list::skip_iterator Base_it; public: Vertex_it() : Vertex_it::iterator_adaptor_() {} - Vertex_it(typename Vertex_list::skip_iterator it) : Vertex_it::iterator_adaptor_(it) {} + Vertex_it(Base_it it) : Vertex_it::iterator_adaptor_(it) {} operator Point_it() const { return Point_it(this->base()); } - bool& input() { return this->base()->input; } + bool& input() { return this->base()->input(); } + const bool& input() const { return this->base()->input(); } + + friend bool operator==(const Vertex_it& a, const Base_it& it) { return a.base() == it; } + friend bool operator==(const Base_it& it, const Vertex_it& a) { return a.base() == it; } + friend bool operator!=(const Vertex_it& a, const Base_it& it) { return a.base() != it; } + friend bool operator!=(const Base_it& it, const Vertex_it& a) { return a.base() != it; } + private: friend class boost::iterator_core_access; Vertex_handle dereference() const { return this->base()->vertex(); } }; - typedef typename Constraint_list::iterator Constraint_it; + struct Constraint_id + { + Vertex_list_ptr vl = nullptr; + size_type id = std::numeric_limits::max(); - struct Constraint_id { - Vertex_list* second; + Constraint_id(std::nullptr_t = nullptr) {} + Constraint_id(Vertex_list_ptr vl, size_type id) : vl(vl), id(id) {} - Constraint_id(): second(nullptr) {} + Vertex_list_ptr vl_ptr() const { return vl; } - Constraint_id(Vertex_list* vl) - : second(vl) - {} + operator std::pair() const{ + Edge edge = vl == nullptr ? Edge() : Edge(vl->front().vertex(), vl->back().vertex()); + return std::make_pair(edge, vl); + } - Vertex_list* vl_ptr() const {return second;} + Constraint_id& operator=(std::nullptr_t) { + vl = nullptr; + id = std::numeric_limits::max(); + return *this; + } + bool operator==(std::nullptr_t n) const { return vl == n; } + bool operator!=(std::nullptr_t n) const { return vl != n; } - operator std::pair,Vertex_list*>() + bool operator==(const Constraint_id& other) const { - if (second!=nullptr){ - return std::make_pair(std::make_pair(second->front().vertex(), - second->back().vertex()),second); - } - return std::make_pair(std::make_pair(Vertex_handle(),Vertex_handle()),second); + CGAL_assertion((vl == other.vl) == (id == other.id)); + return vl == other.vl; } - bool operator == (const Constraint_id& other) const + bool operator!=(const Constraint_id& other) const { - return second == other.second; + CGAL_assertion((vl == other.vl) == (id == other.id)); + return vl != other.vl; } - bool operator != (const Constraint_id& other) const + + bool operator<(const Constraint_id& other) const { - return second != other.second; + CGAL_assertion((vl == other.vl) == (id == other.id)); + return id < other.id; } - bool operator<(const Constraint_id& other) const{ - return second < other.second; - } - }; + // forward a new Vertex_list operations + decltype(auto) begin() const { return vl->skip_begin(); } + decltype(auto) end() const { return vl->skip_end(); } + decltype(auto) elements() const { return vl->skip_elements(); } + decltype(auto) clear() const { return vl->clear(); } + decltype(auto) size() const { return vl->skip_size(); } + decltype(auto) front() const { return vl->front(); } + decltype(auto) back() const { return vl->back(); } + + }; // end Constraint_id class Pair_compare { Compare comp; @@ -158,16 +186,16 @@ class Polyline_constraint_hierarchy_2 class Context { friend class Polyline_constraint_hierarchy_2; private: - Vertex_list* enclosing; - Vertex_it pos; + Constraint_id enclosing; + Vertex_it pos; public: Context() : enclosing(nullptr) {} - Vertex_it vertices_begin()const { return enclosing->skip_begin();} + Vertex_it vertices_begin()const { return enclosing.begin();} Vertex_it current()const {return pos;} - Vertex_it vertices_end()const {return enclosing->skip_end();} + Vertex_it vertices_end()const {return enclosing.end();} Constraint_id id()const { return enclosing; } - std::size_t number_of_vertices() const {return enclosing->skip_size(); } + size_type number_of_vertices() const {return enclosing.size(); } }; typedef std::list Context_list; @@ -212,9 +240,11 @@ class Polyline_constraint_hierarchy_2 bool is_constrained_vertex(T v) const; Vertex_it vertices_in_constraint_begin(Constraint_id cid) const - { return cid.vl_ptr()->skip_begin(); } + { return cid.begin(); } Vertex_it vertices_in_constraint_end(Constraint_id cid) const - { return cid.vl_ptr()->skip_end(); } + { return cid.end(); } + auto vertices_in_constraint(Constraint_id cid) const + { return Iterator_range(cid.begin(), cid.end()); } Point_it points_in_constraint_begin(Constraint_id cid) const @@ -224,23 +254,22 @@ class Polyline_constraint_hierarchy_2 bool enclosing_constraint(Edge he, Constraint& hc) const; bool enclosing_constraint(T vaa, T vbb, T& va, T& vb) const; - bool enclosing_constraints(T vaa, T vbb, Constraint_list& hcl) const; bool next_along_sc(T va, T vb, T& w) const; void oriented_end(T va, T vb, T& vc) const; Context context(T va, T vb); - std::size_t number_of_enclosing_constraints(T va, T vb) const; + size_type number_of_enclosing_constraints(T va, T vb) const; Context_iterator contexts_begin(T va, T vb) const; Context_iterator contexts_end(T va, T vb) const; Iterator_range contexts_range(T va, T vb) const; - std::size_t number_of_constraints() const { return constraint_set.size();} - std::size_t number_of_subconstraints()const {return sc_to_c_map.size();} + size_type number_of_constraints() const { return constraint_set.size();} + size_type number_of_subconstraints()const {return sc_to_c_map.size();} // insert/remove void add_Steiner(T va, T vb, T vx); - Vertex_list* insert_constraint_old_API(T va, T vb); - Vertex_list* insert_constraint(T va, T vb); + Constraint_id insert_constraint_old_API(T va, T vb); + Constraint_id insert_constraint(T va, T vb); void append_constraint(Constraint_id cid, T va, T vb); void swap(Constraint_id first, Constraint_id second); void remove_constraint(Constraint_id cid); @@ -251,8 +280,8 @@ class Polyline_constraint_hierarchy_2 Vertex_it v, Vertex_it w); - std::size_t remove_points_without_corresponding_vertex(Constraint_id); - std::size_t remove_points_without_corresponding_vertex(); + size_type remove_points_without_corresponding_vertex(Constraint_id); + size_type remove_points_without_corresponding_vertex(); Constraint_id concatenate(Constraint_id first, Constraint_id second); Constraint_id concatenate2(Constraint_id first, Constraint_id second); @@ -278,13 +307,23 @@ class Polyline_constraint_hierarchy_2 C_iterator c_begin() const{ return constraint_set.begin(); } C_iterator c_end() const{ return constraint_set.end(); } + // Ranges + auto constraints() const { return Iterator_range(c_begin(), c_end()); } + const auto & subconstraints() const { return sc_to_c_map; } + + // Helper functions void copy(const Polyline_constraint_hierarchy_2& ch); void copy(const Polyline_constraint_hierarchy_2& ch, std::map& vmap); void swap(Polyline_constraint_hierarchy_2& ch); private: + Constraint_id new_constraint_id() const { + auto id = number_of_constraints() == 0 ? 0 : constraint_set.rbegin()->id + 1; + return Constraint_id(new Vertex_list, id); + } Edge make_edge(T va, T vb) const; + Edge make_edge(Edge e) { const auto& [va, vb] = e; return make_edge(va, vb); } Vertex_it get_pos(T va, T vb) const; bool get_contexts(T va, T vb, Context_iterator& ctxt, @@ -317,63 +356,58 @@ operator=(const Polyline_constraint_hierarchy_2& ch){ template void Polyline_constraint_hierarchy_2:: -copy(const Polyline_constraint_hierarchy_2& ch1) +copy(const Polyline_constraint_hierarchy_2& other) { // create a identity transfer vertex map - std::map vmap; - C_iterator cit1 = ch1.c_begin(); - for( ; cit1 != ch1.c_end(); ++cit1) { - Vertex_it vit = cit1->second->begin(); - for( ; vit != cit1->second->end(); ++vit) { - vmap[*vit] = *vit; + std::map vmap; + for(const auto& cid : other.constraints()) { + for(const auto& node : cid.elements()) { + auto v = node.vertex(); + vmap[v] = v; } } - copy(ch1, vmap); + copy(other, vmap); } template void Polyline_constraint_hierarchy_2:: -copy(const Polyline_constraint_hierarchy_2& ch1, std::map& vmap) +copy(const Polyline_constraint_hierarchy_2& other, std::map& vmap) // copy with a transfer vertex map { - std::map vlmap; + std::map cstr_map; clear(); // copy constraint_set - C_iterator cit1 = ch1.c_begin(); - for( ; cit1 != ch1.c_end(); ++cit1) { - Vertex_list* hvl1 = cit1->vl_ptr(); - Vertex_list* hvl2 = new Vertex_list; - vlmap[hvl1] = hvl2; - Vertex_it vit = hvl1->skip_begin(), end = hvl1->skip_end(); - for( ; vit != end; ++vit) hvl2->push_back(Node(vmap[*vit], vit.input())); - constraint_set.insert(hvl2); + for(const auto& cid1: other.constraints()) { + Constraint_id cid2 = new_constraint_id(); + cstr_map[cid1] = cid2; + for(const auto& node : cid1.elements()) { + cid2.vl_ptr()->push_back(Node(vmap[node.vertex()], node.input())); + } + constraint_set.insert(cid2); } // copy sc_to_c_map - Sc_iterator scit1 = ch1.sc_begin(); - for( ; scit1 != ch1.sc_end(); ++scit1) { - //vertices of the subconstraints - Vertex_handle uu2 = vmap[scit1->first.first]; - Vertex_handle vv2 = vmap[scit1->first.second]; - Context_list* hcl1 = scit1->second; - Context_list* hcl2 = new Context_list; - Context_iterator cit1 = hcl1->begin(); - for( ; cit1 != hcl1->end(); ++cit1){ + for(const auto& [edge1, hcl1] : other.subconstraints()) { + Context_list* hcl2 = new Context_list; + Vertex_handle uu2 = vmap[edge1.first]; + Vertex_handle vv2 = vmap[edge1.second]; + Edge edge2 = make_edge(uu2, vv2); + sc_to_c_map[edge2] = hcl2; + for(const Context& ctxt1 : *hcl1) { // vertices of the enclosing constraints Context ctxt2; - ctxt2.enclosing = vlmap[cit1->enclosing]; - ctxt2.pos = ctxt2.enclosing->skip_begin(); - Vertex_it aux = cit1->enclosing->skip_begin(); - while( aux != cit1->pos) { + ctxt2.enclosing = cstr_map[ctxt1.enclosing]; + ctxt2.pos = ctxt2.enclosing.begin(); + Vertex_it aux = ctxt1.enclosing.begin(); + while(aux != ctxt1.pos) { ++aux; ++ctxt2.pos; } hcl2->push_back(ctxt2); } - sc_to_c_map[make_edge(uu2,vv2)] = hcl2; } - comp = ch1.comp; + comp = other.comp; return; } @@ -383,6 +417,8 @@ void Polyline_constraint_hierarchy_2:: swap(Polyline_constraint_hierarchy_2& ch) { + using std::swap; + swap(comp, ch.comp); constraint_set.swap(ch.constraint_set); sc_to_c_map.swap(ch.sc_to_c_map); } @@ -412,7 +448,7 @@ enclosing_constraint(Edge he, Constraint& hc) const { Context_iterator hcit, past; if ( !get_contexts(he.first,he.second, hcit ,past)) return false; - hc = make_edge(hcit->enclosing->front(), hcit->enclosing->back()); + hc = make_edge(hcit->enclosing.front(), hcit->enclosing.back()); return true; } @@ -424,9 +460,9 @@ enclosing_constraint(T vaa, T vbb, T& va, T& vb) const { Context_iterator hcit, past; if ( !get_contexts(vaa,vbb, hcit ,past)) return false; - // va = hcit->enclosing->front().vertex(); - // vb = hcit->enclosing->back().vertex(); - // Vertex_list* vl = hcit->enclosing; + // va = hcit->enclosing.front().vertex(); + // vb = hcit->enclosing.back().vertex(); + // Vertex_list_ptr vl = hcit->enclosing; Vertex_it pos = hcit->pos; if(vaa != *pos){ std::swap(vaa,vbb); @@ -445,20 +481,6 @@ enclosing_constraint(T vaa, T vbb, T& va, T& vb) const return true; } -// af: obsolete -template -bool Polyline_constraint_hierarchy_2:: -enclosing_constraints(T vaa, T vbb , Constraint_list& hcl) const -{ - Context_iterator hcit, past; - if ( !get_contexts(vaa,vbb, hcit ,past)) return false; - for (; hcit!=past; hcit++) { - hcl.push_back(make_edge(hcit->enclosing->front(), - hcit->enclosing->back())); - } - return true; -} - template typename Polyline_constraint_hierarchy_2::Context Polyline_constraint_hierarchy_2:: @@ -470,7 +492,7 @@ context(T va, T vb) } template -std::size_t +typename Polyline_constraint_hierarchy_2::size_type Polyline_constraint_hierarchy_2:: number_of_enclosing_constraints(T va, T vb) const { @@ -512,58 +534,33 @@ contexts_range(T va, T vb) const -> Iterator_range { template void Polyline_constraint_hierarchy_2:: -swap(Constraint_id first, Constraint_id second){ +swap(Constraint_id constr_a, Constraint_id constr_b) { + auto substitute_enclosing_in_vertex_list = [this](Vertex_list_ptr vl, Constraint_id old_id, Constraint_id new_id) { // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; - ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); - CGAL_assertion(scit != sc_to_c_map.end()); - Context_list* hcl = scit->second; - - // and replace the context of the constraint - for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = nullptr; - break; + for(Vertex_it it = vl->skip_begin(), succ = it, end = vl->skip_end(); ++succ != end; ++it) { + typename Sc_to_c_map::iterator scit = this->sc_to_c_map.find(make_edge(*it, *succ)); + CGAL_assertion(scit != this->sc_to_c_map.end()); + Context_list* hcl = scit->second; + + // and replace the context of the constraint + for(Context_iterator ctit = hcl->begin(); ctit != hcl->end(); ctit++) { + if(ctit->enclosing == old_id) { + ctit->enclosing = new_id; + break; + } } } - } - // We have to look at all subconstraints - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); - ++succ != end; - ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); - CGAL_assertion(scit != sc_to_c_map.end()); - Context_list* hcl = scit->second; + }; - // and replace the context of the constraint - for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == second.vl_ptr()){ - ctit->enclosing = first.vl_ptr(); - break; - } - } - } - // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); - ++succ != end; - ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); - CGAL_assertion(scit != sc_to_c_map.end()); - Context_list* hcl = scit->second; + Vertex_list_ptr constr_a_vl = constr_a.vl_ptr(); + Vertex_list_ptr constr_b_vl = constr_b.vl_ptr(); - // and replace the context of the constraint - for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == nullptr){ - ctit->enclosing = second.vl_ptr(); - break; - } - } - } - first.vl_ptr()->swap(*second.vl_ptr()); -} + substitute_enclosing_in_vertex_list(constr_a_vl, constr_a, nullptr); + substitute_enclosing_in_vertex_list(constr_b_vl, constr_b, constr_a); + substitute_enclosing_in_vertex_list(constr_a_vl, nullptr, constr_b); + constr_a_vl->swap(*constr_b_vl); +} template void @@ -572,7 +569,7 @@ remove_constraint(Constraint_id cid){ constraint_set.erase(cid); // We have to look at all subconstraints - for(Vertex_it it = cid.vl_ptr()->skip_begin(), succ = it, end = cid.vl_ptr()->skip_end(); + for(Vertex_it it = cid.begin(), succ = it, end = cid.end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -581,7 +578,7 @@ remove_constraint(Constraint_id cid){ // and remove the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == cid.vl_ptr()){ + if(ctit->enclosing == cid){ hcl->erase(ctit); break; } @@ -631,7 +628,7 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, it = uv_hcl->erase(it); }else{ // Remove the list item which points to v - Vertex_list* vertex_list = it->id().vl_ptr(); + Vertex_list_ptr vertex_list = it->id().vl_ptr(); Vertex_it vc_in_context = it->current(); vc_in_context = std::next(vc_in_context); vertex_list->skip(vc_in_context.base()); @@ -644,7 +641,7 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, it = vw_hcl->erase(it); }else{ // Remove the list item which points to v - Vertex_list* vertex_list = it->id().vl_ptr(); + Vertex_list_ptr vertex_list = it->id().vl_ptr(); Vertex_it vc_in_context = it->current(); vc_in_context = std::next(vc_in_context); vertex_list->skip(vc_in_context.base()); @@ -664,10 +661,10 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, template -std::size_t +typename Polyline_constraint_hierarchy_2::size_type Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex(Constraint_id cid) { - std::size_t n = 0; + size_type n = 0; for(Point_it it = points_in_constraint_begin(cid); it != points_in_constraint_end(cid);) { if(cid.vl_ptr()->is_skipped(it.base())) { @@ -681,10 +678,10 @@ Polyline_constraint_hierarchy_2::remove_points_without_correspo } template -std::size_t +typename Polyline_constraint_hierarchy_2::size_type Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex() { - std::size_t n = 0; + size_type n = 0; for(C_iterator it = constraint_set.begin(); it!= constraint_set.end(); ++it){ n+= remove_points_without_corresponding_vertex(*it); } @@ -694,12 +691,15 @@ Polyline_constraint_hierarchy_2::remove_points_without_correspo template typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::concatenate(Constraint_id first, Constraint_id second) +Polyline_constraint_hierarchy_2::concatenate(Constraint_id constr_a, Constraint_id constr_b) { - constraint_set.erase(first); - constraint_set.erase(second); + // std::cerr << std::format("concatenate({}, {}) ", constr_a.id, constr_b.id) << std::endl; + Vertex_list_ptr constr_a_vl = constr_a.vl_ptr(); + Vertex_list_ptr constr_b_vl = constr_b.vl_ptr(); + constraint_set.erase(constr_a); + constraint_set.erase(constr_b); // We have to look at all subconstraints - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = second.vl_ptr()->skip_end(); + for(Vertex_it it = constr_b_vl->skip_begin(), succ = it, end = constr_b_vl->skip_end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -708,23 +708,23 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == second.vl_ptr()){ - ctit->enclosing = first.vl_ptr(); + if(ctit->enclosing == constr_b){ + ctit->enclosing = constr_a; break; } } } // now we really concatenate the vertex lists - // Note that all iterators pointing into second remain valid. + // Note that all iterators pointing into constr_a remain valid. // This concerns user code, as well as the data member "pos" of the Context class - first.vl_ptr()->pop_back(); // because it is the same as second.front() - Vertex_it back_it = first.vl_ptr()->skip_end(); + constr_a_vl->pop_back(); // because it is the same as constr_b_vl.front() + Vertex_it back_it = constr_a_vl->skip_end(); --back_it; - first.vl_ptr()->splice(first.vl_ptr()->skip_end(), *(second.vl_ptr()), second.vl_ptr()->skip_begin(), second.vl_ptr()->skip_end()); + constr_a_vl->splice(constr_a_vl->skip_end(), *(constr_b_vl), constr_b_vl->skip_begin(), constr_b_vl->skip_end()); - // Note that for VC8 with iterator debugging the iterators pointing into second + // Note that for VC8 with iterator debugging the iterators pointing into constr_b // are NOT valid So we have to update them - for(Vertex_it it = back_it, succ = it, end = first.vl_ptr()->skip_end(); + for(Vertex_it it = back_it, succ = it, end = constr_a_vl->skip_end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -733,26 +733,28 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id firs // and update pos in the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == first.vl_ptr()){ + if(ctit->enclosing == constr_a){ ctit->pos = it; break; } } - } - constraint_set.insert(first); + } + constraint_set.insert(constr_a); - delete second.vl_ptr(); - return first; + delete constr_b_vl; + return constr_a; } template typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::concatenate2(Constraint_id first, Constraint_id second) +Polyline_constraint_hierarchy_2::concatenate2(Constraint_id constr_a, Constraint_id constr_b) { - constraint_set.erase(first); - constraint_set.erase(second); + Vertex_list_ptr constr_a_vl = constr_a.vl_ptr(); + Vertex_list_ptr constr_b_vl = constr_b.vl_ptr(); + constraint_set.erase(constr_a); + constraint_set.erase(constr_b); // We have to look at all subconstraints - for(Vertex_it it = first.vl_ptr()->skip_begin(), succ = it, end = first.vl_ptr()->skip_end(); + for(Vertex_it it = constr_a_vl->skip_begin(), succ = it, end = constr_a_vl->skip_end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -761,22 +763,22 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second.vl_ptr(); + if(ctit->enclosing == constr_a){ + ctit->enclosing = constr_b; break; } } } // now we really concatenate the vertex lists - // Note that all iterators pointing into second remain valid. - first.vl_ptr()->pop_back(); // because it is the same as second.front() - Vertex_it back_it = second.vl_ptr()->skip_begin(); + // Note that all iterators pointing into constr_b remain valid. + constr_a_vl->pop_back(); // because it is the same as constr_b_vl.front() + Vertex_it back_it = constr_b_vl->skip_begin(); - second.vl_ptr()->splice(second.vl_ptr()->skip_begin(), *(first.vl_ptr()), first.vl_ptr()->skip_begin(), first.vl_ptr()->skip_end()); + constr_b_vl->splice(constr_b_vl->skip_begin(), *(constr_a_vl), constr_a_vl->skip_begin(), constr_a_vl->skip_end()); - // Note that for VC8 with iterator debugging the iterators pointing into second + // Note that for VC8 with iterator debugging the iterators pointing into constr_a // are NOT valid So we have to update them - for(Vertex_it it = second.vl_ptr()->skip_begin(), succ = it, end = back_it; + for(Vertex_it it = constr_b_vl->skip_begin(), succ = it, end = back_it; ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -785,16 +787,16 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // and update pos in the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == second.vl_ptr()){ + if(ctit->enclosing == constr_b){ ctit->pos = it; break; } } } - constraint_set.insert(second); + constraint_set.insert(constr_b); - delete first.vl_ptr(); - return second.vl_ptr(); + delete constr_a_vl; + return constr_b; } @@ -803,21 +805,23 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id fir // returns the new constraint template typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::split(Constraint_id first, Vertex_it vcit) +Polyline_constraint_hierarchy_2::split(Constraint_id constr, Vertex_it vcit) { - constraint_set.erase(first); - Vertex_list* second = new Vertex_list; - second->splice(second->skip_end(), *(first.vl_ptr()), vcit.base(), first.vl_ptr()->skip_end()); - first.vl_ptr()->push_back(second->front()); // Duplicate the common vertex - Vertex_it vit = second->skip_begin(); + Constraint_id new_constr = new_constraint_id(); + constraint_set.erase(constr); + Vertex_list_ptr new_vl = new_constr.vl_ptr(); + Vertex_list_ptr constr_vl = constr.vl_ptr(); + new_vl->splice(new_vl->skip_end(), *(constr_vl), vcit.base(), constr_vl->skip_end()); + constr_vl->push_back(new_vl->front()); // Duplicate the common vertex + Vertex_it vit = new_vl->skip_begin(); vit.input() = true; - vit = first.vl_ptr()->skip_end(); + vit = constr_vl->skip_end(); --vit; vit.input() = true; - constraint_set.insert(first); - constraint_set.insert(second); + constraint_set.insert(constr); + constraint_set.insert(new_constr); // We have to look at all subconstraints - for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); + for(Vertex_it it = new_vl->skip_begin(), succ = it, end = new_vl->skip_end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -826,32 +830,34 @@ Polyline_constraint_hierarchy_2::split(Constraint_id first, Ver // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second; + if(ctit->enclosing == constr){ + ctit->enclosing = new_constr; break; } } } - return second; + return new_constr; } template typename Polyline_constraint_hierarchy_2::Constraint_id -Polyline_constraint_hierarchy_2::split2(Constraint_id first, Vertex_it vcit) +Polyline_constraint_hierarchy_2::split2(Constraint_id constr, Vertex_it vcit) { - constraint_set.erase(first); - Vertex_list* second = new Vertex_list; - second->splice(second->skip_end(), *first.vl_ptr(), first.vl_ptr()->skip_begin(), vcit.base()); - second->push_back(first.vl_ptr()->front()); // Duplicate the common vertex - Vertex_it vit = second->skip_end(); + Constraint_id new_constr = new_constraint_id(); + constraint_set.erase(constr); + Vertex_list_ptr new_vl = new_constr.vl_ptr(); + Vertex_list_ptr constr_vl = constr.vl_ptr(); + new_vl->splice(new_vl->skip_end(), *constr_vl, constr_vl->skip_begin(), vcit.base()); + new_vl->push_back(constr_vl->front()); // Duplicate the common vertex + Vertex_it vit = new_vl->skip_end(); --vit; vit.input() = true; - vit = first.vl_ptr()->skip_begin(); + vit = constr_vl->skip_begin(); vit.input() = true; - constraint_set.insert(first); - constraint_set.insert(second); + constraint_set.insert(constr); + constraint_set.insert(new_constr); // We have to look at all subconstraints - for(Vertex_it it = second->skip_begin(), succ = it, end = second->skip_end(); + for(Vertex_it it = new_vl->skip_begin(), succ = it, end = new_vl->skip_end(); ++succ != end; ++it){ typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); @@ -860,13 +866,13 @@ Polyline_constraint_hierarchy_2::split2(Constraint_id first, Ve // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = second; + if(ctit->enclosing == constr){ + ctit->enclosing = new_constr; break; } } } - return second; + return new_constr; } @@ -875,71 +881,40 @@ when a constraint is inserted, it is, at first, both a constraint and a subconstraint */ template -typename Polyline_constraint_hierarchy_2::Vertex_list* +typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2:: insert_constraint(T va, T vb){ - Edge he = make_edge(va, vb); - Vertex_list* children = new Vertex_list; - Context_list* fathers; - #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS using CGAL::IO::oformat; std::cerr << CGAL::internal::cdt_2_indent_level << "C_hierachy.insert_constraint( " << IO::oformat(va) << ", " << IO::oformat(vb) << ")\n"; #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(he); - if(scit == sc_to_c_map.end()){ + Edge he = make_edge(va, vb); + Constraint_id cid = new_constraint_id(); + auto children = cid.vl_ptr(); + auto& fathers = sc_to_c_map[he]; + if(fathers == nullptr){ fathers = new Context_list; - sc_to_c_map.insert(std::make_pair(he,fathers)); - } else { - fathers = scit->second; } children->push_front(Node(va, true)); // was he.first children->push_back(Node(vb, true)); // was he.second - constraint_set.insert(children); + constraint_set.insert(cid); Context ctxt; - ctxt.enclosing = children; - ctxt.pos = children->skip_begin(); + ctxt.enclosing = cid; + ctxt.pos = children->skip_begin(); fathers->push_front(ctxt); - return children; + return cid; } template -typename Polyline_constraint_hierarchy_2::Vertex_list* +typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2:: insert_constraint_old_API(T va, T vb){ - Edge he = make_edge(va, vb); - - Vertex_list* children = new Vertex_list; - Context_list* fathers; - -#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS - using CGAL::IO::oformat; - std::cerr << CGAL::internal::cdt_2_indent_level - << "C_hierachy.insert_constraint_old_API( " - << IO::oformat(va) << ", " << IO::oformat(vb) << ")\n"; -#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(he); - if(scit == sc_to_c_map.end()){ - fathers = new Context_list; - sc_to_c_map.insert(std::make_pair(he,fathers)); - } else { - fathers = scit->second; - } - - children->push_front(Node(va, true)); // was he.first - children->push_back(Node(vb, true)); // was he.second - constraint_set.insert(children); - Context ctxt; - ctxt.enclosing = children; - ctxt.pos = children->skip_begin(); - fathers->push_front(ctxt); - - return children; + return insert_constraint(va, vb); } @@ -947,29 +922,24 @@ template void Polyline_constraint_hierarchy_2:: append_constraint(Constraint_id cid, T va, T vb){ - Edge he = make_edge(va, vb); - Context_list* fathers; - #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS using CGAL::IO::oformat; std::cerr << CGAL::internal::cdt_2_indent_level << "C_hierachy.append_constraint( ..., " << IO::oformat(va) << ", " << IO::oformat(vb) << ")\n"; #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(he); - if(scit == sc_to_c_map.end()){ + Edge he = make_edge(va, vb); + auto& fathers = sc_to_c_map[he]; + if(fathers == nullptr){ fathers = new Context_list; - sc_to_c_map.insert(std::make_pair(he,fathers)); - } else { - fathers = scit->second; } - typename Vertex_list::skip_iterator bit = cid.vl_ptr()->skip_end(); - --bit; + typename Vertex_list::skip_iterator last_pos = std::prev(cid.end()); + CGAL_assertion(last_pos->vertex() == va); cid.vl_ptr()->push_back(Node(vb, true)); Context ctxt; - ctxt.enclosing = cid.vl_ptr(); - ctxt.pos = bit; + ctxt.enclosing = cid; + ctxt.pos = last_pos; fathers->push_front(ctxt); } @@ -978,17 +948,15 @@ template void Polyline_constraint_hierarchy_2:: clear() { - C_iterator cit; - Sc_iterator scit; // clean and delete vertices lists - for(cit=constraint_set.begin(); cit != constraint_set.end(); cit++){ - cit->vl_ptr()->clear(); - delete cit->vl_ptr(); + for(auto cid : constraints()) { + cid.clear(); + delete cid.vl_ptr(); } // clean and delete context lists - for(scit=sc_to_c_map.begin(); scit != sc_to_c_map.end(); scit++){ - (*scit).second->clear(); - delete (*scit).second; + for(auto& [_, cl_ptr] : sc_to_c_map) { + cl_ptr->clear(); + delete cl_ptr; } sc_to_c_map.clear(); constraint_set.clear(); @@ -1004,15 +972,21 @@ next_along_sc(T va, T vb, T& w) const Context_iterator ctxtit, past; if(!get_contexts(va, vb, ctxtit, past)) CGAL_assertion(false); - Vertex_it pos; - for( ; ctxtit != past; ctxtit++){ - pos = ctxtit->pos; - if((*pos)==va) { - ++pos; ++pos; - if (pos != ctxtit->enclosing->end()) { w=(*pos); return true;} - } - else { - if (pos != ctxtit->enclosing->begin()) {--pos; w=(*pos); return true;} + for(; ctxtit != past; ctxtit++) { + Vertex_it pos = ctxtit->pos; + if((*pos) == va) { + ++pos; + ++pos; + if(pos != ctxtit->enclosing.end()) { + w = *pos; + return true; + } + } else { + if(pos != ctxtit->enclosing.begin()) { + --pos; + w = *pos; + return true; + } } } return false; @@ -1040,14 +1014,14 @@ remove_Steiner(T v, T va, T vb) for(Context_iterator ctit=hcl1->begin(); ctit != hcl1->end(); ctit++){ pos = ctit->pos; if((*pos)==va) pos++; - pos = ctit->enclosing->erase(pos); + pos = ctit->enclosing.vl_ptr()->erase(pos); ctit->pos = --pos; } sc_to_c_map.erase(make_edge(va,v)); sc_to_c_map.erase(make_edge(v,vb)); delete hcl2; - sc_to_c_map.insert(std::make_pair(make_edge(va,vb),hcl1)); + sc_to_c_map.emplace(make_edge(va,vb),hcl1); } @@ -1091,7 +1065,7 @@ add_Steiner(T va, T vb, T vc){ // insert vc in enclosing constraint pos = ctit->current(); ++pos; - pos = ctit->enclosing->insert(pos.base(), Node(vc)); + pos = ctit->enclosing.vl_ptr()->insert(pos.base(), Node(vc)); --pos; // set ctxt to the context of (vc,vb) @@ -1114,14 +1088,14 @@ add_Steiner(T va, T vb, T vc){ hcl3->splice(hcl3->end(), *hcl); delete hcl; } - else sc_to_c_map.insert(std::make_pair(make_edge(va,vc), hcl)); + else sc_to_c_map.emplace(make_edge(va,vc), hcl); if (get_contexts(vc,vb,hcl3)) {// (vc,vb) is already a subconstraint hcl3->splice(hcl3->end(),*hcl2); delete hcl2; } - else sc_to_c_map.insert(std::make_pair(make_edge(vc,vb), hcl2)); + else sc_to_c_map.emplace(make_edge(vc,vb), hcl2); sc_to_c_map.erase(make_edge(va,vb)); @@ -1146,7 +1120,7 @@ get_contexts(T va, T vb, Context_list* & hcl) const { Sc_iterator sc_iter = sc_to_c_map.find(make_edge(va,vb)); if( sc_iter == sc_to_c_map.end() ) return(false); - hcl = (*sc_iter).second; + hcl = sc_iter->second; return true; } @@ -1185,9 +1159,9 @@ oriented_end(T va, T vb, T& vc) const Context_iterator ctxt, past; if(!get_contexts(va,vb, ctxt, past) ) CGAL_assertion(false); if(*(ctxt->pos) == va) - vc = ctxt->enclosing->back(); + vc = ctxt->enclosing.back(); else - vc = ctxt->enclosing->front(); + vc = ctxt->enclosing.front(); } @@ -1196,17 +1170,26 @@ void Polyline_constraint_hierarchy_2:: print() const { - C_iterator hcit; - std::map vertex_num; + std::map vertex_num_map; int num = 0; - for(hcit = c_begin(); hcit != c_end(); hcit++) { - Constraint_id cid = (*hcit); - Vertex_it vit =cid.vl_ptr()->skip_begin(), end = cid.vl_ptr()->skip_end(); - for (;vit != end; vit++){ - num ++; - vertex_num.insert(std::make_pair((*vit), num)); + for(const auto& cid : constraints()) { + for (const auto& node : cid.elements()){ + vertex_num_map.emplace(node.vertex(), ++num); } } + + struct Vertex_num { + std::map& vertex_num_map; + int operator[](T v) const { +#ifndef CGAL_CDT_2_DEBUG_INTERSECTIONS + auto it = vertex_num_map.find(v); + if(it == vertex_num_map.end()) return -1; + return it->second; +#else + return v->time_stamp(); +#endif + } + } vertex_num{vertex_num_map}; // typename std::map::iterator vnit = vertex_num.begin(); // for(; vnit != vertex_num.end(); vnit++) { // vnit->second = ++num; @@ -1214,41 +1197,35 @@ print() const // << std::endl; // } - C_iterator cit=c_begin(); - Sc_iterator scit=sc_begin(); - - for(; cit != c_end(); cit++){ - std::cout << std::endl ; - std::cout << "constraint " ; - std::cout << cit->vl_ptr(); - std::cout << " subconstraints " ; - Vertex_it vit = (*cit).vl_ptr()->skip_begin(), end = (*cit).vl_ptr()->skip_end(); - for(; vit != end; vit++){ - std::cout << vertex_num[*vit] <<" "; + for(const auto& cid : constraints()) { + std::cout << std::endl; + std::cout << "constraint(" << cid.id << ") "; + std::cout << cid.vl_ptr(); + std::cout << " subconstraints "; + for(const auto& node : cid.elements()) { + std::cout << vertex_num[node.vertex()] << " "; } - vit = (*cit).vl_ptr()->skip_begin(), end = (*cit).vl_ptr()->skip_end(); - for(; vit != end; vit++){ - std::cout << (*vit)->point() <<" "; + std::cout << ": "; + for(const auto& node : cid.elements()) { + std::cout << node.point() << " "; } } - std::cout << std::endl ; - for(;scit != sc_end(); scit++){ - std::cout << "subconstraint " ; - std::cout << vertex_num[scit->first.first] << " " - << vertex_num[scit->first.second]; + std::cout << std::endl; + for(const auto& [edge, _] : subconstraints()) { + std::cout << "subconstraint "; + std::cout << vertex_num[edge.first] << " " << vertex_num[edge.second]; Context_iterator cb, ce; - get_contexts(scit->first.first, scit->first.second, cb, ce); + get_contexts(edge.first, edge.second, cb, ce); - std::cout << " enclosing " ; + std::cout << " enclosing "; for(; cb != ce; cb++) { - std::cout << cb->id().vl_ptr(); - std::cout << " " ; + std::cout << "(" << cb->id().id << ") " << cb->id().vl_ptr(); + std::cout << " "; } - std::cout << std::endl ; + std::cout << std::endl; } return; } - } //namespace CGAL #endif // CGAL_POLYLINE_CONSTRAINT_HIERARCHY_2_H diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_triang_plus_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_triang_plus_2.h index e2cc92ba8b7..a571a364395 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_triang_plus_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_triang_plus_2.h @@ -81,6 +81,9 @@ _test_cls_const_triang_plus_2( const TrP & ) assert( (*currentin2 == va && *++currentin2 == vb) || (*currentin2 == vb && *++currentin2 == va)); + //test copy of the hierarchy + auto hierarchy = trp.hierarchy_ref(); + //test copy and swap std::cout << "test copy and swap" << std::endl; TrP trp2(trp); @@ -151,7 +154,7 @@ _test_cls_const_triang_plus_2( const TrP & ) std::size_t n = 0; for(Constraint_iterator cit = trp.constraints_begin(); cit != trp.constraints_end(); ++cit){ Constraint_id cid = *cit; - n += cid.second->all_size(); + n += cid.vl_ptr()->all_size(); } assert( n == 9); } From e03ba91f5491522e21edeb25d6dc92abccdb281f Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 10 Jan 2025 22:11:53 +0100 Subject: [PATCH 11/20] Boost >= 1.74 is now required --- .../doc/Documentation/Third_party.txt | 3 +-- .../advanced/Configuration_variables.txt | 21 ------------------- Installation/CHANGES.md | 3 +++ .../cmake/modules/CGAL_SetupBoost.cmake | 5 +++-- .../CGAL_SetupCGAL_CoreDependencies.cmake | 2 +- 5 files changed, 8 insertions(+), 26 deletions(-) diff --git a/Documentation/doc/Documentation/Third_party.txt b/Documentation/doc/Documentation/Third_party.txt index 7875c5791d3..5739b44d85e 100644 --- a/Documentation/doc/Documentation/Third_party.txt +++ b/Documentation/doc/Documentation/Third_party.txt @@ -54,7 +54,7 @@ or `h The \stl comes with the compiler, and as such no installation is required. \subsection thirdpartyBoost Boost -Version 1.72 or later +Version 1.74 or later The \boost libraries are a set of portable C++ source libraries. Most of \boost libraries are header-only, but a few of them need to be compiled or @@ -86,7 +86,6 @@ Version supported are GMP Version 5.0.1 or later, MPFR Version 3.0.0 or later The \boost library also provides a module for multi precision integers and rational numbers: \boost multiprecision. -Versions supported are \boost Version 1.72 or later. The components \cgal, and `CGAL_Qt6` require either \gmp and \mpfr, or \boost multiprecision for multi precision numbers. `CGAL_Core` requires \boost multiprecision. diff --git a/Documentation/doc/Documentation/advanced/Configuration_variables.txt b/Documentation/doc/Documentation/advanced/Configuration_variables.txt index d4ac891a30f..399d3e3ea73 100644 --- a/Documentation/doc/Documentation/advanced/Configuration_variables.txt +++ b/Documentation/doc/Documentation/advanced/Configuration_variables.txt @@ -103,21 +103,11 @@ other but never both. \subsection installation_boost Boost Libraries -\subsubsection inst_boost_1_72_plus Version 1.72 and Later Starting from \boost 1.72, the cmake config mode can be used for configuring the \boost version to use by setting the environment variable `Boost_DIR` to the path containing the file `BoostConfig.cmake`. For example if you manually installed \boost 1.77 with `--prefix=`, then you should set `Boost_DIR=/lib/cmake/Boost-1.77.0`. -\subsubsection inst_boost_up_2_1_69 Version 1.69 and Earlier - -\warning If you have a version of Boost greater than 1.69 already installed on your system, and you want to configure and compile with an earlier version of Boost, then you will need to set the CMake variable `Boost_NO_BOOST_CMAKE` to `ON` (otherwise the `FindBoost.cmake` module of CMake will start searching for `BoostConfig.cmake`, and ignore the `BOOST_ROOT` variable). - -In most cases, if \boost is not automatically found, setting the `BOOST_ROOT` -variable is enough. If it is not, you can specify the header and library -directories individually. You can also provide the full pathname to a specific compiled library -if it cannot be found in the library directory or its name is non-standard. - By default, when \boost binary libraries are needed, the shared versions are used if present. You can set the variable `CGAL_Boost_USE_STATIC_LIBS` to `ON` if you want to link @@ -128,17 +118,6 @@ the `.dll` files are found by the dynamic linker, at run time. For example, you can add the path to the \boost `.dll` to the `PATH` environment variable. -| Variable | Description | Type | -| :- | :- | :- | -| `BOOST_ROOT`\cgalFootnote{The environment variable can be spelled either \cgalFootnoteCode{BOOST_ROOT} or \cgalFootnoteCode{BOOSTROOT}} | Root directory of your \boost installation | Either CMake or Environment | -| `Boost_INCLUDE_DIR` | Directory containing the `boost/version.hpp` file | CMake | -| `BOOST_INCLUDEDIR` | Idem | Environment | -| `Boost_LIBRARY_DIRS` | Directory containing the compiled \boost libraries | CMake | -| `BOOST_LIBRARYDIR` | Idem | Environment | -| `Boost_(xyz)_LIBRARY_RELEASE` | Full pathname to a release build of the compiled 'xyz' \boost library | CMake | -| `Boost_(xyz)_LIBRARY_DEBUG` | Full pathname to a debug build of the compiled 'xyz' \boost library | CMake | - - \subsection installation_gmp GMP and MPFR Libraries Under Windows, auto-linking is used, so only the directory diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 7a159e087bf..291dc13ae41 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -3,6 +3,9 @@ ## [Release 6.1](https://github.com/CGAL/cgal/releases/tag/v6.1) +### General Changes +- The minimal supported version of Boost is now 1.74.0. + ### [Algebraic Kernel](https://doc.cgal.org/6.1/Manual/packages.html#PkgAlgebraicKernelD) - **Breaking change**: Classes based on the RS Library are no longer provided. diff --git a/Installation/cmake/modules/CGAL_SetupBoost.cmake b/Installation/cmake/modules/CGAL_SetupBoost.cmake index ee561027370..bd8a6dfe6f4 100644 --- a/Installation/cmake/modules/CGAL_SetupBoost.cmake +++ b/Installation/cmake/modules/CGAL_SetupBoost.cmake @@ -17,9 +17,10 @@ set ( CGAL_Boost_Setup TRUE ) include(${CMAKE_CURRENT_LIST_DIR}/CGAL_TweakFindBoost.cmake) -find_package( Boost 1.72 REQUIRED ) +cmake_policy(VERSION 3.12...3.30) +find_package( Boost 1.74 REQUIRED ) -if(Boost_FOUND AND Boost_VERSION VERSION_LESS 1.72) +if(Boost_FOUND AND Boost_VERSION VERSION_LESS 1.74) if(DEFINED Boost_DIR AND NOT Boost_DIR) # Unset that cache variable that is set in the cache by FindBoost # (while it was searching for boost-cmake). diff --git a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake index 94d2d839375..710a5d7e579 100644 --- a/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGAL_CoreDependencies.cmake @@ -48,7 +48,7 @@ set_property(GLOBAL PROPERTY CGAL_Core_FOUND TRUE) # function(CGAL_setup_CGAL_Core_dependencies target) - find_package( Boost 1.72 REQUIRED ) + find_package( Boost 1.74 REQUIRED ) if (NOT CGAL_DISABLE_GMP AND GMP_FOUND) use_CGAL_GMP_support(CGAL_Core INTERFACE) endif() From 93ac1845fa7d2d8be71a7aaef1a1db9ef30ff5d1 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Fri, 10 Jan 2025 22:13:58 +0100 Subject: [PATCH 12/20] CDT_plus_2 hierarchy: add Edge_iterator, that is deterministic That uses Boost.STLInterfaces from Boost >= 1.74. --- Mesh_2/include/CGAL/Mesh_2/Refine_edges.h | 22 +-- .../Polyline_constraint_hierarchy_2.h | 125 ++++++++++++++++++ 2 files changed, 126 insertions(+), 21 deletions(-) diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index b2bb3b50b3d..055ae0d7a21 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -344,27 +344,7 @@ class Refine_edges_base : void scan_triangulation_impl(Tag_true) { - // with constraint hierarchy - - // create a vector of pairs of vertex handles, from the subconstraints - // and sort it to ensure the determinism - std::vector> subconstraints_vector(tr.number_of_subconstraints()); - std::transform(tr.subconstraints_begin(), tr.subconstraints_end(), subconstraints_vector.begin(), - [](const auto& sc) { - return std::array{sc.first.first, sc.first.second}; - }); - - auto comp_vh = [&] (Vertex_handle va, Vertex_handle vb) { - return tr.compare_xy(va->point(), vb->point()) == SMALLER; - }; - auto comp_pair_vh = [&] (const auto& e1, const auto& e2) { - return comp_vh(e1[0], e2[0]) || - (!comp_vh(e2[0], e1[0]) && comp_vh(e1[1], e2[1])); - }; - - std::sort(subconstraints_vector.begin(), subconstraints_vector.end(), comp_pair_vh); - - for(const auto& [v1, v2] : subconstraints_vector) + for(const auto& [v1, v2] : tr.hierarchy_ref().edges()) { if(!is_locally_conform(tr, v1, v2) ){ add_constrained_edge_to_be_conformed(v1, v2); diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 761d7f75871..5033898200c 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -22,6 +22,8 @@ #include #include +#include + #include #include #include @@ -212,6 +214,115 @@ class Polyline_constraint_hierarchy_2 typedef typename Sc_to_c_map::const_iterator Sc_iterator; typedef Sc_iterator Subconstraint_iterator; + class Edge_iterator : public boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Edge_iterator, +#endif + std::bidirectional_iterator_tag, + Edge> + { + using base_type = boost::stl_interfaces::proxy_iterator_interface< +#if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS + Edge_iterator, +#endif + std::bidirectional_iterator_tag, + Edge>; + + const Constraint_set* constraint_set = nullptr; + C_iterator constraint_it{}; + Vertex_it vertex_it{}; + + public: + // - The object is singular if and only if `constraint_set==nullptr`. + // + // - The end value is when `constraint_it` is the end iterator of `constraint_set`. + // In that case `vertex_it` must be singular. + // + // - Otherwise all members must be valid pointers or dereferencable iterators. + + bool equal(const Edge_iterator& other) const { + return constraint_set == other.constraint_set && + (constraint_set == nullptr || (constraint_it == other.constraint_it && vertex_it == other.vertex_it)); + } + + Vertex_it first_vertex_it(C_iterator constraint_it) const { + if(constraint_it == constraint_set->end()) { + return Vertex_it(); + } + return constraint_it->begin(); + } + + public: + Edge_iterator() = default; + + // Constructors for begin and end. The constructors are public, but only the + // hierarchy can create an iterator of this class, through its friendship of + // the nested class `Construction_access`: Construction_access::begin_tag() and + // Construction_access::end_tag(). + class Construction_access + { + private: + friend class Edge_iterator; + friend class Polyline_constraint_hierarchy_2; + + static auto begin_tag() { return Begin_tag(); } + static auto end_tag() { return End_tag(); } + + struct Begin_tag + {}; + struct End_tag + {}; + }; + // + // constructor for the begin iterator + explicit Edge_iterator(Construction_access::Begin_tag, const Constraint_set* constraint_set) + : constraint_set(constraint_set) + , constraint_it(constraint_set->begin()) + , vertex_it(first_vertex_it(constraint_set->begin())) {} + // + // constructor for the end iterator + explicit Edge_iterator(Construction_access::End_tag, const Constraint_set* constraint_set) + : constraint_set(constraint_set) + , constraint_it(constraint_set->end()) + , vertex_it() {} + + Edge operator*() const { + CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + CGAL_assertion(vertex_it != constraint_it->end()); + CGAL_assertion(std::next(vertex_it) != constraint_it->end()); + return Edge(*vertex_it, *std::next(vertex_it)); + } + + friend bool operator==(const Edge_iterator& lhs, const Edge_iterator& rhs) { return lhs.equal(rhs); } + + using base_type::operator++; + Edge_iterator& operator++() { + CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + + ++vertex_it; + CGAL_assertion(vertex_it != constraint_it->end()); + + if(std::next(vertex_it) == constraint_it->end()) { + ++constraint_it; + vertex_it = first_vertex_it(constraint_it); + } + return *this; + } + + using base_type::operator--; + Edge_iterator& operator--() { + CGAL_precondition(constraint_set != nullptr); + CGAL_precondition(constraint_it != constraint_set->begin() || vertex_it != constraint_it->begin()); + if(constraint_it == constraint_set->end() || vertex_it == constraint_it->begin()) { + --constraint_it; + vertex_it = std::prev(constraint_it->end(), 2); + } else { + --vertex_it; + } + return *this; + } + }; // end class Edge_iterator + private: // data for the 1d hierarchy Compare comp; @@ -302,6 +413,20 @@ class Polyline_constraint_hierarchy_2 return sc_to_c_map.end(); } + Edge_iterator edges_begin() const { + BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(Edge_iterator, std::bidirectional_iterator); + BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(Edge_iterator, std::bidirectional_iterator_tag, + std::bidirectional_iterator, Edge, Edge, + typename Edge_iterator::pointer, std::ptrdiff_t); + return Edge_iterator(Edge_iterator::Construction_access::begin_tag(), &constraint_set); + } + + Edge_iterator edges_end() const { + return Edge_iterator(Edge_iterator::Construction_access::end_tag(), &constraint_set); + } + + auto edges() const { return Iterator_range(edges_begin(), edges_end()); } + Sc_iterator sc_begin() const{ return sc_to_c_map.begin(); } Sc_iterator sc_end() const{ return sc_to_c_map.end(); } C_iterator c_begin() const{ return constraint_set.begin(); } From d46896266336138d5bf55de9664d09565f311b43 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 13 Jan 2025 10:32:42 +0100 Subject: [PATCH 13/20] hierarchy: remove `remove_Steiner(T v, T va, T vb)` That code was never used nor tested, and cannot compile anyway. --- .../Polyline_constraint_hierarchy_2.h | 35 ------------------- 1 file changed, 35 deletions(-) diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 5033898200c..4580c1f3248 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -399,8 +399,6 @@ class Polyline_constraint_hierarchy_2 Constraint_id split(Constraint_id first, Vertex_it vcit); Constraint_id split2(Constraint_id first, Vertex_it vcit); - void remove_Steiner(T v, T va, T vb); - // iterators Subconstraint_iterator subconstraint_begin() const @@ -1118,39 +1116,6 @@ next_along_sc(T va, T vb, T& w) const } - -/* - Attention, le point v DOIT etre un point de Steiner, - et les segments va,v et v,vb sont des sous contraintes. -*/ -template -void Polyline_constraint_hierarchy_2:: -remove_Steiner(T v, T va, T vb) -{ - // remove a Steiner point - CGAL_precondition(!is_constrained_vertex(v)); - - Context_list* hcl1; - Context_list* hcl2; - if(!get_contexts(va,v,hcl1)) CGAL_assertion(false); - if(!get_contexts(v,vb,hcl2)) CGAL_assertion(false); - - Vertex_it pos; - for(Context_iterator ctit=hcl1->begin(); ctit != hcl1->end(); ctit++){ - pos = ctit->pos; - if((*pos)==va) pos++; - pos = ctit->enclosing.vl_ptr()->erase(pos); - ctit->pos = --pos; - } - - sc_to_c_map.erase(make_edge(va,v)); - sc_to_c_map.erase(make_edge(v,vb)); - delete hcl2; - sc_to_c_map.emplace(make_edge(va,vb),hcl1); -} - - - /* same as add_Steiner precondition : va,vb est une souscontrainte. From 926bb0cf89d02e7d7cfe61237d62c2b822833be0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 13 Jan 2025 10:36:02 +0100 Subject: [PATCH 14/20] hierarchy: remove two undefined member functions --- .../Triangulation_2/internal/Polyline_constraint_hierarchy_2.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 4580c1f3248..81d45f4d89e 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -347,8 +347,6 @@ class Polyline_constraint_hierarchy_2 // Query bool is_subconstrained_edge(T va, T vb) const; - bool is_constrained_edge(T va, T vb) const; - bool is_constrained_vertex(T v) const; Vertex_it vertices_in_constraint_begin(Constraint_id cid) const { return cid.begin(); } From eafa97a862a38318e34a150e131db8db894aa1a0 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Mon, 13 Jan 2025 17:06:58 +0100 Subject: [PATCH 15/20] major cleanup of Polyline_constraint_hierarchy_2 - remove all mentions of `Edge` and `Constraint` - `Subconstraint_iterator` is renamed `Subconstraint_and_contexts_iterator` (because of its value type) - a new `Subconstraint_iterator`, with value type `Subconstraint` - a few unused/untested and uncompilable functions are removed from the code - a lot of internal renamings == Breaking changes == For `Constrained_triangulation_plus_2`, there are a few breaking changes... - The value type of `subconstraints_begin()`, `subconstraints_end()`, of the range `subconstraints()` has changed to `Subconstraint` (a simple `std::pair` of vertex handles). That is actually a kind of bug-fix, because it was documented as such in the user manual. - The new member functions `subconstraints_and_contexts_begin()`, `subconstraints_and_contexts_end()`, `subconstraints_and_contexts()` are created get the old value type (`std::pair*>`). - A few range types have changed from `CGAL::Iterator_range` to `unspecified_type`, for efficiency reasons. - Doc fixes. == Determinism == Even if it was not documented, the range `subconstraints()` is deterministic (used by Mesh_2), and `subconstraints_and_contexts()` is not. --- Mesh_2/include/CGAL/Mesh_2/Clusters.h | 7 +- Mesh_2/include/CGAL/Mesh_2/Refine_edges.h | 2 +- Mesh_2/test/Mesh_2/conform_plus.cpp | 19 +- .../CGAL/Constrained_triangulation_plus_2.h | 46 ++- .../constrained_hierarchy_plus.cpp | 10 +- .../polylines_triangulation.cpp | 7 +- .../CGAL/Constrained_triangulation_plus_2.h | 83 ++++- .../internal/CTP2_subconstraint_graph.h | 107 +++---- .../Polyline_constraint_hierarchy_2.h | 294 +++++++++--------- 9 files changed, 302 insertions(+), 273 deletions(-) diff --git a/Mesh_2/include/CGAL/Mesh_2/Clusters.h b/Mesh_2/include/CGAL/Mesh_2/Clusters.h index f52dcb16d20..13533041f46 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Clusters.h +++ b/Mesh_2/include/CGAL/Mesh_2/Clusters.h @@ -160,15 +160,14 @@ class Clusters void create_clusters(Tag_true) { cluster_map.clear(); Unique_hash_map created(false); - for(typename Tr::Subconstraint_iterator it = tr.subconstraints_begin(); - it != tr.subconstraints_end(); ++it) { - Vertex_handle vh = it->first.first; + for(const auto& sc : tr.subconstraints()) { + Vertex_handle vh = sc.first; if(!created[vh]){ created[vh] = true; create_clusters_of_vertex(vh); } - vh = it->first.second; + vh = sc.second; if(!created[vh]){ created[vh] = true; create_clusters_of_vertex(vh); diff --git a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h index 055ae0d7a21..2208f28fc45 100644 --- a/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h +++ b/Mesh_2/include/CGAL/Mesh_2/Refine_edges.h @@ -344,7 +344,7 @@ class Refine_edges_base : void scan_triangulation_impl(Tag_true) { - for(const auto& [v1, v2] : tr.hierarchy_ref().edges()) + for(const auto& [v1, v2] : tr.subconstraints()) { if(!is_locally_conform(tr, v1, v2) ){ add_constrained_edge_to_be_conformed(v1, v2); diff --git a/Mesh_2/test/Mesh_2/conform_plus.cpp b/Mesh_2/test/Mesh_2/conform_plus.cpp index 83978e3d9ef..6e4128dd68e 100644 --- a/Mesh_2/test/Mesh_2/conform_plus.cpp +++ b/Mesh_2/test/Mesh_2/conform_plus.cpp @@ -18,15 +18,7 @@ int main() std::pair p; - for(CDT::Subconstraint_iterator sit = cdt.subconstraints_begin(); - sit != cdt.subconstraints_end(); - ++sit){ - - p = (*sit).first; - - Vertex_handle vh1 = p.first; - Vertex_handle vh2 = p.second; - + for(const auto& [vh1, vh2] : cdt.subconstraints()) { std::cerr << "subconstraint: " << vh1->point() << " -- " << vh2->point() << std::endl; } @@ -36,15 +28,8 @@ int main() int counter = 0; - for(CDT::Subconstraint_iterator sit = cdt.subconstraints_begin(); - sit != cdt.subconstraints_end(); - ++sit){ + for(const auto& [vh1, vh2] : cdt.subconstraints()) { ++counter; - p = (*sit).first; - - Vertex_handle vh1 = p.first; - Vertex_handle vh2 = p.second; - std::cerr << "subconstraint: " << vh1->point() << " -- " << vh2->point() << std::endl; } diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h index 29d2b48d745..1a5d4b691f0 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h @@ -84,9 +84,10 @@ The value type of this iterator is `Constraint_id`. typedef unspecified_type Constraint_iterator; /*! -A range type for iterating over all constraints. +A range type for iterating over all constraints. The iterator type of +the range is `Constraint_iterator`. */ -typedef Iterator_range Constraints; +typedef unspecified_type Constraints; /*! @@ -95,19 +96,30 @@ A subconstraint is a pair of vertices that correspond to an `Edge`. typedef std::pair Subconstraint; /*! -An iterator -to visit all the subconstraints of the triangulation. +An iterator to visit all the subconstraints of the triangulation. The order of visit is undefined. -The value type of this iterator is `std::pair*>` -corresponding to the vertices of the -subconstraint. +The value type of this iterator is `Subconstraint`. */ typedef unspecified_type Subconstraint_iterator; /*! -A range type for iterating over all subconstraints. +A range type for iterating over all subconstraints. The iterator type of +the range is `Subconstraint_iterator`. */ -typedef Iterator_range Subconstraints; +typedef unspecified_type Subconstraints; + +/*! +An iterator to visit all the subconstraints of the triangulation and the +contexts of their enclosing constraints. The order of visit is undefined. +The value type of this iterator is `std::pair*>`. +*/ +typedef unspecified_type Subconstraint_and_contexts_iterator; + +/*! +A range type for iterating over all subconstraints. The iterator type of +the range is `Subconstraint_and_contexts_iterator`. +*/ +typedef unspecified_type Subconstraints_and_contexts; /*! An iterator on the @@ -381,6 +393,22 @@ returns a range of subconstraints. */ Subconstraints subconstraints() const; +/*! +returns a `Subconstraint_and_contexts_iterator` pointing at the first +subconstraint of the triangulation. +*/ +Subconstraint_and_contexts_iterator subconstraints_and_contexts_begin() const; + +/*! +returns the past-the-end iterator of the subconstraints of the triangulation. +*/ +Subconstraint_and_contexts_iterator subconstraints_and_contexts_end() const; + +/*! +returns a range of subconstraints with the contexts of their enclosing constraints. +*/ +Subconstraints_and_contexts subconstraints_and_contexts() const; + /*! returns the number of constraints enclosing the subconstraint `(va,vb)`. diff --git a/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp b/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp index 950cb022632..b243e152693 100644 --- a/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp +++ b/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp @@ -30,15 +30,15 @@ main( ) cdt.insert_constraint( Point(j,0), Point(j,6)); int count = 0; - for (Triangulation::Subconstraint_iterator scit = cdt.subconstraints_begin(); - scit != cdt.subconstraints_end(); - ++scit) ++count; + for (const Triangulation::Subconstraint& sc : cdt.subconstraints()) { + ++count; + } std::cout << "The number of resulting constrained edges is "; std::cout << count << std::endl; //verbose mode of is_valid ; shows the number of vertices at each level std::cout << "The number of vertices at successive levels" << std::endl; - assert(cdt.is_valid(true)); + bool valid = cdt.is_valid(true); - return 0; + return valid ? 0 : 1; } diff --git a/Triangulation_2/examples/Triangulation_2/polylines_triangulation.cpp b/Triangulation_2/examples/Triangulation_2/polylines_triangulation.cpp index bc00e7071ba..b2b38e93765 100644 --- a/Triangulation_2/examples/Triangulation_2/polylines_triangulation.cpp +++ b/Triangulation_2/examples/Triangulation_2/polylines_triangulation.cpp @@ -28,13 +28,14 @@ print(const CDTP& cdtp, Cid cid) void contexts(const CDTP& cdtp) { - for(auto sc : cdtp.subconstraints()){ - Vertex_handle vp = sc.first.first, vq = sc.first.second; + for(const auto& sc_and_contexts : cdtp.subconstraints_and_contexts()) { + const auto& [subconstraint, contexts_list_ptr] = sc_and_contexts; + Vertex_handle vp = subconstraint.first, vq = subconstraint.second; if(cdtp.number_of_enclosing_constraints(vp, vq) == 2){ std::cout << "subconstraint " << vp->point() << " " << vq->point() << " is on constraints starting at:\n"; - for(const CDTP::Context& c : cdtp.contexts(vp,vq)){ + for(const CDTP::Context& c : *contexts_list_ptr) { std::cout << (*(c.vertices_begin()))->point() << std::endl; } } diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index ac3889c5341..1d4cd0dcbfb 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -165,11 +165,14 @@ class Constrained_triangulation_plus_2 typedef typename Constraint_hierarchy::Context_iterator Context_iterator; typedef Iterator_range Contexts; - typedef typename Constraint_hierarchy::C_iterator Constraint_iterator; - typedef Iterator_range Constraints; + typedef typename Constraint_hierarchy::Constraint_iterator Constraint_iterator; + typedef typename Constraint_hierarchy::Constraints Constraints; - typedef typename Constraint_hierarchy::Subconstraint_iterator Subconstraint_iterator; - typedef Iterator_range Subconstraints; + typedef typename Constraint_hierarchy::Subconstraint_iterator Subconstraint_iterator; + typedef typename Constraint_hierarchy::Subconstraints Subconstraints; + + typedef typename Constraint_hierarchy::Subconstraint_and_contexts_iterator Subconstraint_and_contexts_iterator; + typedef typename Constraint_hierarchy::Subconstraints_and_contexts Subconstraints_and_contexts; typedef typename Constraint_hierarchy::Constraint_id Constraint_id; @@ -768,18 +771,15 @@ class Constrained_triangulation_plus_2 // Query of the constraint hierarchy Constraint_iterator constraints_begin() const; Constraint_iterator constraints_end() const; - Constraints constraints() const - { - return Constraints(constraints_begin(),constraints_end()); - } + Constraints constraints() const; Subconstraint_iterator subconstraints_begin() const; Subconstraint_iterator subconstraints_end() const; + Subconstraints subconstraints() const; - Subconstraints subconstraints() const - { - return Subconstraints(subconstraints_begin(),subconstraints_end()); - } + Subconstraint_and_contexts_iterator subconstraints_and_contexts_begin() const; + Subconstraint_and_contexts_iterator subconstraints_and_contexts_end() const; + Subconstraints_and_contexts subconstraints_and_contexts() const; Context context(Vertex_handle va, Vertex_handle vb); //AF: const; @@ -1266,7 +1266,7 @@ Constrained_triangulation_plus_2::Constraint_iterator Constrained_triangulation_plus_2:: constraints_begin() const { - return hierarchy.c_begin(); + return hierarchy.constraints_begin(); } template @@ -1276,7 +1276,17 @@ Constrained_triangulation_plus_2::Constraint_iterator Constrained_triangulation_plus_2:: constraints_end() const { - return hierarchy.c_end(); + return hierarchy.constraints_end(); +} + +template +inline +typename +Constrained_triangulation_plus_2::Constraints +Constrained_triangulation_plus_2:: +constraints() const +{ + return hierarchy.constraints(); } template @@ -1286,7 +1296,7 @@ Constrained_triangulation_plus_2::Subconstraint_iterator Constrained_triangulation_plus_2:: subconstraints_begin() const { - return hierarchy.subconstraint_begin(); + return hierarchy.subconstraints_begin(); } template @@ -1296,9 +1306,48 @@ Constrained_triangulation_plus_2::Subconstraint_iterator Constrained_triangulation_plus_2:: subconstraints_end() const { - return hierarchy.subconstraint_end(); + return hierarchy.subconstraints_end(); +} + +template +inline +typename +Constrained_triangulation_plus_2::Subconstraints +Constrained_triangulation_plus_2:: +subconstraints() const +{ + return hierarchy.subconstraints(); } +template +inline +typename +Constrained_triangulation_plus_2::Subconstraint_and_contexts_iterator +Constrained_triangulation_plus_2:: +subconstraints_and_contexts_begin() const +{ + return hierarchy.subconstraints_and_contexts_begin(); +} + +template +inline +typename +Constrained_triangulation_plus_2::Subconstraint_and_contexts_iterator +Constrained_triangulation_plus_2:: +subconstraints_and_contexts_end() const +{ + return hierarchy.subconstraints_and_contexts_end(); +} + +template +inline +typename +Constrained_triangulation_plus_2::Subconstraints_and_contexts +Constrained_triangulation_plus_2:: +subconstraints_and_contexts() const +{ + return hierarchy.subconstraints_and_contexts(); +} template inline @@ -1325,7 +1374,7 @@ inline bool Constrained_triangulation_plus_2:: is_subconstraint(Vertex_handle va, Vertex_handle vb) { - return hierarchy.is_subconstrained_edge(va,vb); + return hierarchy.is_subconstraint(va,vb); } diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/CTP2_subconstraint_graph.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/CTP2_subconstraint_graph.h index 5eab13d4c1e..e85eb22fa19 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/CTP2_subconstraint_graph.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/CTP2_subconstraint_graph.h @@ -1,4 +1,4 @@ -// Copyright (c) 2020 GeometryFactory (France). All rights reserved. +// Copyright (c) 2020,2025 GeometryFactory (France). All rights reserved. // // This file is part of CGAL (www.cgal.org) // @@ -17,8 +17,6 @@ #include #include -#include - namespace CGAL { @@ -30,90 +28,71 @@ class CTP2_subconstraint_graph { CTP2& ctp2; public: - - typedef typename CTP2::Vertex_handle vertex_descriptor; - typedef typename CTP2::Subconstraint edge_descriptor; - typedef boost::undirected_tag directed_category; - typedef boost::disallow_parallel_edge_tag edge_parallel_category; - struct CTP2_graph_traversal_category : - public virtual boost::bidirectional_graph_tag, - public virtual boost::adjacency_graph_tag, - public virtual boost::edge_list_graph_tag, - public virtual boost::vertex_list_graph_tag - { }; - typedef CTP2_graph_traversal_category traversal_category; - typedef internal::Dereference_to_handle_enforcer< - CTP2, - typename CTP2::Finite_vertices_iterator, - vertex_descriptor> vertex_iterator; - - typedef typename CTP2::Subconstraint_iterator::value_type Subconstr_it_v_t; - typedef First_of_pair_property_map Subconstr_map; - typedef Property_map_to_unary_function Subconstr_uf; - typedef boost::transform_iterator edge_iterator; - - CTP2_subconstraint_graph (CTP2& ctp2) : ctp2(ctp2) { } - - friend Iterator_range vertices (const CTP2_subconstraint_graph& g) - { - return make_range (vertex_iterator(g.ctp2.finite_vertices_begin()), - vertex_iterator(g.ctp2.finite_vertices_end())); + using vertex_descriptor = typename CTP2::Vertex_handle; + using edge_descriptor = typename CTP2::Subconstraint; + using directed_category = boost::undirected_tag; + using edge_parallel_category = boost::disallow_parallel_edge_tag; + struct CTP2_graph_traversal_category : public virtual boost::bidirectional_graph_tag, + public virtual boost::adjacency_graph_tag, + public virtual boost::edge_list_graph_tag, + public virtual boost::vertex_list_graph_tag + {}; + using traversal_category = CTP2_graph_traversal_category; + using vertex_iterator = + internal::Dereference_to_handle_enforcer; + + using edge_iterator = typename CTP2::Subconstraint_iterator; + + CTP2_subconstraint_graph(CTP2& ctp2) + : ctp2(ctp2) {} + + friend Iterator_range vertices(const CTP2_subconstraint_graph& g) { + return make_range(vertex_iterator(g.ctp2.finite_vertices_begin()), vertex_iterator(g.ctp2.finite_vertices_end())); } - friend Iterator_range edges (const CTP2_subconstraint_graph& g) - { - return make_range (boost::make_transform_iterator(g.ctp2.subconstraints_begin(), Subconstr_uf(Subconstr_map())), - boost::make_transform_iterator(g.ctp2.subconstraints_end(), Subconstr_uf(Subconstr_map()))); + friend Iterator_range edges(const CTP2_subconstraint_graph& g) { + return g.ctp2.subconstraints(); } - friend vertex_descriptor source (edge_descriptor ed, const CTP2_subconstraint_graph&) - { - return ed.first; - } + friend vertex_descriptor source(edge_descriptor ed, const CTP2_subconstraint_graph&) { return ed.first; } - friend vertex_descriptor target (edge_descriptor ed, const CTP2_subconstraint_graph&) - { - return ed.second; - } + friend vertex_descriptor target(edge_descriptor ed, const CTP2_subconstraint_graph&) { return ed.second; } }; - template class CTP2_graph_visitor { private: + using Constraint_id = typename CTP2::Constraint_id; + using Vertex_handle = typename CTP2::Vertex_handle; CTP2& ctp2; - std::vector to_remove; - typename CTP2::Constraint_id current; - typename CTP2::Vertex_handle latest_vertex; + std::vector to_remove; + Constraint_id current{}; + Vertex_handle latest_vertex{}; public: + CTP2_graph_visitor(CTP2& ctp2) + : ctp2(ctp2) {} - CTP2_graph_visitor (CTP2& ctp2) : ctp2 (ctp2) { } - - void start_new_polyline() - { - latest_vertex = typename CTP2::Vertex_handle(); - current = typename CTP2::Constraint_id(); + void start_new_polyline() { + latest_vertex = Vertex_handle(); + current = Constraint_id(); } - void add_node (typename CTP2::Vertex_handle vh) - { - if (latest_vertex != typename CTP2::Vertex_handle()) - { - to_remove.push_back (ctp2.context(latest_vertex, vh).id()); - typename CTP2::Constraint_id cid = ctp2.insert_constraint(latest_vertex, vh); - if (current == typename CTP2::Constraint_id()) + void add_node(Vertex_handle vh) { + if(latest_vertex != Vertex_handle()) { + to_remove.push_back(ctp2.context(latest_vertex, vh).id()); + Constraint_id cid = ctp2.insert_constraint(latest_vertex, vh); + if(current == Constraint_id()) current = cid; else - current = ctp2.concatenate (current, cid); + current = ctp2.concatenate(current, cid); } latest_vertex = vh; } - void end_polyline() - { - for (typename CTP2::Constraint_id id : to_remove) + void end_polyline() { + for(Constraint_id id : to_remove) ctp2.remove_constraint(id); to_remove.clear(); } diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 81d45f4d89e..8a6f32ba81f 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -45,8 +45,6 @@ class Polyline_constraint_hierarchy_2 { public: typedef T Vertex_handle; - typedef std::pair Edge; - typedef std::pair Constraint; typedef std::pair Subconstraint; using size_type = std::size_t; @@ -125,9 +123,10 @@ class Polyline_constraint_hierarchy_2 Vertex_list_ptr vl_ptr() const { return vl; } - operator std::pair() const{ - Edge edge = vl == nullptr ? Edge() : Edge(vl->front().vertex(), vl->back().vertex()); - return std::make_pair(edge, vl); + operator std::pair() const { + Subconstraint subconstraint = + vl == nullptr ? Subconstraint() : Subconstraint(vl->front().vertex(), vl->back().vertex()); + return { subconstraint, vl }; } Constraint_id& operator=(std::nullptr_t) { @@ -173,11 +172,11 @@ class Polyline_constraint_hierarchy_2 public: Pair_compare(const Compare& comp) : comp(comp) {} - bool operator()(const Edge& e1, const Edge& e2) const { - if(comp(e1.first, e2.first)) { + bool operator()(const Subconstraint& sc1, const Subconstraint& sc2) const { + if(comp(sc1.first, sc2.first)) { return true; - } else if((! comp(e2.first, e1.first)) && // !less(e1,e2) && !less(e2,e1) == equal - comp(e1.second, e2.second)) { + } else if((! comp(sc2.first, sc1.first)) && // !less(sc1,sc2) && !less(sc2,sc1) == equal + comp(sc1.second, sc2.second)) { return true; } else { return false; @@ -203,57 +202,61 @@ class Polyline_constraint_hierarchy_2 typedef std::list Context_list; typedef typename Context_list::iterator Context_iterator; - typedef std::set Constraint_set; + typedef std::set Constraints_set; #if CGAL_USE_BARE_STD_MAP - typedef std::map Sc_to_c_map; #else - typedef CGAL::unordered_flat_map> Sc_to_c_map; + typedef CGAL::unordered_flat_map> Sc_to_c_map; #endif - typedef typename Constraint_set::iterator C_iterator; + typedef typename Constraints_set::iterator Constraint_iterator; + typedef const Constraints_set& Constraints; typedef typename Sc_to_c_map::const_iterator Sc_iterator; - typedef Sc_iterator Subconstraint_iterator; + typedef Sc_iterator Subconstraint_and_contexts_iterator; + typedef const Sc_to_c_map& Subconstraints_and_contexts; - class Edge_iterator : public boost::stl_interfaces::proxy_iterator_interface< + class Subconstraint_iterator : public boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS - Edge_iterator, + Subconstraint_iterator, #endif std::bidirectional_iterator_tag, - Edge> + Subconstraint> { using base_type = boost::stl_interfaces::proxy_iterator_interface< #if !BOOST_STL_INTERFACES_USE_DEDUCED_THIS - Edge_iterator, + Subconstraint_iterator, #endif std::bidirectional_iterator_tag, - Edge>; + Subconstraint>; - const Constraint_set* constraint_set = nullptr; - C_iterator constraint_it{}; + const Constraints_set* constraints_set = nullptr; + Constraint_iterator constraint_it{}; Vertex_it vertex_it{}; public: - // - The object is singular if and only if `constraint_set==nullptr`. + // - The object is singular if and only if `constraints_set==nullptr`. // - // - The end value is when `constraint_it` is the end iterator of `constraint_set`. + // - The end value is when `constraint_it` is the end iterator of `constraints_set`. // In that case `vertex_it` must be singular. // // - Otherwise all members must be valid pointers or dereferencable iterators. - bool equal(const Edge_iterator& other) const { - return constraint_set == other.constraint_set && - (constraint_set == nullptr || (constraint_it == other.constraint_it && vertex_it == other.vertex_it)); + bool equal(const Subconstraint_iterator& other) const { + return constraints_set == other.constraints_set && + (constraints_set == nullptr || (constraint_it == other.constraint_it && + vertex_it == other.vertex_it)); } - Vertex_it first_vertex_it(C_iterator constraint_it) const { - if(constraint_it == constraint_set->end()) { + Vertex_it begin_or_null(Constraint_iterator constraint_it) const { + if(constraint_it == constraints_set->end()) { return Vertex_it(); } return constraint_it->begin(); } public: - Edge_iterator() = default; + Subconstraint_iterator() = default; // Constructors for begin and end. The constructors are public, but only the // hierarchy can create an iterator of this class, through its friendship of @@ -262,7 +265,7 @@ class Polyline_constraint_hierarchy_2 class Construction_access { private: - friend class Edge_iterator; + friend class Subconstraint_iterator; friend class Polyline_constraint_hierarchy_2; static auto begin_tag() { return Begin_tag(); } @@ -275,45 +278,49 @@ class Polyline_constraint_hierarchy_2 }; // // constructor for the begin iterator - explicit Edge_iterator(Construction_access::Begin_tag, const Constraint_set* constraint_set) - : constraint_set(constraint_set) - , constraint_it(constraint_set->begin()) - , vertex_it(first_vertex_it(constraint_set->begin())) {} + explicit Subconstraint_iterator(typename Construction_access::Begin_tag, + const Constraints_set* constraints_set) + : constraints_set(constraints_set) + , constraint_it(constraints_set->begin()) + , vertex_it(begin_or_null(constraints_set->begin())) {} // // constructor for the end iterator - explicit Edge_iterator(Construction_access::End_tag, const Constraint_set* constraint_set) - : constraint_set(constraint_set) - , constraint_it(constraint_set->end()) + explicit Subconstraint_iterator(typename Construction_access::End_tag, + const Constraints_set* constraints_set) + : constraints_set(constraints_set) + , constraint_it(constraints_set->end()) , vertex_it() {} - Edge operator*() const { - CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + Subconstraint operator*() const { + CGAL_precondition(constraints_set != nullptr && constraint_it != constraints_set->end()); CGAL_assertion(vertex_it != constraint_it->end()); CGAL_assertion(std::next(vertex_it) != constraint_it->end()); - return Edge(*vertex_it, *std::next(vertex_it)); + return Subconstraint(*vertex_it, *std::next(vertex_it)); } - friend bool operator==(const Edge_iterator& lhs, const Edge_iterator& rhs) { return lhs.equal(rhs); } + friend bool operator==(const Subconstraint_iterator& lhs, const Subconstraint_iterator& rhs) { + return lhs.equal(rhs); + } using base_type::operator++; - Edge_iterator& operator++() { - CGAL_precondition(constraint_set != nullptr && constraint_it != constraint_set->end()); + Subconstraint_iterator& operator++() { + CGAL_precondition(constraints_set != nullptr && constraint_it != constraints_set->end()); ++vertex_it; CGAL_assertion(vertex_it != constraint_it->end()); if(std::next(vertex_it) == constraint_it->end()) { ++constraint_it; - vertex_it = first_vertex_it(constraint_it); + vertex_it = begin_or_null(constraint_it); } return *this; } using base_type::operator--; - Edge_iterator& operator--() { - CGAL_precondition(constraint_set != nullptr); - CGAL_precondition(constraint_it != constraint_set->begin() || vertex_it != constraint_it->begin()); - if(constraint_it == constraint_set->end() || vertex_it == constraint_it->begin()) { + Subconstraint_iterator& operator--() { + CGAL_precondition(constraints_set != nullptr); + CGAL_precondition(constraint_it != constraints_set->begin() || vertex_it != constraint_it->begin()); + if(constraint_it == constraints_set->end() || vertex_it == constraint_it->begin()) { --constraint_it; vertex_it = std::prev(constraint_it->end(), 2); } else { @@ -321,12 +328,12 @@ class Polyline_constraint_hierarchy_2 } return *this; } - }; // end class Edge_iterator + }; // end class Subconstraint_iterator + typedef Iterator_range Subconstraints; private: - // data for the 1d hierarchy Compare comp; - Constraint_set constraint_set; + Constraints_set constraints_set; Sc_to_c_map sc_to_c_map; public: @@ -346,7 +353,7 @@ class Polyline_constraint_hierarchy_2 Polyline_constraint_hierarchy_2& operator=(Polyline_constraint_hierarchy_2&& ch) = default; // Query - bool is_subconstrained_edge(T va, T vb) const; + bool is_subconstraint(T va, T vb) const; Vertex_it vertices_in_constraint_begin(Constraint_id cid) const { return cid.begin(); } @@ -361,7 +368,6 @@ class Polyline_constraint_hierarchy_2 Point_it points_in_constraint_end(Constraint_id cid) const { return cid.vl_ptr()->all_end(); } - bool enclosing_constraint(Edge he, Constraint& hc) const; bool enclosing_constraint(T vaa, T vbb, T& va, T& vb) const; bool next_along_sc(T va, T vb, T& w) const; void oriented_end(T va, T vb, T& vc) const; @@ -371,7 +377,7 @@ class Polyline_constraint_hierarchy_2 Context_iterator contexts_begin(T va, T vb) const; Context_iterator contexts_end(T va, T vb) const; Iterator_range contexts_range(T va, T vb) const; - size_type number_of_constraints() const { return constraint_set.size();} + size_type number_of_constraints() const { return constraints_set.size();} size_type number_of_subconstraints()const {return sc_to_c_map.size();} @@ -399,39 +405,41 @@ class Polyline_constraint_hierarchy_2 // iterators - Subconstraint_iterator subconstraint_begin() const + Subconstraint_and_contexts_iterator subconstraints_and_contexts_begin() const { return sc_to_c_map.begin(); } - Subconstraint_iterator subconstraint_end() const + Subconstraint_and_contexts_iterator subconstraints_and_contexts_end() const { return sc_to_c_map.end(); } - Edge_iterator edges_begin() const { - BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(Edge_iterator, std::bidirectional_iterator); - BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS(Edge_iterator, std::bidirectional_iterator_tag, - std::bidirectional_iterator, Edge, Edge, - typename Edge_iterator::pointer, std::ptrdiff_t); - return Edge_iterator(Edge_iterator::Construction_access::begin_tag(), &constraint_set); + Subconstraint_iterator subconstraints_begin() const { + BOOST_STL_INTERFACES_STATIC_ASSERT_CONCEPT(Subconstraint_iterator, std::bidirectional_iterator); + BOOST_STL_INTERFACES_STATIC_ASSERT_ITERATOR_TRAITS( + Subconstraint_iterator, std::bidirectional_iterator_tag, std::bidirectional_iterator, + Subconstraint, Subconstraint, typename Subconstraint_iterator::pointer, std::ptrdiff_t); + return Subconstraint_iterator(Subconstraint_iterator::Construction_access::begin_tag(), + &constraints_set); } - Edge_iterator edges_end() const { - return Edge_iterator(Edge_iterator::Construction_access::end_tag(), &constraint_set); + Subconstraint_iterator subconstraints_end() const { + return Subconstraint_iterator(Subconstraint_iterator::Construction_access::end_tag(), + &constraints_set); } - auto edges() const { return Iterator_range(edges_begin(), edges_end()); } - Sc_iterator sc_begin() const{ return sc_to_c_map.begin(); } Sc_iterator sc_end() const{ return sc_to_c_map.end(); } - C_iterator c_begin() const{ return constraint_set.begin(); } - C_iterator c_end() const{ return constraint_set.end(); } + Constraint_iterator constraints_begin() const{ return constraints_set.begin(); } + Constraint_iterator constraints_end() const{ return constraints_set.end(); } // Ranges - auto constraints() const { return Iterator_range(c_begin(), c_end()); } - const auto & subconstraints() const { return sc_to_c_map; } - + const auto& constraints() const { return constraints_set; } + const auto& subconstraints_and_contexts() const { return sc_to_c_map; } + auto subconstraints() const { + return Iterator_range(subconstraints_begin(), subconstraints_end()); + } // Helper functions void copy(const Polyline_constraint_hierarchy_2& ch); @@ -440,11 +448,13 @@ class Polyline_constraint_hierarchy_2 private: Constraint_id new_constraint_id() const { - auto id = number_of_constraints() == 0 ? 0 : constraint_set.rbegin()->id + 1; + auto id = number_of_constraints() == 0 ? 0 : constraints_set.rbegin()->id + 1; return Constraint_id(new Vertex_list, id); } - Edge make_edge(T va, T vb) const; - Edge make_edge(Edge e) { const auto& [va, vb] = e; return make_edge(va, vb); } + Subconstraint sorted_pair(T va, T vb) const; + Subconstraint sorted_pair(Subconstraint sc) { + const auto& [va, vb] = sc; return sorted_pair(va, vb); + } Vertex_it get_pos(T va, T vb) const; bool get_contexts(T va, T vb, Context_iterator& ctxt, @@ -498,22 +508,22 @@ copy(const Polyline_constraint_hierarchy_2& other, std::map cstr_map; clear(); - // copy constraint_set + // copy constraints_set for(const auto& cid1: other.constraints()) { Constraint_id cid2 = new_constraint_id(); cstr_map[cid1] = cid2; for(const auto& node : cid1.elements()) { cid2.vl_ptr()->push_back(Node(vmap[node.vertex()], node.input())); } - constraint_set.insert(cid2); + constraints_set.insert(cid2); } // copy sc_to_c_map - for(const auto& [edge1, hcl1] : other.subconstraints()) { + for(const auto& [sc1, hcl1] : other.subconstraints_and_contexts()) { Context_list* hcl2 = new Context_list; - Vertex_handle uu2 = vmap[edge1.first]; - Vertex_handle vv2 = vmap[edge1.second]; - Edge edge2 = make_edge(uu2, vv2); - sc_to_c_map[edge2] = hcl2; + Vertex_handle uu2 = vmap[sc1.first]; + Vertex_handle vv2 = vmap[sc1.second]; + Subconstraint sc2 = sorted_pair(uu2, vv2); + sc_to_c_map[sc2] = hcl2; for(const Context& ctxt1 : *hcl1) { // vertices of the enclosing constraints Context ctxt2; @@ -540,37 +550,16 @@ swap(Polyline_constraint_hierarchy_2& ch) { using std::swap; swap(comp, ch.comp); - constraint_set.swap(ch.constraint_set); + constraints_set.swap(ch.constraints_set); sc_to_c_map.swap(ch.sc_to_c_map); } -/* template bool Polyline_constraint_hierarchy_2:: -is_constrained_edge(T va, T vb) const +is_subconstraint(T va, T vb) const { - return( c_to_sc_map.find(make_edge(va, vb)) != c_to_sc_map.end() ); -} -*/ - -template -bool Polyline_constraint_hierarchy_2:: -is_subconstrained_edge(T va, T vb) const -{ - return( sc_to_c_map.find(make_edge(va, vb)) != sc_to_c_map.end() ); -} - - -// af: obsolete -template -bool Polyline_constraint_hierarchy_2:: -enclosing_constraint(Edge he, Constraint& hc) const -{ - Context_iterator hcit, past; - if ( !get_contexts(he.first,he.second, hcit ,past)) return false; - hc = make_edge(hcit->enclosing.front(), hcit->enclosing.back()); - return true; + return( sc_to_c_map.find(sorted_pair(va, vb)) != sc_to_c_map.end() ); } @@ -659,7 +648,7 @@ swap(Constraint_id constr_a, Constraint_id constr_b) { auto substitute_enclosing_in_vertex_list = [this](Vertex_list_ptr vl, Constraint_id old_id, Constraint_id new_id) { // We have to look at all subconstraints for(Vertex_it it = vl->skip_begin(), succ = it, end = vl->skip_end(); ++succ != end; ++it) { - typename Sc_to_c_map::iterator scit = this->sc_to_c_map.find(make_edge(*it, *succ)); + typename Sc_to_c_map::iterator scit = this->sc_to_c_map.find(sorted_pair(*it, *succ)); CGAL_assertion(scit != this->sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -687,13 +676,13 @@ template void Polyline_constraint_hierarchy_2:: remove_constraint(Constraint_id cid){ - constraint_set.erase(cid); + constraints_set.erase(cid); // We have to look at all subconstraints for(Vertex_it it = cid.begin(), succ = it, end = cid.end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -722,14 +711,13 @@ remove_constraint(Constraint_id cid){ // and for the case that the constrained edge u,w has no intersections template void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, - Vertex_it vc, - Vertex_it wc) - + Vertex_it vc, + Vertex_it wc) { // TODO: How do we (want to) deal with u == w ??? Vertex_handle u = *uc, v = *vc, w = *wc; - typename Sc_to_c_map::iterator uv_sc_iter = sc_to_c_map.find(make_edge(u, v)); - typename Sc_to_c_map::iterator vw_sc_iter = sc_to_c_map.find(make_edge(v, w)); + typename Sc_to_c_map::iterator uv_sc_iter = sc_to_c_map.find(sorted_pair(u, v)); + typename Sc_to_c_map::iterator vw_sc_iter = sc_to_c_map.find(sorted_pair(v, w)); Context_list* uv_hcl = uv_sc_iter->second; Context_list* vw_hcl = vw_sc_iter->second; // AF: what is input() about??? @@ -777,7 +765,7 @@ void Polyline_constraint_hierarchy_2::simplify(Vertex_it uc, sc_to_c_map.erase(vw_sc_iter); // reuse other context list - sc_to_c_map[make_edge(u,w)] = uv_hcl; + sc_to_c_map[sorted_pair(u,w)] = uv_hcl; } @@ -803,8 +791,8 @@ typename Polyline_constraint_hierarchy_2::size_type Polyline_constraint_hierarchy_2::remove_points_without_corresponding_vertex() { size_type n = 0; - for(C_iterator it = constraint_set.begin(); it!= constraint_set.end(); ++it){ - n+= remove_points_without_corresponding_vertex(*it); + for(const auto& cid : constraints_set){ + n+= remove_points_without_corresponding_vertex(cid); } return n; } @@ -817,13 +805,13 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id cons // std::cerr << std::format("concatenate({}, {}) ", constr_a.id, constr_b.id) << std::endl; Vertex_list_ptr constr_a_vl = constr_a.vl_ptr(); Vertex_list_ptr constr_b_vl = constr_b.vl_ptr(); - constraint_set.erase(constr_a); - constraint_set.erase(constr_b); + constraints_set.erase(constr_a); + constraints_set.erase(constr_b); // We have to look at all subconstraints for(Vertex_it it = constr_b_vl->skip_begin(), succ = it, end = constr_b_vl->skip_end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -848,7 +836,7 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id cons for(Vertex_it it = back_it, succ = it, end = constr_a_vl->skip_end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -860,7 +848,7 @@ Polyline_constraint_hierarchy_2::concatenate(Constraint_id cons } } } - constraint_set.insert(constr_a); + constraints_set.insert(constr_a); delete constr_b_vl; return constr_a; @@ -872,13 +860,13 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id con { Vertex_list_ptr constr_a_vl = constr_a.vl_ptr(); Vertex_list_ptr constr_b_vl = constr_b.vl_ptr(); - constraint_set.erase(constr_a); - constraint_set.erase(constr_b); + constraints_set.erase(constr_a); + constraints_set.erase(constr_b); // We have to look at all subconstraints for(Vertex_it it = constr_a_vl->skip_begin(), succ = it, end = constr_a_vl->skip_end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -902,7 +890,7 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id con for(Vertex_it it = constr_b_vl->skip_begin(), succ = it, end = back_it; ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -914,7 +902,7 @@ Polyline_constraint_hierarchy_2::concatenate2(Constraint_id con } } } - constraint_set.insert(constr_b); + constraints_set.insert(constr_b); delete constr_a_vl; return constr_b; @@ -929,7 +917,7 @@ typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2::split(Constraint_id constr, Vertex_it vcit) { Constraint_id new_constr = new_constraint_id(); - constraint_set.erase(constr); + constraints_set.erase(constr); Vertex_list_ptr new_vl = new_constr.vl_ptr(); Vertex_list_ptr constr_vl = constr.vl_ptr(); new_vl->splice(new_vl->skip_end(), *(constr_vl), vcit.base(), constr_vl->skip_end()); @@ -939,13 +927,13 @@ Polyline_constraint_hierarchy_2::split(Constraint_id constr, Ve vit = constr_vl->skip_end(); --vit; vit.input() = true; - constraint_set.insert(constr); - constraint_set.insert(new_constr); + constraints_set.insert(constr); + constraints_set.insert(new_constr); // We have to look at all subconstraints for(Vertex_it it = new_vl->skip_begin(), succ = it, end = new_vl->skip_end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -965,7 +953,7 @@ typename Polyline_constraint_hierarchy_2::Constraint_id Polyline_constraint_hierarchy_2::split2(Constraint_id constr, Vertex_it vcit) { Constraint_id new_constr = new_constraint_id(); - constraint_set.erase(constr); + constraints_set.erase(constr); Vertex_list_ptr new_vl = new_constr.vl_ptr(); Vertex_list_ptr constr_vl = constr.vl_ptr(); new_vl->splice(new_vl->skip_end(), *constr_vl, constr_vl->skip_begin(), vcit.base()); @@ -975,13 +963,13 @@ Polyline_constraint_hierarchy_2::split2(Constraint_id constr, V vit.input() = true; vit = constr_vl->skip_begin(); vit.input() = true; - constraint_set.insert(constr); - constraint_set.insert(new_constr); + constraints_set.insert(constr); + constraints_set.insert(new_constr); // We have to look at all subconstraints for(Vertex_it it = new_vl->skip_begin(), succ = it, end = new_vl->skip_end(); ++succ != end; ++it){ - typename Sc_to_c_map::iterator scit = sc_to_c_map.find(make_edge(*it,*succ)); + typename Sc_to_c_map::iterator scit = sc_to_c_map.find(sorted_pair(*it,*succ)); CGAL_assertion(scit != sc_to_c_map.end()); Context_list* hcl = scit->second; @@ -1011,17 +999,17 @@ insert_constraint(T va, T vb){ << "C_hierachy.insert_constraint( " << IO::oformat(va) << ", " << IO::oformat(vb) << ")\n"; #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - Edge he = make_edge(va, vb); + Subconstraint sc = sorted_pair(va, vb); Constraint_id cid = new_constraint_id(); auto children = cid.vl_ptr(); - auto& fathers = sc_to_c_map[he]; + auto& fathers = sc_to_c_map[sc]; if(fathers == nullptr){ fathers = new Context_list; } - children->push_front(Node(va, true)); // was he.first - children->push_back(Node(vb, true)); // was he.second - constraint_set.insert(cid); + children->push_front(Node(va, true)); // was sc.first + children->push_back(Node(vb, true)); // was sc.second + constraints_set.insert(cid); Context ctxt; ctxt.enclosing = cid; ctxt.pos = children->skip_begin(); @@ -1049,8 +1037,8 @@ append_constraint(Constraint_id cid, T va, T vb){ << "C_hierachy.append_constraint( ..., " << IO::oformat(va) << ", " << IO::oformat(vb) << ")\n"; #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - Edge he = make_edge(va, vb); - auto& fathers = sc_to_c_map[he]; + Subconstraint sc = sorted_pair(va, vb); + auto& fathers = sc_to_c_map[sc]; if(fathers == nullptr){ fathers = new Context_list; } @@ -1080,7 +1068,7 @@ clear() delete cl_ptr; } sc_to_c_map.clear(); - constraint_set.clear(); + constraints_set.clear(); } @@ -1176,28 +1164,28 @@ add_Steiner(T va, T vb, T vc){ hcl3->splice(hcl3->end(), *hcl); delete hcl; } - else sc_to_c_map.emplace(make_edge(va,vc), hcl); + else sc_to_c_map.emplace(sorted_pair(va,vc), hcl); if (get_contexts(vc,vb,hcl3)) {// (vc,vb) is already a subconstraint hcl3->splice(hcl3->end(),*hcl2); delete hcl2; } - else sc_to_c_map.emplace(make_edge(vc,vb), hcl2); + else sc_to_c_map.emplace(sorted_pair(vc,vb), hcl2); - sc_to_c_map.erase(make_edge(va,vb)); + sc_to_c_map.erase(sorted_pair(va,vb)); return; } template inline -typename Polyline_constraint_hierarchy_2::Edge +typename Polyline_constraint_hierarchy_2::Subconstraint Polyline_constraint_hierarchy_2:: -make_edge(T va, T vb) const +sorted_pair(T va, T vb) const { - return comp(va, vb) ? Edge(va,vb) : Edge(vb,va); + return comp(va, vb) ? Subconstraint(va,vb) : Subconstraint(vb,va); } template @@ -1206,7 +1194,7 @@ bool Polyline_constraint_hierarchy_2:: get_contexts(T va, T vb, Context_list* & hcl) const { - Sc_iterator sc_iter = sc_to_c_map.find(make_edge(va,vb)); + Sc_iterator sc_iter = sc_to_c_map.find(sorted_pair(va,vb)); if( sc_iter == sc_to_c_map.end() ) return(false); hcl = sc_iter->second; return true; @@ -1236,7 +1224,7 @@ Polyline_constraint_hierarchy_2:: get_pos(T va, T vb) const //return pos in the first context { - return (*sc_to_c_map.find(make_edge(va,vb))).second->begin().pos; + return (*sc_to_c_map.find(sorted_pair(va,vb))).second->begin().pos; } template @@ -1299,11 +1287,11 @@ print() const } } std::cout << std::endl; - for(const auto& [edge, _] : subconstraints()) { + for(const auto& subconstraint : subconstraints()) { std::cout << "subconstraint "; - std::cout << vertex_num[edge.first] << " " << vertex_num[edge.second]; + std::cout << vertex_num[subconstraint.first] << " " << vertex_num[subconstraint.second]; Context_iterator cb, ce; - get_contexts(edge.first, edge.second, cb, ce); + get_contexts(subconstraint.first, subconstraint.second, cb, ce); std::cout << " enclosing "; for(; cb != ce; cb++) { From 1f70e59210cf5cd463dbfaeaf6dd4e32edc4dc42 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 14 Jan 2025 14:11:08 +0100 Subject: [PATCH 16/20] doc bug-fix --- .../doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h index 1a5d4b691f0..34aee28ad9c 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h @@ -111,7 +111,7 @@ typedef unspecified_type Subconstraints; /*! An iterator to visit all the subconstraints of the triangulation and the contexts of their enclosing constraints. The order of visit is undefined. -The value type of this iterator is `std::pair*>`. +The value type of this iterator is `const std::pair*>`. */ typedef unspecified_type Subconstraint_and_contexts_iterator; From d4e6ffddf4733df0b5f1c32c4454da20f4b07bdd Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Tue, 14 Jan 2025 16:12:34 +0100 Subject: [PATCH 17/20] fix protection against min/max macros The regular expression I used was: ``` ((?!(?:^.*(\/\/|\/\*).*|^ *\* .*|^[^"]*"(?:"[^"]*"|[^"])*))^(?:.*[ ,\(]|))(\b(?:(?:[A-Za-z]+::)*)(?:max|min))\b *\( ``` --- .../Alpha_wrap_3/Quality/quality_benchmark.cpp | 10 +++++----- .../GUI_country_pick_handler.cpp | 2 +- .../Arrangement_on_surface_2_earth/Main_widget.cpp | 2 +- CGAL_Core/include/CGAL/CORE/poly/Curves.tcc | 2 +- .../internal_functions_on_circular_arc_2.h | 2 +- .../include/CGAL/Distance_3/Triangle_3_Triangle_3.h | 2 +- Lab/demo/Lab/MainWindow.cpp | 8 ++++++-- ...erpolated_corrected_principal_curvatures_plugin.cpp | 3 ++- .../test/Matrix_search/sorted_matrix_search_test.cpp | 2 +- Number_types/include/CGAL/leda_bigfloat_interval.h | 4 ++-- STL_Extension/include/CGAL/Random_allocator.h | 4 ++-- .../benchmark/Spatial_searching/include/nanoflann.hpp | 6 +++--- .../path_homotopy_with_schema.cpp | 8 ++++---- .../internal/Polyline_constraint_hierarchy_2.h | 4 ++-- 14 files changed, 32 insertions(+), 27 deletions(-) diff --git a/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/quality_benchmark.cpp b/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/quality_benchmark.cpp index f8e54c488a4..12fa0690c9d 100644 --- a/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/quality_benchmark.cpp +++ b/Alpha_wrap_3/benchmark/Alpha_wrap_3/Quality/quality_benchmark.cpp @@ -75,7 +75,7 @@ double mean_min_angle(const Mesh& mesh) const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh); std::array angles = triangle_angles(tr); - FT min_angle = std::min({angles[0], angles[1], angles[2]}); + FT min_angle = (std::min)({angles[0], angles[1], angles[2]}); min_angle = min_angle * (180.0 / CGAL_PI); mean_min_angle += min_angle; @@ -93,7 +93,7 @@ double mean_max_angle(const Mesh& mesh) const Triangle_3 tr = surface_mesh_face_to_triangle(f, mesh); std::array angles = triangle_angles(tr); - FT max_angle = std::max({angles[0], angles[1], angles[2]}); + FT max_angle = (std::max)({angles[0], angles[1], angles[2]}); max_angle = max_angle * (180.0 / CGAL_PI); mean_max_angle += max_angle; @@ -151,8 +151,8 @@ double mean_edge_ratio(const Mesh& mesh, FT a = std::sqrt(CGAL::squared_distance(tr[0], tr[1])); FT b = std::sqrt(CGAL::squared_distance(tr[1], tr[2])); FT c = std::sqrt(CGAL::squared_distance(tr[2], tr[0])); - FT min_edge = std::min({a, b, c}); - FT max_edge = std::max({a, b, c}); + FT min_edge = (std::min)({a, b, c}); + FT max_edge = (std::max)({a, b, c}); FT edge_ratio = max_edge / min_edge; mean_edge_ratio += edge_ratio; @@ -181,7 +181,7 @@ double mean_aspect_ratio(const Mesh& mesh, FT c = std::sqrt(CGAL::squared_distance(tr[2], tr[0])); FT s = 0.5 * (a + b + c); FT inscribed_radius = std::sqrt((s * (s - a) * (s - b) * (s - c)) / s); - FT max_edge = std::max({a, b, c}); + FT max_edge = (std::max)({a, b, c}); FT aspect_ratio = max_edge / inscribed_radius; aspect_ratio /= (2. * std::sqrt(3.)); // normalized mean_aspect_ratio += aspect_ratio; diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/GUI_country_pick_handler.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/GUI_country_pick_handler.cpp index 58bc34f3ca2..53f7aba4972 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/GUI_country_pick_handler.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/GUI_country_pick_handler.cpp @@ -62,7 +62,7 @@ void GUI_country_pick_handler::mouse_press_event(QMouseEvent* e) { auto sd = sqrt(d); auto t1 = (-b - sd) / (2 * a); auto t2 = (-b + sd) / (2 * a); - if (t1 > 0 && t2 > 0) ti = std::min(t1, t2); + if (t1 > 0 && t2 > 0) ti = (std::min)(t1, t2); else if (t1 > 0) ti = t1; else ti = t2; } diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/Main_widget.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/Main_widget.cpp index f99c6c7e55b..decff54e3d5 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/Main_widget.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2_earth/Main_widget.cpp @@ -140,7 +140,7 @@ void Main_widget::initializeGL() { for (auto& [country_name, triangle_points] : country_triangles_map) { auto country_triangles = std::make_unique(triangle_points); auto color = QVector4D(rndm(), rndm(), rndm(), 1); - auto m = std::max(color.x(), std::max(color.y(), color.z())); + auto m = (std::max)(color.x(), (std::max)(color.y(), color.z())); color /= m; color *= m_dimming_factor; color.setW(1); diff --git a/CGAL_Core/include/CGAL/CORE/poly/Curves.tcc b/CGAL_Core/include/CGAL/CORE/poly/Curves.tcc index 3f53e34da44..b287edaecc7 100644 --- a/CGAL_Core/include/CGAL/CORE/poly/Curves.tcc +++ b/CGAL_Core/include/CGAL/CORE/poly/Curves.tcc @@ -544,7 +544,7 @@ template int BiPoly::getXdegree(){ int deg=-1; for(int i=0; i <=ydeg; i++) - deg = max(deg, coeffX[i].getTrueDegree()); + deg = (max)(deg, coeffX[i].getTrueDegree()); return deg; } diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h index b5830954ec7..0bfc65d0a55 100644 --- a/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/internal_functions_on_circular_arc_2.h @@ -1565,7 +1565,7 @@ advanced_make_xy_monotone( const typename CK::Circular_arc_2 &a, double ymax = (is_on_upper) ? to_interval ( CircularFunctors::y_extremal_point(a.supporting_circle(),false).y() ).second : - CGAL::max(left_bb.ymax(),right_bb.ymax()); + (CGAL::max)(left_bb.ymax(),right_bb.ymax()); */ return Bbox_2(left_bb.xmin(),ymin,right_bb.xmax(),ymax); } diff --git a/Distance_3/include/CGAL/Distance_3/Triangle_3_Triangle_3.h b/Distance_3/include/CGAL/Distance_3/Triangle_3_Triangle_3.h index 73f4b0eb69c..f6bf77fd39b 100644 --- a/Distance_3/include/CGAL/Distance_3/Triangle_3_Triangle_3.h +++ b/Distance_3/include/CGAL/Distance_3/Triangle_3_Triangle_3.h @@ -207,7 +207,7 @@ squared_distance(const typename K::Triangle_3& tr1, FT sqd_q2 = CGAL::squared_distance(vertex(tr2, 1), tr1); FT sqd_r2 = CGAL::squared_distance(vertex(tr2, 2), tr1); - const FT m = std::min({sqd_p1, sqd_q1, sqd_r1, sqd_p2, sqd_q2, sqd_r2}); + const FT m = (std::min)({sqd_p1, sqd_q1, sqd_r1, sqd_p2, sqd_q2, sqd_r2}); return m; #endif diff --git a/Lab/demo/Lab/MainWindow.cpp b/Lab/demo/Lab/MainWindow.cpp index dd133dbf44f..60b75d24fe4 100644 --- a/Lab/demo/Lab/MainWindow.cpp +++ b/Lab/demo/Lab/MainWindow.cpp @@ -2396,8 +2396,12 @@ void MainWindow::viewerShowObject() } if(item) { const Scene::Bbox bbox = item->bbox(); - CGAL::qglviewer::Vec min(static_cast(bbox.xmin())+viewer->offset().x, static_cast(bbox.ymin())+viewer->offset().y, static_cast(bbox.zmin())+viewer->offset().z), - max(static_cast(bbox.xmax())+viewer->offset().x, static_cast(bbox.ymax())+viewer->offset().y, static_cast(bbox.zmax())+viewer->offset().z); + CGAL::qglviewer::Vec min{static_cast(bbox.xmin()) + viewer->offset().x, + static_cast(bbox.ymin()) + viewer->offset().y, + static_cast(bbox.zmin()) + viewer->offset().z}; + CGAL::qglviewer::Vec max{static_cast(bbox.xmax()) + viewer->offset().x, + static_cast(bbox.ymax()) + viewer->offset().y, + static_cast(bbox.zmax()) + viewer->offset().z}; viewer->setSceneBoundingBox(min, max); viewerShow(static_cast(min.x), static_cast(min.y), static_cast(min.z), static_cast(max.x), static_cast(max.y), static_cast(max.z)); diff --git a/Lab/demo/Lab/Plugins/PMP/Interpolated_corrected_principal_curvatures_plugin.cpp b/Lab/demo/Lab/Plugins/PMP/Interpolated_corrected_principal_curvatures_plugin.cpp index dbe630ad09f..489b5baca5f 100644 --- a/Lab/demo/Lab/Plugins/PMP/Interpolated_corrected_principal_curvatures_plugin.cpp +++ b/Lab/demo/Lab/Plugins/PMP/Interpolated_corrected_principal_curvatures_plugin.cpp @@ -84,7 +84,8 @@ void compute(SMesh* sMesh, for (Vertex_descriptor v : vertices(*sMesh)) { const PMP::Principal_curvatures_and_directions pc = principal_curvatures_and_directions_map[v]; - max_curvature_magnitude_on_mesh = std::max(max_curvature_magnitude_on_mesh, std::max(abs(pc.min_curvature), abs(pc.max_curvature))); + max_curvature_magnitude_on_mesh = + (std::max)(max_curvature_magnitude_on_mesh, (std::max)(abs(pc.min_curvature), abs(pc.max_curvature))); } for(Vertex_descriptor v : vertices(*sMesh)) diff --git a/Matrix_search/test/Matrix_search/sorted_matrix_search_test.cpp b/Matrix_search/test/Matrix_search/sorted_matrix_search_test.cpp index 22b2e16b82d..e5088183176 100644 --- a/Matrix_search/test/Matrix_search/sorted_matrix_search_test.cpp +++ b/Matrix_search/test/Matrix_search/sorted_matrix_search_test.cpp @@ -148,7 +148,7 @@ main( int argc, char* argv[]) */ // evt. update max_entry: - max_entry = max( a[dim - 1] + b[dim - 1], max_entry); + max_entry = (max)( a[dim - 1] + b[dim - 1], max_entry); // keep both vectors: vectors.push_back( a); diff --git a/Number_types/include/CGAL/leda_bigfloat_interval.h b/Number_types/include/CGAL/leda_bigfloat_interval.h index 25b0e2d8c66..8e347812b9d 100644 --- a/Number_types/include/CGAL/leda_bigfloat_interval.h +++ b/Number_types/include/CGAL/leda_bigfloat_interval.h @@ -202,8 +202,8 @@ template <> class Real_embeddable_traits< leda_bigfloat_interval > std::pair lower_I(CGAL::to_interval(x.lower())); std::pair upper_I(CGAL::to_interval(x.upper())); return std::pair< double, double >( - CGAL::min(lower_I.first , upper_I.first ), - CGAL::max(lower_I.second, upper_I.second)); + (CGAL::min)(lower_I.first , upper_I.first ), + (CGAL::max)(lower_I.second, upper_I.second)); } }; }; diff --git a/STL_Extension/include/CGAL/Random_allocator.h b/STL_Extension/include/CGAL/Random_allocator.h index 51d36a901fd..69bde52db9b 100644 --- a/STL_Extension/include/CGAL/Random_allocator.h +++ b/STL_Extension/include/CGAL/Random_allocator.h @@ -149,7 +149,7 @@ Random_allocator::allocate(size_type n, const void* hint) #endif // CGAL_DEBUG_RANDOM_ALLOCATOR return block->data + index; } - size_type block_size = std::max(n * random_size, minimal_block_size); + size_type block_size = (std::max)(n * random_size, minimal_block_size); ptr_->allocate_new_block(block_size); return allocate(n, hint); } @@ -183,7 +183,7 @@ template typename Random_allocator::size_type Random_allocator::max_size() const noexcept { - return std::numeric_limits::max() / sizeof(T); + return (std::numeric_limits::max)() / sizeof(T); } } // namespace CGAL diff --git a/Spatial_searching/benchmark/Spatial_searching/include/nanoflann.hpp b/Spatial_searching/benchmark/Spatial_searching/include/nanoflann.hpp index 3dd0b399892..a9972641131 100644 --- a/Spatial_searching/benchmark/Spatial_searching/include/nanoflann.hpp +++ b/Spatial_searching/benchmark/Spatial_searching/include/nanoflann.hpp @@ -1002,7 +1002,7 @@ namespace nanoflann if(node->child1 == NULL && node->child2 == NULL) return 1; else{ - return std::max(depth(node->child1)+1,depth(node->child2)+1); + return (std::max)(depth(node->child1)+1,depth(node->child2)+1); } } @@ -1130,8 +1130,8 @@ namespace nanoflann node->sub.divhigh = right_bbox[cutfeat].low; for (int i=0; i<(DIM>0 ? DIM : dim); ++i) { - bbox[i].low = std::min(left_bbox[i].low, right_bbox[i].low); - bbox[i].high = std::max(left_bbox[i].high, right_bbox[i].high); + bbox[i].low = (std::min)(left_bbox[i].low, right_bbox[i].low); + bbox[i].high = (std::max)(left_bbox[i].high, right_bbox[i].high); } } diff --git a/Surface_mesh_topology/benchmark/Surface_mesh_topology/path_homotopy_with_schema.cpp b/Surface_mesh_topology/benchmark/Surface_mesh_topology/path_homotopy_with_schema.cpp index 9a5f36d352b..e6d3b3d7104 100644 --- a/Surface_mesh_topology/benchmark/Surface_mesh_topology/path_homotopy_with_schema.cpp +++ b/Surface_mesh_topology/benchmark/Surface_mesh_topology/path_homotopy_with_schema.cpp @@ -118,13 +118,13 @@ int main(int argc, char** argv) if (!withE) { E=static_cast(random.get_int - (10, std::max(std::size_t(11), - cm.number_of_darts()/10))); } + (10, (std::max)(std::size_t(11), + cm.number_of_darts()/10))); } if (!withD) { D=static_cast(random.get_int - (10, std::max(std::size_t(11), - cm.number_of_darts()/10))); } + (10, (std::max)(std::size_t(11), + cm.number_of_darts()/10))); } diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 8a6f32ba81f..43925c10b52 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -116,7 +116,7 @@ class Polyline_constraint_hierarchy_2 struct Constraint_id { Vertex_list_ptr vl = nullptr; - size_type id = std::numeric_limits::max(); + size_type id = (std::numeric_limits::max)(); Constraint_id(std::nullptr_t = nullptr) {} Constraint_id(Vertex_list_ptr vl, size_type id) : vl(vl), id(id) {} @@ -131,7 +131,7 @@ class Polyline_constraint_hierarchy_2 Constraint_id& operator=(std::nullptr_t) { vl = nullptr; - id = std::numeric_limits::max(); + id = (std::numeric_limits::max)(); return *this; } bool operator==(std::nullptr_t n) const { return vl == n; } From 2869ad810baca7f9055879cf627cb20c4af96875 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Wed, 15 Jan 2025 19:08:01 +0100 Subject: [PATCH 18/20] fix compilation errors with C++<20 --- Mesh_2/test/Mesh_2/CMakeLists.txt | 2 +- Mesh_2/test/Mesh_2/test_mesh_terrain.cpp | 13 ++++++++ Mesh_2/test/Mesh_2/test_meshing.cpp | 6 ---- STL_Extension/include/CGAL/Random_allocator.h | 32 ++++++++++++------- 4 files changed, 35 insertions(+), 18 deletions(-) diff --git a/Mesh_2/test/Mesh_2/CMakeLists.txt b/Mesh_2/test/Mesh_2/CMakeLists.txt index 877831c292e..1553aae3ce4 100644 --- a/Mesh_2/test/Mesh_2/CMakeLists.txt +++ b/Mesh_2/test/Mesh_2/CMakeLists.txt @@ -16,5 +16,5 @@ foreach(cppfile ${cppfiles}) endforeach() if(cxx_std_20 IN_LIST CMAKE_CXX_COMPILE_FEATURES) - target_compile_features(test_meshing PRIVATE cxx_std_20) + target_compile_features(test_mesh_terrain PRIVATE cxx_std_20) endif() diff --git a/Mesh_2/test/Mesh_2/test_mesh_terrain.cpp b/Mesh_2/test/Mesh_2/test_mesh_terrain.cpp index 4ac052fab12..2fe8c8058de 100644 --- a/Mesh_2/test/Mesh_2/test_mesh_terrain.cpp +++ b/Mesh_2/test/Mesh_2/test_mesh_terrain.cpp @@ -1,3 +1,13 @@ +// Test also CGAL::Random_allocator +#if __has_include() +# include +# if __cpp_lib_format >= 201907L +# define CGAL_DEBUG_RANDOM_ALLOCATOR 1 +# endif +#endif +#include +#define CGAL_ALLOCATOR(T) CGAL::Random_allocator + #include #include #include @@ -21,6 +31,9 @@ typedef K::Point_3 Point; int main() { +#if CGAL_DEBUG_RANDOM_ALLOCATOR + std::clog << "CGAL::Random_allocator debug mode is enabled..." << std::endl; +#endif Delaunay dt; typedef Delaunay::Vertex_handle Vertex_handle; Vertex_handle va = dt.insert(Point(-4,0, 0)); diff --git a/Mesh_2/test/Mesh_2/test_meshing.cpp b/Mesh_2/test/Mesh_2/test_meshing.cpp index ed6801d28f1..db91f5a0c08 100644 --- a/Mesh_2/test/Mesh_2/test_meshing.cpp +++ b/Mesh_2/test/Mesh_2/test_meshing.cpp @@ -1,10 +1,4 @@ // 154 515 565 -#include -#if CGAL_CXX20 -# define CGAL_DEBUG_RANDOM_ALLOCATOR 1 -# include -# define CGAL_ALLOCATOR(T) CGAL::Random_allocator -#endif #include "test_dependencies.h" #include #if CGAL_USE_CORE || CGAL_USE_LEDA diff --git a/STL_Extension/include/CGAL/Random_allocator.h b/STL_Extension/include/CGAL/Random_allocator.h index 69bde52db9b..6c8b9dd49cf 100644 --- a/STL_Extension/include/CGAL/Random_allocator.h +++ b/STL_Extension/include/CGAL/Random_allocator.h @@ -15,12 +15,20 @@ #include #include #include - -// This header requires C++20 or later. -#include #include -#include -#include + +#if CGAL_DEBUG_RANDOM_ALLOCATOR +# if __has_include() +# include +# include +# if __cpp_lib_format >= 201907L +# define CGAL_DEBUG_RANDOM_ALLOCATOR_OKAY 1 +# endif +# endif +# if ! CGAL_DEBUG_RANDOM_ALLOCATOR_OKAY +# error "CGAL_DEBUG_RANDOM_ALLOCATOR requires and C++20 std::format" +# endif +#endif namespace CGAL { @@ -50,9 +58,9 @@ template > class Ran void allocate_new_block(std::size_t block_size = minimal_block_size) { - auto& block = blocks.emplace_back(nullptr, boost::dynamic_bitset<>(block_size)); + auto& block = blocks.emplace_back(); block.data = alloc.allocate(block_size); - block.available.set(); + block.available.resize(block_size, true); block.maximal_continuous_free_space = block_size; } @@ -93,7 +101,8 @@ template > class Ran template struct rebind { - using other_upstream_allocator = std::allocator_traits::template rebind_alloc; + using upstream_traits = std::allocator_traits; + using other_upstream_allocator = typename upstream_traits::template rebind_alloc; using other = Random_allocator; }; @@ -113,7 +122,8 @@ typename Random_allocator::pointer Random_allocator::allocate(size_type n, const void* hint) { boost::container::static_vector, random_size> found_spaces; - for(auto& block : ptr_->blocks | std::views::reverse) { + for(auto it = ptr_->blocks.rbegin(), end = ptr_->blocks.rend(); it != end; ++it) { + auto& block = *it; if(block.maximal_continuous_free_space < n) continue; auto& available = block.available; @@ -127,7 +137,7 @@ Random_allocator::allocate(size_type n, const void* hint) auto free_space = end_of_free_block - index; found_max_free_space = (std::max)(found_max_free_space, free_space); while(free_space > n && found_spaces.size() < found_spaces.capacity()) { - found_spaces.push_back({std::addressof(block), index}); + found_spaces.emplace_back(std::addressof(block), index); free_space -= n; index += n; } @@ -144,7 +154,7 @@ Random_allocator::allocate(size_type n, const void* hint) block->available.set(index, n, false); #if CGAL_DEBUG_RANDOM_ALLOCATOR std::clog << std::format("CGAL::Random_allocator debug info: n = {}, found_spaces.size() = {}, i = {}," - "block nb = {}, block size = {}, index = {}\n", + " block id = {}, block size = {}, index = {}\n", n, found_spaces.size(), i, block - ptr_->blocks.data(), block->size(), index); #endif // CGAL_DEBUG_RANDOM_ALLOCATOR return block->data + index; From cf50ad8b13222989225881e9ad39fce2d0487560 Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 16 Jan 2025 13:47:33 +0100 Subject: [PATCH 19/20] document the breakng change --- Installation/CHANGES.md | 6 ++++++ .../Triangulation_2/CGAL/Constrained_triangulation_plus_2.h | 5 +++++ .../examples/Triangulation_2/constrained_hierarchy_plus.cpp | 3 ++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 291dc13ae41..1a59d0c3b39 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -14,6 +14,12 @@ - Introduces two traits decorators, namely `Arr_tracing_traits_2` and `Arr_counting_traits_2`, which can be used to extract debugging and informative metadata about the traits in use while a program is being executed. +### [2D Triangulations](https://doc.cgal.org/6.1/Manual/packages.html#PkgTriangulation2) + +- **Breaking change**: In the class template `Constrained_triangulation_plus_2`, the value type of the range returned + by `subconstraints()` has changed from `const std::pair*>` to `Subconstraint`. + The old range type is now returned by a new function named `subconstraints_and_contexts()`. + ## [Release 6.0.1](https://github.com/CGAL/cgal/releases/tag/v6.0.1) ### [Poisson Surface Reconstruction](https://doc.cgal.org/6.0.1/Manual/packages.html#PkgPoissonSurfaceReconstruction3) diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h index 34aee28ad9c..edd6655527f 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h @@ -360,6 +360,11 @@ void remove_constraint(Constraint_id cid); /// \name Access /// @{ +/// +/// \note +/// Since CGAL-6.1, the value type of the range returned by `subconstraints()` has changed from +/// `const std::pair*>` to `Subconstraint`. +/// The old range type is now returned by the function `subconstraints_and_contexts()`. /*! returns a `Constraint_iterator` that points at the first diff --git a/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp b/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp index b243e152693..b67d5a5a507 100644 --- a/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp +++ b/Triangulation_2/examples/Triangulation_2/constrained_hierarchy_plus.cpp @@ -30,7 +30,8 @@ main( ) cdt.insert_constraint( Point(j,0), Point(j,6)); int count = 0; - for (const Triangulation::Subconstraint& sc : cdt.subconstraints()) { + using Sc = Triangulation::Subconstraint; + for ([[maybe_unused]] const Sc& sc : cdt.subconstraints()) { ++count; } std::cout << "The number of resulting constrained edges is "; From cf815b823f21b9bba00d60b772faa8b3798e90af Mon Sep 17 00:00:00 2001 From: Laurent Rineau Date: Thu, 16 Jan 2025 14:14:38 +0100 Subject: [PATCH 20/20] doc fix: add that iterators are all bidirectional --- .../CGAL/Constrained_triangulation_plus_2.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h index edd6655527f..f9786d793f3 100644 --- a/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/doc/Triangulation_2/CGAL/Constrained_triangulation_plus_2.h @@ -77,7 +77,7 @@ A default constructed `Constraint_id` is a singular value that can not be the ID typedef unspecified_type Constraint_id; /*! -An iterator to visit +A bidirectional iterator to visit all the input constraints. The order of visit is undefined. The value type of this iterator is `Constraint_id`. */ @@ -96,7 +96,7 @@ A subconstraint is a pair of vertices that correspond to an `Edge`. typedef std::pair Subconstraint; /*! -An iterator to visit all the subconstraints of the triangulation. +A bidirectional iterator to visit all the subconstraints of the triangulation. The order of visit is undefined. The value type of this iterator is `Subconstraint`. */ @@ -109,7 +109,7 @@ the range is `Subconstraint_iterator`. typedef unspecified_type Subconstraints; /*! -An iterator to visit all the subconstraints of the triangulation and the +A bidirectional iterator to visit all the subconstraints of the triangulation and the contexts of their enclosing constraints. The order of visit is undefined. The value type of this iterator is `const std::pair*>`. */ @@ -122,7 +122,7 @@ the range is `Subconstraint_and_contexts_iterator`. typedef unspecified_type Subconstraints_and_contexts; /*! -An iterator on the +A bidirectional iterator on the vertices of the chain of subconstraints representing a constraint. The value type of this iterator is `Vertex_handle`. */ @@ -164,10 +164,8 @@ through a subconstraint. }; /*! -An iterator on -constraints enclosing a given subconstraint. The value type of this -iterator -is `Context`. +A bidirectional iterator on constraints enclosing a given subconstraint. +The value type of this iterator is `Context`. */ typedef unspecified_type Context_iterator;