diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h index 6b6d57339cd..e9053489a95 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h @@ -1043,7 +1043,7 @@ class Arrangement_on_surface_2 { } /*! - returns a range over handles of the arrangement vertices . + returns a range over handles of the arrangement vertices. */ Iterator_range<Prevent_deref<Vertex_iterator> > vertex_handles() @@ -1068,7 +1068,7 @@ class Arrangement_on_surface_2 { } /*! - returns a const range (model of `ConstRange`) over handles of the arrangement vertices . + returns a const range (model of `ConstRange`) over handles of the arrangement vertices. */ Iterator_range<Prevent_deref<Vertex_const_iterator> > vertex_handles() const @@ -1098,7 +1098,7 @@ class Arrangement_on_surface_2 { } /*! - returns a range over handles of the arrangement halfedges . + returns a range over handles of the arrangement halfedges. */ Iterator_range<Prevent_deref<Halfedge_iterator> > halfedge_handles() @@ -1122,7 +1122,7 @@ class Arrangement_on_surface_2 { _Is_valid_halfedge(&m_topol_traits))); } /*! - returns a const range (model of `ConstRange`) over handles of the arrangement halfedges . + returns a const range (model of `ConstRange`) over handles of the arrangement halfedges. */ Iterator_range<Prevent_deref<Halfedge_const_iterator> > halfedge_handles() const @@ -1149,7 +1149,7 @@ class Arrangement_on_surface_2 { } /*! - returns a range over handles of the arrangement edges . + returns a range over handles of the arrangement edges. */ Iterator_range<Prevent_deref<Edge_iterator> > edge_handles() @@ -1172,7 +1172,7 @@ class Arrangement_on_surface_2 { } /*! - returns a const range (model of `ConstRange`) over handles of the arrangement edges . + returns a const range (model of `ConstRange`) over handles of the arrangement edges. */ Iterator_range<Prevent_deref<Edge_const_iterator> > edge_handles() const @@ -1199,7 +1199,7 @@ class Arrangement_on_surface_2 { } /*! - returns a range over handles of the arrangement faces . + returns a range over handles of the arrangement faces. */ Iterator_range<Prevent_deref<Face_iterator> > face_handles() @@ -1221,7 +1221,7 @@ class Arrangement_on_surface_2 { } /*! - returns a const range (model of `ConstRange`) over handles of the arrangement faces . + returns a const range (model of `ConstRange`) over handles of the arrangement faces. */ Iterator_range<Prevent_deref<Face_const_iterator> > face_handles() const diff --git a/Circulator/include/CGAL/circulator.h b/Circulator/include/CGAL/circulator.h index 1c111779ef8..c622fb615ad 100644 --- a/Circulator/include/CGAL/circulator.h +++ b/Circulator/include/CGAL/circulator.h @@ -698,14 +698,18 @@ typedef Iterator_from_circulator< C, const_reference, const_pointer> }; template <class Container> class Circulator_from_container { + static auto begin(Container* c) { + using std::begin; + return begin(*c); + } + + static auto end(Container* c) { + using std::end; + return end(*c); + } + typedef Circulator_from_container<Container> Self; - typedef typename Container::iterator container_iterator; - typedef typename Container::const_iterator container_const_iterator; - typedef std::conditional_t< - std::is_const<Container>::value, - container_const_iterator, - container_iterator - > iterator; + using iterator = decltype(begin(std::declval<Container*>())); typedef std::iterator_traits<iterator> iterator_traits; public: typedef typename iterator_traits::value_type value_type; @@ -717,7 +721,7 @@ class Circulator_from_container { typename iterator_traits::iterator_category >::iterator_category iterator_category; - typedef typename Container::size_type size_type; + using size_type = decltype(std::size(std::declval<Container&>())); private: Container* ctnr; iterator i; @@ -734,27 +738,27 @@ class Circulator_from_container { bool operator==( std::nullptr_t p) const { CGAL_USE(p); CGAL_assertion( p == nullptr); - return (ctnr == nullptr) || (ctnr->begin() == ctnr->end()); + return (ctnr == nullptr) || (begin(ctnr) == end(ctnr)); } bool operator!=( std::nullptr_t p) const { return !(*this == p); } bool operator==( const Self& c) const { return i == c.i; } bool operator!=( const Self& c) const { return !(*this == c); } reference operator*() const { CGAL_assertion( ctnr != nullptr); - CGAL_assertion( i != ctnr->end()); + CGAL_assertion( i != end(ctnr)); return *i; } pointer operator->() const { CGAL_assertion( ctnr != nullptr); - CGAL_assertion( i != ctnr->end()); + CGAL_assertion( i != end(ctnr)); return i.operator->(); } Self& operator++() { CGAL_assertion( ctnr != nullptr); - CGAL_assertion( i != ctnr->end()); + CGAL_assertion( i != end(ctnr)); ++i; - if ( i == ctnr->end()) - i = ctnr->begin(); + if ( i == end(ctnr)) + i = begin(ctnr); return *this; } Self operator++(int) { @@ -764,9 +768,9 @@ class Circulator_from_container { } Self& operator--() { CGAL_assertion( ctnr != nullptr); - CGAL_assertion( i != ctnr->end()); - if ( i == ctnr->begin()) - i = ctnr->end(); + CGAL_assertion( i != end(ctnr)); + if ( i == begin(ctnr)) + i = end(ctnr); --i; return *this; } @@ -777,15 +781,15 @@ class Circulator_from_container { } Self& operator+=( difference_type n) { CGAL_assertion( ctnr != nullptr); - CGAL_assertion( i != ctnr->end()); - typename Container::difference_type j = i - ctnr->begin(); + CGAL_assertion( i != end(ctnr)); + typename Container::difference_type j = i - begin(ctnr); typename Container::difference_type size = ctnr->size(); CGAL_assertion( j >= 0); CGAL_assertion( size >= 0); j = non_negative_mod( j + n, size); CGAL_assertion( j >= 0); CGAL_assertion( j < size); - i = ctnr->begin() + j; + i = begin(ctnr) + j; return *this; } Self operator+( difference_type n) const { diff --git a/Hash_map/include/CGAL/Hash_map/internal/chained_map.h b/Hash_map/include/CGAL/Hash_map/internal/chained_map.h index 729e2a58092..bea9b0993f0 100644 --- a/Hash_map/include/CGAL/Hash_map/internal/chained_map.h +++ b/Hash_map/include/CGAL/Hash_map/internal/chained_map.h @@ -19,6 +19,8 @@ #include <CGAL/memory.h> #include <iostream> #include <limits> +#include <type_traits> +#include <utility> namespace CGAL { @@ -85,6 +87,10 @@ class chained_map chained_map(std::size_t n = default_size, const T& d = T()); chained_map(const chained_map<T, Allocator>& D); chained_map& operator=(const chained_map<T, Allocator>& D); + chained_map(chained_map<T, Allocator>&& D) + noexcept(std::is_nothrow_move_constructible_v<Allocator> && std::is_nothrow_move_constructible_v<T>); + chained_map& operator=(chained_map<T, Allocator>&& D) + noexcept(std::is_nothrow_move_assignable_v<Allocator> && std::is_nothrow_move_assignable_v<T>); void reserve(std::size_t n); void clear(); @@ -246,6 +252,18 @@ chained_map<T, Allocator>::chained_map(const chained_map<T, Allocator>& D) } } } +template <typename T, typename Allocator> +chained_map<T, Allocator>::chained_map(chained_map<T, Allocator>&& D) + noexcept(std::is_nothrow_move_constructible_v<Allocator> && std::is_nothrow_move_constructible_v<T>) + : table(std::exchange(D.table, nullptr)) + , table_end(std::exchange(D.table_end, nullptr)) + , free(std::exchange(D.free, nullptr)) + , table_size(std::exchange(D.table_size, 0)) + , table_size_1(std::exchange(D.table_size_1, 0)) + , alloc(std::move(D.alloc)) + , reserved_size(std::exchange(D.reserved_size, 0)) + , def(std::move(D.def)) +{} template <typename T, typename Allocator> chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_map<T, Allocator>& D) @@ -263,6 +281,24 @@ chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(const chained_ma return *this; } +template <typename T, typename Allocator> +chained_map<T, Allocator>& chained_map<T, Allocator>::operator=(chained_map<T, Allocator>&& D) + noexcept(std::is_nothrow_move_assignable_v<Allocator> && std::is_nothrow_move_assignable_v<T>) +{ + clear(); + + table = std::exchange(D.table, nullptr); + table_end = std::exchange(D.table_end, nullptr); + free = std::exchange(D.free, nullptr); + table_size = std::exchange(D.table_size, 0); + table_size_1 = std::exchange(D.table_size_1, 0); + alloc = std::move(D.alloc); + reserved_size = std::exchange(D.reserved_size, 0); + def = std::move(D.def); + + return *this; +} + template <typename T, typename Allocator> void chained_map<T, Allocator>::reserve(std::size_t n) { diff --git a/Hash_map/test/Hash_map/Unique_hash_map_test.cpp b/Hash_map/test/Hash_map/Unique_hash_map_test.cpp index 814fd7d94f3..bae896f360b 100644 --- a/Hash_map/test/Hash_map/Unique_hash_map_test.cpp +++ b/Hash_map/test/Hash_map/Unique_hash_map_test.cpp @@ -1,6 +1,7 @@ #include <list> #include <CGAL/Unique_hash_map.h> #include <CGAL/test_macros.h> +#include <type_traits> using namespace std; typedef list<int>::iterator Iterator; @@ -24,6 +25,10 @@ int main() { H1[it1] = 2; CGAL_TEST(H1[it1]==2); CGAL_TEST(H2[it1]==-1); + static_assert(std::is_nothrow_move_constructible_v<decltype(H1)>); + auto H1_moved = std::move(H1); + CGAL_TEST(H1_moved[it1]==2); + CGAL_TEST(H1[it1]==H1.default_value()); H1.clear(); H2.clear(-2); H2[it1] = 2; @@ -67,6 +72,7 @@ int main() { CGAL_TEST(get(H4_pmap, L.begin()) == 0); typedef CGAL::Unique_hash_map<int, int, Integer_hash_function> Int_hmap; + static_assert(std::is_nothrow_move_constructible_v<Int_hmap>); typedef boost::associative_property_map<Int_hmap> Int_pmap; Int_hmap H5(-1); Int_pmap H5_pmap(H5); diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index b2dad48f364..541d4ad7463 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,8 +1,6 @@ -Release History -=============== +# Release History -[Release 6.0](https://github.com/CGAL/cgal/releases/tag/v6.0) ------------ +## [Release 6.0](https://github.com/CGAL/cgal/releases/tag/v6.0) Release date: June 2024 @@ -119,6 +117,9 @@ Release date: June 2024 ### [Surface Mesh Parameterization](https://doc.cgal.org/6.0/Manual/packages.html#PkgSurfaceMeshParameterization) - **Breaking change**: LSCM_parameterizer_3 needs Eigen +### [2D Triangulations](https://doc.cgal.org/6.0/Manual/packages.html#PkgTriangulation2) +- **Breaking change**: the concept [`TriangulationTraits_2`](https://doc.cgal.org/6.0/Triangulation_2/classTriangulationTraits__2.html) now requires an additional functor `Compare_xy_2`. + ### [3D Triangulations](https://doc.cgal.org/6.0/Manual/packages.html#PkgTriangulation3) - Added three functions `vertices()` to the class `Triangulation_3`. Each of them returns an array containing the vertices of the given triangulation simplex. diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index c31b233091e..bd5dafbf017 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -293,7 +293,9 @@ using std::max; // Macros to detect features of clang. We define them for the other // compilers. // See https://clang.llvm.org/docs/LanguageExtensions.html -// See also https://en.cppreference.com/w/cpp/experimental/feature_test +// +// Some of those macro have been standardized. See C++20 feature testing: +// https://en.cppreference.com/w/cpp/feature_test #ifndef __has_feature #define __has_feature(x) 0 // Compatibility with non-clang compilers. #endif @@ -316,6 +318,10 @@ using std::max; #define __has_warning(x) 0 // Compatibility with non-clang compilers. #endif +#if __has_include(<version>) +# include <version> +#endif + // Macro to specify a 'unused' attribute. #if __has_cpp_attribute(maybe_unused) # define CGAL_UNUSED [[maybe_unused]] @@ -470,6 +476,14 @@ namespace cpp11{ }//namespace cpp11 } //namespace CGAL +#if __cpp_lib_concepts >= 201806L +# define CGAL_CPP20_REQUIRE_CLAUSE(x) requires x +# define CGAL_TYPE_CONSTRAINT(x) x +#else +# define CGAL_CPP20_REQUIRE_CLAUSE(x) +# define CGAL_TYPE_CONSTRAINT(x) typename +#endif + // The fallthrough attribute // See for clang: // https://clang.llvm.org/docs/AttributeReference.html#statement-attributes @@ -487,6 +501,10 @@ namespace cpp11{ # define CGAL_FALLTHROUGH while(false){} #endif +#if __cpp_lib_format >= 201907L || (__has_include(<format>) && (__cplusplus >= 202000L || _MSVC_LANG >= 202000L)) +# define CGAL_CAN_USE_CXX20_FORMAT 1 +#endif + #ifndef CGAL_NO_ASSERTIONS # define CGAL_NO_ASSERTIONS_BOOL false #else diff --git a/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h b/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h index 07a13938bee..be7d5862fb3 100644 --- a/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h +++ b/Interpolation/include/CGAL/Voronoi_intersection_2_traits_3.h @@ -291,6 +291,24 @@ class Voronoi_intersection_2_traits_3 typedef typename Rep::Less_distance_to_point_3 Less_distance_to_point_2; typedef typename Rep::Compute_squared_distance_3 Compute_squared_distance_2; + struct Compare_xy_2 { + Compare_x_2 cx_2; + Compare_y_2 cy_2; + + Compare_xy_2(const Compare_x_2& cx_2, const Compare_y_2& cy_2) + : cx_2(cx_2), cy_2(cy_2) + {} + + Comparison_result operator()(const Point_2& p, const Point_2& q) const + { + Comparison_result res = cx_2(p, q); + if (res == EQUAL) { + return cy_2(p, q); + } + return res; + } + }; + //instantiations and creation of functors: //for the triangulation: Orientation_2 @@ -312,6 +330,10 @@ class Voronoi_intersection_2_traits_3 compare_y_2_object() const { return Compare_y_2(normal); } + Compare_xy_2 + compare_xy_2_object() const + { return Compare_xy_2(compare_x_2_object(), compare_y_2_object()); } + Less_x_2 less_x_2_object() const { return compare_to_less(compare_x_2_object()); } diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 71e56de4785..d8ae9f4bbf4 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -205,6 +205,44 @@ namespace CommonKernelFunctors { public: typedef typename K::Comparison_result result_type; + result_type + operator()(const Point_3& a1, const Point_3& b1, const Point_3& c1, + const Point_3& a2, const Point_3& b2, const Point_3& c2) const + { + using FT = typename K::FT; + const Vector_3 ba1 = a1 - b1; + const Vector_3 bc1 = c1 - b1; + const Vector_3 ba2 = a2 - b2; + const Vector_3 bc2 = c2 - b2; + const FT sc_prod_1 = ba1 * bc1; + const FT sc_prod_2 = ba2 * bc2; + // Reminder: cos(angle) = scalar_product(ba, bc) / (length(ba)*length(bc)) + // cosine is decreasing on 0, pi + // thus angle1 < angle2 is equivalent to cos(angle1) > cos(angle2) + if(sc_prod_1 >= 0) { + if(sc_prod_2 >= 0) { + // the two cosine are >= 0, we can compare the squares + // (square(x) is increasing when x>=0 + return CGAL::compare(CGAL::square(sc_prod_2)* + ba1.squared_length()*bc1.squared_length(), + CGAL::square(sc_prod_1)* + ba2.squared_length()*bc2.squared_length()); + } else { + return SMALLER; + } + } else { + if(sc_prod_2 < 0) { + // the two cosine are < 0, square(x) is decreasing when x<0 + return CGAL::compare(CGAL::square(sc_prod_1)* + ba2.squared_length()*bc2.squared_length(), + CGAL::square(sc_prod_2)* + ba1.squared_length()*bc1.squared_length()); + } else { + return LARGER; + } + } + } + result_type operator()(const Point_3& a, const Point_3& b, const Point_3& c, const FT& cosine) const diff --git a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h index 1cc09421944..bc691bf27d7 100644 --- a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h +++ b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_3.h @@ -971,6 +971,7 @@ class Projection_traits_3 typedef typename Rp::Construct_triangle_3 Construct_triangle_2; typedef typename Rp::Construct_line_3 Construct_line_2; + typedef typename Rp::Compare_xyz_3 Compare_xy_2; struct Less_xy_2 { typedef typename R::Boolean result_type; @@ -1065,6 +1066,10 @@ class Projection_traits_3 less_x_2_object() const { return Less_x_2();} + Compare_xy_2 + compare_xy_2_object() const + { return Compare_xy_2();} + Less_xy_2 less_xy_2_object() const { return Less_xy_2();} diff --git a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h index 089fe5ba6cb..e179fecc677 100644 --- a/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h +++ b/Kernel_23/include/CGAL/Kernel_23/internal/Projection_traits_base_3.h @@ -426,6 +426,7 @@ class Projection_traits_base_3 typedef typename K::Line_3 Line_2; typedef typename K::Angle_3 Angle_2; + typedef typename K::Compare_xyz_3 Compare_xy_2; typedef TriangulationProjectionTraitsCartesianFunctors:: Compare_along_axis<Self> Compare_x_2; @@ -524,6 +525,9 @@ class Projection_traits_base_3 Angle_2 angle_2_object() const {return Angle_2();} + Compare_xy_2 compare_xy_2_object() const + {return Compare_xy_2();} + Construct_point_2 construct_point_2_object() const {return Construct_point_2();} diff --git a/Mesh_3/test/Mesh_3/test_meshing_utilities.h b/Mesh_3/test/Mesh_3/test_meshing_utilities.h index 5b5fbc61316..72e2a245c31 100644 --- a/Mesh_3/test/Mesh_3/test_meshing_utilities.h +++ b/Mesh_3/test/Mesh_3/test_meshing_utilities.h @@ -71,6 +71,8 @@ void verify_time_stamps(const C3t3& c3t3, CGAL::Sequential_tag) { assert(prev->time_stamp() < cit->time_stamp()); } } + assert(tds.vertices().check_timestamps_are_valid()); + assert(tds.cells().check_timestamps_are_valid()); } // Do not verify time stamps in parallel mode diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h index 3d6d588b142..87091d84300 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Kernel_2_interface.h @@ -48,6 +48,25 @@ template <class Base_> struct Kernel_2_interface : public Base_ { typedef Help_2p_i<Less_point_cartesian_coordinate_tag,1> Less_y_2; typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,0> Compare_x_2; typedef Help_2p_i<Compare_point_cartesian_coordinate_tag,1> Compare_y_2; + + struct Compare_xy_2 { + Compare_x_2 cx_2; + Compare_y_2 cy_2; + + Compare_xy_2(const Compare_x_2 & cx_2, const Compare_y_2 & cy_2) + : cx_2(cx_2), cy_2(cy_2) + {} + + typename Compare_x_2::result_type operator()(const Point_2 & p, const Point_2 & q) + { + auto res = cx_2(p, q); + if (res == EQUAL) { + return cy_2(p, q); + } + return res; + } + }; + struct Compare_distance_2 { typedef typename Get_functor<Base, Compare_distance_tag>::type CD; typedef typename CD::result_type result_type; @@ -88,6 +107,9 @@ template <class Base_> struct Kernel_2_interface : public Base_ { Less_y_2 less_y_2_object()const{ return Less_y_2(*this); } Compare_x_2 compare_x_2_object()const{ return Compare_x_2(*this); } Compare_y_2 compare_y_2_object()const{ return Compare_y_2(*this); } + + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(compare_x_2_object(), compare_y_2_object()); } + Compare_distance_2 compare_distance_2_object()const{ return Compare_distance_2(*this); } Orientation_2 orientation_2_object()const{ return Orientation_2(*this); } Side_of_oriented_circle_2 side_of_oriented_circle_2_object()const{ return Side_of_oriented_circle_2(*this); } diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 4bc63fcf8b3..67743dbd907 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -9,6 +9,7 @@ find_package(CGAL REQUIRED) create_single_source_cgal_program("sample_example.cpp" ) create_single_source_cgal_program("extrude.cpp" ) +create_single_source_cgal_program( "list_non_pure_triangle_meshes.cpp" ) create_single_source_cgal_program("polyhedral_envelope.cpp" ) create_single_source_cgal_program("polyhedral_envelope_of_triangle_soup.cpp" ) create_single_source_cgal_program("polyhedral_envelope_mesh_containment.cpp" ) diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp new file mode 100644 index 00000000000..b885602f54d --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/list_non_pure_triangle_meshes.cpp @@ -0,0 +1,29 @@ +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> +#include <CGAL/Polygon_mesh_processing/IO/polygon_mesh_io.h> +#include <CGAL/Surface_mesh.h> + +#include <CGAL/boost/graph/helpers.h> + +#include <iostream> +#include <string> + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Surface_mesh<Point> Surface_mesh; + +namespace PMP = CGAL::Polygon_mesh_processing; + +int main(int argc, char* argv[]) +{ + for(int i = 1; i < argc; ++i) { + Surface_mesh mesh; + if(!PMP::IO::read_polygon_mesh(argv[i], mesh)) { + std::cerr << "Invalid input: " << argv[i] << '\n'; + } + if(!is_triangle_mesh(mesh)) { + std::cout << argv[i] << std::endl; + } + } + + return 0; +} diff --git a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index c58110c9b32..db0cc2fa28d 100644 --- a/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/SMDS_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -444,8 +444,8 @@ class Mesh_complex_3_in_triangulation_3 */ void remove_from_complex(const Vertex_handle& v) { - corners_.erase(v); v->set_dimension(-1); + corners_.erase(v); } /** sets the index of vertex \p vertex to \p index @@ -983,7 +983,7 @@ class Mesh_complex_3_in_triangulation_3 pointer operator->() const { return *(this->base()); } reference operator*() const { return **(this->base()); } - operator Vertex_handle() { return Vertex_handle(*(this->base())); } + operator const Vertex_handle&() const { return *(this->base()); } }; public: @@ -1048,13 +1048,13 @@ class Mesh_complex_3_in_triangulation_3 Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Cell_handle() const { return Cell_handle(this->base()); } + operator const Cell_handle&() const { return this->base(); } }; // end class Cells_in_complex_iterator - typedef Iterator_range<Prevent_deref<Vertices_in_complex_iterator> > Vertices_in_complex; - typedef Iterator_range<Edges_in_complex_iterator> Edges_in_complex; - typedef Iterator_range<Facets_in_complex_iterator> Facets_in_complex; - typedef Iterator_range<Prevent_deref<Cells_in_complex_iterator> > Cells_in_complex; + typedef Iterator_range<Prevent_deref<Vertices_in_complex_iterator, const Vertex_handle&>> Vertices_in_complex; + typedef Iterator_range<Edges_in_complex_iterator> Edges_in_complex; + typedef Iterator_range<Facets_in_complex_iterator> Facets_in_complex; + typedef Iterator_range<Prevent_deref<Cells_in_complex_iterator, const Cell_handle&>> Cells_in_complex; #endif @@ -1162,8 +1162,7 @@ class Mesh_complex_3_in_triangulation_3 */ Vertices_in_complex vertices_in_complex() const { - return make_prevent_deref_range(vertices_in_complex_begin(), - vertices_in_complex_end()); + return { vertices_in_complex_begin(), vertices_in_complex_end() }; } /*! returns a range of iterators over the edges of the 1D complex, @@ -1193,8 +1192,7 @@ class Mesh_complex_3_in_triangulation_3 */ Cells_in_complex cells_in_complex() const { - return make_prevent_deref_range(cells_in_complex_begin(), - cells_in_complex_end()); + return { cells_in_complex_begin(), cells_in_complex_end() }; } /// @} diff --git a/SMDS_3/include/CGAL/SMDS_3/io_signature.h b/SMDS_3/include/CGAL/SMDS_3/io_signature.h index 1a5f6e54aa3..bae31c072c7 100644 --- a/SMDS_3/include/CGAL/SMDS_3/io_signature.h +++ b/SMDS_3/include/CGAL/SMDS_3/io_signature.h @@ -27,6 +27,7 @@ #include <CGAL/Regular_triangulation_3.h> #include <CGAL/Regular_triangulation_cell_base_3.h> #include <CGAL/Regular_triangulation_cell_base_with_weighted_circumcenter_3.h> +#include <CGAL/type_traits.h> #ifdef CGAL_PERIODIC_3_MESH_3_CONFIG_H #include <CGAL/Periodic_3_triangulation_3.h> @@ -36,21 +37,17 @@ #include <variant> #include <boost/tuple/tuple.hpp> #include <utility> +#include <type_traits> namespace CGAL { // SFINAE test -template <typename T, typename U> -class has_io_signature -{ -private: - template <U> struct helper; - template <typename V> static char check(helper<&V::io_signature> *); - template <typename V> static char (&check(...))[2]; +template <typename T, class = void> +struct has_io_signature : public std::false_type {}; -public: - enum { value = (sizeof(check<T>(0)) == sizeof(char)) }; -}; +template <typename T> +struct has_io_signature<T, std::void_t<decltype(T::io_signature())>> +: public std::true_type {}; template <class T, bool has_io_signature> struct Get_io_signature_aux @@ -76,10 +73,7 @@ template <class T> struct Get_io_signature : public Get_io_signature_aux< T, - (has_io_signature<T, std::string (T::*)() >::value || - has_io_signature<T, std::string (T::*)() const >::value || - has_io_signature<T, std::string (*)() >::value ) // signature for - // static mem func + has_io_signature<T>::value > { }; @@ -366,6 +360,18 @@ Get_io_signature<Regular_triangulation_cell_base_with_weighted_circumcenter_3<Gt }; #endif +#ifdef CGAL_BASE_WITH_TIME_STAMP_H +template <class Base> +struct +Get_io_signature<Base_with_time_stamp<Base> > +{ + std::string operator()() { + return Get_io_signature<Base>()(); + } +}; +#endif + + } // end namespace CGAL diff --git a/SMDS_3/test/SMDS_3/test_c3t3.cpp b/SMDS_3/test/SMDS_3/test_c3t3.cpp index 78835c78fda..9fe7b744aae 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3.cpp @@ -49,6 +49,9 @@ struct Tester typedef typename C3t3::Facets_in_complex_iterator Facet_iterator; typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Vertices_in_complex Vertices_in_complex; + typedef typename C3t3::Cells_in_complex Cells_in_complex; + typedef typename C3t3::Subdomain_index Subdomain_index; typedef typename C3t3::Surface_patch_index Surface_patch_index; typedef typename C3t3::Index Index; @@ -120,6 +123,15 @@ struct Tester assert(c3t3.is_in_complex(ch)); assert(c3t3.subdomain_index(ch) == subdomain_index); + // Test iterator range + { + Cell_handle ch = *c3t3.cells_in_complex().begin(); + for (auto c : c3t3.cells_in_complex()) { + assert(c == ch); + break; + } + } + //------------------------------------------------------- // Test move construction //------------------------------------------------------- diff --git a/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp b/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp index 737bfcacb33..4373da1fdc0 100644 --- a/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp +++ b/SMDS_3/test/SMDS_3/test_c3t3_with_features.cpp @@ -218,6 +218,18 @@ struct Tester || ( v == vp4 && tr.point(vit) == p4 ) ); assert ( tv1.in_dimension() == tv2.in_dimension() ); + + + // Test iterator range + { + Vertex_handle vh = *c3t3.vertices_in_complex().begin(); + for (auto v : c3t3.vertices_in_complex()) { + assert(v == vh); + break; + } + } + + //------------------------------------------------------- // Check adjacencies //------------------------------------------------------- @@ -335,8 +347,13 @@ struct Tester //------------------------------------------------------- std::cout << "Test vertex iterators\n"; const Vertex_handle& vertex_to_modify = c3t3.vertices_in_complex_begin(); + Vertex_handle vertex_to_modify_copy = vertex_to_modify; + c3t3.remove_from_complex(vertex_to_modify); - c3t3.add_to_complex(vertex_to_modify,corner_index_bis); + // now `vertex_to_modify` is a dangling ref to a `Vertex_handle` + + // use a copy of it: `vertex_to_modify_copy` + c3t3.add_to_complex(vertex_to_modify_copy,corner_index_bis); typename C3t3::Vertices_in_complex_iterator corner_vit = c3t3.vertices_in_complex_begin(corner_index); diff --git a/STL_Extension/include/CGAL/Base_with_time_stamp.h b/STL_Extension/include/CGAL/Base_with_time_stamp.h index cbed66de81f..962eec8a1e1 100644 --- a/STL_Extension/include/CGAL/Base_with_time_stamp.h +++ b/STL_Extension/include/CGAL/Base_with_time_stamp.h @@ -18,9 +18,11 @@ namespace CGAL { template <typename Base> class Base_with_time_stamp : public Base { - std::size_t time_stamp_ = -1; + std::size_t time_stamp_ = std::size_t(-2); public: - typedef CGAL::Tag_true Has_timestamp; + using Base::Base; + + using Has_timestamp = CGAL::Tag_true; std::size_t time_stamp() const { return time_stamp_; diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 81ff5cf1bce..073300c8a82 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -27,6 +27,7 @@ #include <functional> #include <atomic> +#include <CGAL/use.h> #include <CGAL/memory.h> #include <CGAL/iterator.h> #include <CGAL/CC_safe_handle.h> @@ -271,7 +272,7 @@ class Compact_container { init(); block_size = c.block_size; - time_stamp = c.time_stamp.load(); + time_stamp = 0; std::copy(c.begin(), c.end(), CGAL::inserter(*this)); } @@ -302,6 +303,20 @@ class Compact_container clear(); } + bool check_timestamps_are_valid() const { + if constexpr (Time_stamper::has_timestamp) { + for(size_type i = 0, end = capacity(); i < end; ++i) { + if(!is_used(i)) { + continue; + } + if(Time_stamper::time_stamp(&operator[](i)) != i) { + return false; + } + } + } + return true; + } + bool is_used(const_iterator ptr) const { return (type(&*ptr)==USED); @@ -382,10 +397,18 @@ class Compact_container pointer ret = free_list; free_list = clean_pointee(ret); + std::size_t ts; + CGAL_USE(ts); + if constexpr (Time_stamper::has_timestamp) { + ts = ret->time_stamp(); + } new (ret) value_type(args...); + if constexpr (Time_stamper::has_timestamp) { + ret->set_time_stamp(ts); + } + Time_stamper::set_time_stamp(ret, time_stamp); CGAL_assertion(type(ret) == USED); ++size_; - Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -396,10 +419,18 @@ class Compact_container pointer ret = free_list; free_list = clean_pointee(ret); + std::size_t ts; + CGAL_USE(ts); + if constexpr (Time_stamper::has_timestamp) { + ts = ret->time_stamp(); + } std::allocator_traits<allocator_type>::construct(alloc, ret, t); + if constexpr (Time_stamper::has_timestamp) { + ret->set_time_stamp(ts); + } + Time_stamper::set_time_stamp(ret, time_stamp); CGAL_assertion(type(ret) == USED); ++size_; - Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -424,7 +455,15 @@ class Compact_container CGAL_precondition(type(&*x) == USED); EraseCounterStrategy::increment_erase_counter(*x); + std::size_t ts; + CGAL_USE(ts); + if constexpr (Time_stamper::has_timestamp) { + ts = x->time_stamp(); + } std::allocator_traits<allocator_type>::destroy(alloc, &*x); + if constexpr (Time_stamper::has_timestamp) { + x->set_time_stamp(ts); + } put_on_free_list(&*x); --size_; @@ -1166,6 +1205,61 @@ class Output_rep<CGAL::internal::CC_iterator<DSC, Const> > { } }; +struct With_offset_tag { + int offset = 0; +}; + +struct With_point_tag : public With_offset_tag { +}; + +struct With_point_and_info_tag : public With_point_tag {}; + +template <class DSC, bool Const> +struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_offset_tag> + : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>> +{ + int offset = 0; + + using CC_iterator = CGAL::internal::CC_iterator<DSC, Const>; + using Compact_container = typename CC_iterator::CC; + using Time_stamper = typename Compact_container::Time_stamper; + using Base = Output_rep<CC_iterator>; + using Base::Base; + + Output_rep(const CC_iterator it, With_offset_tag tag = {}) + : Base(it), offset(tag.offset) {} + + std::ostream& operator()(std::ostream& out) const { + out << Time_stamper::display_id(this->it.operator->(), offset); + return out; + } +}; + +template <class DSC, bool Const> +struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag> + : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_offset_tag> +{ + using CC_iterator = CGAL::internal::CC_iterator<DSC, Const>; + using Base = Output_rep<CC_iterator, With_offset_tag>; + using Time_stamper = typename Base::Time_stamper; + + using Base::Base; + + Output_rep(const CC_iterator it, With_point_tag tag = {}) + : Base(it, tag) {} + + std::ostream& operator()(std::ostream& out) const { + this->Base::operator()(out); + if(this->it.operator->() != nullptr) { + if(Time_stamper::time_stamp(this->it.operator->()) == 0) + return out << "= infinite_vertex()"; + return out << "= " << this->it->point(); + } + else + return out; + } +}; + } //namespace CGAL namespace std { @@ -1183,7 +1277,6 @@ namespace std { }; #endif // CGAL_CFG_NO_STD_HASH - } // namespace std #include <CGAL/enable_warnings.h> diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index f48f5307ef0..295717b8041 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -28,12 +28,15 @@ constexpr size_t rounded_down_log2(size_t n) template <typename T> struct Time_stamper { + static constexpr bool has_timestamp = true; + static void initialize_time_stamp(T* pt) { pt->set_time_stamp(std::size_t(-1)); } template <typename time_stamp_t> static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) { + CGAL_assertion(pt->time_stamp() != std::size_t(-2)); if(pt->time_stamp() == std::size_t(-1)) { const std::size_t new_ts = time_stamp_++; pt->set_time_stamp(new_ts); @@ -61,18 +64,23 @@ struct Time_stamper static std::size_t time_stamp(const T* pt) { + CGAL_assertion(pt == nullptr || pt->time_stamp() != std::size_t(-2)); if(pt == nullptr){ return std::size_t(-1); } return pt->time_stamp(); } - static auto display_id(const T* pt) + static auto display_id(const T* pt, int offset = 0) { - return std::string("#") + std::to_string(pt->time_stamp()); + if(pt == nullptr) + return std::string("nullptr"); + else + return std::string("#") + std::to_string(pt->time_stamp() + offset); } static std::size_t hash_value(const T* p) { + CGAL_assertion(p == nullptr || p->time_stamp() != std::size_t(-2)); if(nullptr == p) return std::size_t(-1); else @@ -92,6 +100,7 @@ struct Time_stamper template <typename T> struct No_time_stamp { + static constexpr bool has_timestamp = false; public: template <typename time_stamp_t> static void set_time_stamp(T*, time_stamp_t&) {} @@ -107,7 +116,7 @@ struct No_time_stamp return 0; } - static auto display_id(const T* pt) + static auto display_id(const T* pt, int) { return static_cast<const void*>(pt); } diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 326557344a6..0e72a1ed44e 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -25,6 +25,7 @@ #include <CGAL/circulator.h> #include <CGAL/Iterator_range.h> #include <CGAL/tuple.h> +#include <CGAL/type_traits.h> #include <CGAL/use.h> #include <variant> @@ -37,28 +38,34 @@ namespace CGAL { -template<typename I> +template<typename I, typename Reference_type = const I&> class Prevent_deref : public boost::iterator_adaptor< - Prevent_deref<I> + Prevent_deref<I, Reference_type> , I // base - , I // value + , CGAL::cpp20::remove_cvref_t<Reference_type> // value + , boost::use_default // category + , Reference_type // ref > { public: - typedef boost::iterator_adaptor< - Prevent_deref<I> + using Value_type = CGAL::cpp20::remove_cvref_t<Reference_type>; + using Base = boost::iterator_adaptor< + Prevent_deref<I, Reference_type> , I // base - , I // value - > Base; - typedef typename Base::reference reference; + , Value_type // value + , boost::use_default // category + , Reference_type // ref + >; typedef typename std::pair<I, I> range; - Prevent_deref() : Base() {} + Prevent_deref() = default; Prevent_deref(const I& i) : Base(i) {} private: friend class boost::iterator_core_access; - reference dereference() const { return const_cast<std::remove_reference_t<reference>&>(this->base_reference()); } + Reference_type dereference() const { + return this->base_reference(); + } }; template<typename I> @@ -608,7 +615,7 @@ struct Filter_iterator { reference operator*() const { return *c_; } pointer operator->() const { return &*c_; } const Predicate& predicate() const { return p_; } - Iterator base() const { return c_; } + const Iterator& base() const { return c_; } Iterator end() const { return e_; } bool is_end() const { return (c_ == e_); } diff --git a/STL_Extension/include/CGAL/utility.h b/STL_Extension/include/CGAL/utility.h index 277476c6079..88f63fb115b 100644 --- a/STL_Extension/include/CGAL/utility.h +++ b/STL_Extension/include/CGAL/utility.h @@ -295,22 +295,8 @@ struct Default_using_type }; }; -template <class T_ = Default_using_type> -struct less_cpp14 -{ - template <class T1, class T2> - bool operator() (T1&& t1, T2&& t2) const - { - typedef typename Default_using_type::Get< - T_, - typename std::common_type<typename std::decay<T1>::type, - typename std::decay<T2>::type> >::type T; - return std::less<T>()(t1,t2); - } -}; - template <class T = Default_using_type, - class Compare = less_cpp14<T>, + class Compare = std::less<>, class T1, class T2, class A = typename Default_using_type::Get<T, typename std::common_type< @@ -323,6 +309,40 @@ inline P make_sorted_pair(T1&& t1, T2&& t2, Compare comp = Compare()) : P(std::forward<T2>(t2), std::forward<T1>(t1)); } +template <class Pair> +auto make_sorted_pair(Pair&& pair) { + auto&& [a, b] = std::forward<Pair>(pair); + return make_sorted_pair(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b)); +} + +template <class F> +class [[nodiscard]] Scope_exit { + CGAL_NO_UNIQUE_ADDRESS F exit_function; + +public: + template <typename G> + explicit Scope_exit(G&& g, std::enable_if_t<!std::is_same_v<std::decay_t<G>, Scope_exit>>* = nullptr) + : exit_function(std::forward<G>(g)) + { + } + + Scope_exit(const Scope_exit&) = delete; + Scope_exit& operator=(const Scope_exit&) = delete; + Scope_exit(Scope_exit&&) = delete; + Scope_exit& operator=(Scope_exit&&) = delete; + + ~Scope_exit() { + exit_function(); + } +}; + +template<typename F> Scope_exit(F) -> Scope_exit<F>; + +template <typename F> +Scope_exit<F> make_scope_exit(F&& f) { + return Scope_exit<F>(std::forward<F>(f)); +} + } //namespace CGAL namespace std { diff --git a/STL_Extension/test/STL_Extension/CMakeLists.txt b/STL_Extension/test/STL_Extension/CMakeLists.txt index 3b54df0088d..4207a5aef8e 100644 --- a/STL_Extension/test/STL_Extension/CMakeLists.txt +++ b/STL_Extension/test/STL_Extension/CMakeLists.txt @@ -12,6 +12,7 @@ if(NOT TARGET CGAL::TBB_support) message(STATUS "NOTICE: Tests are not using TBB.") endif() +create_single_source_cgal_program("issue_7400.cpp") create_single_source_cgal_program("test_Boolean_tag.cpp") create_single_source_cgal_program("test_Cache.cpp") create_single_source_cgal_program("test_Compact_container.cpp") diff --git a/STL_Extension/test/STL_Extension/issue_7400.cpp b/STL_Extension/test/STL_Extension/issue_7400.cpp new file mode 100644 index 00000000000..d7787116610 --- /dev/null +++ b/STL_Extension/test/STL_Extension/issue_7400.cpp @@ -0,0 +1,54 @@ +#include <type_traits> +#include <iterator> +#include <CGAL/type_traits.h> + +// Add C++20 utilities to C++14 +template <class Iterator> +using iter_value_t = std::remove_reference_t<decltype(*std::declval<Iterator>())>; + +template<class Range> +using range_value_t = iter_value_t<CGAL::cpp20::remove_cvref_t<decltype(std::begin(std::declval<Range>()))>>; + +template< class T, class U > +constexpr bool is_same_v = std::is_same<T, U>::value; + +template< class T, class U > +constexpr bool is_convertible_v = std::is_convertible<T, U>::value; + + +#include <CGAL/Exact_predicates_inexact_constructions_kernel.h> +#include <CGAL/Triangulation_3.h> + +using Triangulation = CGAL::Triangulation_3<CGAL::Exact_predicates_inexact_constructions_kernel>; + +using Vertex_handle = Triangulation::Vertex_handle; + +Triangulation t; + +// Tds::vertex_handles() -> Vertex_handle +static_assert(is_same_v<range_value_t<decltype(t.tds().vertex_handles())>, const Vertex_handle>); + +// Triangulation::all_vertex_handles() -> Vertex_handle +static_assert(is_same_v<range_value_t<decltype(t.all_vertex_handles())>, const Vertex_handle>); + +// Triangulation::finite_vertex_handles() -> convertible to Vertex_handle +static_assert(is_convertible_v<decltype(*std::begin(t.finite_vertex_handles())), Vertex_handle>); + +// But is it equal to Vertex_handle +static_assert(is_same_v<range_value_t<decltype(t.finite_vertex_handles())>, const Vertex_handle>); + +int main() +{ + Vertex_handle v_inf = t.infinite_vertex(); + for(auto v: t.finite_vertex_handles()) { + Vertex_handle v2 = v; + CGAL_USE(v2); + if(v == v_inf) return 1; + } + for (auto v : t.all_vertex_handles()) { + Vertex_handle v2 = v; + CGAL_USE(v2); + if (v == v_inf) std::cout << "found inf" << std::endl; + } + return 0; +} diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index 60aa43db0e2..bf6b0d83948 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -305,10 +305,10 @@ int main() typedef Node_1<CGAL::Tag_false> T2; typedef CGAL::Compact_container<T2> C2; // without timestamps - typedef CGAL::Compact_container<T2, + typedef CGAL::Compact_container<T1, CGAL::Default, CGAL::Default, - CGAL::Time_stamper<T2> > C4; + CGAL::Time_stamper<T1> > C4; // with timestamps typedef Node_2 T3; @@ -337,7 +337,7 @@ int main() { std::cerr << "Error timestamper of C3\n"; return 1; } - if(! std::is_base_of<CGAL::Time_stamper<T2>, + if(! std::is_base_of<CGAL::Time_stamper<T1>, C4::Time_stamper>::value) { std::cerr << "Error timestamper of C4\n"; return 1; diff --git a/Stream_support/include/CGAL/IO/Generic_writer.h b/Stream_support/include/CGAL/IO/Generic_writer.h index b91a8a5b7f7..e425fc51866 100644 --- a/Stream_support/include/CGAL/IO/Generic_writer.h +++ b/Stream_support/include/CGAL/IO/Generic_writer.h @@ -55,7 +55,7 @@ class Generic_writer for(std::size_t i=0, end=points.size(); i<end; ++i) { const typename boost::property_traits<PointMap>::value_type& p = get(point_map, points[i]); - m_writer.write_vertex(p.x(), p.y(), p.z()); + m_writer.write_vertex(to_double(p.x()), to_double(p.y()), to_double(p.z())); } m_writer.write_facet_header(); diff --git a/Stream_support/include/CGAL/IO/PLY/PLY_reader.h b/Stream_support/include/CGAL/IO/PLY/PLY_reader.h index ee8b18ef59c..c35bc6d4141 100644 --- a/Stream_support/include/CGAL/IO/PLY/PLY_reader.h +++ b/Stream_support/include/CGAL/IO/PLY/PLY_reader.h @@ -17,7 +17,7 @@ #include <CGAL/Kernel_traits.h> #include <CGAL/property_map.h> -#include <boost/cstdint.hpp> +#include <cstdint> #include <boost/range/value_type.hpp> #include <iostream> diff --git a/Stream_support/include/CGAL/IO/io.h b/Stream_support/include/CGAL/IO/io.h index d9c2ea7f761..aa7d650e72b 100644 --- a/Stream_support/include/CGAL/IO/io.h +++ b/Stream_support/include/CGAL/IO/io.h @@ -183,7 +183,7 @@ class Output_rep public: //! initialize with a const reference to \a t. - Output_rep( const T& tt) : t(tt) {} + Output_rep( const T& tt, F = {}) : t(tt) {} //! perform the output, calls \c operator\<\< by default. std::ostream& operator()( std::ostream& os) const { return (os << t); } }; @@ -248,7 +248,12 @@ Convenience function to construct an output representation (`Output_rep`) for ty Generic IO for type `T` with formatting tag. */ template <class T, class F> -Output_rep<T,F> oformat( const T& t, F) { return Output_rep<T,F>(t); } +Output_rep<T,F> oformat( const T& t, F format) { + if constexpr (std::is_constructible_v<Output_rep<T,F>, const T&, F>) + return Output_rep<T,F>(t, format); + else + return Output_rep<T,F>(t); +} } // namespace IO @@ -990,6 +995,53 @@ inline void read_float_or_quotient(std::istream& is, Rat &z) } // namespace CGAL +#if CGAL_CAN_USE_CXX20_FORMAT +# include <format> +# include <sstream> + +namespace std { + +template <typename T, typename F, typename CharT> +struct formatter<CGAL::Output_rep<T, F>, CharT> : public std::formatter<std::basic_string<CharT>> +{ + constexpr auto parse(std::basic_format_parse_context<CharT>& ctx) + { + auto it = ctx.begin(); + const auto end = ctx.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}`"); + } + if(++it == end) + throw std::format_error("Missing precision"); + if(*it < CharT('0') || *it > CharT('9')) + throw std::format_error("Invalid value for precision"); + precision = *it - CharT('0'); + while(++it != end) { + if(*it < CharT('0') || *it > CharT('9')) + return it; + precision = precision * 10 + (*it - CharT('0')); + } + return it; + } + + template <typename FormatContext> + auto format(const CGAL::Output_rep<T, F> &rep, FormatContext& ctx) const + { + std::basic_stringstream<CharT> ss; + ss.precision(precision); + ss << rep; + return std::formatter<std::basic_string<CharT>>::format(ss.str(), ctx); + } + + int precision = 17; +}; + +} // namespace std +#endif // CGAL_CAN_USE_CXX20_FORMAT + #include <CGAL/enable_warnings.h> #endif // CGAL_IO_H diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index 322e6cef1b8..f7c386b9d3f 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -183,7 +183,7 @@ class Triangulation_data_structure_2 } Face_handles face_handles() const { - return make_prevent_deref_range(faces_begin(),faces_end()); + return { faces_begin(), faces_end() }; } Vertex_iterator vertices_begin() const { @@ -195,7 +195,7 @@ class Triangulation_data_structure_2 } Vertex_handles vertex_handles() const { - return make_prevent_deref_range(vertices_begin(),vertices_end()); + return { vertices_begin(), vertices_end() }; } Edge_iterator edges_begin() const { diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index 6f63f08162d..ca34d9f92c5 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -31,6 +31,9 @@ #include <limits> #include <boost/unordered_set.hpp> +#include <boost/container/flat_set.hpp> +#include <boost/container/small_vector.hpp> +#include <boost/iterator/function_output_iterator.hpp> #include <CGAL/utility.h> #include <CGAL/iterator.h> #include <CGAL/STL_Extension/internal/Has_member_visited.h> @@ -661,7 +664,7 @@ class Triangulation_data_structure_3 Cell_handles cell_handles() const { - return make_prevent_deref_range(cells_begin(), cells_end()); + return { cells_begin(), cells_end() }; } Cell_iterator raw_cells_begin() const @@ -720,7 +723,7 @@ class Triangulation_data_structure_3 Vertex_handles vertex_handles() const { - return make_prevent_deref_range(vertices_begin(), vertices_end()); + return { vertices_begin(), vertices_end() }; } // CIRCULATOR METHODS @@ -802,7 +805,7 @@ class Triangulation_data_structure_3 { CGAL_precondition(dimension() == 3); - std::stack<Cell_handle> cell_stack; + std::stack<Cell_handle, boost::container::small_vector<Cell_handle, 128>> cell_stack; cell_stack.push(d); d->tds_data().mark_in_conflict(); *it.first++ = d; @@ -828,13 +831,16 @@ class Triangulation_data_structure_3 return it; } - template <class IncidentFacetIterator> + template <class IncidentFacetIterator, typename CellsContainers> void incident_cells_3_threadsafe(Vertex_handle v, Cell_handle d, - std::vector<Cell_handle> &cells, + CellsContainers &cells, IncidentFacetIterator facet_it) const { - boost::unordered_set<Cell_handle, Handle_hash_function> found_cells; + boost::container::flat_set<Cell_handle, + std::less<>, + boost::container::small_vector<Cell_handle, 128>> found_cells; + // boost::unordered_set<Cell_handle, Handle_hash_function> found_cells; cells.push_back(d); found_cells.insert(d); @@ -1381,20 +1387,16 @@ class Triangulation_data_structure_3 Visitor visit(v, output, this, f); - std::vector<Cell_handle> tmp_cells; - tmp_cells.reserve(64); + boost::container::small_vector<Cell_handle, 128> tmp_cells; if ( dimension() == 3 ) incident_cells_3(v, v->cell(), std::make_pair(std::back_inserter(tmp_cells), visit.facet_it())); else incident_cells_2(v, v->cell(), std::back_inserter(tmp_cells)); - typename std::vector<Cell_handle>::iterator cit; - for(cit = tmp_cells.begin(); - cit != tmp_cells.end(); - ++cit) + for(auto c : tmp_cells) { - (*cit)->tds_data().clear(); - visit(*cit); + c->tds_data().clear(); + visit(c); } return visit.result(); @@ -1413,20 +1415,16 @@ class Triangulation_data_structure_3 Visitor visit(v, output, this, f); - std::vector<Cell_handle> tmp_cells; - tmp_cells.reserve(64); + boost::container::small_vector<Cell_handle, 128> tmp_cells; if ( dimension() == 3 ) incident_cells_3_threadsafe( v, v->cell(), tmp_cells, visit.facet_it()); else incident_cells_2(v, v->cell(), std::back_inserter(tmp_cells)); - typename std::vector<Cell_handle>::iterator cit; - for(cit = tmp_cells.begin(); - cit != tmp_cells.end(); - ++cit) + for(auto c : tmp_cells) { - visit(*cit); + visit(c); } return visit.result(); @@ -2059,29 +2057,67 @@ is_edge(Vertex_handle u, Vertex_handle v, Cell_handle &c, int &i, int &j) const // returns false when dimension <1 or when indices wrong { - CGAL_expensive_precondition( is_vertex(u) && is_vertex(v) ); + CGAL_expensive_precondition(is_vertex(u) && is_vertex(v)); - if (u==v) - return false; + if(u == v) + return false; - std::vector<Cell_handle> cells; - cells.reserve(64); - incident_cells(u, std::back_inserter(cells)); + if(dimension() == 3) { + auto d = u->cell(); + boost::container::small_vector<Cell_handle, 128> cells; + cells.emplace_back(d); + d->tds_data().mark_in_conflict(); - for (typename std::vector<Cell_handle>::iterator cit = cells.begin(); - cit != cells.end(); ++cit) - if ((*cit)->has_vertex(v, j)) { - c = *cit; - i = c->index(u); - return true; + auto cleanup_tds_data = make_scope_exit([&] { + for(auto c : cells) { + c->tds_data().clear(); + } + }); + + int head = 0; + int tail = 1; + do { + Cell_handle ch = cells[head]; + + for(j = 0; j < 4; ++j) { // use parameter j on purpose + if(ch->vertex(j) == v) { + c = ch; + i = ch->index(u); + return true; } + if(ch->vertex(j) == u) + continue; + Cell_handle next = ch->neighbor(j); + if(!next->tds_data().is_clear()) + continue; + cells.emplace_back(next); + ++tail; + next->tds_data().mark_in_conflict(); + } + ++head; + } while(head != tail); return false; + } + + bool edge_found = false; + // try { + incident_cells_threadsafe(u, boost::make_function_output_iterator([&](Cell_handle ch) { + if(ch->has_vertex(v, j)) { + c = ch; + i = c->index(u); + // throw true; + edge_found = true; + } + })); + // } catch(bool b) { + // result = b; + // } + + return edge_found; } template <class Vb, class Cb, class Ct> -bool -Triangulation_data_structure_3<Vb,Cb,Ct>:: -is_edge(Vertex_handle u, Vertex_handle v) const +bool Triangulation_data_structure_3<Vb, Cb, Ct>::is_edge(Vertex_handle u, Vertex_handle v) const { Cell_handle c; int i, j; @@ -3573,6 +3609,12 @@ is_valid(bool verbose, int level ) const size_type cell_count; if ( ! count_cells(cell_count,verbose,level) ) return false; + if( number_of_cells() != cell_count ) { + if (verbose) + std::cerr << "wrong number of cells" << std::endl; + CGAL_assertion(false); + return false; + } size_type edge_count; if ( ! count_edges(edge_count,verbose,level) ) return false; diff --git a/TDS_3/include/CGAL/Triangulation_simplex_3.h b/TDS_3/include/CGAL/Triangulation_simplex_3.h index 0754fb021c5..d00422df1ba 100644 --- a/TDS_3/include/CGAL/Triangulation_simplex_3.h +++ b/TDS_3/include/CGAL/Triangulation_simplex_3.h @@ -19,6 +19,7 @@ #include <CGAL/assertions.h> #include <algorithm> +#include <CGAL/IO/io.h> namespace CGAL { @@ -280,6 +281,57 @@ operator<< (std::ostream& os, return os; } +template < typename TriangulationDataStructure_3, typename Tag > +struct Output_rep<Triangulation_simplex_3<TriangulationDataStructure_3>, Tag > +{ + using TDS = TriangulationDataStructure_3; + using Simplex = Triangulation_simplex_3<TriangulationDataStructure_3>; + using Vertex_handle = typename Simplex::Vertex_handle; + using Edge = typename Simplex::Edge; + using Facet = typename Simplex::Facet; + using Cell_handle = typename Simplex::Cell_handle; + + Simplex simplex; + Tag tag; + + std::ostream& operator()(std::ostream& os) const { + auto display_vert = [&](auto v) { + return CGAL::IO::oformat(v, tag); + }; + switch(simplex.dimension()) { + case 0: { + os << "vertex " << display_vert(static_cast<Vertex_handle>(simplex)); + break; + } + case 1: { + const auto [c, index1, index2] = static_cast<Edge>(simplex); + os << "edge " + << display_vert(c->vertex(index1)) << " - " + << display_vert(c->vertex(index2)); + break; + } + case 2: { + const auto [c, index] = static_cast<Facet>(simplex); + os << "facet " + << display_vert(c->vertex(TDS::vertex_triple_index(index, 0))) << " - " + << display_vert(c->vertex(TDS::vertex_triple_index(index, 1))) << " - " + << display_vert(c->vertex(TDS::vertex_triple_index(index, 2))); + break; + } + case 3: { + const auto c = static_cast<Cell_handle>(simplex); + os << "cell " + << display_vert(c->vertex(0)) << " - " + << display_vert(c->vertex(1)) << " - " + << display_vert(c->vertex(2)) << " - " + << display_vert(c->vertex(3)); + break; + } + default: CGAL_assume(false); + } + return os; + } +}; } //namespace CGAL diff --git a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h index 0d810e92288..68d24483b34 100644 --- a/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h +++ b/Triangulation_2/doc/Triangulation_2/Concepts/TriangulationTraits_2.h @@ -144,6 +144,19 @@ according to the */ typedef unspecified_type Compare_y_2; +/*! +A function object that lexicographically compares two points by their Cartesian +coordinates. +It provides the operator: + +`Comparison_result operator()(Point p, Point q)` + +which returns +(`SMALLER, EQUAL` or `LARGER`) +according to the lexicographical order of points `p` and `q`. +*/ +typedef unspecified_type Compare_xy_2; + /*! A function object to compute the orientation of three points. @@ -245,6 +258,11 @@ Compare_y_2 compare_y_2_object(); /*! +*/ +Compare_xy_2 compare_xy_2_object(); + +/*! + */ Orientation_2 orientation_2_object(); diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 884644147f1..90d6448f0e5 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -37,28 +37,6 @@ #include <boost/mpl/has_xxx.hpp> #include <boost/iterator/filter_iterator.hpp> -#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS -# include <CGAL/IO/io.h> -# include <CGAL/Compact_container.h> -# include <iostream> -namespace CGAL { - -struct With_point_tag {}; - -template <class DSC, bool Const> -struct Output_rep<CGAL::internal::CC_iterator<DSC, Const>, With_point_tag> - : public Output_rep<CGAL::internal::CC_iterator<DSC, Const>> -{ - using Base = Output_rep<CGAL::internal::CC_iterator<DSC, Const>>; - using Base::Base; - - std::ostream& operator()(std::ostream& out) const { - return Base::operator()(out) << "= " << this->it->point(); - } -}; -} // namespace CGAL -#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS - namespace CGAL { struct No_constraint_intersection_tag{}; @@ -367,13 +345,9 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb, OutputIterator out) // if the segment (or a subpart of the segment) that we are trying to constraint is already // present in the triangulation and is already marked as constrained, // then this is an intersection - if(std::is_same<Itag, No_constraint_intersection_tag>::value) { - if(dimension() == 1) { - if(fr->is_constrained(2)) - throw Intersection_of_constraints_exception(); - } else { - if(fr->is_constrained(i)) - throw Intersection_of_constraints_exception(); + if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>) { + if(fr->is_constrained(dimension() == 1 ? 2 : i)) { + throw Intersection_of_constraints_exception(); } } @@ -749,7 +723,7 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) } if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { - if(std::is_same<Itag, No_constraint_intersection_tag>::value) + if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>) throw Intersection_of_constraints_exception(); insert_in_constrained_edge = true; @@ -851,7 +825,7 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) << " , " << display_vertex(vbb) << " ) remaining stack size: " << stack.size() << '\n'; - CGAL_assertion(this->is_valid()); + CGAL_assertion(this->is_valid(true)); #endif // CGAL_CDT_2_DEBUG_INTERSECTIONS Vertex_handle vi; @@ -862,13 +836,9 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) // if the segment (or a subpart of the segment) that we are trying to constraint is already // present in the triangulation and is already marked as constrained, // then this is an intersection - if(std::is_same<Itag, No_constraint_intersection_tag>::value) { - if(dimension() == 1) { - if(fr->is_constrained(2)) - throw Intersection_of_constraints_exception(); - } else { - if(fr->is_constrained(i)) - throw Intersection_of_constraints_exception(); + if constexpr (std::is_same_v<Itag, No_constraint_intersection_tag>) { + if(fr->is_constrained(dimension() == 1 ? 2 : i)) { + throw Intersection_of_constraints_exception(); } } diff --git a/Triangulation_2/include/CGAL/Regular_triangulation_2.h b/Triangulation_2/include/CGAL/Regular_triangulation_2.h index 3353b7d7603..54938928e5c 100644 --- a/Triangulation_2/include/CGAL/Regular_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Regular_triangulation_2.h @@ -162,7 +162,7 @@ class Regular_triangulation_2 Self & operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Vertex_handle() const { return Base::base(); } + operator const Vertex_handle&() const { return Base::base(); } }; typedef Iterator_range<Prevent_deref<All_vertices_iterator> > All_vertex_handles; @@ -179,10 +179,11 @@ class Regular_triangulation_2 Self & operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Vertex_handle() const { return Base::base(); } + operator const Vertex_handle&() const { return Base::base(); } }; - typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles; + typedef Iterator_range<Prevent_deref<Finite_vertices_iterator, + const Vertex_handle&>> Finite_vertex_handles; class Hidden_vertices_iterator : public Filter_iterator<Finite_vib, Unhidden_tester> @@ -196,10 +197,11 @@ class Regular_triangulation_2 Self & operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Vertex_handle() const { return Base::base(); } + operator const Vertex_handle&() const { return Base::base(); } }; - typedef Iterator_range<Prevent_deref<Hidden_vertices_iterator> > Hidden_vertex_handles; + typedef Iterator_range<Prevent_deref<Hidden_vertices_iterator, + const Vertex_handle&>> Hidden_vertex_handles; //for backward compatibility typedef Finite_faces_iterator Face_iterator; @@ -2233,7 +2235,7 @@ typename Regular_triangulation_2<Gt,Tds>::Finite_vertex_handles Regular_triangulation_2<Gt,Tds>:: finite_vertex_handles() const { - return make_prevent_deref_range(finite_vertices_begin(),finite_vertices_end()); + return { finite_vertices_begin(), finite_vertices_end() }; } template < class Gt, class Tds > @@ -2260,7 +2262,7 @@ typename Regular_triangulation_2<Gt,Tds>::Hidden_vertex_handles Regular_triangulation_2<Gt,Tds>:: hidden_vertex_handles() const { - return make_prevent_deref_range(hidden_vertices_begin(),hidden_vertices_end()); + return { hidden_vertices_begin(), hidden_vertices_end() }; } template < class Gt, class Tds > diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index c0f2c7ba50e..433ea5cb5af 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -172,7 +172,7 @@ class Triangulation_2 Self & operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Vertex_handle() const { return Base::base(); } + operator const Vertex_handle&() const { return Base::base(); } }; class Finite_faces_iterator @@ -187,7 +187,7 @@ class Triangulation_2 Self & operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Face_handle() const { return Base::base(); } + operator const Face_handle&() const { return Base::base(); } }; typedef Filter_iterator<All_edges_iterator, @@ -214,8 +214,10 @@ class Triangulation_2 typedef typename Tds::Vertex_handles All_vertex_handles; typedef typename Tds::Edges All_edges; - typedef Iterator_range<Prevent_deref<Finite_faces_iterator> > Finite_face_handles; - typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles; + typedef Iterator_range<Prevent_deref<Finite_faces_iterator, + const Face_handle&>> Finite_face_handles; + typedef Iterator_range<Prevent_deref<Finite_vertices_iterator, + const Vertex_handle&>> Finite_vertex_handles; typedef Iterator_range<Finite_edges_iterator> Finite_edges; typedef Iterator_range<Point_iterator> Points; @@ -3267,7 +3269,7 @@ typename Triangulation_2<Gt, Tds>::Finite_face_handles Triangulation_2<Gt, Tds>:: finite_face_handles() const { - return make_prevent_deref_range(finite_faces_begin(),finite_faces_end()); + return { finite_faces_begin(), finite_faces_end() }; } template <class Gt, class Tds > @@ -3296,7 +3298,7 @@ typename Triangulation_2<Gt, Tds>::Finite_vertex_handles Triangulation_2<Gt, Tds>:: finite_vertex_handles() const { - return make_prevent_deref_range(finite_vertices_begin(),finite_vertices_end()); + return { finite_vertices_begin(), finite_vertices_end() }; } template <class Gt, class Tds > @@ -3671,13 +3673,8 @@ Comparison_result Triangulation_2<Gt, Tds>:: compare_xy(const Point& p, const Point& q) const { - Comparison_result res = geom_traits().compare_x_2_object()(construct_point(p), - construct_point(q)); - if(res == EQUAL){ - return geom_traits().compare_y_2_object()(construct_point(p), - construct_point(q)); - } - return res; + return geom_traits().compare_xy_2_object()(construct_point(p), + construct_point(q)); } template <class Gt, class Tds > 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 21144872845..73a7db231ac 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 @@ -163,7 +163,7 @@ class Polyline_constraint_hierarchy_2 Vertex_it vertices_begin()const { return enclosing->skip_begin();} Vertex_it current()const {return pos;} Vertex_it vertices_end()const {return enclosing->skip_end();} - Constraint_id id() { return enclosing; } + Constraint_id id()const { return enclosing; } std::size_t number_of_vertices() const {return enclosing->skip_size(); } }; @@ -221,6 +221,7 @@ class Polyline_constraint_hierarchy_2 std::size_t 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<Context_iterator> 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();} @@ -488,6 +489,15 @@ contexts_end(T va, T vb) const return last; } +template <class T, class Compare, class Point> +auto +Polyline_constraint_hierarchy_2<T,Compare,Point>:: +contexts_range(T va, T vb) const -> Iterator_range<Context_iterator> { + Context_iterator first, last; + if( !get_contexts(va,vb,first,last)) return { first, first }; + else return { first, last }; +} + template <class T, class Compare, class Point> void Polyline_constraint_hierarchy_2<T,Compare,Point>:: diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h index 29e66a38e1b..bb3087c11ef 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h @@ -188,6 +188,19 @@ class Triangulation_test_Compare_y_2{ } }; +class Triangulation_test_Compare_xy_2{ +public: + typedef Triangulation_test_point Point; + CGAL::Comparison_result operator()( const Point& p, const Point& q) const + { + if (p.test_x() < q.test_x()) return CGAL::SMALLER; + if (p.test_x() > q.test_x()) return CGAL::LARGER; + if (p.test_y() < q.test_y()) return CGAL::SMALLER; + if (p.test_y() > q.test_y()) return CGAL::LARGER; + else return CGAL::EQUAL; + } +}; + class Triangulation_test_Orientation_2 { public: @@ -416,6 +429,7 @@ class _Triangulation_test_traits { typedef Triangulation_test_Less_y_2 Less_y_2; typedef Triangulation_test_Compare_x_2 Compare_x_2; typedef Triangulation_test_Compare_y_2 Compare_y_2; + typedef Triangulation_test_Compare_xy_2 Compare_xy_2; typedef Triangulation_test_Orientation_2 Orientation_2; typedef Triangulation_test_Side_of_oriented_circle_2 Side_of_oriented_circle_2; @@ -450,6 +464,10 @@ class _Triangulation_test_traits { compare_y_2_object() const { return Compare_y_2();} + Compare_xy_2 + compare_xy_2_object() const + { return Compare_xy_2();} + Orientation_2 orientation_2_object() const { return Orientation_2();} diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 12e92b65447..5b2df86f1e0 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -495,7 +495,7 @@ class Triangulation_3 Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Cell_handle() const { return Base::base(); } + operator const Cell_handle&() const { return Base::base(); } }; // We derive in order to add a conversion to handle. @@ -514,11 +514,13 @@ class Triangulation_3 Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator Vertex_handle() const { return Base::base(); } + operator const Vertex_handle&() const { return Base::base(); } }; - typedef Iterator_range<Prevent_deref<Finite_cells_iterator> > Finite_cell_handles; - typedef Iterator_range<Prevent_deref<Finite_vertices_iterator> > Finite_vertex_handles; + typedef Iterator_range<Prevent_deref<Finite_cells_iterator, + const Cell_handle&> > Finite_cell_handles; + typedef Iterator_range<Prevent_deref<Finite_vertices_iterator, + const Vertex_handle&> > Finite_vertex_handles; typedef Filter_iterator<Edge_iterator, Infinite_tester> Finite_edges_iterator; typedef Filter_iterator<Facet_iterator, Infinite_tester> Finite_facets_iterator; @@ -529,7 +531,8 @@ class Triangulation_3 typedef Triangulation_segment_cell_iterator_3<Self> Segment_cell_iterator; typedef Triangulation_segment_simplex_iterator_3<Self> Segment_simplex_iterator; - typedef Iterator_range<Prevent_deref<Segment_cell_iterator> > Segment_traverser_cell_handles; + typedef Iterator_range<Prevent_deref<Segment_cell_iterator, + const Cell_handle&> > Segment_traverser_cell_handles; typedef Iterator_range<Segment_simplex_iterator> Segment_traverser_simplices; private: @@ -899,6 +902,7 @@ class Triangulation_3 Cell_handle& c, int& i, int& j) const; bool is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w, Cell_handle& c, int& i, int& j, int& k) const; + bool is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w) const; bool is_cell(Cell_handle c) const; bool is_cell(Vertex_handle u, Vertex_handle v, Vertex_handle w, Vertex_handle t, @@ -1801,7 +1805,7 @@ class Triangulation_3 Finite_cell_handles finite_cell_handles() const { - return make_prevent_deref_range(finite_cells_begin(), finite_cells_end()); + return {finite_cells_begin(), finite_cells_end()}; } @@ -1831,7 +1835,7 @@ class Triangulation_3 Finite_vertex_handles finite_vertex_handles() const { - return make_prevent_deref_range(finite_vertices_begin(), finite_vertices_end()); + return {finite_vertices_begin(), finite_vertices_end()}; } Vertex_iterator vertices_begin() const { return _tds.vertices_begin(); } @@ -2266,15 +2270,13 @@ class Triangulation_3 Segment_traverser_cell_handles segment_traverser_cell_handles(Vertex_handle vs, Vertex_handle vt) const { - return make_prevent_deref_range(segment_traverser_cells_begin(vs, vt), - segment_traverser_cells_end()); + return {segment_traverser_cells_begin(vs, vt), segment_traverser_cells_end()}; } Segment_traverser_cell_handles segment_traverser_cell_handles(const Point& ps, const Point& pt, Cell_handle hint = Cell_handle()) const { - return make_prevent_deref_range(segment_traverser_cells_begin(ps, pt, hint), - segment_traverser_cells_end()); + return {segment_traverser_cells_begin(ps, pt, hint), segment_traverser_cells_end()}; } //// Segment Simplex Iterator @@ -2714,6 +2716,16 @@ is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w, return _tds.is_facet(u, v, w, c, i, j, k); } +template < class GT, class Tds, class Lds > +bool +Triangulation_3<GT,Tds,Lds>:: +is_facet(Vertex_handle u, Vertex_handle v, Vertex_handle w) const +{ + Cell_handle c; + int i; int j; int k; + return _tds.is_facet(u, v, w, c, i, j, k); +} + template < class GT, class Tds, class Lds > inline bool @@ -4976,35 +4988,22 @@ create_triangulation_inner_map(const Triangulation& t, const Vertex_handle_unique_hash_map& vmap, bool all_cells) { Vertex_triple_Facet_map inner_map; - - if(all_cells) - { - for(All_cells_iterator it = t.all_cells_begin(), - end = t.all_cells_end(); it != end; ++it) - { - for(unsigned int index=0; index < 4; index++) - { - Facet f = std::pair<Cell_handle,int>(it,index); - Vertex_triple vt_aux = make_vertex_triple(f); - Vertex_triple vt{vmap[vt_aux[0]], vmap[vt_aux[2]], vmap[vt_aux[1]]}; - make_canonical_oriented_triple(vt); - inner_map[vt] = f; - } - } - } else - { - for(Finite_cells_iterator it = t.finite_cells_begin(), - end = t.finite_cells_end(); it != end; ++it) - { - for(unsigned int index=0; index < 4; index++) - { - Facet f = std::pair<Cell_handle,int>(it,index); + auto create_triangulation_inner_map_aux = [&](const auto& cells_range) { + for(auto ch : cells_range) { + for(unsigned int index = 0; index < 4; index++) { + Facet f = std::pair<Cell_handle, int>(ch, index); Vertex_triple vt_aux = make_vertex_triple(f); Vertex_triple vt{vmap[vt_aux[0]], vmap[vt_aux[2]], vmap[vt_aux[1]]}; make_canonical_oriented_triple(vt); inner_map[vt] = f; } } + }; + + if(all_cells) { + create_triangulation_inner_map_aux(t.all_cell_handles()); + } else { + create_triangulation_inner_map_aux(t.finite_cell_handles()); } return inner_map; } @@ -5095,7 +5094,7 @@ Triangulation_3<Gt,Tds,Lds>:: copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, Vertex_triple_Facet_map&& outer_map, const Vertex_triple_Facet_map& inner_map, - OutputItCells fit) + OutputItCells cit) { while(! outer_map.empty()) { @@ -5109,20 +5108,20 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, // because the infinite vertices are different } - typename Vertex_triple_Facet_map::value_type o_vt_f_pair = *oit; + const auto vertex_triple = oit->first; + const auto facet = oit->second; outer_map.erase(oit); - Cell_handle o_ch = o_vt_f_pair.second.first; - unsigned int o_i = o_vt_f_pair.second.second; + const Cell_handle o_ch = facet.first; + const unsigned int o_i = facet.second; - auto iit = inner_map.find(o_vt_f_pair.first); + const auto iit = inner_map.find(vertex_triple); CGAL_assertion(iit != inner_map.end()); - typename Vertex_triple_Facet_map::value_type i_vt_f_pair = *iit; - Cell_handle i_ch = i_vt_f_pair.second.first; - unsigned int i_i = i_vt_f_pair.second.second; + const auto i_facet = iit->second; + const Cell_handle i_ch = i_facet.first; + const unsigned int i_i = i_facet.second; // Create a new cell and glue it to the outer surface Cell_handle new_ch = tds().create_cell(); - *fit++ = new_ch; new_ch->set_vertices(vmap[i_ch->vertex(0)], vmap[i_ch->vertex(1)], vmap[i_ch->vertex(2)], vmap[i_ch->vertex(3)]); @@ -5132,12 +5131,14 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, for(int j=0; j<4; j++) new_ch->vertex(j)->set_cell(new_ch); + *cit++ = new_ch; + // For the other faces check, if they can also be glued for(unsigned int index = 0; index < 4; index++) { if(index != i_i) { - Facet f = std::pair<Cell_handle, int>(new_ch, index); + Facet f{new_ch, index}; Vertex_triple vt = make_vertex_triple(f); make_canonical_oriented_triple(vt); std::swap(vt[1], vt[2]); @@ -5151,9 +5152,9 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, else { // glue the faces - typename Vertex_triple_Facet_map::value_type o_vt_f_pair2 = *oit2; - Cell_handle o_ch2 = o_vt_f_pair2.second.first; - int o_i2 = o_vt_f_pair2.second.second; + const auto facet2 = oit2->second; + const Cell_handle o_ch2 = facet2.first; + const int o_i2 = facet2.second; o_ch2->set_neighbor(o_i2, new_ch); new_ch->set_neighbor(index, o_ch2); outer_map.erase(oit2); @@ -5161,7 +5162,7 @@ copy_triangulation_into_hole(const Vertex_handle_unique_hash_map& vmap, } } } - return fit; + return cit; } diff --git a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h index e588e7f6cf9..2f75230ebbd 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h +++ b/Triangulation_3/include/CGAL/Triangulation_3/internal/Triangulation_segment_traverser_3_impl.h @@ -505,9 +505,15 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre continue; } const Point* const backup_vert_li = std::exchange(vert[li], &_target); - + bool op_li_is_null = false; + if(_t_vertex != Vertex_handle()) { + for(int i = 0; i < 4; ++i) { + if(li == i) continue; + if(cur_cell->vertex(i) == _t_vertex) op_li_is_null = true; + } + } // Check if the target is on the opposite side of the supporting plane. - op[li] = _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); + op[li] = op_li_is_null ? ZERO : _tr->orientation(*vert[0], *vert[1], *vert[2], *vert[3]); if(op[li] == POSITIVE) pos += li; if(op[li] != NEGATIVE) { @@ -597,7 +603,7 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre // The target lies inside this cell. CGAL_assertion( incell ); return { - [&]() -> Simplex { + std::invoke([&]() -> Simplex { switch( op[0] + op[1] + op[2] + op[3] ) { case 4: CGAL_assertion( pos == 6 ); @@ -625,7 +631,7 @@ Triangulation_segment_cell_iterator_3<Tr,Inc>::walk_to_next_3(const Simplex& pre default: CGAL_unreachable(); } - }(), + }), { Cell_handle() } }; } @@ -748,7 +754,7 @@ template < class Tr, class Inc > void Triangulation_segment_cell_iterator_3<Tr,Inc>:: walk_to_next_2() { - std::array<Point*, 3> vert + const std::array<const Point*, 3> vert = { &(cell()->vertex(0)->point()), &(cell()->vertex(1)->point()), &(cell()->vertex(2)->point()) }; diff --git a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h index c098ec429d3..6f25e793fda 100644 --- a/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_segment_traverser_3.h @@ -328,7 +328,7 @@ class Triangulation_segment_cell_iterator_3 // provides a conversion operator. /* \return a handle to the current cell. */ - operator Cell_handle() const + operator const Cell_handle&() const { return _cur.cell; } diff --git a/Triangulation_3/test/Triangulation_3/data/1435440-min1.off b/Triangulation_3/test/Triangulation_3/data/1435440-min1.off new file mode 100644 index 00000000000..ebaac7effc6 --- /dev/null +++ b/Triangulation_3/test/Triangulation_3/data/1435440-min1.off @@ -0,0 +1,44 @@ +OFF +24 16 0 + +123.67813110351562 60.241893768310547 65.796310424804688 +120.50373840332031 57.575332641601562 65.796310424804688 +120.533935546875 57.536079406738281 39.293754577636719 +115.67936706542969 54.544418334960938 16.005954742431641 +117.02452850341797 55.327865600585938 16.005954742431641 +117.08579254150391 55.232322692871094 21.716342926025391 +118.41075134277344 56.176109313964844 18.36799430847168 +118.40937805175781 56.175144195556641 18.36907958984375 +118.29840850830078 56.096733093261719 18.45704460144043 +118.2930908203125 56.092964172363281 18.462148666381836 +118.28346252441406 56.086151123046875 18.471376419067383 +118.189697265625 56.019577026367188 18.57948112487793 +118.18498229980469 56.016223907470703 18.584924697875977 +118.10399627685547 55.958229064941406 18.713644027709961 +117.99317169189453 55.876365661621094 19.02931022644043 +117.99261474609375 55.875930786132812 19.032327651977539 +117.98808288574219 55.872333526611328 19.057277679443359 +117.97309875488281 55.859172821044922 19.2037353515625 +117.97169494628906 55.857933044433594 19.217502593994141 +137.00740051269531 110.97613525390625 65.796310424804688 +137.4010009765625 109.5654296875 72.631622314453125 +136.79624938964844 110.9072265625 90.521072387695312 +117.75778198242188 56.629554748535156 18.515251159667969 +117.81118774414062 56.667350769042969 18.465158462524414 +3 0 1 2 +3 3 4 5 +3 4 6 7 +3 4 7 8 +3 8 9 4 +3 4 9 10 +3 4 10 11 +3 11 12 4 +3 4 12 13 +3 4 14 15 +3 4 15 16 +3 16 17 4 +3 4 17 18 +3 20 19 21 +3 22 11 10 +3 22 10 23 + diff --git a/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h b/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h index 8b3fb4f448e..35c2ef8d7e0 100644 --- a/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h +++ b/Triangulation_on_sphere_2/include/CGAL/Triangulation_on_sphere_2.h @@ -262,7 +262,7 @@ class Triangulation_on_sphere_2 Self& operator--() { Base::operator--(); return *this; } Self operator++(int) { Self tmp(*this); ++(*this); return tmp; } Self operator--(int) { Self tmp(*this); --(*this); return tmp; } - operator const Face_handle() const { return Base::base(); } + operator const Face_handle&() const { return Base::base(); } }; typedef Iterator_range<Prevent_deref<Vertices_iterator> > Vertex_handles; @@ -275,7 +275,7 @@ class Triangulation_on_sphere_2 // solid edges: both incident faces are solid typedef Filter_iterator<All_edges_iterator, Ghost_tester> Solid_edges_iterator; typedef Iterator_range<Solid_edges_iterator> Solid_edges; - typedef Iterator_range<Prevent_deref<Solid_faces_iterator> > Solid_face_handles; + typedef Iterator_range<Prevent_deref<Solid_faces_iterator, const Face_handle&>> Solid_face_handles; typedef Project_point<Vertex> Pt_proj; typedef boost::transform_iterator<Pt_proj, Vertices_iterator> Point_iterator; @@ -321,7 +321,7 @@ class Triangulation_on_sphere_2 Solid_face_handles solid_faces() const { - return make_prevent_deref_range(solid_faces_begin(), solid_faces_end()); + return { solid_faces_begin(), solid_faces_end() }; } Solid_edges_iterator solid_edges_begin() const diff --git a/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp b/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp index e3c66570792..06f8ce3c290 100644 --- a/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp +++ b/Triangulation_on_sphere_2/test/Triangulation_on_sphere_2/test_dtos.cpp @@ -98,6 +98,12 @@ int main(int, char**) assert(sfs.size() == 4); assert(tr.number_of_solid_faces() + tr.number_of_ghost_faces() == tr.number_of_faces()); + Tr::Face_handle fh = *tr.solid_faces().begin(); + for(auto f: tr.solid_faces()) { + assert(f == fh); + break; + } + Tr::Points pts = tr.points(); assert(pts.size() == tr.number_of_vertices() && pts.size() == 5);