diff --git a/.github/workflows/cmake-all.yml b/.github/workflows/cmake-all.yml index e619a597cf3..5e2faa05026 100644 --- a/.github/workflows/cmake-all.yml +++ b/.github/workflows/cmake-all.yml @@ -1,9 +1,9 @@ -name: CMake all CGAL +name: CMake Testsuite on: [push, pull_request] jobs: - build: + cmake-testsuite: runs-on: ubuntu-latest @@ -12,4 +12,21 @@ jobs: - name: install dependencies run: sudo apt-get install -y libboost-dev libboost-program-options-dev libmpfr-dev libeigen3-dev - name: configure all - run: mkdir build && cd build && CXX=clang++ cmake -DWITH_examples=ON -DWITH_tests=ON -DWITH_demos=ON .. + run: | + set -e + mkdir build && cd build && CXX=clang++ cmake -DWITH_examples=ON -DWITH_tests=ON -DWITH_demos=ON -DBUILD_TESTING=ON .. + ctest -L CGAL_cmake_testsuite + + cmake-testsuite-with-qt5: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.0.0 + - name: install dependencies + run: sudo bash -e .github/install.sh + - name: configure all + run: | + set -e + mkdir build && cd build && CXX=clang++ cmake -DWITH_examples=ON -DWITH_tests=ON -DWITH_demos=ON -DBUILD_TESTING=ON .. + ctest -L CGAL_cmake_testsuite diff --git a/.github/workflows/delete_doc.yml b/.github/workflows/delete_doc.yml index 38dbc242e31..0abf8bb7046 100644 --- a/.github/workflows/delete_doc.yml +++ b/.github/workflows/delete_doc.yml @@ -22,11 +22,10 @@ jobs: if [ -n "$(diff -q ./index.html ./tmp.html)" ]; then mv tmp.html index.html fi - if [ -d ${PR_NUMBER} ]; then - git rm -r ${PR_NUMBER} + if [ -d ${PR_NUMBER} ]; then + git rm -r ${PR_NUMBER} fi - #git diff exits with 1 if there is no diff - if git diff --quiet; then + # `git diff --quiet` exits with 1 if there is a diff + if ! git diff --quiet; then git commit -a --amend -m"base commit" && git push -f -u origin master fi - diff --git a/AABB_tree/doc/AABB_tree/Concepts/AABBGeomTraits.h b/AABB_tree/doc/AABB_tree/Concepts/AABBGeomTraits.h index e9a664c2ff8..808f4506c5c 100644 --- a/AABB_tree/doc/AABB_tree/Concepts/AABBGeomTraits.h +++ b/AABB_tree/doc/AABB_tree/Concepts/AABBGeomTraits.h @@ -3,13 +3,19 @@ \ingroup PkgAABBTreeConcepts \cgalConcept -The concept `AABBGeomTraits` defines the requirements for the first template parameter of the class `CGAL::AABB_traits`. It provides predicates and constructors to detect and compute intersections between query objects and the primitives stored in the AABB tree. In addition, it contains predicates and constructors to compute distances between a point query and the primitives stored in the AABB tree. +The concept `AABBGeomTraits` defines the requirements for the first template parameter of the class +`CGAL::AABB_traits`. It provides predicates and constructors to detect +and compute intersections between query objects and the primitives stored in the AABB tree. +In addition, it contains predicates and constructors to compute distances between a point query +and the primitives stored in the AABB tree. \cgalRefines `SearchGeomTraits_3` -\cgalHasModel Any 3D Kernel is a model of this traits concept. +\cgalHasModel All models of the concept `Kernel` \sa `CGAL::AABB_traits` +\sa `CGAL::AABB_tree` +\sa `AABBPrimitive` */ @@ -19,118 +25,123 @@ public: /// \name Types /// @{ -/*! -A number type model of `Field`. -*/ -typedef unspecified_type FT; - -/*! -Sphere type, that should be consistent with the distance function chosen for the distance queries, namely the `Squared_distance_3` functor. -*/ -typedef unspecified_type Sphere_3; - -/*! -Point type. -*/ -typedef unspecified_type Point_3; - /*! A functor object to detect intersections between two geometric objects. -Provides the operators: -`bool operator()(const Type_1& type_1, const Type_2& type_2);` -where `Type_1` and `Type_2` are relevant types -among `Ray_3`, `Segment_3`, `Line_3`, `Triangle_3`, `Plane_3` and `Bbox_3`. Relevant herein means that a line primitive (ray, segment, line) is tested against a planar or solid primitive (plane, triangle, box), and a solid primitive is tested against another solid primitive (box against box). The operator returns `true` iff `type_1` and `type_2` have a non empty intersection. +Provides the following operators: + +`bool operator()(Query, Bbox_3)`, + +`bool operator()(Query, Primitive::Datum)`, + +`bool operator()(Sphere_3, Bbox_3)`. + +The operator returns `true` iff there exists a non-empty intersection. */ typedef unspecified_type Do_intersect_3; /*! A functor object to construct the intersection between two geometric objects. -Provides the operators: -`decltype(auto) operator()(const A& a, const B& b);` -where `A` and `B` are any relevant types among `Ray_3`, `Segment_3`, `Line_3`, -`Triangle_3`, `Plane_3` and `Bbox_3`. -Relevant herein means that a line primitive (ray, segment, line) is tested -against a planar or solid primitive (plane, triangle, box). -A model of `Kernel::Intersect_3` fulfills those requirements. +Provides the operator: + +`return_type operator()(const Query& q, const Primitive::Datum& d)`, + +which computes the intersection between `q` and `d`. The type of the returned object +must be a `boost::optional` of a `boost::variant` of the possible intersection types. */ typedef unspecified_type Intersect_3; /*! -A functor object to construct the sphere centered at one point and passing through another one. Provides the operator: -- `Sphere_3 operator()(const Point_3& p, const FT & sr)` which returns the sphere centered at `p` with `sr` as squared radius. +A functor object to construct the sphere centered at one point and passing through another one. +Provides the operator: + +`Sphere_3 operator()(const Point_3& p, const FT & sr)`, + +which returns the sphere centered at `p` with `sr` as squared radius. */ typedef unspecified_type Construct_sphere_3; /*! -A functor object to compute the point on a geometric primitive which is closest from a query. Provides the operator: -`Point_3 operator()(const Type_2& type_2, const Point_3& p);` where `Type_2` can be any of the following types : `Segment_3`, `Ray_3`, or `Triangle_3`. -The operator returns the point on `type_2` which is closest to `p`. +A functor object to compute the point on a geometric primitive which is closest from a query. +Provides the operator: + +`Point_3 operator()(const Primitive::Datum& d, const Point_3& p)`, + +which returns the point on `d` that is closest to `p`. */ typedef unspecified_type Construct_projected_point_3; /*! -A functor object to compare the distance of two points wrt a third one. -Provides the operator: -`CGAL::Comparision_result operator()(const Point_3& p1, const Point_3& p2, const Point_3& p3)`. The operator compare the distance between `p1 and `p2`, and between `p2` and `p3`. +A functor object to compare the distance of two points wrt a third one. Provides the operator: + +`CGAL::Comparision_result operator()(const Point_3& p1, const Point_3& p2, const Point_3& p3)`, + +which compares the distance between `p1 and `p2`, and between `p2` and `p3`. */ typedef unspecified_type Compare_distance_3; /*! -A functor object to detect if a point lies inside a sphere or not. +A functor object to compute the squared radius of a sphere. Provides the operator: -`bool operator()(const Sphere_3& s, const Point_3& p);` which returns `true` iff the closed volume bounded by `s` contains `p`. -*/ -typedef unspecified_type Has_on_bounded_side_3; -/*! -A functor object to compute the squared radius of a sphere. Provides the operator: -`FT operator()(const Sphere_3& s);` which returns the squared radius of `s`. +`FT operator()(const Sphere_3& s),` + +which returns the squared radius of `s`. */ typedef unspecified_type Compute_squared_radius_3; /*! A functor object to compute the squared distance between two points. Provides the operator: -`FT operator()(const Point_3& p, const Point_3& q);}` which returns the squared distance between `p` and `q`. + +`FT operator()(const Point_3& p, const Point_3& q),` + +which returns the squared distance between `p` and `q`. */ typedef unspecified_type Compute_squared_distance_3; /*! A functor object to compare the x-coordinates of two points. Provides the operator: -`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the x-coordinate of `p` is smaller -than the x-coordinate of `q`. + +`bool operator()(const Point_3& p, const Point_3& q)`, + + which returns `true` iff the x-coordinate of `p` is smaller than the x-coordinate of `q`. */ typedef unspecified_type Less_x_3; /*! A functor object to compare the y-coordinates of two points. Provides the operator: -`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the y-coordinate of `p` is smaller -than the y-coordinate of `q`. + +`bool operator()(const Point_3& p, const Point_3& q)`, + +which returns `true` iff the y-coordinate of `p` is smaller than the y-coordinate of `q`. */ typedef unspecified_type Less_y_3; /*! A functor object to compare the z-coordinates of two points. Provides the operator: -`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if the z-coordinate of `p` is smaller -than the z-coordinate of `q`. + +`bool operator()(const Point_3& p, const Point_3& q)`, + +which returns `true` iff the z-coordinate of `p` is smaller than the z-coordinate of `q`. */ typedef unspecified_type Less_z_3; /*! A functor object to compare two points. Provides the operator: -`bool operator()(const Point_3& p, const Point_3& q);}` which returns `true` if `p` is equal to `q`. + +`bool operator()(const Point_3& p, const Point_3& q)`, + +which returns `true` iff `p` is equal to `q`. */ typedef unspecified_type Equal_3; - - /// @} /// \name Operations /// @{ /*! -returns the intersection detection functor. +returns the intersection detection predicate. */ Do_intersect_3 do_intersect_3_object(); @@ -150,15 +161,10 @@ returns the closest point constructor. Construct_projected_point_3 construct_projected_point_3_object(); /*! -returns the compare distance constructor. +returns the compare distance predicate. */ Compare_distance_3 compare_distance_3_object(); -/*! -returns the closest point constructor. -*/ -Has_on_bounded_side_3 has_on_bounded_side_3_object(); - /*! returns the squared radius functor. */ @@ -170,22 +176,22 @@ returns the squared distance functor. Compute_squared_distance_3 compute_squared_distance_3_object(); /*! -returns the `Less_x_3` functor. +returns the `Less_x_3` predicate. */ Less_x_3 less_x_3_object(); /*! -returns the `Less_y_3` functor. +returns the `Less_y_3` predicate. */ Less_y_3 less_y_3_object(); /*! -returns the `Less_z_3` functor. +returns the `Less_z_3` predicate. */ Less_z_3 less_z_3_object(); /*! -returns the equal functor. +returns the equal predicate. */ Equal_3 equal_3_object(); diff --git a/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionGeomTraits.h b/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionGeomTraits.h index 22ce34118d3..de83a001ec8 100644 --- a/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionGeomTraits.h +++ b/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionGeomTraits.h @@ -8,7 +8,8 @@ concept `AABBGeomTraits`. In addition to the types required by define the Intersection_distance functor. \cgalRefines `AABBGeomTraits` -\cgalHasModel Any 3D Kernel is a model of this concept. + +\cgalHasModel All models of the concept `Kernel` \sa `CGAL::AABB_traits` \sa `CGAL::AABB_tree` @@ -17,11 +18,6 @@ define the Intersection_distance functor. */ class AABBRayIntersectionGeomTraits { public: - /*! - Type of a 3D point. - */ - typedef unspecified_type Point_3; - /*! Type of a 3D ray. */ diff --git a/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionTraits.h b/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionTraits.h index 2633242ab96..630a569ebfb 100644 --- a/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionTraits.h +++ b/AABB_tree/doc/AABB_tree/Concepts/AABBRayIntersectionTraits.h @@ -9,7 +9,6 @@ distance of an intersection along a ray. \cgalHasModel `CGAL::AABB_traits` -\sa `CGAL::AABB_traits` \sa `CGAL::AABB_tree` \sa `AABBPrimitive` diff --git a/AABB_tree/doc/AABB_tree/PackageDescription.txt b/AABB_tree/doc/AABB_tree/PackageDescription.txt index 931f14adb53..d59794e62d5 100644 --- a/AABB_tree/doc/AABB_tree/PackageDescription.txt +++ b/AABB_tree/doc/AABB_tree/PackageDescription.txt @@ -25,8 +25,10 @@ \cgalCRPSection{Concepts} - `AABBPrimitive` - `AABBPrimitiveWithSharedData` -- `AABBTraits` - `AABBGeomTraits` +- `AABBTraits` +- `AABBRayIntersectionGeomTraits` +- `AABBRayIntersectionTraits` \cgalCRPSection{Classes} - `CGAL::AABB_traits` diff --git a/AABB_tree/include/CGAL/AABB_traits.h b/AABB_tree/include/CGAL/AABB_traits.h index 4afce689bc9..4e83a3ad7c1 100644 --- a/AABB_tree/include/CGAL/AABB_traits.h +++ b/AABB_tree/include/CGAL/AABB_traits.h @@ -160,7 +160,7 @@ class AABB_tree; /// \tparam BboxMap must be a model of `ReadablePropertyMap` that has as key type a primitive id, /// and as value type a `Bounding_box`. /// If the type is `Default` the `Datum` must have the -/// member function `bbox()` that returns the bounding box of the primitive. +/// member function `bbox()` that returns the bounding box of the primitive. /// /// If the argument `GeomTraits` is a model of the concept \ref /// AABBRayIntersectionGeomTraits, this class is also a model of \ref @@ -366,7 +366,7 @@ public: template boost::optional< typename Intersection_and_primitive_id::Type > operator()(const Query& query, const typename AT::Primitive& primitive) const { - auto inter_res = GeomTraits().intersect_3_object()(internal::Primitive_helper::get_datum(primitive,m_traits),query); + auto inter_res = GeomTraits().intersect_3_object()(query, internal::Primitive_helper::get_datum(primitive,m_traits)); if (!inter_res) return boost::none; return boost::make_optional( std::make_pair(*inter_res, primitive.id()) ); @@ -391,9 +391,9 @@ public: GeomTraits geom_traits; Point closest_point = geom_traits.construct_projected_point_3_object()( internal::Primitive_helper::get_datum(pr,m_traits), p); - return - geom_traits.compare_distance_3_object()(p, closest_point, bound)==LARGER ? - bound : closest_point; + + return (geom_traits.compare_distance_3_object()(p, closest_point, bound) == LARGER) ? + bound : closest_point; } }; @@ -406,15 +406,6 @@ public: typedef typename AT::FT FT; typedef typename AT::Primitive Primitive; public: - template - CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const Point& bound) const - { - return GeomTraits().do_intersect_3_object() - (GeomTraits().construct_sphere_3_object() - (p, GeomTraits().compute_squared_distance_3_object()(p, bound)), pr)? - CGAL::SMALLER : CGAL::LARGER; - } - CGAL::Comparison_result operator()(const Point& p, const Bounding_box& bb, const Point& bound, Tag_true) const { return GeomTraits().do_intersect_3_object() @@ -436,6 +427,16 @@ public: return (*this)(p, bb, bound, Boolean_tag::value>()); } + // The following functions seem unused...? + template + CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const Point& bound) const + { + return GeomTraits().do_intersect_3_object() + (GeomTraits().construct_sphere_3_object() + (p, GeomTraits().compute_squared_distance_3_object()(p, bound)), pr)? + CGAL::SMALLER : CGAL::LARGER; + } + template CGAL::Comparison_result operator()(const Point& p, const Solid& pr, const FT& sq_distance) const { @@ -445,7 +446,6 @@ public: CGAL::SMALLER : CGAL::LARGER; } - }; Closest_point closest_point_object() const {return Closest_point(*this);} diff --git a/AABB_tree/test/AABB_tree/aabb_test_is_ray_intersection_geomtraits.cpp b/AABB_tree/test/AABB_tree/aabb_test_is_ray_intersection_geomtraits.cpp index 7552e4ab53d..c7198fe98e0 100644 --- a/AABB_tree/test/AABB_tree/aabb_test_is_ray_intersection_geomtraits.cpp +++ b/AABB_tree/test/AABB_tree/aabb_test_is_ray_intersection_geomtraits.cpp @@ -12,14 +12,12 @@ struct AABBGeomTraits { typedef nope Intersect_3; typedef nope Construct_sphere_3; typedef nope Compute_closest_point_3; - typedef nope Has_on_bounded_side_3; typedef nope Compute_squared_radius_3; typedef nope Compute_squared_distance_3; Do_intersect_3 do_intersect_3_object(); Intersect_3 intersect_3_object(); Construct_sphere_3 construct_sphere_3_object(); Compute_closest_point_3 compute_closest_point_3_object(); - Has_on_bounded_side_3 has_on_bounded_side_3_object(); Compute_squared_radius_3 compute_squared_radius_3_object(); Compute_squared_distance_3 compute_squared_distance_3_object(); }; /* end AABBGeomTraits */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_counting_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_counting_traits_2.h index ab71867c2bc..7aa1fded18f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_counting_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_counting_traits_2.h @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -885,11 +886,11 @@ public: /*! Clean all operation counters */ void clear_counters() - { memset(m_counters, 0, sizeof(m_counters)); } + { m_counters = {}; } private: /*! The operation counters */ - mutable size_t m_counters[NUMBER_OF_OPERATIONS]; + mutable std::array m_counters; }; template diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index b6587f4e1ab..761e38b1693 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -263,7 +263,7 @@ public: Comparison_result res = ker.compare_x_2_object()(this->_source, this->_target); - this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); + this->_info = (static_cast(Conic_arc_2::IS_VALID) | static_cast(DEGREE_1)); if (res == EQUAL) { // Mark that the segment is vertical. this->_info = (this->_info | IS_VERTICAL_SEGMENT); diff --git a/Arrangement_on_surface_2/include/CGAL/IO/Fig_stream.h b/Arrangement_on_surface_2/include/CGAL/IO/Fig_stream.h index 22562cd1663..0a89ec038a3 100644 --- a/Arrangement_on_surface_2/include/CGAL/IO/Fig_stream.h +++ b/Arrangement_on_surface_2/include/CGAL/IO/Fig_stream.h @@ -20,6 +20,7 @@ #include #include +#include #include namespace CGAL { @@ -750,14 +751,17 @@ public: return; // Prepare a string desribing the color. - char color_desc [10]; - sprintf ("#%02x%02x%02x", r, g, b); + std::stringstream out; + out << "0x" << std::hex + << std::setfill('0') << std::setw(2) << r + << std::setfill('0') << std::setw(2) << g + << std::setfill('0') << std::setw(2) << b; // Write the color to the FIG file. _ofile << "0 " // Desginates a color pseudo-object. << static_cast(color) << ' ' - << color_desc << std::endl; + << out.str() << std::endl; // Mark that the color is now defined. colors[static_cast(color)] = true; @@ -1700,7 +1704,6 @@ protected: _ofile << ' ' << ix << ' ' << iy << ' '; // Write the text. - char oct[10]; int i; for (i = 0; i < len_text; i++) @@ -1712,9 +1715,11 @@ protected: } else { - // Convert the current character to an octal string and write it. - sprintf (oct, "\\%03o", text[i]); - _ofile << oct; + // Convert the current character to an octal string and write + // it. + std::stringstream out; + out << "\\" << std::setfill('0') << std::setw(3) << std::oct << text[i]; + _ofile << out.str(); } } diff --git a/BGL/include/CGAL/boost/graph/IO/PLY.h b/BGL/include/CGAL/boost/graph/IO/PLY.h index 38af496f723..f14ad0173af 100644 --- a/BGL/include/CGAL/boost/graph/IO/PLY.h +++ b/BGL/include/CGAL/boost/graph/IO/PLY.h @@ -84,7 +84,7 @@ bool read_PLY_BGL(std::istream& is, The data is expected to represent a 2-manifold (possibly with borders). - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam Graph a model of `MutableFaceGraph` \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" @@ -266,7 +266,9 @@ bool read_PLY(const std::string& fname, Graph& g, \brief writes the graph in an output stream, using the \ref IOStreamPLY. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink + of the stream must be set to `BINARY`. \tparam Graph a model of `FaceListGraph` \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" diff --git a/BGL/include/CGAL/boost/graph/IO/STL.h b/BGL/include/CGAL/boost/graph/IO/STL.h index 11e9ed59ac1..1a1c05e082c 100644 --- a/BGL/include/CGAL/boost/graph/IO/STL.h +++ b/BGL/include/CGAL/boost/graph/IO/STL.h @@ -73,7 +73,7 @@ public: \attention The graph `g` is not cleared, and the data from the stream are appended. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam Graph a model of `MutableFaceGraph` \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" @@ -208,7 +208,9 @@ bool read_STL(const std::string& fname, Graph& g) { return read_STL(fname, g, pa \brief writes the graph `g` in the output stream `os`, using the \ref IOStreamSTL. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink of the stream + must be set to `BINARY`. \tparam Graph a model of `FaceListGraph` and `HalfedgeListGraph` \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" diff --git a/BGL/include/CGAL/boost/graph/iterator.h b/BGL/include/CGAL/boost/graph/iterator.h index c5df2626252..c8af78eaf8b 100644 --- a/BGL/include/CGAL/boost/graph/iterator.h +++ b/BGL/include/CGAL/boost/graph/iterator.h @@ -205,7 +205,7 @@ private: public: Halfedge_around_source_iterator() - : anchor(), pos(), g(0) + : anchor(), pos(), g(nullptr), winding(0) {} Halfedge_around_source_iterator(halfedge_descriptor hd, const Graph& g, int n=0) @@ -305,7 +305,7 @@ private: public: Halfedge_around_target_iterator() - : anchor(), pos(), g(0) + : anchor(), pos(), g(nullptr), winding(0) {} Halfedge_around_target_iterator(halfedge_descriptor hd, const Graph& g, int n=0) diff --git a/BGL/include/CGAL/boost/graph/split_graph_into_polylines.h b/BGL/include/CGAL/boost/graph/split_graph_into_polylines.h index 581cf898979..679d48896f1 100644 --- a/BGL/include/CGAL/boost/graph/split_graph_into_polylines.h +++ b/BGL/include/CGAL/boost/graph/split_graph_into_polylines.h @@ -153,7 +153,7 @@ void duplicate_terminal_vertices(Graph& graph, { typename boost::graph_traits::vertex_descriptor orig_v = graph[v]; typename boost::graph_traits::degree_size_type deg = degree(v, graph); - if ((deg != 0 && is_terminal(orig_v, orig)) || deg > 2) + if (deg != 2 || is_terminal(orig_v, orig)) { out_edge_iterator b, e; boost::tie(b, e) = out_edges(v, graph); @@ -170,7 +170,6 @@ void duplicate_terminal_vertices(Graph& graph, const std::pair pair = add_edge(vc, w, graph); graph[pair.first] = orig_e; } - CGAL_assertion(degree(v, graph) == 1); } } diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h index b6c086dc9c8..c86dd852c03 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Discrete_harmonic_2.h @@ -32,6 +32,8 @@ namespace CGAL { // Barycentric coordinates namespace. namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + // Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html. // [1] Reference: "M. S. Floater, K. Hormann, and G. Kos. A general construction of barycentric coordinates over convex polygons. Advances in Computational Mathematics, 24(1-4):311-331, 2006.". @@ -430,6 +432,8 @@ private: } }; +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h index 5faf72b6f98..ef4bfc7f365 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Generalized_barycentric_coordinates_2.h @@ -32,6 +32,8 @@ namespace CGAL { // Barycentric coordinates namespace. namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + // Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html. /*! @@ -585,6 +587,8 @@ private: } }; +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Mean_value_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Mean_value_2.h index abc0a783139..406d1d6b0bf 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Mean_value_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Mean_value_2.h @@ -37,6 +37,8 @@ namespace CGAL { // Barycentric coordinates namespace. namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + /////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // Try to find a square root object in the provided `Traits` class. If not, then use the default square root from CGAL. @@ -498,6 +500,8 @@ private: } }; +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Wachspress_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Wachspress_2.h index 6fecef7ffe7..f4aaa32412c 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Wachspress_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/Wachspress_2.h @@ -32,6 +32,8 @@ namespace CGAL { // Barycentric coordinates namespace. namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + // Examples: see the User Manual here - https://doc.cgal.org/latest/Manual/index.html. // [1] Reference: "M. S. Floater, K. Hormann, and G. Kos. A general construction of barycentric coordinates over convex polygons. Advances in Computational Mathematics, 24(1-4):311-331, 2006.". @@ -413,6 +415,8 @@ private: } }; +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/barycentric_enum_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/barycentric_enum_2.h index 1a0e5480dd3..740d5716beb 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/barycentric_enum_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/barycentric_enum_2.h @@ -73,6 +73,8 @@ enum class Computation_policy_2 { namespace CGAL { namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + /// \name Locations of a Query Point /// @{ @@ -142,6 +144,8 @@ enum Type_of_polygon { /// \endcond +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/segment_coordinates_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/segment_coordinates_2.h index 60514f58f51..8ef4719853c 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/segment_coordinates_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/segment_coordinates_2.h @@ -172,6 +172,8 @@ namespace Barycentric_coordinates { namespace CGAL { namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + /*! \ingroup PkgBarycentricCoordinates2RefDeprecated * The class `Segment_coordinates_2` implements barycentric coordinates with respect to an arbitrary non-degenerate segment along an arbitrary line in the plane. @@ -376,6 +378,8 @@ namespace Barycentric_coordinates { return CGAL::make_array(b_first, FT(1) - b_first); } +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h index ea16596a4ec..8fd076c12d7 100644 --- a/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h +++ b/Barycentric_coordinates_2/include/CGAL/Barycentric_coordinates_2/triangle_coordinates_2.h @@ -182,6 +182,8 @@ namespace Barycentric_coordinates { namespace CGAL { namespace Barycentric_coordinates { +#if !defined(CGAL_NO_DEPRECATED_CODE) || defined(DOXYGEN_RUNNING) + /*! * \ingroup PkgBarycentricCoordinates2RefDeprecated * The class `Triangle_coordinates_2` implements barycentric coordinates ( [1], @@ -413,6 +415,8 @@ namespace Barycentric_coordinates { return CGAL::make_array(b_first, b_second, FT(1) - b_first - b_second); } +#endif // CGAL_NO_DEPRECATED_CODE + } // namespace Barycentric_coordinates } // namespace CGAL diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_dh_deprecated_api.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_dh_deprecated_api.cpp index 221f55a02b6..c19f597f43f 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_dh_deprecated_api.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_dh_deprecated_api.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_const_linear_precision.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_const_linear_precision.cpp index ed349c1a5c4..e39d545d569 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_const_linear_precision.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_const_linear_precision.cpp @@ -1,7 +1,3 @@ -// #define HMC_SparseLU -// #define HMC_SimplicialLLT -// #define HMC_SimplicialLDLT // default - #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_triangle.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_triangle.cpp index 5f2ff679f24..73e718ebc69 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_triangle.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_triangle.cpp @@ -1,7 +1,3 @@ -// #define HMC_SparseLU -// #define HMC_SimplicialLLT -// #define HMC_SimplicialLDLT // default - #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_unit_square.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_unit_square.cpp index 8fa5a2a5e32..4dc8f6853ee 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_unit_square.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_hm_unit_square.cpp @@ -1,7 +1,3 @@ -// #define HMC_SparseLU -// #define HMC_SimplicialLLT -// #define HMC_SimplicialLDLT // default - #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_mv_deprecated_api.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_mv_deprecated_api.cpp index b41a9720a30..25436a0bd6e 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_mv_deprecated_api.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_mv_deprecated_api.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_sc_deprecated_api.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_sc_deprecated_api.cpp index 152257cd72d..d0b363c7a7e 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_sc_deprecated_api.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_sc_deprecated_api.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_tc_deprecated_api.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_tc_deprecated_api.cpp index 68db234168a..e37784a8adb 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_tc_deprecated_api.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_tc_deprecated_api.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_wp_deprecated_api.cpp b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_wp_deprecated_api.cpp index 5dc2f114399..a44bdb5391d 100644 --- a/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_wp_deprecated_api.cpp +++ b/Barycentric_coordinates_2/test/Barycentric_coordinates_2/test_wp_deprecated_api.cpp @@ -1,5 +1,3 @@ -#include -#include #include #include #include diff --git a/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h b/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h index 93a3e659a1b..3cbd077e487 100644 --- a/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h +++ b/CGAL_Core/include/CGAL/CORE/BigFloat_impl.h @@ -39,6 +39,7 @@ #include +#include #include #include #include @@ -1057,8 +1058,8 @@ void BigFloatRep :: fromString(const char *str, extLong prec ) { CGAL_INLINE_FUNCTION std::istream& BigFloatRep :: operator >>(std::istream& i) { int size = 20; - char *str = new char[size]; - char *p = str; + std::string str; + str.reserve(size); char c; int d = 0, e = 0, s = 0; // d=1 means dot is found @@ -1078,14 +1079,13 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) { // Chen Li, "if (c == EOF)" is unsafe since c is of char type and // EOF is of int tyep with a negative value -1 if (i.eof()) { - delete [] str; i.clear(std::ios::eofbit | std::ios::failbit); return i; } // the current content in "c" should be the first non-whitespace char if (c == '-' || c == '+') { - *p++ = c; + str += c; i.get(c); } @@ -1097,19 +1097,8 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) { // xxxx.xxxe+xxx.xxx: if (e && (c == '.')) break; - if (p - str == size) { - char *t = str; - str = new char[size*2]; - memcpy(str, t, size); - delete [] t; - p = str + size; - size *= 2; - } -#ifdef CGAL_CORE_DEBUG - CGAL_assertion((p-str) < size); -#endif - *p++ = c; + str += c; if (c == '.') d = 1; // Chen Li: fix a bug -- the sign of exponent can not happen before @@ -1121,24 +1110,8 @@ std::istream& BigFloatRep :: operator >>(std::istream& i) { e = 1; } - // chenli: make sure that the p is still in the range - if (p - str >= size) { - std::size_t len = p - str; - char *t = str; - str = new char[len + 1]; - memcpy(str, t, len); - delete [] t; - p = str + len; - } - -#ifdef CGAL_CORE_DEBUG - CGAL_assertion(p - str < size); -#endif - - *p = '\0'; i.putback(c); - fromString(str); - delete [] str; + fromString(str.c_str()); return i; }//operator >> diff --git a/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h b/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h index 341c83c5819..3a01758911f 100644 --- a/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h +++ b/CGAL_Core/include/CGAL/CORE/CoreAux_impl.h @@ -139,27 +139,6 @@ long gcd(long m, long n) { return p; } -// char* core_itoa(int n, char* buffer, int buffer_size) -// returns a pointer to the null-terminated string in buffer -// NOTES: -// 0. Buffer size should be 17 bytes (resp., 33 bytes, 65 bytes) on 16-bit -// (resp., 32-bit, 64-bit) machines. Formula: 1+sizeof(int)*8 bytes. -// 1. itoa(...) is available on some stdlib.h, but it is -// not defined by ANSI-C and so not all compilers support it. -// 2. Our use of sprintf(...) to do the job is known to -// be inefficient, but this is hardly critical for our usage. -// 3. A more general program should take a 3rd argument (the radix of -// output number). We assume radix 10. -CGAL_INLINE_FUNCTION -char * core_itoa(int n, char* buffer, int buffer_size) { -#if defined(_MSC_VER) - sprintf_s(buffer, buffer_size, "%d", n); -#else - CGAL_USE(buffer_size); - std::sprintf(buffer, "%d", n); -#endif - return buffer; -} /// implements the "integer mantissa" function // (See CORE_PATH/progs/ieee/frexp.cpp for details) @@ -197,11 +176,8 @@ void core_error(std::string msg, std::string file, int lineno, bool err) { << msg << std::endl; outFile.close(); if (err) { - char buf[65]; - // perror((std::string("CORE ERROR") + " (file " + file + ", line " - // + core_itoa(lineno,buf, 65) +"):" + msg + "\n").c_str()); std::cerr << (std::string("CORE ERROR") + " (file " + file + ", line " - + core_itoa(lineno,buf, 65) +"):" + msg + "\n").c_str(); + + std::to_string(lineno) +"):" + msg + "\n").c_str(); std::exit(1); //Note: do not call abort() } } diff --git a/CGAL_Core/include/CGAL/CORE/Real_impl.h b/CGAL_Core/include/CGAL/CORE/Real_impl.h index ee55ed80891..c3a3041720a 100644 --- a/CGAL_Core/include/CGAL/CORE/Real_impl.h +++ b/CGAL_Core/include/CGAL/CORE/Real_impl.h @@ -33,6 +33,7 @@ #include +#include #include #include #include @@ -189,8 +190,9 @@ void Real::constructFromString(const char *str, const extLong& prec ) CGAL_INLINE_FUNCTION std::istream& operator >>(std::istream& i, Real& x) { int size = 20; - char *str = new char[size]; - char *p = str; + std::string str; + str.reserve(size); + char c; int d = 0, e = 0, s = 0; // int done = 0; @@ -211,13 +213,12 @@ std::istream& operator >>(std::istream& i, Real& x) { if (i.eof()) { i.clear(std::ios::eofbit | std::ios::failbit); - delete [] str; return i; } // the current content in "c" should be the first non-whitespace char if (c == '-' || c == '+') { - *p++ = c; + str += c; i.get(c); } @@ -230,19 +231,9 @@ std::istream& operator >>(std::istream& i, Real& x) { // xxxx.xxxe+xxx.xxx: if (e && (c == '.')) break; - if (p - str == size) { - char *t = str; - str = new char[size*2]; - std::memcpy(str, t, size); - delete [] t; - p = str + size; - size *= 2; - } -#ifdef CORE_DEBUG - CGAL_assertion((p-str) < size); -#endif - *p++ = c; + str += c; + if (c == '.') d = 1; // Chen Li: fix a bug -- the sign of exponent can not happen before @@ -255,29 +246,13 @@ std::istream& operator >>(std::istream& i, Real& x) { } if (!i && !i.eof()) { - delete [] str; return i; } - // chenli: make sure that the p is still in the range - if (p - str >= size) { - std::ptrdiff_t len = p - str; - char *t = str; - str = new char[len + 1]; - std::memcpy(str, t, len); - delete [] t; - p = str + len; - } -#ifdef CORE_DEBUG - CGAL_assertion(p - str < size); -#endif - - *p = '\0'; i.putback(c); i.clear(); // old: x = Real(str, i.precision()); // use precision of input stream. - x = Real(str); // default precision = get_static_defInputDigits() - delete [] str; + x = Real(str.c_str()); // default precision = get_static_defInputDigits() return i; }//operator >> (std::istream&, Real&) diff --git a/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h b/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h index ce58ca93cc4..e5b2c6f9de5 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h @@ -3341,8 +3341,17 @@ namespace CartesianKernelFunctors { typedef typename K::Segment_3 Segment_3; typedef typename K::Ray_3 Ray_3; typedef typename K::FT FT; + public: - typedef Point_3 result_type; + template + struct result { + typedef const Point_3 type; + }; + + template + struct result { + typedef const Point_3& type; + }; Point_3 operator()( const Line_3& l, const Point_3& p ) const @@ -3369,15 +3378,19 @@ namespace CartesianKernelFunctors { Point_3 operator()( const Triangle_3& t, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,t,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(t,p,K()); } Point_3 operator()( const Segment_3& s, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,s,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(s,p,K()); } Point_3 operator()( const Ray_3& r, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,r,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(r,p,K()); } + + const Point_3& + operator()( const Point_3& p, const Point_3& q) const + { return CommonKernelFunctors::Construct_projected_point_3()(p,q,K()); } }; template diff --git a/Cone_spanners_2/include/CGAL/Cone_spanners_2/Plane_scan_tree_impl.h b/Cone_spanners_2/include/CGAL/Cone_spanners_2/Plane_scan_tree_impl.h index 411a671f843..b76b5a64208 100644 --- a/Cone_spanners_2/include/CGAL/Cone_spanners_2/Plane_scan_tree_impl.h +++ b/Cone_spanners_2/include/CGAL/Cone_spanners_2/Plane_scan_tree_impl.h @@ -20,7 +20,7 @@ #include - +#include #include namespace CGAL { @@ -134,9 +134,8 @@ public: _Leaf (const key_compare& less, const value_compare& vless, tree_type *const t, _leaf_type *const prev = nullptr, _leaf_type *const next = nullptr) - : _node_type (less, vless, t), prev (prev), next (next) { - std::memset (values, 0, 2*sizeof(value_type*)); - } + : _node_type (less, vless, t), values({nullptr,nullptr}), prev (prev), next (next) + {} /* Destructor. * Frees memory used for storing key-value pair, thus invalidating any @@ -242,7 +241,7 @@ protected: private: /* Key-value pairs */ - value_type* values[2]; + std::array values; /* Linked list structure of the B+ tree */ _leaf_type* prev; @@ -268,11 +267,8 @@ public: typedef typename _node_type::tree_type tree_type; _Internal (const Comp& less, const VComp& vless, tree_type *const t) - : _node_type(less, vless, t) { - std::memset (keys, 0, 2*sizeof(key_type*)); - std::memset (children, 0, 3*sizeof(_node_type*)); - std::memset (vMin, 0, 3*sizeof(mapped_type*)); - } + : _node_type(less, vless, t), keys({nullptr, nullptr}), children({nullptr, nullptr, nullptr}), vMin({nullptr, nullptr, nullptr}) + {} virtual ~_Internal() { keys[0] = nullptr; @@ -492,9 +488,9 @@ protected: } private: - const key_type* keys[2]; - _node_type* children[3]; - const mapped_type* vMin[3]; + std::array keys; + std::array< _node_type*, 3> children; + std::array vMin; }; template diff --git a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Edge_sorter.h b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Edge_sorter.h index 1516219ce2f..c54f3ab89f5 100644 --- a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Edge_sorter.h +++ b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Edge_sorter.h @@ -212,7 +212,7 @@ template SNC_point_locator* pl; public: - Edge_sorter(Container& cin) : c(cin) {} + Edge_sorter(Container& cin) : c(cin), sncp(nullptr), pl(nullptr) {} void operator()(SNC_and_PL& sncpl) { sncp = sncpl.sncp; diff --git a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Ray_hit_generator2.h b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Ray_hit_generator2.h index c0e8cdeb858..6fb98e4f858 100644 --- a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Ray_hit_generator2.h +++ b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Ray_hit_generator2.h @@ -69,7 +69,8 @@ class Ray_hit_generator2 : public Modifier_base { bool vertex_added; public: - Ray_hit_generator2(Vector_3 d, Vertex_handle v) : dir(d), vs(v) {} + Ray_hit_generator2(Vector_3 d, Vertex_handle v) + : dir(d), vs(v), sncp(nullptr), pl(nullptr), edge_splitted(false), vertex_added(false) {} Vertex_handle create_vertex_on_first_hit(const Ray_3& r) { diff --git a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Single_wall_creator.h b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Single_wall_creator.h index d0e8b498a59..5497f197db8 100644 --- a/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Single_wall_creator.h +++ b/Convex_decomposition_3/include/CGAL/Convex_decomposition_3/Single_wall_creator.h @@ -74,7 +74,7 @@ class Single_wall_creator : public Modifier_base { public: Single_wall_creator(SVertex_handle e, Vector_3 d) - : ein(e), dir(d) + : ein(e), dir(d), sncp(nullptr), pl(nullptr) #ifndef CGAL_NEF_NO_INDEXED_ITEMS , index1(0), index2(0) #endif diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 02d557a8a44..3bf83132a3a 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -160,11 +160,11 @@ public: &arrays[SMOOTH_NORMAL_COLORED_FACES]) { // Define 'Control+Q' as the new exit shortcut (default was 'Escape') - setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL+::Qt::Key_Q); + setShortcut(qglviewer::EXIT_VIEWER, ::Qt::CTRL, ::Qt::Key_Q); // Add custom key description (see keyPressEvent). setKeyDescription(::Qt::Key_C, "Switch clipping plane display mode"); - setKeyDescription(::Qt::Key_C+::Qt::AltModifier, "Toggle clipping plane rendering on/off"); + setKeyDescription(::Qt::AltModifier, ::Qt::Key_C, "Toggle clipping plane rendering on/off"); setKeyDescription(::Qt::Key_E, "Toggles edges display"); setKeyDescription(::Qt::Key_M, "Toggles mono color"); setKeyDescription(::Qt::Key_N, "Inverse direction of normals"); @@ -175,8 +175,8 @@ public: setKeyDescription(::Qt::Key_W, "Toggles faces display"); setKeyDescription(::Qt::Key_Plus, "Increase size of edges"); setKeyDescription(::Qt::Key_Minus, "Decrease size of edges"); - setKeyDescription(::Qt::Key_Plus+::Qt::ControlModifier, "Increase size of vertices"); - setKeyDescription(::Qt::Key_Minus+::Qt::ControlModifier, "Decrease size of vertices"); + setKeyDescription(::Qt::ControlModifier, ::Qt::Key_Plus, "Increase size of vertices"); + setKeyDescription(::Qt::ControlModifier, ::Qt::Key_Minus, "Decrease size of vertices"); setKeyDescription(::Qt::Key_PageDown, "Increase light (all colors, use shift/alt/ctrl for one rgb component)"); setKeyDescription(::Qt::Key_PageUp, "Decrease light (all colors, use shift/alt/ctrl for one rgb component)"); setKeyDescription(::Qt::Key_O, "Toggles 2D mode only"); diff --git a/GraphicsView/include/CGAL/Qt/qglviewer.h b/GraphicsView/include/CGAL/Qt/qglviewer.h index 1c11c9e4a52..da0dbace517 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer.h @@ -833,8 +833,26 @@ public: public Q_SLOTS: void setShortcut(qglviewer::KeyboardAction action, unsigned int key); + void setShortcut(qglviewer::KeyboardAction action, ::Qt::Modifier modifier, ::Qt::Key key) + { + setShortcut(action, + static_cast(modifier)+ + static_cast(key)); + } void setKeyDescription(unsigned int key, QString description); + void setKeyDescription(::Qt::KeyboardModifier modifier, ::Qt::Key key, QString description) + { + setKeyDescription(static_cast(modifier) + + static_cast(key), + description); + } + void setKeyDescription(::Qt::Modifier modifier, ::Qt::Key key, QString description) + { + setKeyDescription(static_cast(modifier) + + static_cast(key), + description); + } void clearShortcuts(); // Key Frames shortcut keys diff --git a/GraphicsView/include/CGAL/Qt/qglviewer_impl.h b/GraphicsView/include/CGAL/Qt/qglviewer_impl.h index 7aa487408c3..70fdfdd9a15 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer_impl.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer_impl.h @@ -657,10 +657,10 @@ void CGAL::QGLViewer::setDefaultShortcuts() { setShortcut(qglviewer::DRAW_AXIS, ::Qt::Key_A); setShortcut(qglviewer::DRAW_GRID, ::Qt::Key_G); setShortcut(qglviewer::DISPLAY_FPS, ::Qt::Key_F); - setShortcut(qglviewer::ENABLE_TEXT, ::Qt::SHIFT + ::Qt::Key_Question); + setShortcut(qglviewer::ENABLE_TEXT, ::Qt::SHIFT, ::Qt::Key_Question); setShortcut(qglviewer::EXIT_VIEWER, ::Qt::Key_Escape); setShortcut(qglviewer::CAMERA_MODE, ::Qt::Key_Space); - setShortcut(qglviewer::FULL_SCREEN, ::Qt::ALT + ::Qt::Key_Return); + setShortcut(qglviewer::FULL_SCREEN, ::Qt::ALT, ::Qt::Key_Return); setShortcut(qglviewer::ANIMATION, ::Qt::Key_Return); setShortcut(qglviewer::HELP, ::Qt::Key_H); setShortcut(qglviewer::MOVE_CAMERA_LEFT, ::Qt::Key_Left); diff --git a/Heat_method_3/doc/Heat_method_3/Concepts/HeatMethodTraits_3.h b/Heat_method_3/doc/Heat_method_3/Concepts/HeatMethodTraits_3.h index f33440e95cf..dcfe6d573e0 100644 --- a/Heat_method_3/doc/Heat_method_3/Concepts/HeatMethodTraits_3.h +++ b/Heat_method_3/doc/Heat_method_3/Concepts/HeatMethodTraits_3.h @@ -49,6 +49,8 @@ public: /// Functor with operator: `FT operator()(const Point_3& p, const Point_3& q) const` which computes the squared distance between `p` and `q`. typedef unspecified_type Compute_squared_distance_3; + /// Functor with operator: `FT operator()(const Vector_3& v) const` which computes the squared length of `v`. + typedef unspecified_type Compute_squared_length_3; /// @} diff --git a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h index 96f7846baa6..d8592b1346f 100644 --- a/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h +++ b/Heat_method_3/include/CGAL/Heat_method_3/Surface_mesh_geodesic_distances_3.h @@ -29,6 +29,7 @@ #include #endif +#include #include #include @@ -361,7 +362,6 @@ private: void compute_divergence() { - typename Traits::Construct_cross_product_vector_3 cross_product = Traits().construct_cross_product_vector_3_object(); typename Traits::Compute_scalar_product_3 scalar_product = Traits().compute_scalar_product_3_object(); typename Traits::Construct_vector_3 construct_vector = Traits().construct_vector_3_object(); Matrix indexD(dimension,1); @@ -374,36 +374,30 @@ private: Index i = get(vertex_id_map, current); Index j = get(vertex_id_map, neighbor_one); Index k = get(vertex_id_map, neighbor_two); - VertexPointMap_reference p_i = get(vpm,current); + VertexPointMap_reference p_i = get(vpm, current); VertexPointMap_reference p_j = get(vpm, neighbor_one); VertexPointMap_reference p_k = get(vpm, neighbor_two); Index face_i = get(face_id_map, f); - Vector_3 v_ij = construct_vector(p_i,p_j); - Vector_3 v_ik = construct_vector(p_i,p_k); - Vector_3 cross = cross_product(v_ij, v_ik); - double norm_cross = CGAL::sqrt(to_double(scalar_product(cross,cross))); - double dot = to_double(scalar_product(v_ij, v_ik)); - double cotan_i = dot/norm_cross; + const Vector_3 v_ij = construct_vector(p_i, p_j); + const Vector_3 v_ik = construct_vector(p_i, p_k); + const Vector_3 v_ji = construct_vector(p_j, p_i); + const Vector_3 v_jk = construct_vector(p_j, p_k); + const Vector_3 v_ki = construct_vector(p_k, p_i); + const Vector_3 v_kj = construct_vector(p_k, p_j); - Vector_3 v_ji = construct_vector(p_j, p_i); - Vector_3 v_jk = construct_vector(p_j, p_k); + const Traits traits; + const FT cotan_i = CGAL::Weights::cotangent(p_k, p_i, p_j, traits); + const FT cotan_j = CGAL::Weights::cotangent(p_k, p_j, p_i, traits); + const FT cotan_k = CGAL::Weights::cotangent(p_j, p_k, p_i, traits); - cross = cross_product(v_ji, v_jk); - dot = to_double(scalar_product(v_ji, v_jk)); - double cotan_j = dot/norm_cross; - - Vector_3 v_ki = construct_vector(p_k,p_i); - Vector_3 v_kj = construct_vector(p_k,p_j); - - cross = cross_product(v_ki, v_kj); - dot = to_double(scalar_product(v_ki,v_kj)); - double cotan_k = dot/norm_cross; - - const Vector_3& a = m_X[face_i]; - double i_entry = (to_double(scalar_product(a,v_ij)) * cotan_k) + (to_double(scalar_product(a,v_ik)) * cotan_j); - double j_entry = (to_double(scalar_product(a,v_jk)) * cotan_i) + (to_double(scalar_product(a,v_ji)) * cotan_k); - double k_entry = (to_double(scalar_product(a,v_ki)) * cotan_j) + (to_double(scalar_product(a,v_kj)) * cotan_i); + const Vector_3& a = m_X[face_i]; + const double i_entry = (CGAL::to_double(scalar_product(a, v_ij) * cotan_k)) + + (CGAL::to_double(scalar_product(a, v_ik) * cotan_j)); + const double j_entry = (CGAL::to_double(scalar_product(a, v_jk) * cotan_i)) + + (CGAL::to_double(scalar_product(a, v_ji) * cotan_k)); + const double k_entry = (CGAL::to_double(scalar_product(a, v_ki) * cotan_j)) + + (CGAL::to_double(scalar_product(a, v_kj) * cotan_i)); indexD.add_coef(i, 0, (1./2)*i_entry); indexD.add_coef(j, 0, (1./2)*j_entry); @@ -549,47 +543,40 @@ private: Index k = get(vertex_id_map, neighbor_two); Point_3 pi, pj, pk; - VertexPointMap_reference p_i = get(vpm,current); + const Traits traits; + VertexPointMap_reference p_i = get(vpm, current); VertexPointMap_reference p_j = get(vpm, neighbor_one); VertexPointMap_reference p_k = get(vpm, neighbor_two); pi = p_i; pj = p_j; pk = p_k; - Vector_3 v_ij = construct_vector(p_i,p_j); - Vector_3 v_ik = construct_vector(p_i,p_k); + const double cotan_i = CGAL::to_double( + CGAL::Weights::cotangent(pk, pi, pj, traits)); + m_cotan_matrix.add_coef(j, k, -(1./2) * cotan_i); + m_cotan_matrix.add_coef(k, j, -(1./2) * cotan_i); + m_cotan_matrix.add_coef(j, j, (1./2) * cotan_i); + m_cotan_matrix.add_coef(k, k, (1./2) * cotan_i); - Vector_3 cross = cross_product(v_ij, v_ik); - double dot = to_double(scalar_product(v_ij,v_ik)); + const double cotan_j = CGAL::to_double( + CGAL::Weights::cotangent(pk, pj, pi, traits)); + m_cotan_matrix.add_coef(i, k, -(1./2) * cotan_j); + m_cotan_matrix.add_coef(k, i, -(1./2) * cotan_j); + m_cotan_matrix.add_coef(i, i, (1./2) * cotan_j); + m_cotan_matrix.add_coef(k, k, (1./2) * cotan_j); - double norm_cross = (CGAL::sqrt(to_double(scalar_product(cross,cross)))); + const double cotan_k = CGAL::to_double( + CGAL::Weights::cotangent(pj, pk, pi, traits)); + m_cotan_matrix.add_coef(i, j, -(1./2) * cotan_k); + m_cotan_matrix.add_coef(j, i, -(1./2) * cotan_k); + m_cotan_matrix.add_coef(i, i, (1./2) * cotan_k); + m_cotan_matrix.add_coef(j, j, (1./2) * cotan_k); - double cotan_i = dot/norm_cross; - m_cotan_matrix.add_coef(j,k ,-(1./2)*cotan_i); - m_cotan_matrix.add_coef(k,j,-(1./2)* cotan_i); - m_cotan_matrix.add_coef(j,j,(1./2)*cotan_i); - m_cotan_matrix.add_coef(k,k,(1./2)* cotan_i); - - Vector_3 v_ji = construct_vector(p_j,p_i); - Vector_3 v_jk = construct_vector(p_j,p_k); - - cross = cross_product(v_ji, v_jk); - dot = to_double(scalar_product(v_ji, v_jk)); - double cotan_j = dot/norm_cross; - m_cotan_matrix.add_coef(i,k ,-(1./2)*cotan_j); - m_cotan_matrix.add_coef(k,i,-(1./2)* cotan_j); - m_cotan_matrix.add_coef(i,i,(1./2)* cotan_j); - m_cotan_matrix.add_coef(k,k,(1./2)* cotan_j); - - Vector_3 v_ki = construct_vector(p_k,p_i); - Vector_3 v_kj = construct_vector(p_k,p_j); - cross = cross_product(v_ki, v_kj); - dot = to_double(scalar_product(v_ki,v_kj)); - double cotan_k = dot/norm_cross; - m_cotan_matrix.add_coef(i,j,-(1./2)*cotan_k); - m_cotan_matrix.add_coef(j,i,-(1./2)* cotan_k); - m_cotan_matrix.add_coef(i,i,(1./2)* cotan_k); - m_cotan_matrix.add_coef(j,j,(1./2)* cotan_k); + const Vector_3 v_ij = construct_vector(p_i, p_j); + const Vector_3 v_ik = construct_vector(p_i, p_k); + const Vector_3 cross = cross_product(v_ij, v_ik); + const double norm_cross = CGAL::sqrt( + CGAL::to_double(scalar_product(cross, cross))); //double area_face = CGAL::Polygon_mesh_processing::face_area(f,tm); //cross is 2*area diff --git a/Heat_method_3/package_info/Heat_method_3/dependencies b/Heat_method_3/package_info/Heat_method_3/dependencies index 90510db1ab2..50488d5544f 100644 --- a/Heat_method_3/package_info/Heat_method_3/dependencies +++ b/Heat_method_3/package_info/Heat_method_3/dependencies @@ -18,3 +18,4 @@ Random_numbers STL_Extension Solver_interface Stream_support +Weights diff --git a/Heat_method_3/test/Heat_method_3/Heat_method_traits_3.h b/Heat_method_3/test/Heat_method_3/Heat_method_traits_3.h index b64613c641b..8b8e28c76f4 100644 --- a/Heat_method_3/test/Heat_method_3/Heat_method_traits_3.h +++ b/Heat_method_3/test/Heat_method_3/Heat_method_traits_3.h @@ -59,6 +59,11 @@ struct Heat_method_traits_3 { return 0;} }; + struct Compute_squared_length_3 { + + double operator()(const Vector_3&) const + { return 0;} + }; Construct_vector_3 construct_vector_3_object() const { @@ -79,6 +84,11 @@ struct Heat_method_traits_3 return Compute_squared_distance_3(); } + Compute_squared_length_3 compute_squared_length_3_object() const + { + return Compute_squared_length_3(); + } + Compute_scalar_product_3 compute_scalar_product_3_object() const { return Compute_scalar_product_3(); diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/SphereH3.h b/Homogeneous_kernel/include/CGAL/Homogeneous/SphereH3.h index 2515212200a..a00ec51b275 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/SphereH3.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/SphereH3.h @@ -198,7 +198,7 @@ template CGAL_KERNEL_MEDIUM_INLINE Oriented_side SphereH3::oriented_side(const typename SphereH3::Point_3& p) const -{ return Oriented_side(bounded_side(p) * orientation()); } +{ return Oriented_side(static_cast(bounded_side(p)) * static_cast(orientation())); } template CGAL_KERNEL_INLINE diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h b/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h index 8091a640d18..833d09e413d 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h @@ -3398,8 +3398,17 @@ namespace HomogeneousKernelFunctors { typedef typename K::Triangle_3 Triangle_3; typedef typename K::Segment_3 Segment_3; typedef typename K::Ray_3 Ray_3; + public: - typedef Point_3 result_type; + template + struct result { + typedef const Point_3 type; + }; + + template + struct result { + typedef const Point_3& type; + }; Point_3 operator()( const Line_3& l, const Point_3& p ) const @@ -3429,15 +3438,19 @@ namespace HomogeneousKernelFunctors { Point_3 operator()( const Triangle_3& t, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,t,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(t,p,K()); } Point_3 operator()( const Segment_3& s, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,s,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(s,p,K()); } Point_3 operator()( const Ray_3& r, const Point_3& p ) const - { return CommonKernelFunctors::Construct_projected_point_3()(p,r,K()); } + { return CommonKernelFunctors::Construct_projected_point_3()(r,p,K()); } + + const Point_3& + operator()( const Point_3& p, const Point_3& q) const + { return CommonKernelFunctors::Construct_projected_point_3()(p,q,K()); } }; template @@ -4675,7 +4688,7 @@ namespace HomogeneousKernelFunctors { result_type operator()( const Circle_2& c, const Point_2& p) const - { return Oriented_side(c.bounded_side(p) * c.orientation()); } + { return Oriented_side(static_cast(c.bounded_side(p)) * static_cast(c.orientation())); } result_type operator()( const Line_2& l, const Point_2& p) const diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 27dc295dcf1..9ca67be1cc9 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -37,7 +37,7 @@ Release date: December 2021 ### [2D and 3D Linear Geometry Kernel](https://doc.cgal.org/5.4/Manual/packages.html#PkgKernel23) - Added `construct_centroid_2_object()` and `compute_determinant_2_object()` in `Projection_traits_xy_3`, `Projection_traits_xz_3`, - and`Projection_traits_yz_3` classes. + and `Projection_traits_yz_3` classes. - Added documentation for the class `Projection_traits_3`, which enables the use of 2D algorithms on the projections of 3D data onto an arbitrary plane. @@ -62,6 +62,10 @@ Release date: December 2021 - Added an option to [`CGAL::Polygon_mesh_processing::self_intersections()`](https://doc.cgal.org/5.4/Polygon_mesh_processing/group__PMP__intersection__grp.html#gaf19c80ec12cbff7ebe9e69453f1d40b8) to report only a limited number of intersections (`maximum_number()`) +### [The Heat Method](https://doc.cgal.org/5.4/Manual/packages.html#PkgHeatMethod) + +- **Breaking change**: Added the functor `Compute_squared_length_3` that has an operator `operator(const Vector_3& v)`, which computes the squared length of `v`, to the `HeatMethodTraits_3` concept. + ### [Shape Regularization](https://doc.cgal.org/5.4/Manual/packages.html#PkgShapeRegularization) (new package) - This package enables to regularize a set of segments and open or closed contours in 2D diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index 43d3cbadc95..e050c6b9c2b 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -653,6 +653,10 @@ cache_get(CGAL_3RD_PARTY_LIBRARIES ) cache_get(CGAL_3RD_PARTY_LIBRARIES_DIRS) install(DIRECTORY "${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/include/CGAL/Qt/" DESTINATION "${CGAL_INSTALL_INC_DIR}/CGAL/Qt" COMPONENT CGAL_Qt5) +if(CGAL_BRANCH_BUILD) + install(DIRECTORY "${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/demo/resources/" DESTINATION "${CGAL_INSTALL_CMAKE_DIR}/demo/resources" COMPONENT CGAL_Qt5) + install(DIRECTORY "${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/demo/icons/" DESTINATION "${CGAL_INSTALL_CMAKE_DIR}/demo/icons" COMPONENT CGAL_Qt5) +endif() # # Variables used when WITH_{demos|examples|tests} are TRUE diff --git a/Installation/cmake/modules/CGAL_pointmatcher_support.cmake b/Installation/cmake/modules/CGAL_pointmatcher_support.cmake index 7323feae702..ab55c3b86f9 100644 --- a/Installation/cmake/modules/CGAL_pointmatcher_support.cmake +++ b/Installation/cmake/modules/CGAL_pointmatcher_support.cmake @@ -9,7 +9,7 @@ if(libpointmatcher_FOUND AND NOT TARGET CGAL::pointmatcher_support) add_library(CGAL::pointmatcher_support INTERFACE IMPORTED) target_compile_definitions(CGAL::pointmatcher_support INTERFACE "CGAL_LINKED_WITH_POINTMATCHER") target_include_directories(CGAL::pointmatcher_support INTERFACE "${libpointmatcher_INCLUDE_DIR}") - target_link_libraries(CGAL::pointmatcher_support INTERFACE "${libpointmatcher_LIBRARIES}") + target_link_libraries(CGAL::pointmatcher_support INTERFACE ${libpointmatcher_LIBRARIES}) else() message(STATUS "NOTICE : the libpointmatcher library requires the following boost components: thread filesystem system program_options date_time chrono.") endif() diff --git a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Line_2.h b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Line_2.h index 3315328d876..a8d188a7a42 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Line_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Line_2.h @@ -36,11 +36,10 @@ namespace internal { template class Line_2_Iso_rectangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Line_2_Iso_rectangle_2_pair(typename K::Line_2 const *line, typename K::Iso_rectangle_2 const *iso) - : _known(false), - _ref_point(line->point()), + : _ref_point(line->point()), _dir(line->direction().to_vector()), _isomin((iso->min)()), _isomax((iso->max)()) {} @@ -50,8 +49,7 @@ public: typename K::Point_2 intersection_point() const; typename K::Segment_2 intersection_segment() const; protected: - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::FT _min, _max; typename K::Point_2 _ref_point; typename K::Vector_2 _dir; @@ -84,10 +82,9 @@ typename Line_2_Iso_rectangle_2_pair::Intersection_results Line_2_Iso_rectangle_2_pair::intersection_type() const { //typedef typename K::Line_2 line_t; - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; typedef typename K::FT FT; typedef typename K::RT RT; bool all_values = true; @@ -156,7 +153,7 @@ intersection_point() const typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return translated_point(_ref_point, construct_scaled_vector(_dir, _min)); @@ -170,7 +167,7 @@ intersection_segment() const typename K::Construct_segment_2 construct_segment_2; typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return construct_segment_2(translated_point(_ref_point, construct_scaled_vector(_dir,_min)), diff --git a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Ray_2.h b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Ray_2.h index 8f4136e0843..5f2b52a311a 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Ray_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Ray_2.h @@ -35,10 +35,10 @@ namespace internal { template class Ray_2_Iso_rectangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Ray_2_Iso_rectangle_2_pair(typename K::Ray_2 const *ray, typename K::Iso_rectangle_2 const *iso) - : _known(false), _ref_point(ray->source()), _dir(ray->direction().to_vector()), + : _ref_point(ray->source()), _dir(ray->direction().to_vector()), _isomin((iso->min)()), _isomax((iso->max)()), _min((typename K::FT)(0)) {} Intersection_results intersection_type() const; @@ -46,8 +46,7 @@ public: typename K::Point_2 intersection_point() const; typename K::Segment_2 intersection_segment() const; protected: - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _ref_point; mutable typename K::Vector_2 _dir; mutable typename K::Point_2 _isomin; @@ -109,9 +108,8 @@ Ray_2_Iso_rectangle_2_pair::intersection_type() const { typedef typename K::RT RT; typedef typename K::FT FT; - if (_known) + if (_result!=UNKNOWN) return _result; - _known = true; bool to_infinity = true; typename K::Construct_cartesian_const_iterator_2 construct_cccit; @@ -175,7 +173,7 @@ Ray_2_Iso_rectangle_2_pair::intersection_segment() const typedef typename K::Segment_2 Segment_2; typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); typename K::Point_2 p1(translated_point(_ref_point, construct_scaled_vector(_dir,_min))); @@ -190,7 +188,7 @@ Ray_2_Iso_rectangle_2_pair::intersection_point() const typedef typename K::Point_2 Point_2; typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return Point_2(translated_point(_ref_point, construct_scaled_vector(_dir, _min))); diff --git a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Segment_2.h index 3b82ffd42a3..28121109d10 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Iso_rectangle_2_Segment_2.h @@ -36,7 +36,7 @@ namespace internal { template class Segment_2_Iso_rectangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Segment_2_Iso_rectangle_2_pair(typename K::Segment_2 const *seg, typename K::Iso_rectangle_2 const *rect) ; @@ -45,8 +45,7 @@ public: typename K::Point_2 intersection_point() const; typename K::Segment_2 intersection_segment() const; protected: - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _ref_point; mutable typename K::Vector_2 _dir; mutable typename K::Point_2 _isomin; @@ -108,7 +107,6 @@ Segment_2_Iso_rectangle_2_pair( typename K::Segment_2 const *seg, typename K::Iso_rectangle_2 const *iso) { - _known = false; _isomin = (iso->min)(); _isomax = (iso->max)(); _ref_point = seg->source(); @@ -130,9 +128,8 @@ Segment_2_Iso_rectangle_2_pair::intersection_type() const { typedef typename K::RT RT; typedef typename K::FT FT; - if (_known) + if (_result!=UNKNOWN) return _result; - _known = true; typename K::Construct_cartesian_const_iterator_2 construct_cccit; typename K::Cartesian_const_iterator_2 ref_point_it = construct_cccit(_ref_point); @@ -190,7 +187,7 @@ intersection_segment() const typedef typename K::Segment_2 Segment_2; typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); typename K::Point_2 p1(translated_point(_ref_point, construct_scaled_vector(_dir,_min))); @@ -205,7 +202,7 @@ intersection_point() const { typename K::Construct_translated_point_2 translated_point; typename K::Construct_scaled_vector_2 construct_scaled_vector; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return translated_point(_ref_point, construct_scaled_vector(_dir,_min)); diff --git a/Intersections_2/include/CGAL/Intersections_2/Line_2_Line_2.h b/Intersections_2/include/CGAL/Intersections_2/Line_2_Line_2.h index d95ddec8f2a..8d2d3e6ae0d 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Line_2_Line_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Line_2_Line_2.h @@ -36,10 +36,10 @@ namespace internal { template class Line_2_Line_2_pair { public: - enum Intersection_results {NOT_COMPUTED_YET, NO_INTERSECTION, POINT, LINE}; + enum Intersection_results {NO_INTERSECTION, POINT, LINE, UNKNOWN}; Line_2_Line_2_pair(typename K::Line_2 const *line1, typename K::Line_2 const *line2) - : _line1(line1), _line2(line2), _result(NOT_COMPUTED_YET) {} + : _line1(line1), _line2(line2) {} Intersection_results intersection_type() const; @@ -48,7 +48,7 @@ public: protected: typename K::Line_2 const* _line1; typename K::Line_2 const * _line2; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; }; @@ -140,7 +140,7 @@ typename Line_2_Line_2_pair::Intersection_results Line_2_Line_2_pair::intersection_type() const { typedef typename K::RT RT; - if (_result != NOT_COMPUTED_YET) + if (_result != UNKNOWN) return _result; RT nom1, nom2, denom; // The non const this pointer is used to cast away const. @@ -178,7 +178,7 @@ template typename K::Point_2 Line_2_Line_2_pair::intersection_point() const { - if (_result == NOT_COMPUTED_YET) + if (_result == UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -188,7 +188,7 @@ template typename K::Line_2 Line_2_Line_2_pair::intersection_line() const { - if (_result == NOT_COMPUTED_YET) + if (_result == UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == LINE); return *_line1; diff --git a/Intersections_2/include/CGAL/Intersections_2/Line_2_Ray_2.h b/Intersections_2/include/CGAL/Intersections_2/Line_2_Ray_2.h index eada9a07ec2..87f59d8a45a 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Line_2_Ray_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Line_2_Ray_2.h @@ -35,11 +35,11 @@ namespace internal { template class Ray_2_Line_2_pair { public: - enum Intersection_results {NOT_COMPUTED_YET, NO_INTERSECTION, POINT, RAY}; + enum Intersection_results {NO_INTERSECTION, POINT, RAY, UNKNOWN}; typedef typename K::FT FT; Ray_2_Line_2_pair(typename K::Ray_2 const *ray, typename K::Line_2 const *line) - : _ray(ray), _line(line), _result(NOT_COMPUTED_YET), + : _ray(ray), _line(line), _intersection_point(K().construct_point_2_object()(ORIGIN)) {} @@ -50,7 +50,7 @@ public: protected: typename K::Ray_2 const * _ray; typename K::Line_2 const * _line; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; }; @@ -117,7 +117,7 @@ template typename Ray_2_Line_2_pair::Intersection_results Ray_2_Line_2_pair::intersection_type() const { - if (_result != NOT_COMPUTED_YET) + if (_result != UNKNOWN) return _result; // The non const this pointer is used to cast away const. const typename K::Line_2 &l1 = _ray->supporting_line(); @@ -144,7 +144,7 @@ template typename K::Point_2 Ray_2_Line_2_pair::intersection_point() const { - if (_result == NOT_COMPUTED_YET) + if (_result == UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -154,7 +154,7 @@ template typename K::Ray_2 Ray_2_Line_2_pair::intersection_ray() const { - if (_result == NOT_COMPUTED_YET) + if (_result == UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == RAY); return *_ray; diff --git a/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h index 17d60e41a07..0c5d881b544 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Line_2_Segment_2.h @@ -34,10 +34,10 @@ namespace internal { template class Segment_2_Line_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Segment_2_Line_2_pair(typename K::Segment_2 const *seg, typename K::Line_2 const *line) - : _seg(seg), _line(line), _known(false) {} + : _seg(seg), _line(line) {} Intersection_results intersection_type() const; @@ -46,8 +46,7 @@ public: protected: typename K::Segment_2 const*_seg; typename K::Line_2 const * _line; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; }; @@ -108,10 +107,9 @@ template typename Segment_2_Line_2_pair::Intersection_results Segment_2_Line_2_pair::intersection_type() const { - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; const typename K::Line_2 &l1 = _seg->supporting_line(); Line_2_Line_2_pair linepair(&l1, _line); switch ( linepair.intersection_type()) { @@ -136,7 +134,7 @@ template typename K::Point_2 Segment_2_Line_2_pair::intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -146,7 +144,7 @@ template typename K::Segment_2 Segment_2_Line_2_pair::intersection_segment() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return *_seg; diff --git a/Intersections_2/include/CGAL/Intersections_2/Line_2_Triangle_2.h b/Intersections_2/include/CGAL/Intersections_2/Line_2_Triangle_2.h index 7dc337bade3..9f514030f8a 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Line_2_Triangle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Line_2_Triangle_2.h @@ -36,10 +36,10 @@ namespace internal { template class Line_2_Triangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Line_2_Triangle_2_pair(typename K::Line_2 const *line, typename K::Triangle_2 const *trian) - : _line(line), _trian(trian), _known(false) {} + : _line(line), _trian(trian) {} Intersection_results intersection_type() const; @@ -48,8 +48,7 @@ public: protected: typename K::Line_2 const*_line; typename K::Triangle_2 const * _trian; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; mutable typename K::Point_2 _other_point; }; @@ -81,10 +80,9 @@ typename Line_2_Triangle_2_pair::Intersection_results Line_2_Triangle_2_pair::intersection_type() const { typedef typename K::Line_2 Line_2; - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; Straight_2_ straight(*_line); Line_2 l(_trian->vertex(0), _trian->vertex(1)); if (l.oriented_side(_trian->vertex(2)) == ON_POSITIVE_SIDE) { @@ -133,7 +131,7 @@ typename K::Point_2 Line_2_Triangle_2_pair:: intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -145,7 +143,7 @@ Line_2_Triangle_2_pair:: intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_intersection_point, _other_point); diff --git a/Intersections_2/include/CGAL/Intersections_2/Point_2_Triangle_2.h b/Intersections_2/include/CGAL/Intersections_2/Point_2_Triangle_2.h index 74f8db8c01a..ba496198cd9 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Point_2_Triangle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Point_2_Triangle_2.h @@ -33,10 +33,10 @@ namespace internal { template class Point_2_Triangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT}; + enum Intersection_results {NO_INTERSECTION, POINT, UNKNOWN}; Point_2_Triangle_2_pair(typename K::Point_2 const *pt, typename K::Triangle_2 const *trian) - : _pt(pt), _trian(trian), _known(false) {} + : _pt(pt), _trian(trian) {} Intersection_results intersection_type() const; @@ -44,8 +44,7 @@ public: protected: typename K::Point_2 const * _pt; typename K::Triangle_2 const * _trian; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; mutable typename K::Point_2 _other_point; }; @@ -73,10 +72,9 @@ template typename Point_2_Triangle_2_pair::Intersection_results Point_2_Triangle_2_pair::intersection_type() const { - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; if (_trian->has_on_unbounded_side(*_pt)) { _result = NO_INTERSECTION; } else { @@ -92,7 +90,7 @@ typename K::Point_2 Point_2_Triangle_2_pair:: intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return *_pt; diff --git a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Ray_2.h b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Ray_2.h index a59f4ba4443..2b0c166797b 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Ray_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Ray_2.h @@ -36,10 +36,10 @@ namespace internal { template class Ray_2_Ray_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, RAY}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, RAY, UNKNOWN}; Ray_2_Ray_2_pair(typename K::Ray_2 const *ray1, typename K::Ray_2 const *ray2) - : _ray1(ray1), _ray2(ray2), _known(false) {} + : _ray1(ray1), _ray2(ray2) {} Intersection_results intersection_type() const; @@ -49,8 +49,7 @@ public: protected: typename K::Ray_2 const* _ray1; typename K::Ray_2 const * _ray2; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point, _other_point; }; @@ -71,10 +70,9 @@ template typename Ray_2_Ray_2_pair::Intersection_results Ray_2_Ray_2_pair::intersection_type() const { - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; // if (!do_overlap(_ray1->bbox(), _ray2->bbox())) // return NO_INTERSECTION; const typename K::Line_2 &l1 = _ray1->supporting_line(); @@ -196,7 +194,7 @@ template typename K::Point_2 Ray_2_Ray_2_pair::intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -207,7 +205,7 @@ typename K::Segment_2 Ray_2_Ray_2_pair::intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_ray1->source(), _ray2->source()); @@ -218,7 +216,7 @@ typename K::Ray_2 Ray_2_Ray_2_pair::intersection_ray() const { typedef typename K::Ray_2 Ray_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == RAY); return Ray_2(_intersection_point, _ray1->direction()); diff --git a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Segment_2.h index 579938c97fc..2cdebe84a13 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Segment_2.h @@ -37,10 +37,10 @@ namespace internal { template class Ray_2_Segment_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Ray_2_Segment_2_pair(typename K::Ray_2 const *ray, typename K::Segment_2 const *seg) - : _ray(ray), _seg(seg), _known(false) {} + : _ray(ray), _seg(seg) {} Intersection_results intersection_type() const; @@ -49,8 +49,7 @@ public: protected: typename K::Ray_2 const * _ray; typename K::Segment_2 const * _seg; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point, _other_point; }; @@ -76,10 +75,9 @@ template typename Ray_2_Segment_2_pair::Intersection_results Ray_2_Segment_2_pair::intersection_type() const { - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; // if (!do_overlap(_ray->bbox(), _seg->bbox())) // return NO_INTERSECTION; const typename K::Line_2 &l1 = _ray->supporting_line(); @@ -211,7 +209,7 @@ template typename K::Point_2 Ray_2_Segment_2_pair::intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -222,7 +220,7 @@ typename K::Segment_2 Ray_2_Segment_2_pair::intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_intersection_point, _other_point); diff --git a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Triangle_2.h b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Triangle_2.h index 8384f917299..6db56586c55 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Ray_2_Triangle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Ray_2_Triangle_2.h @@ -34,10 +34,10 @@ namespace internal { template class Ray_2_Triangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Ray_2_Triangle_2_pair(typename K::Ray_2 const *ray, typename K::Triangle_2 const *trian) - : _ray(ray), _trian(trian), _known(false) {} + : _ray(ray), _trian(trian) {} Intersection_results intersection_type() const; @@ -46,8 +46,7 @@ public: protected: typename K::Ray_2 const* _ray; typename K::Triangle_2 const * _trian; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; mutable typename K::Point_2 _other_point; }; @@ -59,10 +58,9 @@ typename Ray_2_Triangle_2_pair::Intersection_results Ray_2_Triangle_2_pair::intersection_type() const { typedef typename K::Line_2 Line_2; - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; Straight_2_ straight(*_ray); Line_2 l(_trian->vertex(0), _trian->vertex(1)); if (l.oriented_side(_trian->vertex(2)) == ON_POSITIVE_SIDE) { @@ -111,7 +109,7 @@ typename K::Point_2 Ray_2_Triangle_2_pair:: intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -123,7 +121,7 @@ Ray_2_Triangle_2_pair:: intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_intersection_point, _other_point); diff --git a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h index ba3d8b9567c..3b9e7003a40 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Segment_2.h @@ -274,10 +274,10 @@ do_intersect(const typename K::Segment_2 &seg1, template class Segment_2_Segment_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Segment_2_Segment_2_pair(typename K::Segment_2 const *seg1, typename K::Segment_2 const *seg2) - : _seg1(seg1), _seg2(seg2), _known(false) {} + : _seg1(seg1), _seg2(seg2) {} Intersection_results intersection_type() const; @@ -286,8 +286,7 @@ public: protected: typename K::Segment_2 const* _seg1; typename K::Segment_2 const * _seg2; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point, _other_point; }; @@ -296,9 +295,8 @@ typename Segment_2_Segment_2_pair::Intersection_results Segment_2_Segment_2_pair::intersection_type() const { typename K::Construct_vector_2 construct_vector; - if (_known) + if (_result!=UNKNOWN) return _result; - _known = true; if (!internal::do_intersect(*_seg1, *_seg2, K())) { _result = NO_INTERSECTION; return _result; @@ -408,7 +406,7 @@ template typename K::Point_2 Segment_2_Segment_2_pair::intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -419,7 +417,7 @@ typename K::Segment_2 Segment_2_Segment_2_pair::intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_intersection_point, _other_point); diff --git a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Triangle_2.h b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Triangle_2.h index f048c2bd35f..4d2b93c05cf 100644 --- a/Intersections_2/include/CGAL/Intersections_2/Segment_2_Triangle_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/Segment_2_Triangle_2.h @@ -34,10 +34,10 @@ namespace internal { template class Segment_2_Triangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, UNKNOWN}; Segment_2_Triangle_2_pair(typename K::Segment_2 const *seg, typename K::Triangle_2 const *trian) - : _seg(seg), _trian(trian), _known(false) {} + : _seg(seg), _trian(trian) {} Intersection_results intersection_type() const; @@ -46,8 +46,7 @@ public: protected: typename K::Segment_2 const * _seg; typename K::Triangle_2 const * _trian; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable typename K::Point_2 _intersection_point; mutable typename K::Point_2 _other_point; }; @@ -71,10 +70,9 @@ template typename Segment_2_Triangle_2_pair::Intersection_results Segment_2_Triangle_2_pair::intersection_type() const { - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; Straight_2_ straight(*_seg); typedef typename K::Line_2 Line_2; @@ -124,7 +122,7 @@ typename K::Point_2 Segment_2_Triangle_2_pair:: intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -136,7 +134,7 @@ Segment_2_Triangle_2_pair:: intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_intersection_point, _other_point); diff --git a/Intersections_2/include/CGAL/Intersections_2/internal/Triangle_2_Triangle_2_intersection_impl.h b/Intersections_2/include/CGAL/Intersections_2/internal/Triangle_2_Triangle_2_intersection_impl.h index 3a22168af8e..d752d7c87e9 100644 --- a/Intersections_2/include/CGAL/Intersections_2/internal/Triangle_2_Triangle_2_intersection_impl.h +++ b/Intersections_2/include/CGAL/Intersections_2/internal/Triangle_2_Triangle_2_intersection_impl.h @@ -154,10 +154,10 @@ void _cut_off(Pointlist_2_ &list, template class Triangle_2_Triangle_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, TRIANGLE, POLYGON}; + enum Intersection_results {NO_INTERSECTION, POINT, SEGMENT, TRIANGLE, POLYGON, UNKNOWN}; Triangle_2_Triangle_2_pair(typename K::Triangle_2 const *trian1, typename K::Triangle_2 const *trian2) - : _trian1(trian1), _trian2(trian2), _known(false) {} + : _trian1(trian1), _trian2(trian2) {} Intersection_results intersection_type() const; @@ -170,8 +170,7 @@ public: protected: typename K::Triangle_2 const* _trian1; typename K::Triangle_2 const * _trian2; - mutable bool _known; - mutable Intersection_results _result; + mutable Intersection_results _result = UNKNOWN; mutable Pointlist_2_ _pointlist; }; @@ -180,10 +179,9 @@ typename Triangle_2_Triangle_2_pair::Intersection_results Triangle_2_Triangle_2_pair::intersection_type() const { typedef typename K::Line_2 Line_2; - if (_known) + if (_result!=UNKNOWN) return _result; // The non const this pointer is used to cast away const. - _known = true; if (!do_overlap(_trian1->bbox(), _trian2->bbox())) { _result = NO_INTERSECTION; return _result; @@ -235,7 +233,7 @@ bool Triangle_2_Triangle_2_pair::intersection( /* Polygon_2 &result */) const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); if (_result != TRIANGLE && _result != POLYGON) return false; @@ -255,7 +253,7 @@ template int Triangle_2_Triangle_2_pair::vertex_count() const { - CGAL_kernel_assertion(_known); + CGAL_kernel_assertion(_result!=UNKNOWN); return _pointlist.size; } @@ -263,7 +261,7 @@ template typename K::Point_2 Triangle_2_Triangle_2_pair::vertex(int n) const { - CGAL_kernel_assertion(_known); + CGAL_kernel_assertion(_result!=UNKNOWN); CGAL_kernel_assertion(n >= 0 && n < _pointlist.size); Pointlist_2_rec_ *cur; int k; @@ -279,7 +277,7 @@ typename K::Triangle_2 Triangle_2_Triangle_2_pair::intersection_triangle() const { typedef typename K::Triangle_2 Triangle_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == TRIANGLE); if(CGAL::left_turn(_pointlist.first->point, @@ -302,7 +300,7 @@ typename K::Segment_2 Triangle_2_Triangle_2_pair::intersection_segment() const { typedef typename K::Segment_2 Segment_2; - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == SEGMENT); return Segment_2(_pointlist.first->point, @@ -313,7 +311,7 @@ template typename K::Point_2 Triangle_2_Triangle_2_pair::intersection_point() const { - if (!_known) + if (_result==UNKNOWN) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _pointlist.first->point; diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 06758a7d7a3..c3a7337aefb 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -2850,8 +2850,8 @@ namespace CommonKernelFunctors { public: typename K::Point_3 - operator()(const typename K::Point_3& origin, - const typename K::Triangle_3& triangle, + operator()(const typename K::Triangle_3& triangle, + const typename K::Point_3& origin, const K& k) { typedef typename K::Point_3 Point_3; @@ -2890,18 +2890,18 @@ namespace CommonKernelFunctors { if(linf_ab > linf_ac) { if(linf_ab > linf_bc) { // ab is the maximal segment - return this->operator()(origin, seg(a, b), k); + return this->operator()(seg(a, b), origin, k); } else { // ab > ac, bc >= ab, use bc - return this->operator()(origin, seg(b, c), k); + return this->operator()(seg(b, c), origin, k); } } else { // ab <= ac if(linf_ac > linf_bc) { // ac is the maximal segment - return this->operator()(origin, seg(a, c), k); + return this->operator()(seg(a, c), origin, k); } else { // ab <= ac, ac <= bc, use bc - return this->operator()(origin, seg(b, c), k); + return this->operator()(seg(b, c), origin, k); } } } // degenerate plane @@ -2923,8 +2923,8 @@ namespace CommonKernelFunctors { } typename K::Point_3 - operator()(const typename K::Point_3& query, - const typename K::Segment_3& segment, + operator()(const typename K::Segment_3& segment, + const typename K::Point_3& query, const K& k) { @@ -2945,8 +2945,8 @@ namespace CommonKernelFunctors { } typename K::Point_3 - operator()(const typename K::Point_3& query, - const typename K::Ray_3& ray, + operator()(const typename K::Ray_3& ray, + const typename K::Point_3& query, const K& k) { if ( ray.to_vector() * (query-ray.source()) <= 0) @@ -2957,6 +2957,14 @@ namespace CommonKernelFunctors { } } + const typename K::Point_3& + operator()(const typename K::Point_3& point, + const typename K::Point_3&, + const K&) + { + return point; + } + // code for operator for plane and point is defined in // CGAL/Cartesian/function_objects.h and CGAL/Homogeneous/function_objects.h }; @@ -3005,7 +3013,6 @@ namespace CommonKernelFunctors { public: typedef typename K::Boolean result_type; - // There are 36 combinaisons, so I use a template. template result_type operator()(const T1& t1, const T2& t2) const @@ -3018,7 +3025,6 @@ namespace CommonKernelFunctors { public: typedef typename K::Boolean result_type; - // There are x combinaisons, so I use a template. template result_type operator()(const T1& t1, const T2& t2) const diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_constructions_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_constructions_3.h index e45abb683e9..1931c2ae7e2 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_constructions_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_constructions_3.h @@ -131,6 +131,8 @@ _test_fct_constructions_3(const R& r) assert( r.construct_projected_point_3_object()(ray, Point(-1,0,0)) == Point(0,0,0)); assert( r.construct_projected_point_3_object()(s, Point(-1,0,0)) == Point(0,0,0)); assert( r.construct_projected_point_3_object()(s, Point(2,0,0)) == Point(1,1,0)); + assert( r.construct_projected_point_3_object()(Point(0,0,0), Point(2,0,0)) == Point(0,0,0)); + return true; } diff --git a/Kernel_d/include/CGAL/Kernel_d/Segment_d.h b/Kernel_d/include/CGAL/Kernel_d/Segment_d.h index 5a399babf4d..bd30d04f3a7 100644 --- a/Kernel_d/include/CGAL/Kernel_d/Segment_d.h +++ b/Kernel_d/include/CGAL/Kernel_d/Segment_d.h @@ -19,7 +19,6 @@ #include #include -#include #include #include #include diff --git a/Maintenance/test_handling/testsuite_comparison/diff_testsuites.html b/Maintenance/test_handling/testsuite_comparison/diff_testsuites.html index 6cb41ecb451..4ec2720540f 100644 --- a/Maintenance/test_handling/testsuite_comparison/diff_testsuites.html +++ b/Maintenance/test_handling/testsuite_comparison/diff_testsuites.html @@ -18,6 +18,9 @@
+

+Note that the diff should be done from left to right, as red or yellow squares in the left testsuite that become green in the right testsuite will be ignored. +

I = Master
Ic = integration

diff --git a/Maintenance/test_handling/testsuite_comparison/diff_testsuites.js b/Maintenance/test_handling/testsuite_comparison/diff_testsuites.js index 04486118b8d..567dad05351 100644 --- a/Maintenance/test_handling/testsuite_comparison/diff_testsuites.js +++ b/Maintenance/test_handling/testsuite_comparison/diff_testsuites.js @@ -30,22 +30,23 @@ function diff_testsuites(baseTest, newTest){ var init = false; for(s = 0; s < suffixes.length; s++) { var new_column = new Array(); - xhr.open('GET', URL_testsuite+baseTest+'/'+suffixes[s], false); + var suffixe=suffixes[s].replace("\r", ""); + xhr.open('GET', URL_testsuite+baseTest+'/'+suffixe, false); xhr.send(null); var base_exists = (xhr.status === 200); - var base=xhr.responseText; - xhr.open('GET', URL_testsuite+newTest+'/'+suffixes[s], false); + var base=xhr.responseText.replace("\r", ""); + xhr.open('GET', URL_testsuite+newTest+'/'+suffixe, false); xhr.send(null); var new_exists = (xhr.status === 200) if(base_exists && !new_exists) { - diffArray.push("-"+suffixes[s]); + diffArray.push("-"+suffixe); continue; } if(!base_exists && new_exists) { - diffArray.push("+"+suffixes[s]); + diffArray.push("+"+suffixe); continue; } if(!base_exists && !new_exists) @@ -53,11 +54,17 @@ function diff_testsuites(baseTest, newTest){ continue; } - var newtext=xhr.responseText; + var newtext=xhr.responseText.replace("\r", ""); var sp_base=base.split("\n"); sp_base.sort(); + for(i=0; i< sp_base.length; i++){ + sp_base[i]=sp_base[i].replace("\r", ""); + } var sp_newtext=newtext.split("\n"); sp_newtext.sort(); + for(i=0; i< sp_newtext.length; i++){ + sp_newtext[i]=sp_newtext[i].replace("\r", ""); + } addMissingLines(sp_base, sp_newtext); if(!init) { @@ -73,7 +80,7 @@ function diff_testsuites(baseTest, newTest){ myArray.push(first_column); init = true; } - var fragments = suffixes[s].split("_"); + var fragments = suffixe.split("_"); fragments.shift(); var name = fragments.join("_"); name = name.replace('.txt', ''); @@ -82,29 +89,29 @@ function diff_testsuites(baseTest, newTest){ for(i=0; i< sp_base.length; i++){ var broken = false; var res = print_diff(sp_base[i], sp_newtext[i]); - var compensator=0; - if(sp_base[i] !== ""){ - while(sp_base[i].substr(0, sp_base[i].length-2) !== first_column[i+compensator]){ - if(compensator >10){ - broken=true; - break; - } - compensator++; - } + var compensator=0; + if(sp_base[i] !== ""){ + while(sp_base[i].substr(0, sp_base[i].length-2) !== first_column[i+compensator]){ + if(compensator >10){ + broken=true; + break; + } + compensator++; } - else{ - while(sp_newtext[i].substr(0, sp_newtext[i].length-2) !== first_column[i+compensator]){ - if(compensator >10){ - broken=true; - break; - } - compensator++; - } - } - if(broken) - { - continue; + } + else{ + while(sp_newtext[i].substr(0, sp_newtext[i].length-2) !== first_column[i+compensator]){ + if(compensator >10){ + broken=true; + break; + } + compensator++; } + } + if(broken) + { + continue; + } var new_line=first_column[i+compensator]+"||"+" "+result; } else if(res[1]=== "n"){ new_line+=" background-color: rgb(100%,50%,50%)'> "+result; - } - else if(res[1]==="" && res[0]!==""){ + } else if(res[1]== "t"){ + new_line+=" background-color: rgb(75%,100%,50%)'> "+result; + } else if(res[1]==="" && res[0]!==""){ new_line+=" background-color: rgb(50%,25%,75%)'>"+result; } else{ @@ -146,3 +154,4 @@ function diff_testsuites(baseTest, newTest){ return [myArray, diffArray]; } + diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index de889e42acf..2ba606c5de3 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -45,6 +45,7 @@ #include #include #include +#include #ifdef CGAL_MESH_3_USE_OLD_SURFACE_RESTRICTED_DELAUNAY_UPDATE #include @@ -765,6 +766,18 @@ initialize() facets_mesher_.scan_triangulation(); refinement_stage = REFINE_FACETS; } + + if (r_c3t3_.number_of_facets() == 0) + { + CGAL::warning_fail("r_c3t3_.number_of_facets() == 0", + __FILE__, + __LINE__, + "Warning : The mesh refinement process can't start.\n" + "When calling refine_mesh_3(), the input `c3t3` should have been initialized and have " + "at least one facet in the complex. Try to solve this issue using :\n" + "\t- The automatic initialization provided by make_mesh_3()\n" + "\t- Adding more and better chosen points on the input surface\n"); + } } diff --git a/Nef_3/include/CGAL/Nef_3/K3_tree.h b/Nef_3/include/CGAL/Nef_3/K3_tree.h index be2c8b79f5e..8329767d8eb 100644 --- a/Nef_3/include/CGAL/Nef_3/K3_tree.h +++ b/Nef_3/include/CGAL/Nef_3/K3_tree.h @@ -291,7 +291,7 @@ public: Segment_3 segment; bool initialized; public: - Objects_around_segment() : initialized(false) {} + Objects_around_segment() : root_node(nullptr), initialized(false) {} Objects_around_segment( const K3_tree& k, const Segment_3& s) : root_node(k.root), segment(s), initialized(true) { CGAL_NEF_TRACEN("Objects_around_segment: input segment: "< #include #include +#include #define CGAL_NEF3_MARKED_VERTEX_COLOR 183,232,92 #define CGAL_NEF3_MARKED_EDGE_COLOR 171,216,86 @@ -226,7 +227,7 @@ namespace OGL { inline void CGAL_GLU_TESS_CALLBACK errorCallback(GLenum errorCode) { const GLubyte *estring; estring = gluErrorString(errorCode); - fprintf(stderr, "Tessellation Error: %s\n", estring); + std::cerr << "Tessellation Error: " << estring << std::endl; std::exit (0); } diff --git a/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h b/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h index c0ddcc5ff22..aab28de6795 100644 --- a/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h +++ b/Nef_3/include/CGAL/Nef_3/SNC_io_parser.h @@ -1088,7 +1088,10 @@ public: template SNC_io_parser::SNC_io_parser(std::istream& is, SNC_structure& W) : - Base(W), in(is), out(std::cout) { + Base(W), in(is), out(std::cout), + reduce(false), sorted(false), addInfiBox(false), + i(0), vn(0), en(0), fn(0), cn(0), sen(0), sln(0), sfn(0) +{ W.clear(); CGAL_assertion(W.is_empty()); verbose = false; @@ -1099,11 +1102,13 @@ template SNC_io_parser::SNC_io_parser(std::ostream& os, SNC_structure& W, bool sort, bool reduce_) : Base(W), in(std::cin), out(os), + addInfiBox(false), FI(W.halffacets_begin(),W.halffacets_end(),'F'), CI(W.volumes_begin(),W.volumes_end(),'C'), SEI(W.shalfedges_begin(),W.shalfedges_end(),'e'), SLI(W.shalfloops_begin(),W.shalfloops_end(),'l'), SFI(W.sfaces_begin(),W.sfaces_end(),'f'), + i(0), vn(W.number_of_vertices()), en(W.number_of_halfedges()), fn(W.number_of_halffacets()), diff --git a/Number_types/include/CGAL/CORE_BigFloat.h b/Number_types/include/CGAL/CORE_BigFloat.h index ffefaecb748..812036e3aa6 100644 --- a/Number_types/include/CGAL/CORE_BigFloat.h +++ b/Number_types/include/CGAL/CORE_BigFloat.h @@ -16,7 +16,6 @@ #include #include -#include #include #include #include @@ -513,7 +512,6 @@ template <> class Real_embeddable_traits< CORE::BigFloat > #include #include #include -#include #include namespace Eigen { diff --git a/Number_types/include/CGAL/CORE_BigInt.h b/Number_types/include/CGAL/CORE_BigInt.h index a069a4948cd..0b599543164 100644 --- a/Number_types/include/CGAL/CORE_BigInt.h +++ b/Number_types/include/CGAL/CORE_BigInt.h @@ -18,7 +18,6 @@ #include #include -#include #include #include @@ -189,7 +188,6 @@ public: //since types are included by CORE_coercion_traits.h: #include -#include #include #include #include diff --git a/Number_types/include/CGAL/CORE_BigRat.h b/Number_types/include/CGAL/CORE_BigRat.h index 0f51dac5663..caf9b73886e 100644 --- a/Number_types/include/CGAL/CORE_BigRat.h +++ b/Number_types/include/CGAL/CORE_BigRat.h @@ -18,7 +18,6 @@ #include #include -#include #include #include // used for To_interval-functor @@ -226,7 +225,6 @@ public: //since types are included by CORE_coercion_traits.h: #include #include -#include #include #include diff --git a/Number_types/include/CGAL/CORE_Expr.h b/Number_types/include/CGAL/CORE_Expr.h index 27491b01a85..4b720bc126b 100644 --- a/Number_types/include/CGAL/CORE_Expr.h +++ b/Number_types/include/CGAL/CORE_Expr.h @@ -21,7 +21,6 @@ #include #include -#include #include @@ -177,7 +176,6 @@ template <> class Real_embeddable_traits< CORE::Expr > } //namespace CGAL //since types are included by CORE_coercion_traits.h: -#include #include #include #include diff --git a/Number_types/include/CGAL/FPU.h b/Number_types/include/CGAL/FPU.h index 429e8fe29f0..d5a123608c4 100644 --- a/Number_types/include/CGAL/FPU.h +++ b/Number_types/include/CGAL/FPU.h @@ -248,6 +248,8 @@ inline __m128d IA_opacify128(__m128d x) # ifdef _MSC_VER // With VS, __m128d is a union, where volatile doesn't disappear automatically // However, this version generates wrong code with clang, check before enabling it for more compilers. + // The usage here is safe as we write from a __m128d to a __m128d + // and we know that this type has 16 bytes std::memcpy(&x, (void*)&e, 16); return x; # else diff --git a/Number_types/include/CGAL/Gmpq.h b/Number_types/include/CGAL/Gmpq.h index 87d240ecef6..9816d719b19 100644 --- a/Number_types/include/CGAL/Gmpq.h +++ b/Number_types/include/CGAL/Gmpq.h @@ -209,7 +209,6 @@ namespace Eigen { //since types are included by Gmp_coercion_traits.h: #include -#include #include #include diff --git a/Number_types/include/CGAL/Gmpz.h b/Number_types/include/CGAL/Gmpz.h index c67035a1e03..63be45e78fd 100644 --- a/Number_types/include/CGAL/Gmpz.h +++ b/Number_types/include/CGAL/Gmpz.h @@ -241,7 +241,6 @@ namespace Eigen { //since types are included by Gmp_coercion_traits.h: -#include #include #include #include diff --git a/Number_types/include/CGAL/Gmpzf.h b/Number_types/include/CGAL/Gmpzf.h index 5b6a0448eb6..128d0f94d36 100644 --- a/Number_types/include/CGAL/Gmpzf.h +++ b/Number_types/include/CGAL/Gmpzf.h @@ -171,7 +171,6 @@ public: //since types are included by Gmp_coercion_traits.h: #include #include -#include #endif // CGAL_GMPZF_H diff --git a/Point_set_3/include/CGAL/Point_set_3/IO.h b/Point_set_3/include/CGAL/Point_set_3/IO.h index 5baf100079a..6d5e5b1f9a3 100644 --- a/Point_set_3/include/CGAL/Point_set_3/IO.h +++ b/Point_set_3/include/CGAL/Point_set_3/IO.h @@ -53,7 +53,7 @@ class Point_set_3; normal vectors, the normal map is added to the point set. For PLY input, all point properties found in the header are added. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \param is input stream \param ps point set @@ -167,7 +167,9 @@ bool read_point_set(const std::string& fname, CGAL::Point_set_3& All properties are inserted in their instantiation order. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink + of the stream must be set to `BINARY`. \param os the output stream \param ps the point set diff --git a/Point_set_3/include/CGAL/Point_set_3/IO/LAS.h b/Point_set_3/include/CGAL/Point_set_3/IO/LAS.h index b68091e5fbb..7ecf30255ba 100644 --- a/Point_set_3/include/CGAL/Point_set_3/IO/LAS.h +++ b/Point_set_3/include/CGAL/Point_set_3/IO/LAS.h @@ -54,7 +54,7 @@ void check_if_property_is_used(PointSet& point_set, \brief reads the content of an intput stream in the \ref IOStreamLAS into a point set. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \param is the input stream \param point_set the point set @@ -194,7 +194,7 @@ namespace IO { \brief writes the content of a point set into an output stream in the \ref IOStreamLAS. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. \tparam Point the point type of the `Point_set_3` \tparam Vector the vector type of the `Point_set_3` diff --git a/Point_set_3/include/CGAL/Point_set_3/IO/PLY.h b/Point_set_3/include/CGAL/Point_set_3/IO/PLY.h index dd96c762556..aaab12817f4 100644 --- a/Point_set_3/include/CGAL/Point_set_3/IO/PLY.h +++ b/Point_set_3/include/CGAL/Point_set_3/IO/PLY.h @@ -234,7 +234,7 @@ public: header. Each line starting by "comment " in the header is appended to the `comments` string (without the "comment " word). - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \param is the input stream \param point_set the point set @@ -443,7 +443,9 @@ namespace IO { the header of the PLY stream (each line will be precedeed by "comment "). - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink + of the stream must be set to `BINARY`. \tparam Point the point type of the `Point_set_3` \tparam Vector the vector type of the `Point_set_3` diff --git a/Point_set_processing_3/include/CGAL/IO/read_las_points.h b/Point_set_processing_3/include/CGAL/IO/read_las_points.h index 5e9e127d0f8..45c9a02e1d3 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_las_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_las_points.h @@ -365,7 +365,7 @@ void process_properties (const LASpoint& reader, OutputValueType& new_element, - `LAS_property::B` with type `unsigned short` - `LAS_property::I` with type `unsigned short` - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -430,7 +430,7 @@ bool read_LAS_with_properties(std::istream& is, Potential additional properties are ignored. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. diff --git a/Point_set_processing_3/include/CGAL/IO/read_off_points.h b/Point_set_processing_3/include/CGAL/IO/read_off_points.h index 8fee80ba6bf..1a459a48a56 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_off_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_off_points.h @@ -190,12 +190,15 @@ bool read_OFF(std::istream& is, put(normal_map, pwn, normal); // normal_map[&pwn] = normal *output++ = pwn; pointsRead++; + } // ...or skip comment line } // Skip remaining lines } - + if(is.eof()) { + is.clear(is.rdstate() & ~std::ios_base::failbit); // set by getline + } return true; } diff --git a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h index 55c79e8a989..7ef8d18806e 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_ply_points.h @@ -124,7 +124,7 @@ make_ply_normal_reader(VectorMap normal_map); second element of the tuple should be a functor that constructs the value type of `PropertyMap` from N objects of types `T`. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. @@ -207,7 +207,7 @@ bool read_PLY_with_properties(std::istream& is, Potential additional point properties and faces are ignored. - \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. \tparam OutputIteratorValueType type of objects that can be put in `PointOutputIterator`. It must be a model of `DefaultConstructible` and defaults to `value_type_traits::%type`. diff --git a/Point_set_processing_3/include/CGAL/IO/read_xyz_points.h b/Point_set_processing_3/include/CGAL/IO/read_xyz_points.h index a414ddb839a..0de735fadf8 100644 --- a/Point_set_processing_3/include/CGAL/IO/read_xyz_points.h +++ b/Point_set_processing_3/include/CGAL/IO/read_xyz_points.h @@ -179,6 +179,9 @@ bool read_XYZ(std::istream& is, return false; } } + if(is.eof()) { + is.clear(is.rdstate() & ~std::ios_base::failbit); // set by getline + } return true; } diff --git a/Point_set_processing_3/include/CGAL/IO/write_las_points.h b/Point_set_processing_3/include/CGAL/IO/write_las_points.h index 14679ca570a..2fbb8d09af7 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_las_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_las_points.h @@ -176,10 +176,10 @@ namespace LAS { See documentation of `read_LAS_with_properties()` for the list of available `LAS_property::Tag` classes. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. \tparam PointRange is a model of `ConstRange`. The value type of - its iterator is the key type of the named parameter `point_map`. + its iterator is the key type of the named parameter `point_map`. \tparam PointMap is a model of `ReadablePropertyMap` with a value_type = `CGAL::Point_3`. \tparam PropertyHandler handlers to recover properties. @@ -254,10 +254,10 @@ bool write_LAS_with_properties(std::ostream& os, ///< output stream. \brief writes the range of `points` (positions only), using the \ref IOStreamLAS. - \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation of the `ofstream`. \tparam PointRange is a model of `ConstRange`. The value type of - its iterator is the key type of the named parameter `point_map`. + its iterator is the key type of the named parameter `point_map`. \tparam NamedParameters a sequence of \ref bgl_namedparameters "Named Parameters" \param os output stream diff --git a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h index 41281a1360f..27dfe372ba9 100644 --- a/Point_set_processing_3/include/CGAL/IO/write_ply_points.h +++ b/Point_set_processing_3/include/CGAL/IO/write_ply_points.h @@ -96,11 +96,13 @@ namespace IO { be provided for `PropertyMap::value_type` that handles both ASCII and binary output (see `CGAL::IO::get_mode()`). - \attention When writing to a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink + of the stream must be set to `BINARY`. \tparam PointRange is a model of `ConstRange`. The value type of - its iterator is the key type of the `PropertyMap` objects provided - within the `PropertyHandler` parameter. + its iterator is the key type of the `PropertyMap` objects provided + within the `PropertyHandler` parameter. \tparam PropertyHandler handlers to recover properties. \returns `true` if writing was successful, `false` otherwise. @@ -145,10 +147,12 @@ template = 2 || neighbor_radius > FT(0)); - std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Creates KD-tree\n"); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Creates KD-tree\n"; Neighbor_query neighbor_query (points, point_map); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Computes normals\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Computes normals\n"; std::size_t nb_points = points.size(); @@ -251,8 +253,9 @@ jet_estimate_normals( callback_wrapper.join(); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE("End of jet_estimate_normals()\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << "End of jet_estimate_normals()\n"; } diff --git a/Point_set_processing_3/include/CGAL/mst_orient_normals.h b/Point_set_processing_3/include/CGAL/mst_orient_normals.h index 544614a7fbc..cdc316fc7ad 100644 --- a/Point_set_processing_3/include/CGAL/mst_orient_normals.h +++ b/Point_set_processing_3/include/CGAL/mst_orient_normals.h @@ -245,7 +245,7 @@ mst_find_source( NormalMap normal_map, ///< property map: value_type of ForwardIterator -> Vector_3 const Kernel& /*kernel*/) ///< geometric traits. { - CGAL_TRACE(" mst_find_source()\n"); + CGAL_TRACE_STREAM << " mst_find_source()\n"; // Input points types typedef typename boost::property_traits::value_type Vector; @@ -270,8 +270,8 @@ mst_find_source( Vector_ref normal = get(normal_map,*top_point); const Vector Z(0, 0, 1); if (Z * normal < 0) { - CGAL_TRACE(" Flip top point normal\n"); - put(normal_map,*top_point, -normal); + CGAL_TRACE_STREAM << " Flip top point normal\n"; + put(normal_map,*top_point, -normal); } return top_point; @@ -329,13 +329,15 @@ create_riemannian_graph( // Number of input points const std::size_t num_input_points = points.size(); - std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Creates KD-tree\n"); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Creates KD-tree\n"; Neighbor_query neighbor_query (points, point_map); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Creates Riemannian Graph\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Creates Riemannian Graph\n"; // Iterates over input points and creates Riemannian Graph: // - vertices are numbered like the input points index. @@ -465,8 +467,9 @@ create_mst_graph( // Number of input points const std::size_t num_input_points = num_vertices(riemannian_graph) - 1; - std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Calls boost::prim_minimum_spanning_tree()\n"); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Calls boost::prim_minimum_spanning_tree()\n"; // Computes Minimum Spanning Tree. std::size_t source_point_index = num_input_points; @@ -478,8 +481,9 @@ create_mst_graph( weight_map( riemannian_graph_weight_map ) .root_vertex( vertex(source_point_index, riemannian_graph) )); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Creates MST Graph\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Creates MST Graph\n"; // Converts predecessor map to a MST graph: // - vertices are numbered like the input points index. @@ -605,7 +609,7 @@ mst_orient_normals( using parameters::choose_parameter; using parameters::get_parameter; - CGAL_TRACE("Calls mst_orient_normals()\n"); + CGAL_TRACE_STREAM << "Calls mst_orient_normals()\n"; typedef typename CGAL::GetPointMap::type PointMap; typedef typename Point_set_processing_3::GetNormalMap::type NormalMap; @@ -643,8 +647,9 @@ mst_orient_normals( // Precondition: at least 2 nearest neighbors CGAL_point_set_processing_precondition(k >= 2); - std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Create Index_property_map\n"); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Create Index_property_map\n"; // Create a property map Iterator -> index. // - if typename PointRange::iterator is a random access iterator (typically vector and deque), @@ -686,8 +691,9 @@ mst_orient_normals( kernel, riemannian_graph); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Calls boost::breadth_first_search()\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Calls boost::breadth_first_search()\n"; const std::size_t num_input_points = distance(points.begin(), points.end()); std::size_t source_point_index = num_input_points; @@ -717,10 +723,11 @@ mst_orient_normals( std::copy(unoriented_points.begin(), unoriented_points.end(), first_unoriented_point); // At this stage, we have typically 0 unoriented normals if k is large enough - CGAL_TRACE(" => %u normals are unoriented\n", unoriented_points.size()); + CGAL_TRACE_STREAM << " => " << unoriented_points.size() << " normals are unoriented\n"; - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE("End of mst_orient_normals()\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << "End of mst_orient_normals()\n"; return first_unoriented_point; } diff --git a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h index 8f20104b64d..5979f11086e 100644 --- a/Point_set_processing_3/include/CGAL/pca_estimate_normals.h +++ b/Point_set_processing_3/include/CGAL/pca_estimate_normals.h @@ -159,7 +159,7 @@ pca_estimate_normals( using parameters::choose_parameter; using parameters::get_parameter; - CGAL_TRACE("Calls pca_estimate_normals()\n"); + CGAL_TRACE_STREAM << "Calls pca_estimate_normals()\n"; // basic geometric types typedef typename CGAL::GetPointMap::type PointMap; @@ -192,13 +192,15 @@ pca_estimate_normals( // precondition: at least 2 nearest neighbors CGAL_point_set_processing_precondition(k >= 2); - std::size_t memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Creates KD-tree\n"); + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Creates KD-tree\n"; Neighbor_query neighbor_query (points, point_map); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE(" Computes normals\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << " Computes normals\n"; std::size_t nb_points = points.size(); @@ -223,8 +225,9 @@ pca_estimate_normals( callback_wrapper.join(); - memory = CGAL::Memory_sizer().virtual_size(); CGAL_TRACE(" %ld Mb allocated\n", memory>>20); - CGAL_TRACE("End of pca_estimate_normals()\n"); + memory = CGAL::Memory_sizer().virtual_size(); + CGAL_TRACE_STREAM << (memory >> 20) << " Mb allocated\n"; + CGAL_TRACE_STREAM << "End of pca_estimate_normals()\n"; } /// \cond SKIP_IN_MANUAL diff --git a/Point_set_processing_3/test/Point_set_processing_3/test_deprecated_io_point_set.cpp b/Point_set_processing_3/test/Point_set_processing_3/test_deprecated_io_point_set.cpp index 701692d16f3..218f4f42b63 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/test_deprecated_io_point_set.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/test_deprecated_io_point_set.cpp @@ -77,116 +77,150 @@ points[1] = std::make_pair(Point_3(0,1,0), Color{0,255,0,255}); points[2] = std::make_pair(Point_3(0,0,1), Color{0,0,255,255}); -std::ofstream os; -std::ifstream is; bool ok; std::vector ps; ps.push_back(Point_3(1,0,0)); ps.push_back(Point_3(0,1,0)); ps.push_back(Point_3(0,0,1)); + + //LAS #ifdef CGAL_LINKED_WITH_LASLIB -os.open("tmp.las", std::ios::binary); -ok = CGAL::write_las_points_with_properties(os, points, - CGAL::make_las_point_writer(CGAL::First_of_pair_property_map()), - std::make_pair(GetRedMap(),CGAL::LAS_property::R()), - std::make_pair(GetGreenMap(), CGAL::LAS_property::G()), - std::make_pair(GetBlueMap(), CGAL::LAS_property::B()), - std::make_pair(GetAlphaMap(), CGAL::LAS_property::I()) - ); -os.close(); -assert(ok); -points.clear(); -is.open("tmp.las", std::ios::binary); -ok = CGAL::read_las_points_with_properties(is, std::back_inserter (points), - CGAL::make_las_point_reader(CGAL::First_of_pair_property_map()), - std::make_tuple(CGAL::Second_of_pair_property_map(), - CGAL::Construct_array(), - CGAL::LAS_property::R(), - CGAL::LAS_property::G(), - CGAL::LAS_property::B(), - CGAL::LAS_property::I())); -is.close(); -assert(ok); -assert(points.size() == 3); -assert(points[1].second[1] == 255); -os.open("tmp.las", std::ios_base::binary); -CGAL::write_las_points(os, ps, CGAL::parameters::all_default()); -os.close(); -assert(ok); -ps.clear(); -is.open("tmp.las", std::ios::binary); -ok = CGAL::read_las_points(is, std::back_inserter (ps),CGAL::parameters::all_default()); -is.close(); -assert(ok); -assert(ps.size() == 3); + { + std::ofstream os("tmp1.las", std::ios::binary); + ok = CGAL::write_las_points_with_properties(os, points, + CGAL::make_las_point_writer(CGAL::First_of_pair_property_map()), + std::make_pair(GetRedMap(),CGAL::LAS_property::R()), + std::make_pair(GetGreenMap(), CGAL::LAS_property::G()), + std::make_pair(GetBlueMap(), CGAL::LAS_property::B()), + std::make_pair(GetAlphaMap(), CGAL::LAS_property::I()) + ); + assert(ok); + + } + + { + points.clear(); + std::ifstream is("tmp1.las", std::ios::binary); + ok = CGAL::read_las_points_with_properties(is, std::back_inserter (points), + CGAL::make_las_point_reader(CGAL::First_of_pair_property_map()), + std::make_tuple(CGAL::Second_of_pair_property_map(), + CGAL::Construct_array(), + CGAL::LAS_property::R(), + CGAL::LAS_property::G(), + CGAL::LAS_property::B(), + CGAL::LAS_property::I())); + assert(ok); + assert(points.size() == 3); + assert(points[1].second[1] == 255); + } + + { + std::ofstream os("tmp2.las", std::ios_base::binary); + CGAL::write_las_points(os, ps, CGAL::parameters::all_default()); + assert(ok); + } + + { + ps.clear(); + std::ifstream is("tmp2.las", std::ios::binary); + ok = CGAL::read_las_points(is, std::back_inserter (ps),CGAL::parameters::all_default()); + assert(ok); + assert(ps.size() == 3); + } #endif + + //PLY -os.open("tmp.ply"); -ok = CGAL::write_ply_points_with_properties(os, points, - CGAL::make_ply_point_writer (CGAL::First_of_pair_property_map()), - std::make_pair(GetRedMap(),CGAL::PLY_property("red")), - std::make_pair(GetGreenMap(), CGAL::PLY_property("green")), - std::make_pair(GetBlueMap(), CGAL::PLY_property("blue")), - std::make_pair(GetAlphaMap(), CGAL::PLY_property("alpha")) - ); -os.close(); -assert(ok); + { + std::ofstream os("tmp1.ply"); + assert(os.good()); + ok = CGAL::write_ply_points_with_properties(os, points, + CGAL::make_ply_point_writer (CGAL::First_of_pair_property_map()), + std::make_pair(GetRedMap(),CGAL::PLY_property("red")), + std::make_pair(GetGreenMap(), CGAL::PLY_property("green")), + std::make_pair(GetBlueMap(), CGAL::PLY_property("blue")), + std::make_pair(GetAlphaMap(), CGAL::PLY_property("alpha")) + ); + assert(! os.fail()); + assert(ok); + } -is.open("tmp.ply"); -points.clear(); -ok = CGAL::read_ply_points_with_properties(is, std::back_inserter (points), - CGAL::make_ply_point_reader(CGAL::First_of_pair_property_map()), - std::make_tuple(CGAL::Second_of_pair_property_map(), - CGAL::Construct_array(), - CGAL::PLY_property("red"), - CGAL::PLY_property("green"), - CGAL::PLY_property("blue"), - CGAL::PLY_property("alpha"))); -is.close(); -assert(ok); -assert(points.size() == 3); -assert(points[1].second[1] == 255); + { + std::ifstream is("tmp1.ply"); + assert(is.good()); + points.clear(); + ok = CGAL::read_ply_points_with_properties(is, std::back_inserter (points), + CGAL::make_ply_point_reader(CGAL::First_of_pair_property_map()), + std::make_tuple(CGAL::Second_of_pair_property_map(), + CGAL::Construct_array(), + CGAL::PLY_property("red"), + CGAL::PLY_property("green"), + CGAL::PLY_property("blue"), + CGAL::PLY_property("alpha"))); + assert(! is.fail()); + assert(ok); + assert(points.size() == 3); + assert(points[1].second[1] == 255); + } -os.open("tmp.ply"); -ok = CGAL::write_ply_points(os, ps, CGAL::parameters::all_default()); -os.close(); -assert(ok); + { + std::ofstream os("tmp2.ply"); + assert(os.good()); + ok = CGAL::write_ply_points(os, ps, CGAL::parameters::all_default()); + assert(! os.fail()); + assert(ok); + } -is.open("tmp.ply"); -ps.clear(); -ok = CGAL::read_ply_points(is, std::back_inserter (ps), - CGAL::parameters::all_default()); -is.close(); -assert(ok); -assert(ps.size() == 3); + { + std::ifstream is("tmp2.ply"); + assert(is.good()); + ps.clear(); + ok = CGAL::read_ply_points(is, std::back_inserter (ps), + CGAL::parameters::all_default()); + assert(! is.fail()); + assert(ok); + assert(ps.size() == 3); + } //OFF -os.open("tmp.off"); -ok = CGAL::write_off_points(os, ps, CGAL::parameters::all_default()); -os.close(); -assert(ok); + { + std::ofstream os("tmp.off"); + assert(os.good()); + ok = CGAL::write_off_points(os, ps, CGAL::parameters::all_default()); + assert(! os.fail()); + assert(ok); + } -is.open("tmp.off"); -ps.clear(); -ok = CGAL::read_off_points(is, std::back_inserter (ps), - CGAL::parameters::all_default()); -is.close(); -assert(ok); -assert(ps.size() == 3); + { + std::ifstream is("tmp.off"); + assert(is.good()); + ps.clear(); + ok = CGAL::read_off_points(is, std::back_inserter (ps), + CGAL::parameters::all_default()); + assert(! is.fail()); + assert(ok); + assert(ps.size() == 3); + } //XYZ -os.open("tmp.xyz"); -ok = CGAL::write_xyz_points(os, ps, CGAL::parameters::all_default()); -os.close(); -assert(ok); + { + std::ofstream os("tmp.xyz"); + assert(os.good()); + ok = CGAL::write_xyz_points(os, ps, CGAL::parameters::all_default()); + assert(! os.fail()); + assert(ok); + } -is.open("tmp.xyz"); -ps.clear(); -ok = CGAL::read_xyz_points(is, std::back_inserter (ps), - CGAL::parameters::all_default()); -is.close(); -assert(ok); -assert(ps.size() == 3); + { + std::ifstream is("tmp.xyz"); + assert(is.good()); + ps.clear(); + ok = CGAL::read_xyz_points(is, std::back_inserter (ps), + CGAL::parameters::all_default()); + assert(! is.fail()); + assert(ok); + assert(ps.size() == 3); + } } diff --git a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h index e526d4ac91f..2c4cc8d1f7a 100644 --- a/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h +++ b/Poisson_surface_reconstruction_3/include/CGAL/Poisson_reconstruction_function.h @@ -770,7 +770,7 @@ private: SparseLinearAlgebraTraits_d solver, ///< sparse linear solver double lambda) { - CGAL_TRACE("Calls solve_poisson()\n"); + CGAL_TRACE_STREAM << "Calls solve_poisson()\n"; double time_init = clock(); @@ -786,7 +786,7 @@ private: m_tr->index_unconstrained_vertices(); unsigned int nb_variables = static_cast(m_tr->number_of_vertices()-1); - CGAL_TRACE(" Number of variables: %ld\n", (long)(nb_variables)); + CGAL_TRACE_STREAM << " Number of variables: " << nb_variables << std::endl; // Assemble linear system A*X=B typename SparseLinearAlgebraTraits_d::Matrix A(nb_variables); // matrix is symmetric definite positive @@ -815,9 +815,9 @@ private: clear_duals(); clear_normals(); duration_assembly = (clock() - time_init)/CLOCKS_PER_SEC; - CGAL_TRACE(" Creates matrix: done (%.2lf s)\n", duration_assembly); + CGAL_TRACE_STREAM << " Creates matrix: done (" << duration_assembly << "sec.)\n"; - CGAL_TRACE(" Solve sparse linear system...\n"); + CGAL_TRACE_STREAM << " Solve sparse linear system...\n"; // Solve "A*X = B". On success, solution is (1/D) * X. time_init = clock(); @@ -827,7 +827,7 @@ private: CGAL_surface_reconstruction_points_assertion(D == 1.0); duration_solve = (clock() - time_init)/CLOCKS_PER_SEC; - CGAL_TRACE(" Solve sparse linear system: done (%.2lf s)\n", duration_solve); + CGAL_TRACE_STREAM << " Solve sparse linear system: done (" << duration_solve << "sec.)\n"; // copy function's values to vertices unsigned int index = 0; @@ -835,7 +835,7 @@ private: if(!m_tr->is_constrained(v)) v->f() = X[index++]; - CGAL_TRACE("End of solve_poisson()\n"); + CGAL_TRACE_STREAM << "End of solve_poisson()\n"; return true; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h deleted file mode 100644 index 22c308757e1..00000000000 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h +++ /dev/null @@ -1,917 +0,0 @@ -// Copyright (c) 2015 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Yin Xu, Andreas Fabri and Ilker O. Yaz - -#ifndef CGAL_PMP_WEIGHTS_H -#define CGAL_PMP_WEIGHTS_H - -#include - -/// @cond CGAL_DOCUMENT_INTERNAL - -#include -#include -#include - -namespace CGAL { -namespace internal { - -// Returns the cotangent value of half angle v0 v1 v2 -// using formula in -[Meyer02] Discrete Differential-Geometry Operators for- page 19 -// The potential problem with previous one (Cotangent_value) is that it does not produce symmetric results -// (i.e. for v0, v1, v2 and v2, v1, v0 returned cot weights can be slightly different) -// This one provides stable results. -template -struct Cotangent_value_Meyer_impl -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - template - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2, const VertexPointMap& ppmap) - { - typedef typename Kernel_traits< - typename boost::property_traits::value_type >::Kernel::Vector_3 Vector; - - Vector a = get(ppmap, v0) - get(ppmap, v1); - Vector b = get(ppmap, v2) - get(ppmap, v1); - - double dot_ab = to_double(a*b); - // rewritten for safer fp arithmetic - //double dot_aa = a.squared_length(); - //double dot_bb = b.squared_length(); - //double divider = CGAL::sqrt( dot_aa * dot_bb - dot_ab * dot_ab ); - - Vector cross_ab = CGAL::cross_product(a, b); - double divider = to_double(CGAL::approximate_sqrt(cross_ab*cross_ab)); - - if(divider == 0 /*|| divider != divider*/) - { - CGAL::collinear(get(ppmap, v0), get(ppmap, v1), get(ppmap, v2)) ? - CGAL_warning_msg(false, "Infinite Cotangent value with degenerate triangle!") : - CGAL_warning_msg(false, "Infinite Cotangent value due to floating point arithmetic!"); - - - return dot_ab > 0 ? (std::numeric_limits::max)() : - -(std::numeric_limits::max)(); - } - - return dot_ab / divider; - } -}; - -// Same as above but with a different API -template::type> -class Cotangent_value_Meyer -{ -protected: - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef VertexPointMap Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - PolygonMesh& pmesh_; - Point_property_map ppmap_; - -public: - - Cotangent_value_Meyer(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : pmesh_(pmesh_) - , ppmap_(vpmap_) - {} - - PolygonMesh& pmesh() - { - return pmesh_; - } - - Point_property_map& ppmap() - { - return ppmap_; - } - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - return Cotangent_value_Meyer_impl()(v0, v1, v2, ppmap()); - } -}; - - -// imported from skeletonization -template::type> -class Cotangent_value_Meyer_secure -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef VertexPointMap Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - PolygonMesh& pmesh_; - Point_property_map ppmap_; - -public: - - Cotangent_value_Meyer_secure(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : pmesh_(pmesh_) - , ppmap_(vpmap_) - {} - - PolygonMesh& pmesh() - { - return pmesh_; - } - - Point_property_map& ppmap() - { - return ppmap_; - } - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - Vector a = get(ppmap(), v0) - get(ppmap(), v1); - Vector b = get(ppmap(), v2) - get(ppmap(), v1); - - double dot_ab = CGAL::to_double(a * b); - double dot_aa = CGAL::to_double(a.squared_length()); - double dot_bb = CGAL::to_double(b.squared_length()); - double lb = -0.999, ub = 0.999; - double cosine = dot_ab / CGAL::sqrt(dot_aa) / CGAL::sqrt(dot_bb); - cosine = (cosine < lb) ? lb : cosine; - cosine = (cosine > ub) ? ub : cosine; - double sine = std::sqrt(1.0 - cosine * cosine); - return cosine / sine; - } -}; - -// Returns the cotangent value of half angle v0 v1 v2 by clamping between [1, 89] degrees -// as suggested by -[Friedel] Unconstrained Spherical Parameterization- -template::type - , class CotangentValue = Cotangent_value_Meyer > -class Cotangent_value_clamped : CotangentValue -{ - Cotangent_value_clamped() - {} -public: - - Cotangent_value_clamped(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - const double cot_1 = 57.289962; - const double cot_89 = 0.017455; - double value = CotangentValue::operator()(v0, v1, v2); - return (std::max)(cot_89, (std::min)(value, cot_1)); - } -}; - -template::type - , class CotangentValue = Cotangent_value_Meyer > -class Cotangent_value_clamped_2 : CotangentValue -{ - Cotangent_value_clamped_2() - {} - -public: - - Cotangent_value_clamped_2(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - const double cot_5 = 5.671282; - const double cot_175 = -cot_5; - double value = CotangentValue::operator()(v0, v1, v2); - return (std::max)(cot_175, (std::min)(value, cot_5)); - } -}; - -template::type - , class CotangentValue = Cotangent_value_Meyer > -class Cotangent_value_minimum_zero : CotangentValue -{ - Cotangent_value_minimum_zero() - {} -public: - Cotangent_value_minimum_zero(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - double value = CotangentValue::operator()(v0, v1, v2); - return (std::max)(0.0, value); - } -}; - -template > -struct Cotangent_value_minimum_zero_impl : CotangentValue -{ - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - template - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2, const VertexPointMap ppmap) - { - double value = CotangentValue::operator()(v0, v1, v2, ppmap); - return (std::max)(0.0, value); - } -}; - -template::type - , class CotangentValue - = Cotangent_value_Meyer > -class Voronoi_area : CotangentValue -{ -public: - Voronoi_area(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::in_edge_iterator in_edge_iterator; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - typedef VertexPointMap Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - double operator()(vertex_descriptor v0) { - - //return 1.0; - double voronoi_area = 0.0; - for(halfedge_descriptor he : - halfedges_around_target( halfedge(v0,pmesh()), pmesh()) ) - { - if( is_border(he,pmesh()) ) { continue; } - - CGAL_expensive_assertion(CGAL::is_valid_polygon_mesh(pmesh())); - CGAL_expensive_assertion(CGAL::is_triangle_mesh(pmesh())); - CGAL_assertion( v0 == target(he, pmesh()) ); - vertex_descriptor v1 = source(he, pmesh()); - vertex_descriptor v_op = target(next(he, pmesh()), pmesh()); - - const Point& v0_p = get(ppmap(), v0); - const Point& v1_p = get(ppmap(), v1); - const Point& v_op_p = get(ppmap(), v_op); - - // (?) check if there is a better way to predicate triangle is obtuse or not - CGAL::Angle angle0 = CGAL::angle(v1_p, v0_p, v_op_p); - CGAL::Angle angle1 = CGAL::angle(v_op_p, v1_p, v0_p); - CGAL::Angle angle_op = CGAL::angle(v0_p, v_op_p, v1_p); - - bool obtuse = (angle0 == CGAL::OBTUSE) || (angle1 == CGAL::OBTUSE) || (angle_op == CGAL::OBTUSE); - - if(!obtuse) { - double cot_v1 = CotangentValue::operator()(v_op, v1, v0); - double cot_v_op = CotangentValue::operator()(v0, v_op, v1); - - double term1 = cot_v1 * to_double((v_op_p - v0_p).squared_length()); - double term2 = cot_v_op * to_double((v1_p - v0_p).squared_length()); - voronoi_area += (1.0 / 8.0) * (term1 + term2); - } - else { - double area_t = to_double(CGAL::approximate_sqrt(squared_area(v0_p, v1_p, v_op_p))); - if(angle0 == CGAL::OBTUSE) { - voronoi_area += area_t / 2.0; - } - else { - voronoi_area += area_t / 4.0; - } - } - } - CGAL_warning_msg(voronoi_area != 0, "Zero voronoi area!"); - return voronoi_area; - } -}; -// Returns the cotangent value of half angle v0 v1 v2 by dividing the triangle area -// as suggested by -[Mullen08] Spectral Conformal Parameterization- -template::type - , class CotangentValue = Cotangent_value_Meyer > -class Cotangent_value_area_weighted : CotangentValue -{ - Cotangent_value_area_weighted() - {} - -public: - - Cotangent_value_area_weighted(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double operator()(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - return CotangentValue::operator()(v0, v1, v2) / - CGAL::sqrt(squared_area(get(this->ppmap(), v0), - get(this->ppmap(), v1), - get(this->ppmap(), v2))); - } -}; -///////////////////////////////////////////////////////////////////////////////////////// - -///////////////////////////// Edge Weight Calculators /////////////////////////////////// -// Cotangent weight calculator -// Cotangent_value: as suggested by -[Sorkine07] ARAP Surface Modeling- -// Cotangent_value_area_weighted: as suggested by -[Mullen08] Spectral Conformal Parameterization- -template< class PolygonMesh, - class CotangentValue = Cotangent_value_minimum_zero_impl > -struct Cotangent_weight_impl : CotangentValue -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - // Returns the cotangent weight of specified halfedge_descriptor - // Edge orientation is trivial - template - double operator()(halfedge_descriptor he, PolygonMesh& pmesh, const VertexPointMap& ppmap) - { - vertex_descriptor v0 = target(he, pmesh); - vertex_descriptor v1 = source(he, pmesh); - // Only one triangle for border edges - if (is_border_edge(he, pmesh)) - { - - halfedge_descriptor he_cw = opposite( next(he, pmesh) , pmesh ); - vertex_descriptor v2 = source(he_cw, pmesh); - if (is_border_edge(he_cw, pmesh) ) - { - halfedge_descriptor he_ccw = prev( opposite(he, pmesh) , pmesh ); - v2 = source(he_ccw, pmesh); - } - return ( CotangentValue::operator()(v0, v2, v1, ppmap)/2.0 ); - } - else - { - halfedge_descriptor he_cw = opposite( next(he, pmesh) , pmesh ); - vertex_descriptor v2 = source(he_cw, pmesh); - halfedge_descriptor he_ccw = prev( opposite(he, pmesh) , pmesh ); - vertex_descriptor v3 = source(he_ccw, pmesh); - - return ( CotangentValue::operator()(v0, v2, v1, ppmap)/2.0 + - CotangentValue::operator()(v0, v3, v1, ppmap)/2.0 ); - } - } -}; - -template::type - , class CotangentValue - = Cotangent_value_minimum_zero > -class Cotangent_weight : CotangentValue -{ - Cotangent_weight() - {} - -public: - Cotangent_weight(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - Cotangent_weight(PolygonMesh& pmesh_) - : CotangentValue(pmesh_, get(CGAL::vertex_point, pmesh_)) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - // Returns the cotangent weight of specified halfedge_descriptor - // Edge orientation is trivial - double operator()(halfedge_descriptor he) - { - vertex_descriptor v0 = target(he, pmesh()); - vertex_descriptor v1 = source(he, pmesh()); - // Only one triangle for border edges - if (is_border_edge(he, pmesh())) - { - - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - if (is_border_edge(he_cw, pmesh()) ) - { - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - v2 = source(he_ccw, pmesh()); - } - return ( CotangentValue::operator()(v0, v2, v1)/2.0 ); - } - else - { - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - vertex_descriptor v3 = source(he_ccw, pmesh()); - - return ( CotangentValue::operator()(v0, v2, v1)/2.0 + CotangentValue::operator()(v0, v3, v1)/2.0 ); - } - } -}; - -// Single cotangent from -[Chao10] Simple Geometric Model for Elastic Deformation -template > -struct Single_cotangent_weight_impl : CotangentValue -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - // Returns the cotangent of the opposite angle of the edge - // 0 for border edges (which does not have an opposite angle) - template - double operator()(halfedge_descriptor he, PolygonMesh& pmesh, const VertexPointMap& ppmap) - { - if(is_border(he, pmesh)) { return 0.0;} - - vertex_descriptor v0 = target(he, pmesh); - vertex_descriptor v1 = source(he, pmesh); - - vertex_descriptor v_op = target(next(he, pmesh), pmesh); - return CotangentValue::operator()(v0, v_op, v1, ppmap); - } -}; - -template::type - , class CotangentValue = Cotangent_value_Meyer > -class Single_cotangent_weight : CotangentValue -{ - Single_cotangent_weight() - {} -public: - Single_cotangent_weight(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - // Returns the cotangent of the opposite angle of the edge - // 0 for border edges (which does not have an opposite angle) - double operator()(halfedge_descriptor he) - { - if(is_border(he, pmesh())) { return 0.0;} - - vertex_descriptor v0 = target(he, pmesh()); - vertex_descriptor v1 = source(he, pmesh()); - - vertex_descriptor v_op = target(next(he, pmesh()), pmesh()); - return CotangentValue::operator()(v0, v_op, v1); - } -}; - - -template::type - , class CotangentValue = Cotangent_value_Meyer -> -class Cotangent_weight_with_triangle_area : CotangentValue -{ - typedef PolygonMesh PM; - typedef VertexPointMap VPMap; - typedef typename boost::property_traits::value_type Point; - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - Cotangent_weight_with_triangle_area() - {} -public: - Cotangent_weight_with_triangle_area(PolygonMesh& pmesh_, VertexPointMap vpmap_) - : CotangentValue(pmesh_, vpmap_) - {} - - PolygonMesh& pmesh() - { - return CotangentValue::pmesh(); - } - - VertexPointMap& ppmap() - { - return CotangentValue::ppmap(); - } - - double operator()(halfedge_descriptor he) - { - vertex_descriptor v0 = target(he, pmesh()); - vertex_descriptor v1 = source(he, pmesh()); - - // Only one triangle for border edges - if (is_border_edge(he, pmesh())) - { - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - if (is_border_edge(he_cw, pmesh()) ) - { - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - v2 = source(he_ccw, pmesh()); - } - - const Point& v0_p = get(ppmap(), v0); - const Point& v1_p = get(ppmap(), v1); - const Point& v2_p = get(ppmap(), v2); - double area_t = to_double(CGAL::sqrt(squared_area(v0_p, v1_p, v2_p))); - - return ( CotangentValue::operator()(v0, v2, v1) / area_t ); - } - else - { - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - vertex_descriptor v3 = source(he_ccw, pmesh()); - - const Point& v0_p = get(ppmap(), v0); - const Point& v1_p = get(ppmap(), v1); - const Point& v2_p = get(ppmap(), v2); - const Point& v3_p = get(ppmap(), v3); - double area_t1 = to_double(CGAL::sqrt(squared_area(v0_p, v1_p, v2_p))); - double area_t2 = to_double(CGAL::sqrt(squared_area(v0_p, v1_p, v3_p))); - - return ( CotangentValue::operator()(v0, v2, v1) / area_t1 - + CotangentValue::operator()(v0, v3, v1) / area_t2); - } - - return 0.; - } -}; - -// Mean value calculator described in -[Floater04] Mean Value Coordinates- -template::type> -class Mean_value_weight -{ - //Mean_value_weight() - //{} - - PolygonMesh& pmesh_; - VertexPointMap vpmap_; - -public: - Mean_value_weight(PolygonMesh& pmesh_, VertexPointMap vpmap) - : pmesh_(pmesh_), vpmap_(vpmap) - {} - - PolygonMesh& pmesh() - { - return pmesh_; - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - typedef VertexPointMap Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - // Returns the mean-value coordinate of specified halfedge_descriptor - // Returns different value for different edge orientation (which is a normal behaivour according to formula) - double operator()(halfedge_descriptor he) - { - vertex_descriptor v0 = target(he, pmesh()); - vertex_descriptor v1 = source(he, pmesh()); - Vector vec = get(vpmap_, v0) - get(vpmap_, v1); - double norm = CGAL::sqrt( vec.squared_length() ); - - // Only one triangle for border edges - if ( is_border_edge(he, pmesh()) ) - { - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - if ( is_border_edge(he_cw, pmesh()) ) - { - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - v2 = source(he_ccw, pmesh()); - } - - return ( half_tan_value_2(v1, v0, v2)/norm); - } - else - { - halfedge_descriptor he_cw = opposite( next(he, pmesh()) , pmesh() ); - vertex_descriptor v2 = source(he_cw, pmesh()); - halfedge_descriptor he_ccw = prev( opposite(he, pmesh()) , pmesh() ); - vertex_descriptor v3 = source(he_ccw, pmesh()); - - return ( half_tan_value_2(v1, v0, v2)/norm + half_tan_value_2(v1, v0, v3)/norm); - } - } - -private: - // Returns the tangent value of half angle v0_v1_v2/2 - double half_tan_value(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - Vector vec0 = get(vpmap_, v1) - get(vpmap_, v2); - Vector vec1 = get(vpmap_, v2) - get(vpmap_, v0); - Vector vec2 = get(vpmap_, v0) - get(vpmap_, v1); - double e0_square = vec0.squared_length(); - double e1_square = vec1.squared_length(); - double e2_square = vec2.squared_length(); - double e0 = CGAL::sqrt(e0_square); - double e2 = CGAL::sqrt(e2_square); - double cos_angle = ( e0_square + e2_square - e1_square ) / 2.0 / e0 / e2; - cos_angle = (std::max)(-1.0, (std::min)(1.0, cos_angle)); // clamp into [-1, 1] - double angle = acos(cos_angle); - - return ( tan(angle/2.0) ); - } - - // My deviation built on Meyer_02 - double half_tan_value_2(vertex_descriptor v0, vertex_descriptor v1, vertex_descriptor v2) - { - Vector a = get(vpmap_, v0) - get(vpmap_, v1); - Vector b = get(vpmap_, v2) - get(vpmap_, v1); - double dot_ab = a[0]*b[0] + a[1]*b[1] + a[2]*b[2]; - double dot_aa = a.squared_length(); - double dot_bb = b.squared_length(); - double dot_aa_bb = dot_aa * dot_bb; - - double cos_rep = dot_ab; - double sin_rep = CGAL::sqrt(dot_aa_bb - dot_ab * dot_ab); - double normalizer = CGAL::sqrt(dot_aa_bb); // |a|*|b| - - return (normalizer - cos_rep) / sin_rep; // formula from [Floater04] page 4 - // tan(Q/2) = (1 - cos(Q)) / sin(Q) - } -}; - -template< class PolygonMesh, - class PrimaryWeight = Cotangent_weight, - class SecondaryWeight = Mean_value_weight > -class Hybrid_weight : public PrimaryWeight, SecondaryWeight -{ - PrimaryWeight primary; - SecondaryWeight secondary; - - Hybrid_weight() - {} - -public: - Hybrid_weight(PolygonMesh& pmesh_) - : primary(pmesh_), secondary(pmesh_) - {} - - PolygonMesh& pmesh() - { - return primary.pmesh(); - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - double operator()(halfedge_descriptor he) - { - double weight = primary(he); - //if(weight < 0) { std::cout << "Negative weight" << std::endl; } - return (weight >= 0) ? weight : secondary(he); - } -}; - -// Trivial uniform weights (created for test purposes) -template -class Uniform_weight -{ -public: - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - - double operator()(halfedge_descriptor /*e*/) - { return 1.0; } -}; - -//////////////////////////////////////////////////////////////////////////// -// FAIRING // -template -class Scale_dependent_weight_fairing -{ - PolygonMesh& pmesh_; -public: - Scale_dependent_weight_fairing(PolygonMesh& pmesh_) - : pmesh_(pmesh_) - {} - - PolygonMesh& pmesh() - { - return pmesh_; - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - typedef typename boost::property_map::type Point_property_map; - typedef typename boost::property_traits::value_type Point; - typedef typename Kernel_traits::Kernel::Vector_3 Vector; - - double w_i(vertex_descriptor /*v_i*/) { return 1.0; } - - double w_ij(halfedge_descriptor he) - { - Vector v = target(he, pmesh())->point() - source(he, pmesh())->point(); - double divider = CGAL::sqrt(v.squared_length()); - if(divider == 0.0) { - CGAL_warning_msg(false, "Scale dependent weight - zero length edge."); - return (std::numeric_limits::max)(); - } - return 1.0 / divider; - } -}; - -template::type -> -class Cotangent_weight_with_voronoi_area_fairing -{ - typedef PolygonMesh PM; - typedef VertexPointMap VPMap; - Voronoi_area voronoi_functor; - Cotangent_weight > cotangent_functor; - -public: - Cotangent_weight_with_voronoi_area_fairing(PM& pmesh_) - : voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) - , cotangent_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) - {} - - Cotangent_weight_with_voronoi_area_fairing(PM& pmesh_, VPMap vpmap_) - : voronoi_functor(pmesh_, vpmap_) - , cotangent_functor(pmesh_, vpmap_) - {} - - PM& pmesh() - { - return voronoi_functor.pmesh(); - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double w_i(vertex_descriptor v_i) - { - return 0.5 / voronoi_functor(v_i); - } - - double w_ij(halfedge_descriptor he) { - - return cotangent_functor(he) * 2.0; - } -}; - -// Cotangent_value_Meyer has been changed to the version: -// Cotangent_value_Meyer_secure to avoid imprecisions from -// the issue #4706 - https://github.com/CGAL/cgal/issues/4706. -template< -class PolygonMesh, class VertexPointMap = typename boost::property_map::type> -class Cotangent_weight_with_voronoi_area_fairing_secure { - - typedef PolygonMesh PM; - typedef VertexPointMap VPMap; - Voronoi_area voronoi_functor; - Cotangent_weight > cotangent_functor; - -public: - Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_) : - voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)), - cotangent_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) - { } - - Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_, VPMap vpmap_) : - voronoi_functor(pmesh_, vpmap_), - cotangent_functor(pmesh_, vpmap_) - { } - - PM& pmesh() { - return voronoi_functor.pmesh(); - } - - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - double w_i(vertex_descriptor v_i) { - return 0.5 / voronoi_functor(v_i); - } - - double w_ij(halfedge_descriptor he) { - return cotangent_functor(he) * 2.0; - } -}; - -template -class Uniform_weight_fairing -{ -public: - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - Uniform_weight_fairing(PolygonMesh&) - {} - - double w_ij(halfedge_descriptor /*e*/) { return 1.0; } - - double w_i(vertex_descriptor /*v_i*/) { return 1.0; } -}; -//////////////////////////////////////////////////////////////////////////// - -}//namespace internal - - -}//namespace CGAL -/// @endcond -#endif //CGAL_PMP_WEIGHTS_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h index 609352d5fac..6f8c0cb9081 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/border.h @@ -13,7 +13,7 @@ #ifndef CGAL_POLYGON_MESH_PROCESSING_GET_BORDER_H #define CGAL_POLYGON_MESH_PROCESSING_GET_BORDER_H -#include +#include #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h index d4a32b81183..e3109944ec1 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/detect_features.h @@ -16,15 +16,13 @@ #include -#include - #include #include #include #include #include -#include +#include namespace CGAL { namespace Polygon_mesh_processing { @@ -45,29 +43,44 @@ generate_patch_id(std::pair, int i) return std::pair(i, 0); } -template +template bool -is_sharp(PolygonMesh& polygonMesh, - const typename boost::graph_traits::halfedge_descriptor& he, - const typename GT::FT& cos_angle) +is_sharp(const typename boost::graph_traits::halfedge_descriptor h, + const PolygonMesh& pmesh, + const VPM vpm, + const GT gt, + const typename GT::Sign cos_sign, + const typename GT::FT sq_cos_angle) { - typedef typename boost::graph_traits::face_descriptor face_descriptor; - if(is_border(edge(he,polygonMesh),polygonMesh)){ + typedef typename GT::FT FT; + typedef typename GT::Vector_3 Vector_3; + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + if(is_border_edge(h, pmesh)) return false; - } - face_descriptor f1 = face(he,polygonMesh); - face_descriptor f2 = face(opposite(he,polygonMesh),polygonMesh); - const typename GT::Vector_3& n1 = Polygon_mesh_processing::compute_face_normal(f1,polygonMesh); - const typename GT::Vector_3& n2 = Polygon_mesh_processing::compute_face_normal(f2,polygonMesh); + typename GT::Construct_vector_3 vector = gt.construct_vector_3_object(); + typename GT::Construct_cross_product_vector_3 cross = gt.construct_cross_product_vector_3_object(); + typename GT::Compute_squared_length_3 sq_length = gt.compute_squared_length_3_object(); - if ( n1 * n2 <= cos_angle ) - return true; + halfedge_descriptor opp_h = opposite(h, pmesh); + + const Vector_3 vc = vector(get(vpm, source(h, pmesh)), get(vpm, target(h, pmesh))); + const Vector_3 v1 = vector(get(vpm, source(h, pmesh)), get(vpm, target(next(h, pmesh), pmesh))); + const Vector_3 v2 = vector(get(vpm, target(next(opp_h, pmesh), pmesh)), get(vpm, target(opp_h, pmesh))); + + const Vector_3 n1 = cross(vc, v1); + const Vector_3 n2 = cross(vc, v2); + const FT sp = n1 * n2; + + // n1.n2 <= cos() without computing the norms of the vectors + if(cos_sign == NEGATIVE) + return (is_negative(sp) && (square(sp) >= sq_cos_angle * sq_length(n1) * sq_length(n2))); else - return false; + return (is_negative(sp) || (square(sp) <= sq_cos_angle * sq_length(n1) * sq_length(n2))); } - //wrapper for patchid map. template::value_type> @@ -133,7 +146,7 @@ void put(PatchIdMapWrapper >& map, Handle_type h template typename boost::graph_traits::faces_size_type -detect_surface_patches(PolygonMesh& p, +detect_surface_patches(const PolygonMesh& p, PatchIdMap patch_id_map, EdgeIsFeatureMap eif, const NamedParameters& np) @@ -152,7 +165,7 @@ detect_surface_patches(PolygonMesh& p, template typename boost::graph_traits::faces_size_type -detect_surface_patches(PolygonMesh& p, +detect_surface_patches(const PolygonMesh& p, PatchIdMap patch_id_map, EdgeIsFeatureMap eif) { @@ -160,69 +173,64 @@ detect_surface_patches(PolygonMesh& p, } -template - void sharp_call(PolygonMesh& pmesh, - FT angle_in_deg, - EIFMap edge_is_feature_map, - VNFEMap vnfe) +template +void sharp_call(const FT angle_in_deg, + const PolygonMesh& pmesh, + const VPM vpm, + const GT gt, + EIFMap edge_is_feature_map, + VNFEMap vnfe) { // Initialize vertices - for(typename boost::graph_traits::vertex_descriptor vd : - vertices(pmesh)) - { + for(typename boost::graph_traits::vertex_descriptor vd : vertices(pmesh)) put(vnfe, vd, 0); - } - FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) ); + + const FT cos_angle = std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.); + const FT sq_cos_angle = square(cos_angle); // Detect sharp edges for(typename boost::graph_traits::edge_descriptor ed : edges(pmesh)) { - typename boost::graph_traits::halfedge_descriptor he = halfedge(ed,pmesh); - if(is_border_edge(he,pmesh) - || angle_in_deg == FT() - || (angle_in_deg != FT(180) && internal::is_sharp(pmesh,he,cos_angle)) - ) + typename boost::graph_traits::halfedge_descriptor he = halfedge(ed, pmesh); + if(is_border_edge(he, pmesh) || + angle_in_deg == FT() || + (angle_in_deg != FT(180) && internal::is_sharp(he, pmesh, vpm, gt, CGAL::sign(cos_angle), sq_cos_angle))) { put(edge_is_feature_map, edge(he, pmesh), true); - put(vnfe, target(he,pmesh), get(vnfe, target(he,pmesh))+1); - put(vnfe, source(he,pmesh), get(vnfe, source(he,pmesh))+1); + put(vnfe, target(he, pmesh), get(vnfe, target(he, pmesh))+1); + put(vnfe, source(he, pmesh), get(vnfe, source(he, pmesh))+1); } } } - -template - void sharp_call(PolygonMesh& pmesh, - FT& angle_in_deg, - EIFMap edge_is_feature_map, - const internal_np::Param_not_found&) +template +void sharp_call(const FT angle_in_deg, + const PolygonMesh& pmesh, + const VPM vpm, + const GT gt, + EIFMap edge_is_feature_map, + const internal_np::Param_not_found&) { typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - FT cos_angle ( std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.) ); + const FT cos_angle = std::cos(CGAL::to_double(angle_in_deg) * CGAL_PI / 180.); + const FT sq_cos_angle = square(cos_angle); // Detect sharp edges for(edge_descriptor ed : edges(pmesh)) { - halfedge_descriptor he = halfedge(ed,pmesh); - if(is_border_edge(he,pmesh) - || angle_in_deg == FT() - || (angle_in_deg != FT(180) && internal::is_sharp(pmesh,he,cos_angle)) - ) + halfedge_descriptor he = halfedge(ed, pmesh); + if(is_border_edge(he, pmesh) || + angle_in_deg == FT() || + (angle_in_deg != FT(180) && internal::is_sharp(he, pmesh, vpm, gt, CGAL::sign(cos_angle), sq_cos_angle))) { put(edge_is_feature_map, edge(he, pmesh), true); } } } -} //end internal + +} // namespace internal /*! * \ingroup PMP_detect_features_grp @@ -270,24 +278,30 @@ template #endif -void detect_sharp_edges(PolygonMesh& pmesh, +void detect_sharp_edges(const PolygonMesh& pmesh, #ifdef DOXYGEN_RUNNING - FT angle_in_deg, + FT angle_in_deg, #else - typename GetGeomTraits::type::FT angle_in_deg, + typename GetGeomTraits::type::FT angle_in_deg, #endif - EdgeIsFeatureMap edge_is_feature_map, - const NamedParameters& np) + EdgeIsFeatureMap edge_is_feature_map, + const NamedParameters& np) { - //extract types from NPs + using parameters::choose_parameter; + using parameters::get_parameter; + + // extract types from NPs typedef typename GetGeomTraits::type GT; - typedef typename GT::FT FT; + GT gt = choose_parameter(get_parameter(np, internal_np::geom_traits)); - internal::sharp_call(pmesh, angle_in_deg, edge_is_feature_map, - parameters::get_parameter(np, internal_np::vertex_feature_degree)); + typedef typename GetVertexPointMap::const_type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(boost::vertex_point, pmesh)); + + internal::sharp_call(angle_in_deg, pmesh, vpm, gt, edge_is_feature_map, + get_parameter(np, internal_np::vertex_feature_degree)); } - /*! * \ingroup PMP_detect_features_grp * @@ -315,7 +329,7 @@ void detect_sharp_edges(PolygonMesh& pmesh, template -void detect_vertex_incident_patches(PolygonMesh& pmesh, +void detect_vertex_incident_patches(const PolygonMesh& pmesh, const PatchIdMap patch_id_map, VertexIncidentPatchesMap vertex_incident_patches_map, const EdgeIsFeatureMap edge_is_feature_map) @@ -326,19 +340,18 @@ void detect_vertex_incident_patches(PolygonMesh& pmesh, for(vertex_descriptor vit :vertices(pmesh)) { // Look only at feature vertices - if( ! get(edge_is_feature_map, edge(halfedge(vit, pmesh), pmesh) )) - { continue; } + if(!get(edge_is_feature_map, edge(halfedge(vit, pmesh), pmesh))) + continue; // Loop on incident facets of vit - typename VertexIncidentPatchesMap::value_type& - id_set = vertex_incident_patches_map[vit]; - for(halfedge_descriptor he : halfedges_around_target(vit,pmesh)) + typename VertexIncidentPatchesMap::value_type& id_set = vertex_incident_patches_map[vit]; + for(halfedge_descriptor he : halfedges_around_target(vit, pmesh)) { - if( ! is_border(he,pmesh) ) + if(!is_border(he, pmesh)) { id_set.insert(get(patch_id_map, face(he, pmesh))); } - else if( ! is_border(opposite(he,pmesh),pmesh) ) + else if(!is_border(opposite(he, pmesh), pmesh)) { id_set.insert(get(patch_id_map, face(opposite(he, pmesh), pmesh))); } @@ -346,26 +359,22 @@ void detect_vertex_incident_patches(PolygonMesh& pmesh, } } +namespace internal { -namespace internal +template +void vip_call(const PolygonMesh& mesh, PIDMap pid, VIPMap vip, EIFMap eif) { - template - void vip_call(PolygonMesh& mesh, PIDMap pid, VIPMap vip, EIFMap eif ) - { - CGAL::Polygon_mesh_processing::detect_vertex_incident_patches(mesh, pid, vip, eif); - } + CGAL::Polygon_mesh_processing::detect_vertex_incident_patches(mesh, pid, vip, eif); +} + +template +void vip_call(const PolygonMesh&, PIDMap, const internal_np::Param_not_found&, EIFMap) +{ + //do nothing when the parameter is not given +} + +} // namespace internal - template - void vip_call(PolygonMesh&, PIDMap, const internal_np::Param_not_found&, EIFMap) - { - //do nothing when the parameter is not given - } -}//end internal /*! * \ingroup PMP_detect_features_grp * @@ -446,30 +455,30 @@ template #endif typename boost::graph_traits::faces_size_type -sharp_edges_segmentation(PolygonMesh& pmesh, +sharp_edges_segmentation(const PolygonMesh& pmesh, #ifdef DOXYGEN_RUNNING - FT angle_in_deg, + FT angle_in_deg, #else - typename GetGeomTraits::type::FT angle_in_deg, + typename GetGeomTraits::type::FT angle_in_deg, #endif - EdgeIsFeatureMap edge_is_feature_map, - PatchIdMap patch_id_map, - const NamedParameters& np) + EdgeIsFeatureMap edge_is_feature_map, + PatchIdMap patch_id_map, + const NamedParameters& np) { - detect_sharp_edges(pmesh, angle_in_deg, edge_is_feature_map, np); + detect_sharp_edges(pmesh, angle_in_deg, edge_is_feature_map, np); - typename boost::graph_traits::faces_size_type result = - internal::detect_surface_patches(pmesh, patch_id_map, edge_is_feature_map, np); + typename boost::graph_traits::faces_size_type result = + internal::detect_surface_patches(pmesh, patch_id_map, edge_is_feature_map, np); - internal::vip_call(pmesh, patch_id_map, - parameters::get_parameter(np, internal_np::vertex_incident_patches), edge_is_feature_map); + internal::vip_call(pmesh, patch_id_map, + parameters::get_parameter(np, internal_np::vertex_incident_patches), edge_is_feature_map); - return result; + return result; } //Convenient overrides template -void detect_sharp_edges(PolygonMesh& p, +void detect_sharp_edges(const PolygonMesh& p, FT angle_in_deg, EdgeIsFeatureMap edge_is_feature_map) { @@ -480,18 +489,16 @@ void detect_sharp_edges(PolygonMesh& p, template typename boost::graph_traits::faces_size_type -sharp_edges_segmentation(PolygonMesh& p, +sharp_edges_segmentation(const PolygonMesh& p, FT angle_in_deg, EdgeIsFeatureMap edge_is_feature_map, PatchIdMap patch_id_map) { return sharp_edges_segmentation(p, angle_in_deg, edge_is_feature_map, patch_id_map, - parameters::all_default()); + parameters::all_default()); } } // end namespace PMP } // end namespace CGAL -#include - #endif // CGAL_POLYGON_MESH_PROCESSING_DETECT_FEATURES_IN_POLYGON_MESH_H diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h index 727e007995a..b6e9d00b9d0 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h @@ -20,6 +20,7 @@ #include #include #include +#include #if defined(CGAL_EIGEN3_ENABLED) #include // for sparse linear system solver @@ -162,15 +163,14 @@ namespace internal { // Cotangent_weight_with_voronoi_area_fairing has been changed to the version: // Cotangent_weight_with_voronoi_area_fairing_secure to avoid imprecisions from // the issue #4706 - https://github.com/CGAL/cgal/issues/4706. - typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing_secure - Default_Weight_calculator; + typedef CGAL::Weights::Secure_cotangent_weight_with_voronoi_area Default_weight_calculator; VPMap vpmap_ = choose_parameter(get_parameter(np, internal_np::vertex_point), get_property_map(vertex_point, tmesh)); return internal::fair(tmesh, vertices, choose_parameter(get_parameter(np, internal_np::sparse_linear_solver)), - choose_parameter(get_parameter(np, internal_np::weight_calculator), Default_Weight_calculator(tmesh, vpmap_)), + choose_parameter(get_parameter(np, internal_np::weight_calculator), Default_weight_calculator(tmesh, vpmap_)), choose_parameter(get_parameter(np, internal_np::fairing_continuity), 1), vpmap_); } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h index f3098e2422a..fa70904f325 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Isotropic_remeshing/remesh_impl.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include #include #include @@ -1492,6 +1492,8 @@ private: || GeomTraits().collinear_3_object()(t, p, q)) continue; + typename GeomTraits::Construct_cross_product_vector_3 cross_product + = GeomTraits().construct_cross_product_vector_3_object(); #ifdef CGAL_PMP_REMESHING_DEBUG typename GeomTraits::Construct_normal_3 normal = GeomTraits().construct_normal_3_object(); @@ -1499,13 +1501,13 @@ private: Vector_3 normal_after_collapse = normal(t, p, q); CGAL::Sign s1 = CGAL::sign(normal_before_collapse * normal_after_collapse); - CGAL::Sign s2 = CGAL::sign(CGAL::cross_product(Vector_3(s, p), Vector_3(s, q)) - * CGAL::cross_product(Vector_3(t, p), Vector_3(t, q))); + CGAL::Sign s2 = CGAL::sign(cross_product(Vector_3(s, p), Vector_3(s, q)) + * cross_product(Vector_3(t, p), Vector_3(t, q))); CGAL_assertion(s1 == s2); #endif - if(CGAL::sign(CGAL::cross_product(Vector_3(s, p), Vector_3(s, q)) - * CGAL::cross_product(Vector_3(t, p), Vector_3(t, q))) + if(CGAL::sign(cross_product(Vector_3(s, p), Vector_3(s, q)) + * cross_product(Vector_3(t, p), Vector_3(t, q))) != CGAL::POSITIVE) return true; } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h index 0c9e2d9fa0e..fa600557af3 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Smoothing/curvature_flow_impl.h @@ -17,10 +17,9 @@ #include #include -#include #include #include - +#include #include #include @@ -41,45 +40,6 @@ namespace CGAL { namespace Polygon_mesh_processing { namespace internal { -// Empirically, _Meyer seems to produce the best results from the various weights available in Weights.h -template > -struct Edge_cotangent_weight - : public CotangentValue -{ - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - - Edge_cotangent_weight(TriangleMesh& pmesh_, VertexPointMap vpmap_) : CotangentValue(pmesh_, vpmap_) {} - - TriangleMesh& pmesh() { return CotangentValue::pmesh(); } - - double operator()(halfedge_descriptor he) - { - if(is_border_edge(he, pmesh())) - { - halfedge_descriptor h1 = next(he, pmesh()); - vertex_descriptor vs = source(he, pmesh()); - vertex_descriptor vt = target(he, pmesh()); - vertex_descriptor v1 = target(h1, pmesh()); - - return CotangentValue::operator()(vs, v1, vt); - } - else - { - halfedge_descriptor h1 = next(he, pmesh()); - halfedge_descriptor h2 = prev(opposite(he, pmesh()), pmesh()); - vertex_descriptor vs = source(he, pmesh()); - vertex_descriptor vt = target(he, pmesh()); - vertex_descriptor v1 = target(h1, pmesh()); - vertex_descriptor v2 = source(h2, pmesh()); - - return CotangentValue::operator()(vs, v1, vt) + CotangentValue::operator()(vs, v2, vt); - } - } -}; - template constrained_flags_; const GeomTraits& traits_; - Edge_cotangent_weight weight_calculator_; + const CGAL::Weights::Edge_cotangent_weight weight_calculator_; }; } // internal diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h index 5352ca1a8dd..0c3fc465392 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/helper.h @@ -37,7 +37,8 @@ void vertices_as_halfedges(const VertexRange& vertex_range, *out++ = halfedge(v, pmesh); } -// Assigns at each vertex the 'tolerance' value as tolerance, but bounded by a percentage of the length of its shortest incident edge +// Assigns at each vertex the 'tolerance' value as tolerance, +// but bounded by a percentage of the length of its shortest incident edge template = sq_va_l * sq_vb_l * sq_cos); } +template +struct Snapping_default_visitor +{ + bool m_stop = false; + + bool stop() { return m_stop; } + + // ------------------------------- Preprocessing ------------------------------ + + // Called when starting preprocessing phase of the mesh. + void start_mesh_preprocessing() { } + + // Called at the end of the preprocessing phase of the mesh. + void end_mesh_preprocessing() { } + + // ------------------------------- Vertex - Vertex ------------------------------- + + // Called when starting snapping a range of vertices of `A` and a range of vertices of `B`. + void start_vertex_vertex_phase() { } + + // Called when finished snapping a range of vertices of `A` and a range of vertices of `B`. + void end_vertex_vertex_phase() { } + + // Called when trying to find `v`-`v_other` pair (with `v` in `A` and `v_other` in `B`) + // + // Available only if vertex-vertex pair detection is based on the kd-tree. + // Must be threadsafe if parallelism is used. + template + void on_vertex_vertex_inquiry(const Vertex /*v*/, const Mesh&) { } + + // Called when a match between two ranges of vertices is found. + // All vertices in `va` have the same position (and same for `vb`). + // + // Must be threadsafe if parallelism is used. + template + void on_vertex_vertex_match(const VertexContainer& /*va*/, const Mesh&, + const VertexContainer& /*vb*/, const Mesh&) { } + + // Called before proceeding with actual vertex-vertex snapping. + void start_vertex_vertex_snapping() { } + + // Called after proceeding with actual vertex-vertex snapping. + void end_vertex_vertex_snapping() { } + + // Called before two ranges of vertices are snapped together. + // All vertices in `va` have the same position (and same for `vb`). + template + void before_vertex_vertex_snap(const VertexContainer& /*va*/, const Mesh&, + const VertexContainer& /*vb*/, const Mesh&) { } + + // Called after two ranges of vertices have been snapped. + template + void after_vertex_vertex_snap(const VertexContainer& /*va*/, const Mesh&, + const VertexContainer& /*vb*/, const Mesh&) { } + + // ------------------------------- Vertex - Edge ------------------------------- + + // Called when starting snapping a range of vertices of A onto edges of B + void start_first_vertex_edge_phase() { } + + // Called when finished snapping a range of vertices of A onto edges of B + void end_first_vertex_edge_phase() { } + + // Called when starting snapping a range of vertices of B onto edges of A. + // Not called if A and B are the same mesh. + void start_second_vertex_edge_phase() { } + + // Called when starting snapping a range of vertices of B onto edges of A. + // Not called if A and B are the same mesh. + void end_second_vertex_edge_phase() { } + + // Called when trying to find `v`-`edge` pair + // + // Available only if vertex-vertex pair detection is based on the kd-tree. + // Must be threadsafe if parallelism is used. + template + void on_vertex_edge_inquiry(const Vertex /*v*/, const Mesh& /*tm*/) { } + + // Called when a match between a vertex and an edge is found. + // + // Must be threadsafe if parallelism is used. + template + void on_vertex_edge_match(const Vertex, const Mesh&, const Edge, const Mesh&, const Point&) { } + + // Called before proceeding with actual snapping. + void start_vertex_edge_snapping() { } + + // Called after proceeding with actual snapping. + void end_vertex_edge_snapping() { } + + // Called before a new vertex is created. + template + void before_vertex_edge_snap(const Edge, const Mesh&, const Point&) { } + + // Called after a new vertex has been created, splitting an edge. + template + void after_vertex_edge_snap(const Vertex /*new_vertex*/, const Mesh&) { } + + // ------------------------------- Two passes (segmentation or not) ------------------------------ + + // Called at the start of the snapping pass that is restricted to compatible patch (first pass). + void start_patch_snapping() { } + + // Called at the end of the snapping pass that is restricted to compatible patch (first pass). + void end_patch_snapping() { } + + // Called at the start of the second snapping pass, all elements are potentially compatible (second pass). + void start_global_snapping() { } + + // Called at the end of the second snapping pass, all elements are potentially compatible (second pass). + void end_global_snapping() { } +}; + } // namespace internal } // namespace Polygon_mesh_processing } // namespace CGAL diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h index 3571ae48b52..490cc457b13 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap.h @@ -92,6 +92,7 @@ void simplify_range(HalfedgeRange& halfedge_range, typedef typename GT::FT FT; typedef typename GetVertexPointMap::type VPM; + typedef typename boost::property_traits::value_type Point; typedef typename boost::property_traits::reference Point_ref; using parameters::get_parameter; @@ -125,10 +126,10 @@ void simplify_range(HalfedgeRange& halfedge_range, // @fixme what if the source vertex is not to be snapped? Tolerance cannot be obtained... // and where should the post-collapse vertex be since we can't move the source vertex... // --> simply don't collapse? - const FT min_tol = (std::min)(get(tolerance_map, vs), get(tolerance_map, vt)); - const FT max_tol = (std::max)(get(tolerance_map, vs), get(tolerance_map, vt)); + const FT tol_s = get(tolerance_map, vs), tol_t = get(tolerance_map, vt); + const FT max_tol = (std::max)(tol_s, tol_t); - if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol))==SMALLER) + if(gt.compare_squared_distance_3_object()(ps,pt,CGAL::square(max_tol)) == SMALLER) { const halfedge_descriptor prev_h = prev(h, tm); const halfedge_descriptor next_h = next(h, tm); @@ -136,11 +137,23 @@ void simplify_range(HalfedgeRange& halfedge_range, // check that the border has at least 4 edges not to create degenerate volumes if(border_size(h, tm) >= 4) { - const FT h_sq_length = gt.compute_squared_distance_3_object()(ps, pt); - vertex_descriptor v = Euler::collapse_edge(edge(h, tm), tm); + const FT lambda = tol_s / (tol_s + tol_t); + const Point new_p = ps + lambda * (pt - ps); - put(vpm, v, gt.construct_midpoint_3_object()(ps, pt)); - put(tolerance_map, v, min_tol + 0.5 * CGAL::approximate_sqrt(h_sq_length)); + // If we're collapsing onto a vertex that is not allowed to move, keep it fixed + const FT min_tol = (std::min)(tol_s, tol_t); + FT new_tolerance = min_tol; + if(!is_zero(min_tol)) + { + if(tol_t > tol_s) // the new point is closer to ps than to pt + new_tolerance += CGAL::approximate_sqrt(CGAL::squared_distance(new_p, ps)); + else + new_tolerance += CGAL::approximate_sqrt(CGAL::squared_distance(new_p, pt)); + } + + vertex_descriptor v = Euler::collapse_edge(edge(h, tm), tm); + put(vpm, v, new_p); + put(tolerance_map, v, new_tolerance); if(get(range_halfedges, prev_h)) edges_to_test.insert(prev_h); @@ -453,7 +466,8 @@ template + typename VPMS, typename VPMT, typename GT, + typename Visitor> void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, EdgeToSplitMap& edges_to_split, const AABBTree* aabb_tree_ptr, @@ -463,7 +477,8 @@ void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, const TriangleMesh& tm_T, FacePatchMap_T face_patch_map_T, VPMT vpm_T, - const GT& gt) + const GT& gt, + Visitor& visitor) { typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; @@ -477,6 +492,9 @@ void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, typedef internal::Projection_traits Projection_traits; + if(visitor.stop()) + throw CGAL::internal::Throw_at_output_exception(); + // by construction the whole range has the same position const halfedge_descriptor h = vertex_with_tolerance.first; const vertex_descriptor v = target(h, tm_S); @@ -488,6 +506,8 @@ void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, std::cout << "--------------------------- Query: " << v << " (" << query << ")" << std::endl; #endif + visitor.on_vertex_edge_inquiry(v, tm_S); + Projection_traits traversal_traits(h, patch_id, sq_tolerance, tm_S, vpm_S, tm_T, face_patch_map_T, vpm_T, aabb_tree_ptr->traits()); aabb_tree_ptr->traversal(query, traversal_traits); @@ -522,7 +542,6 @@ void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, if(!is_close_enough) return; - CGAL_assertion(get(vpm_T, source(closest_e, tm_T)) != query && get(vpm_T, target(closest_e, tm_T)) != query); @@ -534,43 +553,17 @@ void find_splittable_edge(const VertexWithTolerance& vertex_with_tolerance, // Using a map because we need to know if the same halfedge is split multiple times Edges_to_split_map_inserter()(edges_to_split, closest_h, vertex_with_tolerance.first, closest_p); + + visitor.on_vertex_edge_match(v, tm_S, closest_h, tm_T, closest_p); } #ifdef CGAL_LINKED_WITH_TBB template -struct Find_splittable_edge_for_parallel_for + typename VPMS, typename VPMT, typename GT, typename Visitor> +struct Parallel_find_splittable_edge { - Find_splittable_edge_for_parallel_for(const PointWithToleranceContainer& points_with_tolerance, - EdgeToSplitMap& edges_to_split, - const AABBTree* aabb_tree_ptr, - const TriangleMesh& tm_S, - const VertexPatchMap_S vertex_patch_map_S, - const VPMS vpm_S, - const TriangleMesh& tm_T, - const FacePatchMap_T face_patch_map_T, - const VPMT vpm_T, - const GT& gt) - : - m_points_with_tolerance(points_with_tolerance), - m_edges_to_split(edges_to_split), m_aabb_tree_ptr(aabb_tree_ptr), - m_tm_S(tm_S), m_vertex_patch_map_S(vertex_patch_map_S), m_vpm_S(vpm_S), - m_tm_T(tm_T), m_face_patch_map_T(face_patch_map_T), m_vpm_T(vpm_T), - m_gt(gt) - { } - - void operator()(const tbb::blocked_range& r) const - { - for(std::size_t i=r.begin(); i!=r.end(); ++i) - { - find_splittable_edge(m_points_with_tolerance[i], m_edges_to_split, m_aabb_tree_ptr, - m_tm_S, m_vertex_patch_map_S, m_vpm_S, - m_tm_T, m_face_patch_map_T, m_vpm_T, m_gt); - } - } - private: const PointWithToleranceContainer& m_points_with_tolerance; EdgeToSplitMap& m_edges_to_split; @@ -582,18 +575,51 @@ private: const FacePatchMap_T m_face_patch_map_T; const VPMT m_vpm_T; const GT& m_gt; + Visitor& m_visitor; + +public: + Parallel_find_splittable_edge(const PointWithToleranceContainer& points_with_tolerance, + EdgeToSplitMap& edges_to_split, + const AABBTree* aabb_tree_ptr, + const TriangleMesh& tm_S, + const VertexPatchMap_S vertex_patch_map_S, + const VPMS vpm_S, + const TriangleMesh& tm_T, + const FacePatchMap_T face_patch_map_T, + const VPMT vpm_T, + const GT& gt, + Visitor& visitor) + : + m_points_with_tolerance(points_with_tolerance), + m_edges_to_split(edges_to_split), m_aabb_tree_ptr(aabb_tree_ptr), + m_tm_S(tm_S), m_vertex_patch_map_S(vertex_patch_map_S), m_vpm_S(vpm_S), + m_tm_T(tm_T), m_face_patch_map_T(face_patch_map_T), m_vpm_T(vpm_T), + m_gt(gt), m_visitor(visitor) + { } + + void operator()(const tbb::blocked_range& r) const + { + for(std::size_t i=r.begin(); i!=r.end(); ++i) + { + find_splittable_edge(m_points_with_tolerance[i], m_edges_to_split, m_aabb_tree_ptr, + m_tm_S, m_vertex_patch_map_S, m_vpm_S, + m_tm_T, m_face_patch_map_T, m_vpm_T, m_gt, m_visitor); + } + } }; #endif template + typename TriangleMesh, + typename VPMS, typename VPMT, typename GeomTraits, + typename Visitor> std::size_t split_edges(EdgesToSplitContainer& edges_to_split, TriangleMesh& tm_S, VPMS vpm_S, TriangleMesh& tm_T, VPMT vpm_T, const GeomTraits& gt, + Visitor& visitor, const bool is_source_mesh_fixed) // when snapping is B --> A and the mesh B is fixed { #ifdef CGAL_PMP_SNAP_DEBUG @@ -611,10 +637,14 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, typedef std::vector Vertices_with_new_position; typedef std::pair Edge_and_splitters; - std::size_t snapped_n = 0; - +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME CGAL::Real_timer timer; timer.start(); +#endif + + visitor.start_vertex_edge_snapping(); + + std::size_t snapped_n = 0; for(Edge_and_splitters& es : edges_to_split) { @@ -642,6 +672,9 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, Point previous_split_position = get(vpm_S, *(vertices(tm_S).begin())); // dummy value to avoid "used uninitialized" warning for(const Vertex_with_new_position& vnp : splitters) { + if(visitor.stop()) + return snapped_n; + const halfedge_descriptor splitter_h = vnp.first; const vertex_descriptor splitter_v = target(splitter_h, tm_S); const Point new_position = is_source_mesh_fixed ? get(vpm_S, splitter_v) : vnp.second; @@ -668,9 +701,13 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, vertex_descriptor new_v = boost::graph_traits::null_vertex(); if(do_split) { + visitor.before_vertex_edge_snap(h_to_split, tm_T, vnp.second); + CGAL::Euler::split_edge(h_to_split, tm_T); new_v = source(h_to_split, tm_T); put(vpm_T, new_v, new_position); // position of the new point on the target mesh + + visitor.after_vertex_edge_snap(new_v, tm_T); } if(!is_source_mesh_fixed) @@ -740,6 +777,13 @@ std::size_t split_edges(EdgesToSplitContainer& edges_to_split, } } + visitor.end_vertex_edge_snapping(); + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for actual snapping (vertex-edge) " << timer.time() << " s." << std::endl; +#endif + return snapped_n; } @@ -757,6 +801,7 @@ template std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, TriangleMesh& tm_S, @@ -768,6 +813,7 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, FacePatchMap_T face_patch_map_T, LockedHalfedgeMap locked_halfedges_T, const bool is_source_mesh_fixed, + Visitor& visitor, const SourceNamedParameters& snp, const TargetNamedParameters& tnp) { @@ -839,7 +885,7 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, for(auto& p : vertices_to_snap) p.second = point_tolerance_map[get(vpm_S, target(p.first, tm_S))]; - // Since we're inserting primitives one by one, we can't pass this shared data in the constructor of the tree + // Since primitives are inserted one by one, the shared data cannot be in the constructor of the tree AABB_Traits aabb_traits; aabb_traits.set_shared_data(tm_T, vpm_T); AABB_tree aabb_tree(aabb_traits); @@ -863,10 +909,15 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, std::cout << "Collect edges to split with " << vertices_to_snap.size() << " vertices" << std::endl; #endif +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + CGAL::Real_timer timer; + timer.start(); +#endif + #ifndef CGAL_LINKED_WITH_TBB CGAL_static_assertion_msg (!(std::is_convertible::value), "Parallel_tag is enabled but TBB is unavailable."); -#else +#else // CGAL_LINKED_WITH_TBB if(std::is_convertible::value) { #ifdef CGAL_PMP_SNAP_DEBUG @@ -875,22 +926,45 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, typedef tbb::concurrent_hash_map Concurrent_edge_to_split_container; - typedef internal::Find_splittable_edge_for_parallel_for< + typedef internal::Parallel_find_splittable_edge< Vertices_with_tolerance, TriangleMesh, Concurrent_edge_to_split_container, AABB_tree, - VertexPatchMap_S, FacePatchMap_T, VPMS, VPMT, GT> Functor; - - CGAL::Real_timer timer; - timer.start(); + VertexPatchMap_S, FacePatchMap_T, VPMS, VPMT, GT, Visitor> Functor; Concurrent_edge_to_split_container edges_to_split; Functor f(vertices_to_snap, edges_to_split, &aabb_tree, - tm_S, vertex_patch_map_S, vpm_S, tm_T, face_patch_map_T, vpm_T, gt); - tbb::parallel_for(tbb::blocked_range(0, vertices_to_snap.size()), f); + tm_S, vertex_patch_map_S, vpm_S, tm_T, face_patch_map_T, vpm_T, + gt, visitor); - std::cout << "Time to gather edges: " << timer.time() << std::endl; + try + { + tbb::parallel_for(tbb::blocked_range(0, vertices_to_snap.size()), f); + } + catch(const CGAL::internal::Throw_at_output_exception&) + { + return 0; + } +#if TBB_USE_CAPTURED_EXCEPTION + catch(const tbb::captured_exception& e) + { + const std::string tn1(e.name()); + const std::string tn2(typeid(const CGAL::internal::Throw_at_output_exception&).name()); + if(tn1 != tn2) + { + std::cerr << "Unexpected throw: " << tn1 << std::endl; + throw; + } - return split_edges(edges_to_split, tm_S, vpm_S, tm_T, vpm_T, gt, is_source_mesh_fixed); + return 0; + } +#endif + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for find split edges (parallel): " << timer.time() << std::endl; +#endif + + return split_edges(edges_to_split, tm_S, vpm_S, tm_T, vpm_T, gt, visitor, is_source_mesh_fixed); } else #endif // CGAL_LINKED_WITH_TBB @@ -900,14 +974,28 @@ std::size_t snap_non_conformal_one_way(const HalfedgeRange& halfedge_range_S, #endif std::map edges_to_split; - for(const Vertex_with_tolerance& vt : vertices_to_snap) + + try { - internal::find_splittable_edge(vt, edges_to_split, &aabb_tree, - tm_S, vertex_patch_map_S, vpm_S, - tm_T, face_patch_map_T, vpm_T, gt); + for(const Vertex_with_tolerance& vt : vertices_to_snap) + { + internal::find_splittable_edge(vt, edges_to_split, &aabb_tree, + tm_S, vertex_patch_map_S, vpm_S, + tm_T, face_patch_map_T, vpm_T, + gt, visitor); + } + } + catch(const CGAL::internal::Throw_at_output_exception&) + { + return 0; } - return split_edges(edges_to_split, tm_S, vpm_S, tm_T, vpm_T, gt, is_source_mesh_fixed); +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for find split edges (sequential): " << timer.time() << std::endl; +#endif + + return split_edges(edges_to_split, tm_S, vpm_S, tm_T, vpm_T, gt, visitor, is_source_mesh_fixed); } } @@ -999,15 +1087,28 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, internal_np::face_patch_t, NamedParameters_B, Constant_property_map /*default*/ >::type Face_patch_map_B; + typedef typename internal_np::Lookup_named_param_def < + internal_np::visitor_t, + NamedParameters_A, + internal::Snapping_default_visitor // default + >::reference Visitor; + using CGAL::parameters::choose_parameter; using CGAL::parameters::is_default_parameter; using CGAL::parameters::get_parameter; + using CGAL::parameters::get_parameter_reference; const bool is_same_mesh = (&tm_A == &tm_B); const bool simplify_first_mesh = choose_parameter(get_parameter(np_A, internal_np::do_simplify_border), false); const bool simplify_second_mesh = choose_parameter(get_parameter(np_B, internal_np::do_simplify_border), false); const bool is_second_mesh_fixed = choose_parameter(get_parameter(np_B, internal_np::do_lock_mesh), false); + internal::Snapping_default_visitor default_visitor; + Visitor& visitor = choose_parameter(get_parameter_reference(np_A, internal_np::visitor), default_visitor); + + if(visitor.stop()) + return 0; + // vertex-vertex and vertex-edge snapping is only considered within compatible patches Face_patch_map_A face_patch_map_A = choose_parameter(get_parameter(np_A, internal_np::face_patch), Constant_property_map(-1)); @@ -1053,6 +1154,9 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, /// #1 and #1bis (Simplification of borders) ////////////////////////////////////////////////////////////////////////////////////////////////// + if(visitor.stop()) + return 0; + #ifdef CGAL_PMP_SNAP_DEBUG std::cout << "Simplify ranges (" << simplify_first_mesh << " " << simplify_second_mesh << ")..." << std::endl; #endif @@ -1079,6 +1183,8 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, /// #2 (Two-way vertex-vertex snapping) ////////////////////////////////////////////////////////////////////////////////////////////////// + std::size_t snapped_n = 0; + // We keep in memory pairs of source/target edges that are stitchable after vertex-vertex snapping // --> these halfedges should not be considered as targets in non-conformal snapping // Similarly, matching vertices whose incident edges have matching directions are also locked @@ -1087,8 +1193,6 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, Locked_halfedges locked_halfedges_A = get(Halfedge_bool_tag(), tm_A); Locked_halfedges locked_halfedges_B = get(Halfedge_bool_tag(), tm_B); - std::size_t snapped_n = 0; - std::vector > locked_vertices; std::vector locked_halfedges_A_vector, locked_halfedges_B_vector; @@ -1130,17 +1234,24 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, #endif ////////////////////////////////////////////////////////////////////////////////////////////////// - /// #3 (Two one-way vertex-edge snapping) + /// #3 (Two one-way vertex-edge snappings) ////////////////////////////////////////////////////////////////////////////////////////////////// + if(visitor.stop()) + return snapped_n; + #ifdef CGAL_PMP_SNAP_DEBUG std::cout << " ///////////// Two one-way vertex-edge snapping (A --> B) " << std::endl; #endif + visitor.start_first_vertex_edge_phase(); + snapped_n += internal::snap_non_conformal_one_way( halfedge_range_A, tm_A, tolerance_map_A, vertex_patch_map_A, locked_vertices_A, halfedge_range_B, tm_B, face_patch_map_B, locked_halfedges_B, - false /*source is never fixed*/, np_A, np_B); + false /*source is never fixed*/, visitor, np_A, np_B); + + visitor.end_first_vertex_edge_phase(); #ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT std::ofstream("results/vertex_edge_A.off") << std::setprecision(17) << tm_A; @@ -1149,14 +1260,21 @@ std::size_t snap_non_conformal(HalfedgeRange& halfedge_range_A, if(!is_self_snapping) { + if(visitor.stop()) + return snapped_n; + #ifdef CGAL_PMP_SNAP_DEBUG - std::cout << " ///////////// Two one-way vertex-edge snapping (B --> A) " << std::endl; + std::cout << " ///////////// Two one-way vertex-edge snapping (B --> A) " << std::endl; #endif + visitor.start_second_vertex_edge_phase(); + snapped_n += internal::snap_non_conformal_one_way( halfedge_range_B, tm_B, tolerance_map_B, vertex_patch_map_B, locked_vertices_B, halfedge_range_A, tm_A, face_patch_map_A, locked_halfedges_A, - is_second_mesh_fixed, np_B, np_A); + is_second_mesh_fixed, visitor, np_B, np_A); + + visitor.end_second_vertex_edge_phase(); } return snapped_n; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h index 90df8a56406..98aa23f2862 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Snapping/snap_vertices.h @@ -34,12 +34,18 @@ #include #include #include +#include +#include +#include #include +#include #include #include -#include #include +#include +#include #include +#include #include #include @@ -47,7 +53,9 @@ #include #ifdef CGAL_LINKED_WITH_TBB +#define TBB_PREVIEW_CONCURRENT_ORDERED_CONTAINERS 1 # include +# include # include # include #endif @@ -88,26 +96,41 @@ struct Snapping_pair FT sq_dist; }; -// Functor that just forwards the pair of the two intersecting boxes -template -struct Intersecting_boxes_pairs_report +#ifdef CGAL_LINKED_WITH_TBB +// Functor that forwards the pair of the two intersecting boxes +// Note that Box_intersection_d does a lot of copies of the callback functor, but we are passing it +// with std::ref, so is always refering to the same reporter object (and importantly, the same counter) +template +struct Intersecting_boxes_pairs_parallel_report { - Intersecting_boxes_pairs_report(OutputIterator it) : m_iterator(it) { } + mutable OutputIterator m_iterator; + Visitor& m_visitor; + + Intersecting_boxes_pairs_parallel_report(OutputIterator it, Visitor& visitor) + : m_iterator(it), + m_visitor(visitor) + { } + + Intersecting_boxes_pairs_parallel_report(const Intersecting_boxes_pairs_parallel_report& other) = delete; + Intersecting_boxes_pairs_parallel_report& operator=(const Intersecting_boxes_pairs_parallel_report&) = delete; template - void operator()(const Box* b, const Box* c) const { - *m_iterator++ = std::make_pair(b->info(), c->info()); - } + void operator()(const Box* b, const Box* c) const + { + *m_iterator++ = std::make_pair(b->info(), c->info()); // writing into a concurrent vector - mutable OutputIterator m_iterator; + if(m_visitor.stop()) + throw CGAL::internal::Throw_at_output_exception(); + } }; +#endif template Unique_vertex_pair; +private: + const PolygonMesh& m_tm_A; + ToleranceMap_A m_tolerance_map_A; + VertexPatchMap_A m_vertex_patch_map_A; + VPM_A m_vpm_A; + const PolygonMesh& m_tm_B; + ToleranceMap_B m_tolerance_map_B; + VertexPatchMap_B m_vertex_patch_map_B; + VPM_B m_vpm_B; + const GeomTraits& m_gt; + + Visitor& m_visitor; + SnappingPairContainer& m_snapping_pairs; // will only be filled here in the sequential setting + +#ifdef CGAL_LINKED_WITH_TBB + const UniqueVertexPairContainer* m_uv_pairs; + ToKeepContainer* m_to_keep; +#endif + +public: Vertex_proximity_report(SnappingPairContainer& snapping_pairs, const PolygonMesh& tm_A, ToleranceMap_A tolerance_map_A, @@ -135,7 +178,8 @@ struct Vertex_proximity_report ToleranceMap_B tolerance_map_B, VertexPatchMap_B vertex_patch_map_B, const VPM_B& vpm_B, - const GeomTraits& gt + const GeomTraits& gt, + Visitor& visitor #ifdef CGAL_LINKED_WITH_TBB , const UniqueVertexPairContainer* uv_pairs = nullptr , ToKeepContainer* to_keep = nullptr @@ -151,6 +195,7 @@ struct Vertex_proximity_report m_vertex_patch_map_B(vertex_patch_map_B), m_vpm_B(vpm_B), m_gt(gt), + m_visitor(visitor), m_snapping_pairs(snapping_pairs) #ifdef CGAL_LINKED_WITH_TBB , m_uv_pairs(uv_pairs) @@ -158,7 +203,7 @@ struct Vertex_proximity_report #endif { } - bool are_equal_vertices(Unique_vertex_ptr uv_a, Unique_vertex_ptr uv_b) const + bool are_equal_vertices(const Unique_vertex_ptr uv_a, const Unique_vertex_ptr uv_b) const { if(&m_tm_A != &m_tm_B) // must be the same mesh return false; @@ -171,10 +216,13 @@ struct Vertex_proximity_report return (std::find(uv_b->first.begin(), uv_b->first.end(), ha) != uv_b->first.end()); } - std::pair do_keep(Unique_vertex_ptr uv_a, Unique_vertex_ptr uv_b) const + std::pair do_keep(const Unique_vertex_ptr uv_a, const Unique_vertex_ptr uv_b) const { + CGAL_precondition(uv_a != nullptr && uv_b != nullptr); + const Vertex_container& vs_a = uv_a->first; const Vertex_container& vs_b = uv_b->first; + const vertex_descriptor va = target(vs_a.front(), m_tm_A); const vertex_descriptor vb = target(vs_b.front(), m_tm_B); @@ -204,7 +252,9 @@ struct Vertex_proximity_report #endif if(res == CGAL::LARGER) + { return std::make_pair(-1, false); // ignore + } else { const FT sq_dist = (min)(m_gt.compute_squared_distance_3_object()(get(m_vpm_A, va), get(m_vpm_B, vb)), @@ -213,17 +263,29 @@ struct Vertex_proximity_report } } - // that's the sequential version - void operator()(const Box* a, const Box* b) + // sequential version (kd_tree) + void operator()(const Unique_vertex_ptr uv_a, const Unique_vertex_ptr uv_b) { - Unique_vertex_ptr uv_a = a->info(), uv_b = b->info(); + if(m_visitor.stop()) + throw CGAL::internal::Throw_at_output_exception(); + const std::pair res = do_keep(uv_a, uv_b); if(res.second) - m_snapping_pairs.insert(Snapping_pair(uv_a, uv_b, res.first)); + { + m_snapping_pairs.emplace(uv_a, uv_b, res.first); + m_visitor.on_vertex_vertex_match(uv_a->first, m_tm_A, uv_b->first, m_tm_B); + } } + // sequential version (box_d) + template + void operator()(const BoxPtr a, const BoxPtr b) + { + return this->operator()(a->info(), b->info()); + } + + // parallel version #ifdef CGAL_LINKED_WITH_TBB - // that's the parallel version void operator()(const tbb::blocked_range& r) const { CGAL_assertion(m_uv_pairs != nullptr); @@ -236,26 +298,384 @@ struct Vertex_proximity_report } } #endif - -private: - const PolygonMesh& m_tm_A; - ToleranceMap_A m_tolerance_map_A; - VertexPatchMap_A m_vertex_patch_map_A; - VPM_A m_vpm_A; - const PolygonMesh& m_tm_B; - ToleranceMap_B m_tolerance_map_B; - VertexPatchMap_B m_vertex_patch_map_B; - VPM_B m_vpm_B; - const GeomTraits& m_gt; - - SnappingPairContainer& m_snapping_pairs; // will only be filled here in the sequential setting - -#ifdef CGAL_LINKED_WITH_TBB - const UniqueVertexPairContainer* m_uv_pairs; - ToKeepContainer* m_to_keep; -#endif }; +template +struct Unique_point_position_accessor +{ + typedef Key key_type; + typedef ValueType value_type; + typedef const value_type& reference; + typedef boost::lvalue_property_map_tag category; + + friend reference get(const Unique_point_position_accessor&, const key_type& k) + { + return k->first.first; + } +}; + +template +void find_vertex_vertex_matches_with_kd_tree(Unique_positions& unique_positions_A, // not const because it complicates parallel loops + const Unique_positions& unique_positions_B, + const PolygonMesh& tm_A, + VPM_A vpm_A, + ToleranceMap_A tolerance_map_A, + VertexPatchMap_A vertex_patch_map_A, + const PolygonMesh& tm_B, + VPM_B vpm_B, + ToleranceMap_B tolerance_map_B, + VertexPatchMap_B vertex_patch_map_B, + const GT& gt, + Visitor& visitor, + Snapping_pair_container& snapping_pairs) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + typedef typename GT::FT FT; + typedef typename boost::property_traits::value_type Point; + + typedef std::vector Vertex_container; + typedef std::pair Unique_vertex; + typedef const Unique_vertex* Unique_vertex_ptr; + typedef std::pair Patch_point; + + // Put iterators into the tree: + // - to be lighter + // - because kd_tree.search() returns copies + typedef typename Unique_positions::const_iterator Key; + + typedef CGAL::Search_traits_3 Base_search_traits; + typedef CGAL::Search_traits_adapter, Base_search_traits> Search_traits; + typedef CGAL::Kd_tree Kd_tree; + typedef CGAL::Fuzzy_sphere Fuzzy_sphere; + + typedef std::vector Unique_positions_vector; + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + CGAL::Real_timer timer; + timer.start(); +#endif + + Unique_positions_vector unique_positions_Bv; + unique_positions_Bv.reserve(unique_positions_B.size()); + for(auto it=unique_positions_B.cbegin(); it!=unique_positions_B.cend(); ++it) + unique_positions_Bv.push_back(it); + + Kd_tree tree; + tree.insert(unique_positions_Bv.begin(), unique_positions_Bv.end()); + +#if !defined(CGAL_LINKED_WITH_TBB) + CGAL_static_assertion_msg (!(std::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else + // parallel + if(std::is_convertible::value) + { + typedef std::pair Unique_vertex_pair; + typedef tbb::concurrent_vector Unique_vertex_pairs; + + Unique_vertex_pairs uv_pairs; + + // Functor for the parallel_for over the conccurrent map + auto vertex_inquiry = [&](const typename Unique_positions::range_type &r) + { + for(const auto& e : r) + { + if(visitor.stop()) + return; + + const Patch_point& pp = e.first; + const Point& q = pp.first; + const Unique_vertex& uv = e.second; + const FT tolerance = uv.second; + + visitor.on_vertex_vertex_inquiry(uv, tm_A); + + // @fixme this assumes constant and equal tolerances, because querying the kd tree is one way + // and we don't know the tolerance at the potential match since we don't know the potential match... + Fuzzy_sphere fq(q, 2 * tolerance); + + std::vector res; + tree.search(std::back_inserter(res), fq); + + for(const auto rit : res) + { + uv_pairs.emplace_back(&uv, &(rit->second)); + CGAL_assertion(!rit->second.first.empty()); + } + } + }; + + tbb::parallel_for(unique_positions_A.range(), vertex_inquiry); + + // Filter the range of possible matches (also in parallel) + typedef std::vector > Filters; + typedef Vertex_proximity_report Reporter; + + Filters to_keep(uv_pairs.size()); + Reporter proximity_filterer(snapping_pairs, + tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, + tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, + gt, visitor, &uv_pairs, &to_keep); + + tbb::parallel_for(tbb::blocked_range(0, uv_pairs.size()), proximity_filterer); + + // Now fill the multi-index, sequentially + for(std::size_t i=0, uvps = uv_pairs.size(); ifirst, tm_A, uv_pairs[i].second->first, tm_B); + snapping_pairs.emplace(uv_pairs[i].first, uv_pairs[i].second, to_keep[i].first); + } + } + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for KD Tree (parallel): " << timer.time() << std::endl; +#endif + } + else +#endif // CGAL_LINKED_WITH_TBB + // sequential + { + typedef std::pair Unique_vertex_pair; + typedef std::vector Unique_vertex_pairs; + + Unique_vertex_pairs uv_pairs; + + for(const auto& e : unique_positions_A) + { + if(visitor.stop()) + return; + + const Patch_point& pp = e.first; + const Point& q = pp.first; + const Unique_vertex& uv = e.second; + const FT tolerance = uv.second; + + visitor.on_vertex_vertex_inquiry(uv, tm_A); + + // @fixme this assumes constant and equal tolerances, because querying the kd tree is one way + // and we don't know the tolerance at the potential match since we don't know the potential match... + Fuzzy_sphere fq(q, 2 * tolerance); + + std::vector res; + tree.search(std::back_inserter(res), fq); + + for(const auto rit : res) + { + uv_pairs.emplace_back(&uv, &(rit->second)); + CGAL_assertion(!rit->second.first.empty()); + } + } + + typedef Vertex_proximity_report Reporter; + + Reporter proximity_filterer(snapping_pairs, + tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, + tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, + gt, visitor); + + for(const auto& p : uv_pairs) + proximity_filterer(p.first, p.second); + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for KD Tree (sequential): " << timer.time() << std::endl; +#endif + } +} + +template +void find_vertex_vertex_matches_with_box_d(const Unique_positions& unique_positions_A, + const Unique_positions& unique_positions_B, + const PolygonMesh& tm_A, + VPM_A vpm_A, + ToleranceMap_A tolerance_map_A, + VertexPatchMap_A vertex_patch_map_A, + const PolygonMesh& tm_B, + VPM_B vpm_B, + ToleranceMap_B tolerance_map_B, + VertexPatchMap_B vertex_patch_map_B, + const GT& gt, + Visitor& visitor, + Snapping_pair_container& snapping_pairs) +{ + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + typedef typename GT::FT FT; + + typedef std::vector Vertex_container; + typedef std::pair Unique_vertex; + typedef const Unique_vertex* Unique_vertex_ptr; + + typedef Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; + typedef CGAL::Box_intersection_d::Box_with_info_d Box; + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + CGAL::Real_timer timer; + timer.start(); +#endif + + std::vector boxes_A; + boxes_A.reserve(unique_positions_A.size()); + std::vector boxes_B; + boxes_B.reserve(unique_positions_B.size()); + + // Actually build the boxes now + for(const auto& p : unique_positions_A) + { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Unique_vertex (A), pos: " << p.first.first << " vertices:"; + for(const halfedge_descriptor h : p.second.first) + std::cout << " " << target(h, tm_A); + std::cout << std::endl; +#endif + + const Unique_vertex& ev = p.second; + CGAL_assertion(!ev.first.empty()); + + // this only makes the box a little larger to ease intersection computations, + // the final tolerance is not changed + const double eps = 1.01 * CGAL::to_double(ev.second); + const Bbox_3 pb = gt.construct_bbox_3_object()(p.first.first); + const Bbox_3 b(pb.xmin() - eps, pb.ymin() - eps, pb.zmin() - eps, + pb.xmax() + eps, pb.ymax() + eps, pb.zmax() + eps); + boxes_A.emplace_back(b, &ev); + } + + for(const auto& p : unique_positions_B) + { +#ifdef CGAL_PMP_SNAP_DEBUG_PP + std::cout << "Unique_vertex (B), pos: " << p.first.first << " vertices:"; + for(const halfedge_descriptor h : p.second.first) + std::cout << " " << target(h, tm_B); + std::cout << std::endl; +#endif + + const Unique_vertex& ev = p.second; + CGAL_assertion(!ev.first.empty()); + + const double eps = 1.01 * CGAL::to_double(ev.second); + const Bbox_3 pb = gt.construct_bbox_3_object()(p.first.first); + const Bbox_3 b(pb.xmin() - eps, pb.ymin() - eps, pb.zmin() - eps, + pb.xmax() + eps, pb.ymax() + eps, pb.zmax() + eps); + boxes_B.emplace_back(b, &ev); + } + + // @fixme bench and don't use ptrs if not useful + std::vector boxes_A_ptr; + boxes_A_ptr.reserve(boxes_A.size()); + for(const Box& b : boxes_A) + boxes_A_ptr.push_back(&b); + + std::vector boxes_B_ptr; + boxes_B_ptr.reserve(boxes_B.size()); + for(const Box& b : boxes_B) + boxes_B_ptr.push_back(&b); + +#if !defined(CGAL_LINKED_WITH_TBB) + CGAL_static_assertion_msg (!(std::is_convertible::value), + "Parallel_tag is enabled but TBB is unavailable."); +#else // CGAL_LINKED_WITH_TBB + if(std::is_convertible::value) + { + typedef std::pair Unique_vertex_pair; + typedef tbb::concurrent_vector Unique_vertex_pairs; + typedef std::back_insert_iterator UVP_output_iterator; + + Unique_vertex_pairs uv_pairs; + Intersecting_boxes_pairs_parallel_report box_callback(std::back_inserter(uv_pairs), visitor); + + // Shenanigans to pass a reference as callback (which is copied by value by 'box_intersection_d') + std::function callback(std::ref(box_callback)); + + // Grab the boxes that are interesecting but don't do any extra filtering (in parallel) + CGAL::box_intersection_d(boxes_A_ptr.begin(), boxes_A_ptr.end(), + boxes_B_ptr.begin(), boxes_B_ptr.end(), + callback); + + // Actually filter the range of intersecting boxes now (also in parallel) + typedef std::vector > Filters; + typedef Vertex_proximity_report Reporter; + + Filters to_keep(uv_pairs.size()); + Reporter proximity_filterer(snapping_pairs, + tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, + tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, + gt, visitor, &uv_pairs, &to_keep); + + tbb::parallel_for(tbb::blocked_range(0, uv_pairs.size()), proximity_filterer); + + // Now fill the multi-index, sequentially + for(std::size_t i=0, uvps = uv_pairs.size(); ifirst, uv_pairs[i].second->first); + snapping_pairs.emplace(uv_pairs[i].first, uv_pairs[i].second, to_keep[i].first); + } + } + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for box_d (parallel): " << timer.time() << std::endl; +#endif + } + else +#endif // CGAL_LINKED_WITH_TBB + // Sequential code + { + typedef Vertex_proximity_report Reporter; + + Reporter proximity_filterer(snapping_pairs, + tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, + tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, gt, + visitor); + + // Shenanigans to pass a reference as callback (which is copied by value by 'box_intersection_d') + std::function callback(std::ref(proximity_filterer)); + + CGAL::box_intersection_d(boxes_A_ptr.begin(), boxes_A_ptr.end(), + boxes_B_ptr.begin(), boxes_B_ptr.end(), + callback); + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for box_d (sequential): " << timer.time() << std::endl; +#endif + } +} + template ::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename GetVertexPointMap::type VPM_A; - typedef typename GetVertexPointMap::type VPM_B; + typedef typename GetVertexPointMap::type VPM_A; + typedef typename GetVertexPointMap::type VPM_B; - typedef typename GetGeomTraits::type GT; - typedef typename GT::FT FT; - typedef typename boost::property_traits::value_type Point; + typedef typename GetGeomTraits::type GT; + typedef typename GT::FT FT; + typedef typename boost::property_traits::value_type Point; - typedef std::vector Vertex_container; - typedef std::pair Unique_vertex; - typedef const Unique_vertex* Unique_vertex_ptr; - typedef std::map, Unique_vertex> Unique_positions; + typedef std::vector Vertex_container; + typedef std::pair Unique_vertex; + typedef const Unique_vertex* Unique_vertex_ptr; + typedef std::pair Patch_point; - typedef Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; - typedef CGAL::Box_intersection_d::Box_with_info_d Box; + // @todo in theory could be unordered maps, but this requires defining the hashes & stuff +#ifdef CGAL_LINKED_WITH_TBB + typedef tbb::concurrent_map Unique_positions; +#else + typedef std::map Unique_positions; +#endif + + typedef typename internal_np::Lookup_named_param_def < + internal_np::visitor_t, + NamedParameters_A, + internal::Snapping_default_visitor // default + >::reference Visitor; - using parameters::get_parameter; using parameters::choose_parameter; + using parameters::get_parameter; + using parameters::get_parameter_reference; CGAL_static_assertion((std::is_same::value)); @@ -306,6 +737,13 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, VPM_B vpm_B = choose_parameter(get_parameter(np_B, internal_np::vertex_point), get_property_map(vertex_point, tm_B)); + internal::Snapping_default_visitor default_visitor; + Visitor& visitor = choose_parameter(get_parameter_reference(np_A, internal_np::visitor), default_visitor); + + visitor.start_vertex_vertex_phase(); + if(visitor.stop()) + return 0; + #ifdef CGAL_PMP_SNAP_DEBUG std::cout << "Finding snappables vertices. Range sizes: " << std::distance(halfedge_range_A.begin(), halfedge_range_A.end()) << " and " @@ -316,15 +754,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, is_empty_range(halfedge_range_B.begin(), halfedge_range_B.end())) return 0; - // Vertex-Vertex snapping is performed as follows: - // - Identify points which are already equal and group them together so that they are moved together - // - Create a single box for these points - - std::vector boxes_A; - boxes_A.reserve(halfedge_range_A.size()); - std::vector boxes_B; - boxes_B.reserve(halfedge_range_B.size()); + // Vertex-Vertex snapping is performed by identify points which are already equal + // and grouping them together so that they are moved together + // @todo all range building could be parallel (worth it?) Unique_positions unique_positions_A; for(halfedge_descriptor h : halfedge_range_A) { @@ -336,10 +769,9 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, #endif Vertex_container nvc {{ h }}; - std::pair is_insert_successful = - unique_positions_A.insert(std::make_pair( - std::make_pair(get(vpm_A, v), get(vertex_patch_map_A, v)), // point and patch id - std::make_pair(nvc, tolerance))); + auto is_insert_successful = unique_positions_A.emplace(std::make_pair(get(vpm_A, v), + get(vertex_patch_map_A, v)), + std::make_pair(nvc, tolerance)); if(!is_insert_successful.second) // point was already met { @@ -351,7 +783,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, } } - // same for tm_B (@todo avoid all that for self snapping + use self_intersection_d) + // same for tm_B (@todo when doing boxes, avoid all that for self snapping + use self_intersection_d) Unique_positions unique_positions_B; for(halfedge_descriptor h : halfedge_range_B) { @@ -364,9 +796,8 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, Vertex_container nvc {{ h }}; std::pair is_insert_successful = - unique_positions_B.insert(std::make_pair( - std::make_pair(get(vpm_B, v), get(vertex_patch_map_B, v)), // point and patch id - std::make_pair(nvc, tolerance))); + unique_positions_B.emplace(std::make_pair(get(vpm_B, v), get(vertex_patch_map_B, v)), // point and patch id + std::make_pair(nvc, tolerance)); if(!is_insert_successful.second) // point was already met { @@ -378,62 +809,10 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, } } - // Actually build the boxes now - for(const auto& p : unique_positions_A) - { -#ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Unique_vertex (A), pos: " << p.first.first << " vertices:"; - for(const halfedge_descriptor h : p.second.first) - std::cout << " " << target(h, tm_A); - std::cout << std::endl; -#endif - - const Unique_vertex& ev = p.second; - CGAL_assertion(!ev.first.empty()); - - // this only makes the box a little larger to ease intersection computations, - // the final tolerance is not changed - const double eps = 1.01 * CGAL::to_double(ev.second); - const Bbox_3 pb = gt.construct_bbox_3_object()(p.first.first); - const Bbox_3 b(pb.xmin() - eps, pb.ymin() - eps, pb.zmin() - eps, - pb.xmax() + eps, pb.ymax() + eps, pb.zmax() + eps); - boxes_A.push_back(Box(b, &ev)); - } - - for(const auto& p : unique_positions_B) - { -#ifdef CGAL_PMP_SNAP_DEBUG_PP - std::cout << "Unique_vertex (B), pos: " << p.first.first << " vertices:"; - for(const halfedge_descriptor h : p.second.first) - std::cout << " " << target(h, tm_B); - std::cout << std::endl; -#endif - - const Unique_vertex& ev = p.second; - CGAL_assertion(!ev.first.empty()); - - const double eps = 1.01 * CGAL::to_double(ev.second); - const Bbox_3 pb = gt.construct_bbox_3_object()(p.first.first); - const Bbox_3 b(pb.xmin() - eps, pb.ymin() - eps, pb.zmin() - eps, - pb.xmax() + eps, pb.ymax() + eps, pb.zmax() + eps); - boxes_B.push_back(Box(b, &ev)); - } - - // @fixme bench and don't use ptrs if not useful - std::vector boxes_A_ptr; - boxes_A_ptr.reserve(boxes_A.size()); - for(const Box& b : boxes_A) - boxes_A_ptr.push_back(&b); - - std::vector boxes_B_ptr; - boxes_B_ptr.reserve(boxes_B.size()); - for(const Box& b : boxes_B) - boxes_B_ptr.push_back(&b); - // Use a multi index to sort easily by sources, targets, AND distance. // Then, look up the distances in increasing order, and snap whenever the source and the target // have both not been snapped yet. - typedef internal::Snapping_pair Snapping_pair; + typedef internal::Snapping_pair Snapping_pair; typedef boost::multi_index::multi_index_container< Snapping_pair, boost::multi_index::indexed_by< @@ -444,77 +823,55 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, boost::multi_index::ordered_non_unique< BOOST_MULTI_INDEX_MEMBER(Snapping_pair, FT, sq_dist)> > - > Snapping_pair_container; + > Snapping_pair_container; Snapping_pair_container snapping_pairs; - -#if !defined(CGAL_LINKED_WITH_TBB) - CGAL_static_assertion_msg (!(std::is_convertible::value), - "Parallel_tag is enabled but TBB is unavailable."); -#else - if(std::is_convertible::value) + try { - typedef std::pair Unique_vertex_pair; - typedef tbb::concurrent_vector Unique_vertex_pairs; - typedef std::back_insert_iterator UVP_output_iterator; - - Unique_vertex_pairs uv_pairs; - Intersecting_boxes_pairs_report callback(std::back_inserter(uv_pairs)); - - CGAL::Real_timer timer; - timer.start(); - - // Grab the boxes that are interesecting but don't do any extra filtering (in parallel) - CGAL::box_intersection_d(boxes_A_ptr.begin(), boxes_A_ptr.end(), - boxes_B_ptr.begin(), boxes_B_ptr.end(), - callback); - - std::cout << "time for box_d: " << timer.time() << std::endl; - - // Actually filter the range of intersecting boxes now (in parallel) - typedef std::vector > Filters; - typedef Vertex_proximity_report Reporter; - - Filters to_keep(uv_pairs.size()); - Reporter proximity_filterer(snapping_pairs, tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, - tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, - gt, &uv_pairs, &to_keep); - tbb::parallel_for(tbb::blocked_range(0, uv_pairs.size()), proximity_filterer); - - // Now fill the multi index, sequentially - for(std::size_t i=0, uvps = uv_pairs.size(); i(unique_positions_A, unique_positions_B, + tm_A, vpm_A, tolerance_map_A, vertex_patch_map_A, + tm_B, vpm_B, tolerance_map_B, vertex_patch_map_B, gt, + visitor, snapping_pairs); +#else // CGAL_PMP_SNAP_VERTICES_USE_KD_TREE + find_vertex_vertex_matches_with_box_d(unique_positions_A, unique_positions_B, + tm_A, vpm_A, tolerance_map_A, vertex_patch_map_A, + tm_B, vpm_B, tolerance_map_B, vertex_patch_map_B, gt, + visitor, snapping_pairs); +#endif // CGAL_PMP_SNAP_VERTICES_USE_KD_TREE } - else -#endif + catch(const CGAL::internal::Throw_at_output_exception&) { - typedef Vertex_proximity_report Reporter; - - Reporter vpr(snapping_pairs, tm_A, tolerance_map_A, vertex_patch_map_A, vpm_A, - tm_B, tolerance_map_B, vertex_patch_map_B, vpm_B, gt); - - // Shenanigans to pass a reference as callback (which is copied by value by 'box_intersection_d') - std::function callback(std::ref(vpr)); - - CGAL::box_intersection_d(boxes_A_ptr.begin(), boxes_A_ptr.end(), - boxes_B_ptr.begin(), boxes_B_ptr.end(), - callback); + return 0; } +#if TBB_USE_CAPTURED_EXCEPTION + catch(const tbb::captured_exception& e) + { + const std::string tn1(e.name()); + const std::string tn2(typeid(const CGAL::internal::Throw_at_output_exception&).name()); + if(tn1 != tn2) + { + std::cerr << "Unexpected throw: " << tn1 << std::endl; + throw; + } + + return 0; + } +#endif // TBB_USE_CAPTURED_EXCEPTION ////////////////////////////////////////////////////////////////////////////////////////////////// /// Done collecting; start matching ////////////////////////////////////////////////////////////////////////////////////////////////// - if(snapping_pairs.empty()) + if(snapping_pairs.empty() || visitor.stop()) return 0; +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + CGAL::Real_timer timer; + timer.start(); +#endif + typedef std::pair Unique_vertex_pair; std::vector snappable_vertices_pairs; @@ -566,15 +923,21 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, /// Done matching; start snapping ////////////////////////////////////////////////////////////////////////////////////////////////// - std::size_t counter = 0; + visitor.start_vertex_vertex_snapping(); + if(snappable_vertices_pairs.empty() || visitor.stop()) + return 0; #ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT std::ofstream out_edges("results/snappable.polylines.txt"); out_edges.precision(17); #endif + std::size_t counter = 0; for(const Unique_vertex_pair& uvp : snappable_vertices_pairs) { + if(visitor.stop()) + return counter; + Unique_vertex_ptr uv_a = uvp.first; Unique_vertex_ptr uv_b = uvp.second; const Vertex_container& vs_a = uv_a->first; @@ -582,6 +945,8 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const vertex_descriptor va = target(vs_a.front(), tm_A); const vertex_descriptor vb = target(vs_b.front(), tm_B); + visitor.before_vertex_vertex_snap(vs_a, tm_A, vs_b, tm_B); + #ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT out_edges << "2 " << tm_A.point(va) << " " << tm_B.point(vb) << std::endl; #endif @@ -600,7 +965,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, const FT tol_t = uv_b->second; CGAL_assertion(tol_s != FT(0) || tol_t != FT(0)); - const FT lambda = tol_t / (tol_s + tol_t); + const FT lambda = tol_s / (tol_s + tol_t); const Point new_p = get(vpm_A, va) + lambda * (get(vpm_B, vb) - get(vpm_A, va)); #ifdef CGAL_PMP_SNAP_DEBUG_PP std::cout << "new position of " << va << " " << vb << " --> " << new_p << std::endl; @@ -615,12 +980,16 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, ++counter; } + + visitor.after_vertex_vertex_snap(vs_a, tm_A, vs_b, tm_B); } #ifdef CGAL_PMP_SNAP_DEBUG_OUTPUT out_edges.close(); #endif + visitor.end_vertex_vertex_snapping(); + #ifdef CGAL_PMP_SNAP_DEBUG std::cout << "Snapped " << counter << " pair(s)!" << std::endl; #endif @@ -629,7 +998,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, /// Done snapping; start analyzing ////////////////////////////////////////////////////////////////////////////////////////////////// - // Below is used in non-conformal snapping + // Below is performed to improve non-conformal snapping // @todo could avoid doing it if not required // // Now that vertex-vertex snapping has been performed, look around to see if we can already @@ -640,8 +1009,7 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, // #2 : If pairs on either side of the two matching vertices are compatible (not necessary fully matching), // then the two vertices should be locked as no better match can be obtained // #3 : If a pair of incident edges are not fully matching, but still have compatible directions - // (i.e. collinear and opposite directions), then we don't want to project onto the shorter - // of the two + // (i.e. collinear and opposite directions), then we don't want to project onto the shorter of the two for(const Unique_vertex_pair& uvp : snappable_vertices_pairs) { Unique_vertex_ptr uv_a = uvp.first; @@ -724,6 +1092,13 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, } } + visitor.end_vertex_vertex_phase(); + +#ifdef CGAL_PMP_SNAPPING_PRINT_RUNTIME + timer.stop(); + std::cout << "time for the actual snapping (vertex-vertex): " << timer.time() << std::endl; +#endif + return counter; } @@ -750,15 +1125,15 @@ std::size_t snap_vertices_two_way(const HalfedgeRange_A& halfedge_range_A, using CGAL::parameters::choose_parameter; using CGAL::parameters::get_parameter; - return snap_vertices_two_way(halfedge_range_A, tm_A, tolerance_map_A, - choose_parameter(get_parameter(np_A, internal_np::vertex_incident_patches), - Constant_property_map(-1)), - halfedge_range_B, tm_B, tolerance_map_B, - choose_parameter(get_parameter(np_B, internal_np::vertex_incident_patches), - Constant_property_map(-1)), - lockable_vps_out, lockable_ha_out, lockable_hb_out, - choose_parameter(get_parameter(np_B, internal_np::do_lock_mesh), false), - np_A, np_B); + return snap_vertices_two_way(halfedge_range_A, tm_A, tolerance_map_A, + choose_parameter(get_parameter(np_A, internal_np::vertex_incident_patches), + Constant_property_map(-1)), + halfedge_range_B, tm_B, tolerance_map_B, + choose_parameter(get_parameter(np_B, internal_np::vertex_incident_patches), + Constant_property_map(-1)), + lockable_vps_out, lockable_ha_out, lockable_hb_out, + choose_parameter(get_parameter(np_B, internal_np::do_lock_mesh), false), + np_A, np_B); } } // namespace internal @@ -818,7 +1193,8 @@ namespace experimental { // // \return the number of snapped vertex pairs // -template std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, @@ -832,13 +1208,14 @@ std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, { CGAL::Emptyset_iterator unused_output_iterator; - return internal::snap_vertices_two_way(halfedge_range_A, tm_A, tolerance_map_A, - halfedge_range_B, tm_B, tolerance_map_B, - unused_output_iterator, unused_output_iterator, - unused_output_iterator, np_A, np_B); + return internal::snap_vertices_two_way(halfedge_range_A, tm_A, tolerance_map_A, + halfedge_range_B, tm_B, tolerance_map_B, + unused_output_iterator, unused_output_iterator, + unused_output_iterator, np_A, np_B); } -template std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, PolygonMesh& tm_A, @@ -847,11 +1224,13 @@ std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, PolygonMesh& tm_B, ToleranceMap_B tolerance_map_B) { - return snap_vertices(halfedge_range_A, tm_A, tolerance_map_A, halfedge_range_B, tm_B, tolerance_map_B, - CGAL::parameters::all_default(), CGAL::parameters::all_default()); + return snap_vertices(halfedge_range_A, tm_A, tolerance_map_A, + halfedge_range_B, tm_B, tolerance_map_B, + CGAL::parameters::all_default(), CGAL::parameters::all_default()); } -template std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, @@ -877,21 +1256,23 @@ std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, return snap_vertices(halfedge_range_A, tm_A, tolerance_map_A, halfedge_range_B, tm_B, tolerance_map_B, np_A, np_B); } -template +template std::size_t snap_vertices(const HalfedgeRange_A& halfedge_range_A, PolygonMesh& tm_A, const HalfedgeRange_B& halfedge_range_B, PolygonMesh& tm_B) { - return snap_vertices(halfedge_range_A, tm_A, halfedge_range_B, tm_B, - parameters::all_default(), parameters::all_default()); + return snap_vertices(halfedge_range_A, tm_A, halfedge_range_B, tm_B, + parameters::all_default(), parameters::all_default()); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Border convenience overloads /////////////////////////////////////////////////////////////////////////////////////////////////// -template +template std::size_t snap_border_vertices(PolygonMesh& tm_A, ToleranceMap_A tolerance_map_A, PolygonMesh& tm_B, @@ -904,11 +1285,12 @@ std::size_t snap_border_vertices(PolygonMesh& tm_A, std::vector border_B; border_halfedges(tm_B, std::back_inserter(border_B)); - return snap_vertices(border_A, tm_A, tolerance_map_A, - border_B, tm_B, tolerance_map_B); + return snap_vertices(border_A, tm_A, tolerance_map_A, + border_B, tm_B, tolerance_map_B); } -template +template std::size_t snap_border_vertices(PolygonMesh& tm_A, PolygonMesh& tm_B) { @@ -920,25 +1302,28 @@ std::size_t snap_border_vertices(PolygonMesh& tm_A, std::vector border_vertices_B; border_halfedges(tm_B, std::back_inserter(border_vertices_B)); - return snap_vertices(border_vertices_A, tm_A, border_vertices_B, tm_B); + return snap_vertices(border_vertices_A, tm_A, border_vertices_B, tm_B); } -template +template std::size_t snap_border_vertices(PolygonMesh& tm, ToleranceMap tolerance_map) { - return snap_border_vertices(tm, tolerance_map, tm, tolerance_map); + return snap_border_vertices(tm, tolerance_map, tm, tolerance_map); } -template +template std::size_t snap_border_vertices(PolygonMesh& tm) { - return snap_border_vertices(tm, tm); + return snap_border_vertices(tm, tm); } /////////////////////////////////////////////////////////////////////////////////////////////////// /// Other convenience overloads /////////////////////////////////////////////////////////////////////////////////////////////////// -template +template std::size_t snap_all_vertices(PolygonMesh& tm, ToleranceMap tolerance_map) { typedef boost::graph_traits GT; @@ -952,10 +1337,9 @@ std::size_t snap_all_vertices(PolygonMesh& tm, ToleranceMap tolerance_map) boost::make_transform_iterator(vertices(tm).begin(), get_halfedge), boost::make_transform_iterator(vertices(tm).end(), get_halfedge) ); - return snap_vertices(hedges, tm, tolerance_map, hedges, tm, tolerance_map); + return snap_vertices(hedges, tm, tolerance_map, hedges, tm, tolerance_map); } - } // namespace experimental } // namespace Polygon_mesh_processing } // namespace CGAL diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/fair_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/fair_impl.h index a45ff4b55e9..62e1ce5e5e8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/fair_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/fair_impl.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #ifdef CGAL_PMP_FAIR_DEBUG #include #endif @@ -65,7 +65,7 @@ private: double weight = 0; Halfedge_around_vertex_circulator circ(halfedge(v,pmesh),pmesh), done(circ); do { - weight += weight_calculator.w_ij(*circ); + weight += CGAL::to_double(weight_calculator.w_ij(*circ)); } while(++circ != done); return weight; } @@ -95,11 +95,11 @@ private: } } else { - double w_i = weight_calculator.w_i(v); + double w_i = CGAL::to_double(weight_calculator.w_i(v)); Halfedge_around_vertex_circulator circ(halfedge(v,pmesh),pmesh), done(circ); do { - double w_i_w_ij = w_i * weight_calculator.w_ij(*circ) ; + double w_i_w_ij = w_i * CGAL::to_double(weight_calculator.w_ij(*circ)) ; vertex_descriptor nv = target(opposite(*circ,pmesh),pmesh); compute_row(nv, row_id, matrix, x, y, z, -w_i_w_ij*multiplier, vertex_id_map, depth-1); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h index cb4a1ce9e08..ccad1bf4d50 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_degeneracies.h @@ -42,6 +42,7 @@ #include #include #include +#include // First part of the file: remove_ALMOST_degenerate_faces (needles/caps) // Second part of the file: remove_degenerate_edges/faces @@ -338,6 +339,191 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, return p0p2 <= p1p3; } +template +struct Filter_wrapper_for_cap_needle_removal +{ + Filter_wrapper_for_cap_needle_removal(TriangleMesh& tm, const VPM& vpm, const Functor& functor) + : m_tm(tm) + , m_vpm(vpm) + , m_functor(functor) + {} + + typedef boost::graph_traits Graph_traits; + typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Graph_traits::edge_descriptor edge_descriptor; + typedef typename Graph_traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::Point_3 Point_3; + + bool flip(halfedge_descriptor h) + { + CGAL_assertion(!is_border(h, m_tm)); + + const Point_3& o1 = get(m_vpm, target(next(h, m_tm), m_tm)); + const Point_3& o2 = get(m_vpm, target(next(opposite(h, m_tm), m_tm), m_tm)); + const Point_3& src = get(m_vpm, source(h,m_tm)); + const Point_3& tgt = get(m_vpm, target(h,m_tm)); + + if (!m_functor(o1, o2, src)) + return false; + + if (!m_functor(o1, o2, tgt)) + return false; + + return true; + } + + bool collapse(edge_descriptor e) + { + halfedge_descriptor h = halfedge(e, m_tm), + oh = opposite(h, m_tm); + vertex_descriptor vkept = target(h, m_tm); + const Point_3& p = get(m_vpm, vkept); + + // look at all the triangles that will be created after the collapse of the edge + // and call the functor using them. If we get a negative answer for one of them + // return false. Code copy/pasted/adapted from SMS package + halfedge_descriptor endleft = next(oh, m_tm); + halfedge_descriptor endright = next(h, m_tm); + + // counterclockwise around src + halfedge_descriptor e02 = opposite(prev(h, m_tm), m_tm); + vertex_descriptor v = target(e02, m_tm), v2 = v; + + while(e02 != endleft) + { + bool is_b = is_border(e02, m_tm); + e02 = opposite(prev(e02, m_tm), m_tm); + v = target(e02, m_tm); + if(!is_b) + if (!m_functor(get(m_vpm,v), p, get(m_vpm,v2))) + return false; + v2 = v; + } + + e02 = opposite(prev(oh, m_tm), m_tm); + + // counterclockwise around tgt + v2 = target(e02, m_tm); + v = v2; + while(e02 != endright) + { + bool is_b = is_border(e02, m_tm); + e02 = opposite(prev(e02, m_tm), m_tm); + v = target(e02, m_tm); + + if(!is_b) + if (!m_functor(get(m_vpm,v),p,get(m_vpm,v2))) + return false; + v2 = v; + } + return true; + } + + TriangleMesh& m_tm; + const VPM& m_vpm; + const Functor& m_functor; +}; + +template +struct Filter_wrapper_for_cap_needle_removal > + : public Filter_wrapper_for_cap_needle_removal +{ + typedef Filter_wrapper_for_cap_needle_removal Base; + + Filter_wrapper_for_cap_needle_removal(TriangleMesh& tm, const VPM& vpm, const std::reference_wrapper& functor_ref) + : Base(tm, vpm, functor_ref.get()) + {} +}; + +template +struct Filter_wrapper_for_cap_needle_removal::face_descriptor>&)> > +{ + typedef boost::graph_traits Graph_traits; + typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Graph_traits::edge_descriptor edge_descriptor; + typedef typename Graph_traits::face_descriptor face_descriptor; + + typedef Filter_wrapper_for_cap_needle_removal Base; + typedef std::function&)> Make_env; + + Filter_wrapper_for_cap_needle_removal(TriangleMesh& tm, const VPM& vpm, const Make_env& make_envelope) + : m_tm(tm) + , m_vpm(vpm) + , m_make_envelope(make_envelope) + {} + + void collect_link_faces(edge_descriptor e, std::vector& link_faces) + { + halfedge_descriptor h = halfedge(e, m_tm); + halfedge_descriptor h_opp = opposite(h, m_tm); + + halfedge_descriptor endleft = next(h_opp, m_tm); + halfedge_descriptor endright = next(h, m_tm); + + face_descriptor f = face(h, m_tm); + if(f!=boost::graph_traits::null_face()) + link_faces.push_back(f); + f = face(h_opp, m_tm); + if(f!=boost::graph_traits::null_face()) + link_faces.push_back(f); + + // counterclockwise around src + halfedge_descriptor hl = opposite(prev(h, m_tm), m_tm); + + while(hl != endleft) + { + if (!is_border(hl, m_tm)) + link_faces.push_back(face(hl, m_tm)); + hl = opposite(prev(hl, m_tm), m_tm); + } + + // counterclockwise around tgt + hl = opposite(prev(h_opp, m_tm), m_tm); + + while(hl != endright) + { + if (!is_border(hl, m_tm)) + link_faces.push_back(face(hl, m_tm)); + hl = opposite(prev(hl, m_tm), m_tm); + } + } + + bool flip(halfedge_descriptor h) + { + std::vector link_faces; + collect_link_faces(edge(h, m_tm), link_faces); + Functor f = m_make_envelope(link_faces); + Base base(m_tm, m_vpm, f); + return base.flip(h); + } + + bool collapse(edge_descriptor e) + { + std::vector link_faces; + collect_link_faces(e, link_faces); + Functor f = std::move(m_make_envelope(link_faces)); + Base base(m_tm, m_vpm, f); + return base.collapse(e); + } + + TriangleMesh& m_tm; + const VPM& m_vpm; + const Make_env& m_make_envelope; +}; + +template +struct Filter_wrapper_for_cap_needle_removal > +{ + Filter_wrapper_for_cap_needle_removal(TriangleMesh&, const VPM&, Identity) {} + + typedef boost::graph_traits Graph_traits; + typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Graph_traits::edge_descriptor edge_descriptor; + + bool flip(halfedge_descriptor){ return true; } + bool collapse(edge_descriptor){ return true; } +}; + } // namespace internal namespace experimental { @@ -378,6 +564,16 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, typedef typename GetGeomTraits::type Traits; Traits gt = choose_parameter(get_parameter(np, internal_np::geom_traits), Traits()); + typedef typename internal_np::Lookup_named_param_def< + internal_np::filter_t, + NamedParameters, + Identity + > ::type User_filter; + User_filter user_filter = choose_parameter>(get_parameter(np, internal_np::filter)); + + typedef internal::Filter_wrapper_for_cap_needle_removal Accept_change_functor; + Accept_change_functor accept_change(tmesh, vpm, user_filter); + // Vertex property map that combines the VCM and the fact that extremities of a constrained edge should be constrained typedef CGAL::dynamic_vertex_property_t Vertex_property_tag; typedef typename boost::property_map::type DVCM; @@ -495,6 +691,15 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, continue; } + if (!accept_change.collapse(edge(best_h, tmesh))) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::cout << "\t edge collapse prevented by the user functor" << std::endl; +#endif + next_edges_to_collapse.insert(h); + continue; + } + // Proceeding with the collapse, purge the sets from halfedges being removed for(int i=0; i<2; ++i) { @@ -642,6 +847,14 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, continue; } + if (!accept_change.flip(h)) + { +#ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA + std::cout << "\t Flipping prevented: rejected by user functor" << std::endl; +#endif + continue; + } + #ifdef CGAL_PMP_DEBUG_REMOVE_DEGENERACIES_EXTRA std::cout << "\t step " << kk << " -- Flipping" << std::endl; #endif diff --git a/Polygon_mesh_processing/package_info/Polygon_mesh_processing/dependencies b/Polygon_mesh_processing/package_info/Polygon_mesh_processing/dependencies index e0691224967..6d471658093 100644 --- a/Polygon_mesh_processing/package_info/Polygon_mesh_processing/dependencies +++ b/Polygon_mesh_processing/package_info/Polygon_mesh_processing/dependencies @@ -35,3 +35,4 @@ TDS_3 Triangulation_2 Triangulation_3 Union_find +Weights diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp index 64882963a23..626960b6369 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_detect_features.cpp @@ -2,92 +2,130 @@ #include #include +#include #include -typedef CGAL::Exact_predicates_inexact_constructions_kernel K; -typedef CGAL::Surface_mesh Mesh; -typedef boost::graph_traits::face_descriptor face_descriptor; -typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Surface_mesh Mesh; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::face_descriptor face_descriptor; namespace PMP = CGAL::Polygon_mesh_processing; -int main(int argc, char* argv[]) +void test_cube() { - const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/cube_quad.off"); - std::ifstream input(filename); + std::cout << "Test cube..." << std::endl; - Mesh mesh; - if (!input || !(input >> mesh)) - { - std::cerr << "Not a valid input file." << std::endl; - return 1; - } + std::ifstream input(CGAL::data_file_path("meshes/cube_quad.off")); + Mesh mesh; + if(!input || !(input >> mesh)) + { + std::cerr << "Failed to read cube_quad.off input." << std::endl; + assert(false); + return; + } - typedef boost::property_map >::type PatchID; - typedef boost::property_map >::type VIP; - typedef boost::property_map::type EIF_map; + typedef boost::property_map >::type PatchID; + typedef boost::property_map >::type VIP; + typedef boost::property_map::type EIF_map; - PatchID pid = get(CGAL::face_patch_id_t(), mesh); - VIP vip = get(CGAL::vertex_incident_patches_t(), mesh); - EIF_map eif = get(CGAL::edge_is_feature, mesh); - std::size_t number_of_patches - = PMP::sharp_edges_segmentation(mesh, 90, eif, pid); + PatchID pid = get(CGAL::face_patch_id_t(), mesh); + VIP vip = get(CGAL::vertex_incident_patches_t(), mesh); + EIF_map eif = get(CGAL::edge_is_feature, mesh); + std::size_t number_of_patches = PMP::sharp_edges_segmentation(mesh, 90, eif, pid); - std::size_t nb_sharp_edges = 0; - for(boost::graph_traits::edge_descriptor e : edges(mesh)) - { - if(get(eif, e)) - ++nb_sharp_edges; - } + std::size_t nb_sharp_edges = 0; + for(boost::graph_traits::edge_descriptor e : edges(mesh)) + { + if(get(eif, e)) + ++nb_sharp_edges; + } - CGAL_assertion(nb_sharp_edges == 12); - CGAL_assertion(number_of_patches == 6); - CGAL_USE(number_of_patches); + assert(nb_sharp_edges == 12); + assert(number_of_patches == 6); + CGAL_USE(number_of_patches); - number_of_patches - = PMP::sharp_edges_segmentation(mesh, 90, eif, pid, - PMP::parameters::first_index(1) - .vertex_incident_patches_map(vip)); + number_of_patches = PMP::sharp_edges_segmentation(mesh, 90, eif, pid, + PMP::parameters::first_index(1) + .vertex_incident_patches_map(vip)); - CGAL_assertion(number_of_patches == 6); - - PMP::detect_sharp_edges(mesh, 90, eif); - number_of_patches = PMP::internal::detect_surface_patches(mesh, pid, eif); - PMP::detect_vertex_incident_patches(mesh, pid, vip, eif); - - nb_sharp_edges = 0; - for(boost::graph_traits::edge_descriptor e : edges(mesh)) - { - if(get(eif, e)) - ++nb_sharp_edges; - } + assert(number_of_patches == 6); - CGAL_assertion(nb_sharp_edges == 12); - CGAL_assertion(number_of_patches == 6); + number_of_patches = PMP::internal::detect_surface_patches(mesh, pid, eif); + PMP::detect_vertex_incident_patches(mesh, pid, vip, eif); - Mesh::Property_map > patch_id_map - = mesh.add_property_map >("f:pid",std::pair()).first; - Mesh::Property_map > > vertex_incident_patch_map - = mesh.add_property_map > >("f:vip",std::set >()).first; - PMP::detect_sharp_edges(mesh, 90, eif); - number_of_patches - = PMP::internal::detect_surface_patches(mesh, patch_id_map, eif, - PMP::parameters::first_index(1)); - PMP::detect_vertex_incident_patches(mesh, patch_id_map, vertex_incident_patch_map, eif); + nb_sharp_edges = 0; + for(boost::graph_traits::edge_descriptor e : edges(mesh)) + { + if(get(eif, e)) + ++nb_sharp_edges; + } - nb_sharp_edges =0; - for(boost::graph_traits::edge_descriptor e : edges(mesh)) - { - if(get(eif, e)) - ++nb_sharp_edges; - } + assert(nb_sharp_edges == 12); + assert(number_of_patches == 6); - CGAL_assertion(nb_sharp_edges == 12); - CGAL_assertion(number_of_patches == 6); + Mesh::Property_map > patch_id_map + = mesh.add_property_map >("f:pid",std::pair()).first; + Mesh::Property_map > > vertex_incident_patch_map + = mesh.add_property_map > >("f:vip",std::set >()).first; + PMP::detect_sharp_edges(mesh, 90, eif); + number_of_patches = PMP::internal::detect_surface_patches(mesh, patch_id_map, eif, + PMP::parameters::first_index(1)); + PMP::detect_vertex_incident_patches(mesh, patch_id_map, vertex_incident_patch_map, eif); - return 0; + nb_sharp_edges =0; + for(boost::graph_traits::edge_descriptor e : edges(mesh)) + { + if(get(eif, e)) + ++nb_sharp_edges; + } + + assert(nb_sharp_edges == 12); + assert(number_of_patches == 6); } +void test_blobby() +{ + std::cout << "Test blobby..." << std::endl; + std::ifstream input(CGAL::data_file_path("meshes/blobby.off")); + Mesh mesh; + if(!input || !(input >> mesh)) + { + std::cerr << "Failed to read blobby.off input." << std::endl; + assert(false); + return; + } + + typedef CGAL::dynamic_edge_property_t EIF_tag; + typedef boost::property_map::type EIF; + + EIF eif = get(EIF_tag(), mesh); + + CGAL::Real_timer timer; + timer.start(); + + PMP::detect_sharp_edges(mesh, 5, eif); + + timer.stop(); + std::cout << "Elapsed: " << timer.time() << std::endl; + + unsigned int nb_sharp_edges = 0; + for(auto e : edges(mesh)) + if(get(eif, e)) + ++nb_sharp_edges; + + std::cout << "Found " << nb_sharp_edges << " sharp edges" << std::endl; + assert(nb_sharp_edges == 2565); +} + +int main(int, char**) +{ + test_cube(); + test_blobby(); + + return EXIT_SUCCESS; +} diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp index d8782fde6cd..ed99bc0b0b7 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_remove_caps_needles.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -17,20 +18,22 @@ typedef boost::graph_traits::face_descriptor face_descriptor; namespace PMP = CGAL::Polygon_mesh_processing; -int main(int argc, char** argv) +typedef CGAL::Polyhedral_envelope Envelope; + +void general_test(std::string filename) { - const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/pig.off"); + std::cout << "Removing caps/needles no extra parameters\n"; std::ifstream input(filename); Mesh mesh; if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) { std::cerr << "Not a valid input file." << std::endl; - return 1; + exit(EXIT_FAILURE); } - std::cout << "Input mesh has " << edges(mesh).size() << " edges\n"; + std::cout << " Input mesh has " << edges(mesh).size() << " edges\n"; if (PMP::does_self_intersect(mesh)) - std::cout << "Input mesh has self-intersections\n"; + std::cout << " Input mesh has self-intersections\n"; PMP::experimental::remove_almost_degenerate_faces(mesh, std::cos(160. / 180 * CGAL_PI), @@ -40,9 +43,91 @@ int main(int argc, char** argv) CGAL::IO::write_polygon_mesh("cleaned_mesh.off", mesh, CGAL::parameters::stream_precision(17)); - std::cout << "Output mesh has " << edges(mesh).size() << " edges\n"; + std::cout << " Output mesh has " << edges(mesh).size() << " edges\n"; if (PMP::does_self_intersect(mesh)) - std::cout << "Output mesh has self-intersections\n"; + std::cout << " Output mesh has self-intersections\n"; +} + +void test_with_envelope(std::string filename, double eps) +{ + std::cout << "Removing caps/needles with envelope, epsilon = " << eps << "\n"; + std::ifstream input(filename); + + Mesh mesh, bk; + if (!input || !(input >> mesh) || !CGAL::is_triangle_mesh(mesh)) { + std::cerr << "Not a valid input file." << std::endl; + exit(EXIT_FAILURE); + } + + if (PMP::does_self_intersect(mesh)) + std::cout << " Input mesh has self-intersections\n"; + + // first a test where nothing should be done + struct No_modification_allowed + { + bool operator()(K::Point_3, K::Point_3, K::Point_3) const { return false; } + }; + No_modification_allowed no_modif; + const std::size_t nbv = vertices(mesh).size(); + PMP::experimental::remove_almost_degenerate_faces(mesh, + std::cos(160. / 180 * CGAL_PI), + 4, + 0.14, + CGAL::parameters::filter(no_modif)); + assert(nbv == vertices(mesh).size()); + + // now the real test with a fixed envelope + std::cout << "Using fixed envelope\n"; + std::cout << " Input mesh has " << edges(mesh).size() << " edges\n"; + bk=mesh; + Envelope envelope(mesh, eps); + PMP::experimental::remove_almost_degenerate_faces(mesh, + std::cos(160. / 180 * CGAL_PI), + 4, + 0.14, + CGAL::parameters::filter(std::ref(envelope))); + + CGAL::IO::write_polygon_mesh("cleaned_mesh_with_envelope.off", mesh, CGAL::parameters::stream_precision(17)); + + std::cout << " Output mesh has " << edges(mesh).size() << " edges\n"; + if (PMP::does_self_intersect(mesh)) + std::cout << " Output mesh has self-intersections\n"; + + + // now the real test with an iterative envelope + mesh=bk; + std::cout << "Using iteratively created fixed envelope\n"; + std::cout << " Input mesh has " << edges(mesh).size() << " edges\n"; + auto create_envelope = [&](const std::vector& frange) -> Envelope + { + return Envelope(frange, mesh, eps); + }; + std::function&)> filter(create_envelope); + PMP::experimental::remove_almost_degenerate_faces(mesh, + std::cos(160. / 180 * CGAL_PI), + 4, + 0.14, + CGAL::parameters::filter(filter)); + + CGAL::IO::write_polygon_mesh("cleaned_mesh_with_iterative_envelope.off", mesh, CGAL::parameters::stream_precision(17)); + + std::cout << " Output mesh has " << edges(mesh).size() << " edges\n"; + if (PMP::does_self_intersect(mesh)) + std::cout << " Output mesh has self-intersections\n"; +} + + + +int main(int argc, char** argv) +{ + const std::string filename = (argc > 1) ? argv[1] : CGAL::data_file_path("meshes/pig.off"); + + general_test(filename); + if (argc==2) + test_with_envelope(filename, 0.01); + else + if (argc==3) + test_with_envelope(filename, atof(argv[2])); return 0; } diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_no_delaunay_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_no_delaunay_test.cpp index 8e33c3a02b6..0b1ea949136 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_no_delaunay_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_no_delaunay_test.cpp @@ -16,6 +16,8 @@ #include +#include + #include #include #include @@ -336,16 +338,16 @@ void test_triangulate_refine_and_fair_hole_compile() { read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole (poly, border_reps[0], back_inserter(patch_facets), back_inserter(patch_vertices), - CGAL::Polygon_mesh_processing::parameters::weight_calculator( - CGAL::internal::Uniform_weight_fairing(poly)). + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight()). sparse_linear_solver(Default_solver())); // default solver read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole (poly, border_reps[0], back_inserter(patch_facets), back_inserter(patch_vertices), - CGAL::Polygon_mesh_processing::parameters::weight_calculator( - CGAL::internal::Uniform_weight_fairing(poly))); + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight())); // default solver and weight read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_test.cpp index 2e58a432185..0f1429f051c 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/triangulate_hole_Polyhedron_3_test.cpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -326,16 +327,17 @@ void test_triangulate_refine_and_fair_hole_compile() { read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole (poly, border_reps[0], back_inserter(patch_facets), back_inserter(patch_vertices), - CGAL::Polygon_mesh_processing::parameters::weight_calculator( - CGAL::internal::Uniform_weight_fairing(poly)). - sparse_linear_solver(Default_solver()).use_2d_constrained_delaunay_triangulation(false)); + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight()). + sparse_linear_solver(Default_solver()). + use_2d_constrained_delaunay_triangulation(false)); // default solver read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole (poly, border_reps[0], back_inserter(patch_facets), back_inserter(patch_vertices), - CGAL::Polygon_mesh_processing::parameters::weight_calculator( - CGAL::internal::Uniform_weight_fairing(poly))); + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight())); // default solver and weight read_poly_with_borders("elephant_quad_hole.off", poly, border_reps); diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 284f118bbd0..b595087b242 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -185,7 +185,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren CGAL::Three::Three::s_scene = scene; CGAL::Three::Three::s_connectable_scene = scene; { - QShortcut* shortcut = new QShortcut(QKeySequence(Qt::ALT+Qt::Key_Q), this); + QShortcut* shortcut = new QShortcut(QKeySequence(Qt::ALT,Qt::Key_Q), this); connect(shortcut, SIGNAL(activated()), this, SLOT(setFocusToQuickSearch())); shortcut = new QShortcut(QKeySequence(Qt::Key_F5), this); @@ -194,10 +194,10 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren shortcut = new QShortcut(QKeySequence(Qt::Key_F11), this); connect(shortcut, SIGNAL(activated()), this, SLOT(toggleFullScreen())); - shortcut = new QShortcut(QKeySequence(Qt::CTRL+Qt::Key_R), this); + shortcut = new QShortcut(QKeySequence(Qt::CTRL,Qt::Key_R), this); connect(shortcut, &QShortcut::activated, this, &MainWindow::recenterScene); - shortcut = new QShortcut(QKeySequence(Qt::CTRL+Qt::Key_T), this); + shortcut = new QShortcut(QKeySequence(Qt::CTRL,Qt::Key_T), this); connect(shortcut, &QShortcut::activated, this, [](){ diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Tetrahedra_filtering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Tetrahedra_filtering_plugin.cpp index 1076e094239..ce75e3eafd3 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Tetrahedra_filtering_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/Tetrahedra_filtering_plugin.cpp @@ -61,7 +61,7 @@ public : filter(); }); } - bool applicable(QAction* a) const Q_DECL_OVERRIDE + bool applicable(QAction*) const Q_DECL_OVERRIDE { return qobject_cast( scene->item( scene->mainSelectionIndex() ) ); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp index 93c130d4854..d20d302e43f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Fairing_plugin.cpp @@ -13,6 +13,7 @@ typedef Scene_surface_mesh_item Scene_facegraph_item; #include #include #include +#include #include #include @@ -98,7 +99,8 @@ public Q_SLOTS: if(weight_index == 1) CGAL::Polygon_mesh_processing::fair(*selection_item->polyhedron(), selection_item->selected_vertices, - CGAL::Polygon_mesh_processing::parameters::weight_calculator(CGAL::internal::Uniform_weight_fairing(*selection_item->polyhedron())). + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight()). fairing_continuity(continuity)); if(weight_index == 0) CGAL::Polygon_mesh_processing::fair(*selection_item->polyhedron(), diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp index d746af5fbad..c4a6207c968 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Hole_filling_plugin.cpp @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include #include @@ -716,16 +718,18 @@ bool Polyhedron_demo_hole_filling_plugin::fill if(weight_index == 0) { success = std::get<0>(CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole(poly, it, std::back_inserter(patch), CGAL::Emptyset_iterator(), - CGAL::Polygon_mesh_processing::parameters::weight_calculator - (CGAL::internal::Uniform_weight_fairing(poly)). + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Uniform_weight()). density_control_factor(alpha). fairing_continuity(continuity). use_delaunay_triangulation(use_DT))); } else { + auto pmap = get_property_map(CGAL::vertex_point, poly); success = std::get<0>(CGAL::Polygon_mesh_processing::triangulate_refine_and_fair_hole(poly, it, std::back_inserter(patch), CGAL::Emptyset_iterator(), - CGAL::Polygon_mesh_processing::parameters::weight_calculator(CGAL::internal::Cotangent_weight_with_voronoi_area_fairing(poly)). + CGAL::Polygon_mesh_processing::parameters:: + weight_calculator(CGAL::Weights::Secure_cotangent_weight_with_voronoi_area(poly, pmap)). density_control_factor(alpha). fairing_continuity(continuity). use_delaunay_triangulation(use_DT))); diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 35272952770..4b58030049f 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -309,7 +309,7 @@ void Viewer::doBindings() setKeyDescription(Qt::Key_M, tr("Toggle macro mode: useful to view details very near from the camera, " "but decrease the z-buffer precision")); - setKeyDescription(Qt::Key_I + Qt::CTRL, + setKeyDescription(Qt::CTRL, Qt::Key_I, tr("Toggle the primitive IDs visibility of the selected Item, for the types selected in the context menu of the said item.")); setKeyDescription(Qt::Key_D, tr("Disable the distance between two points visibility.")); diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index 470918b5f80..15081283ede 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -425,9 +425,7 @@ public: CGAL_precondition(type(&*x) == USED); EraseCounterStrategy::increment_erase_counter(*x); std::allocator_traits::destroy(alloc, &*x); -/*#ifndef CGAL_NO_ASSERTIONS - std::memset(&*x, 0, sizeof(T)); -#endif*/ + put_on_free_list(&*x); --size_; } diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index d1f1a4e840f..d3f60bbd381 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -394,10 +394,6 @@ private: std::allocator_traits::destroy(m_alloc, &*x); -/* WE DON'T DO THAT BECAUSE OF THE ERASE COUNTER -#ifndef CGAL_NO_ASSERTIONS - std::memset(&*x, 0, sizeof(T)); -#endif*/ put_on_free_list(&*x, fl); } public: diff --git a/STL_Extension/include/CGAL/assertions_impl.h b/STL_Extension/include/CGAL/assertions_impl.h index cfe4a27cf00..8701e67ccf7 100644 --- a/STL_Extension/include/CGAL/assertions_impl.h +++ b/STL_Extension/include/CGAL/assertions_impl.h @@ -14,6 +14,9 @@ // // Author(s) : Geert-Jan Giezeman and Sven Schönherr +#ifndef CGAL_ASSERTIONS_IMPL_H +#define CGAL_ASSERTIONS_IMPL_H + #ifdef CGAL_HEADER_ONLY #define CGAL_INLINE_FUNCTION inline #else @@ -280,3 +283,5 @@ set_warning_behaviour(Failure_behaviour eb) } } //namespace CGAL + +#endif //CGAL_ASSERTIONS_IMPL_H diff --git a/Skin_surface_3/include/CGAL/make_union_of_balls_3.h b/Skin_surface_3/include/CGAL/make_union_of_balls_3.h index 6f0e242e2c1..e40ecd76707 100644 --- a/Skin_surface_3/include/CGAL/make_union_of_balls_3.h +++ b/Skin_surface_3/include/CGAL/make_union_of_balls_3.h @@ -20,8 +20,6 @@ #include #include -#include - namespace CGAL { template diff --git a/Spatial_searching/doc/Spatial_searching/Concepts/SearchGeomTraits_3.h b/Spatial_searching/doc/Spatial_searching/Concepts/SearchGeomTraits_3.h index a097e1646e7..243277705d8 100644 --- a/Spatial_searching/doc/Spatial_searching/Concepts/SearchGeomTraits_3.h +++ b/Spatial_searching/doc/Spatial_searching/Concepts/SearchGeomTraits_3.h @@ -5,8 +5,7 @@ The concept `SearchGeomTraits_3` defines the requirements for the template parameter of the search traits classes. -\cgalHasModel `Simple_cartesian` -\cgalHasModel `Simple_cartesian` +\cgalHasModel All models of the concept `Kernel` */ diff --git a/Stream_support/doc/Stream_support/IOstream.txt b/Stream_support/doc/Stream_support/IOstream.txt index 085fe65127d..cb098fc45e7 100644 --- a/Stream_support/doc/Stream_support/IOstream.txt +++ b/Stream_support/doc/Stream_support/IOstream.txt @@ -176,7 +176,8 @@ int main() \subsubsection IOstreamUsingOutputFormatting Using Output Formatting -To ensure that non-\cgal types are formatted correctly (i.e., respecting `IO::Mode`), `oformat()` can be used. +To ensure that non-\cgal types are formatted correctly (i.e., respecting \link PkgStreamSupportEnumRef `IO::Mode` \endlink), +`oformat()` can be used. For types with a `Output_rep` specialization, the respective output routine of `Output_rep` will be called by `oformat()`. Otherwise, the stream output operator will be called. @@ -197,7 +198,8 @@ refer to the documentation of the respective type. In some situations, you want to control the output formatting for a type `T`. For external types (third party libraries etc.), there might be problems if their stream output operator does not -respect `IO::Mode`. The purpose of `Output_rep` is to provide a way to +respect \link PkgStreamSupportEnumRef `IO::Mode` \endlink. +The purpose of `Output_rep` is to provide a way to control output formatting that works independently of the object's stream output operator. diff --git a/Stream_support/doc/Stream_support/PackageDescription.txt b/Stream_support/doc/Stream_support/PackageDescription.txt index 9efed4d7e45..9d993ee4779 100644 --- a/Stream_support/doc/Stream_support/PackageDescription.txt +++ b/Stream_support/doc/Stream_support/PackageDescription.txt @@ -58,7 +58,7 @@ All classes in the \cgal kernel provide input and output operators for I/O streams. \cgal provides three different printing mode, defined in the enum -`IO::Mode`, as well as different functions to set and get +\link PkgStreamSupportEnumRef `IO::Mode` \endlink, as well as different functions to set and get the printing mode. \cgalClassifedRefPages diff --git a/Stream_support/include/CGAL/IO/PLY.h b/Stream_support/include/CGAL/IO/PLY.h index 86745f0e6a6..dc11c16e873 100644 --- a/Stream_support/include/CGAL/IO/PLY.h +++ b/Stream_support/include/CGAL/IO/PLY.h @@ -276,7 +276,7 @@ bool read_PLY(std::istream& is, * * \attention The polygon soup is not cleared, and the data from the stream are appended. * - * \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + * \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. * * \tparam PointRange a model of the concepts `RandomAccessContainer` and `BackInsertionSequence` * whose value type is the point type @@ -426,7 +426,9 @@ bool read_PLY(const std::string& fname, PointRange& points, PolygonRange& polygo * * \brief writes the content of `points` and `polygons` in `out`, using the \ref IOStreamPLY. * - * \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. + * \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation + * of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink + * of the stream must be set to `BINARY`. * * \tparam PointRange a model of the concept `RandomAccessContainer` whose value type is the point type * \tparam PolygonRange a model of the concept `SequenceContainer` diff --git a/Stream_support/include/CGAL/IO/STL.h b/Stream_support/include/CGAL/IO/STL.h index 88a3c3d7933..797376e8285 100644 --- a/Stream_support/include/CGAL/IO/STL.h +++ b/Stream_support/include/CGAL/IO/STL.h @@ -49,7 +49,7 @@ namespace IO { * * \attention The polygon soup is not cleared, and the data from the stream are appended. * - * \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. + * \attention To read a binary file, the flag `std::ios::binary` must be set during the creation of the `ifstream`. * * \tparam PointRange a model of the concepts `RandomAccessContainer` and `BackInsertionSequence` * whose value type is the point type @@ -89,7 +89,7 @@ bool read_STL(std::istream& is, if(!is.good()) { if(verbose) - std::cerr<<"File doesn't exist."< -#include #include -#include /// \cond SKIP_IN_MANUAL // Trace utilities // --------------- -// print_stderr() = printf-like function to print to stderr -inline void CGAL_print_stderr(const char *fmt, ...) -{ - va_list argp; - va_start(argp, fmt); - vfprintf(stderr, fmt, argp); - va_end(argp); -} - -// CGAL_TRACE() = printf-like function to print to stderr -// if DEBUG_TRACE is defined (ignored otherwise) -#ifdef DEBUG_TRACE -#define CGAL_TRACE CGAL_print_stderr -#else - #define CGAL_TRACE if (false) CGAL_print_stderr -#endif // CGAL_TRACE_STREAM = C++ stream that prints to std::cerr // if DEBUG_TRACE is defined (ignored otherwise) diff --git a/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h b/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h index a99b5558db6..d0edd60afcc 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/IO/PLY.h @@ -715,7 +715,7 @@ void fill_header(std::ostream& os, const Surface_mesh& sm, /// \ingroup PkgSurfaceMeshIOFuncPLY /// -/// \attention When reading a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. +/// \attention To read a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ifstream`. /// /// \brief extracts the surface mesh from an input stream in the \ref IOStreamPLY /// and appends it to the surface mesh `sm`. @@ -888,7 +888,9 @@ namespace IO { /// simple types are inserted in the stream. The halfedges follow /// the same behavior. /// -/// \attention When writing a binary file, the flag `std::ios::binary` flag must be set during the creation of the `ofstream`. +/// \attention To write to a binary file, the flag `std::ios::binary` must be set during the creation +/// of the `ofstream`, and the \link PkgStreamSupportEnumRef `IO::Mode` \endlink +/// of the stream must be set to `BINARY`. /// /// \tparam Point The type of the \em point property of a vertex. There is no requirement on `P`, /// besides being default constructible and assignable. diff --git a/Surface_mesh_deformation/include/CGAL/Surface_mesh_deformation.h b/Surface_mesh_deformation/include/CGAL/Surface_mesh_deformation.h index 06a8151e9b7..95956028eb4 100644 --- a/Surface_mesh_deformation/include/CGAL/Surface_mesh_deformation.h +++ b/Surface_mesh_deformation/include/CGAL/Surface_mesh_deformation.h @@ -21,8 +21,8 @@ #include #include #include -#include #include +#include #include #include @@ -54,12 +54,15 @@ enum Deformation_algorithm_tag /// @cond CGAL_DOCUMENT_INTERNAL namespace internal { + template struct Types_selectors; template struct Types_selectors { - typedef internal::Single_cotangent_weight_impl Weight_calculator; + + // Get weight from the weight interface. + typedef CGAL::Weights::Single_cotangent_weight Weight_calculator; struct ARAP_visitor{ template @@ -80,7 +83,9 @@ struct Types_selectors { template struct Types_selectors { - typedef internal::Cotangent_weight_impl Weight_calculator; + + // Get weight from the weight interface. + typedef CGAL::Weights::Cotangent_weight Weight_calculator; typedef typename Types_selectors ::ARAP_visitor ARAP_visitor; @@ -88,7 +93,9 @@ struct Types_selectors { template struct Types_selectors { - typedef internal::Cotangent_weight_impl Weight_calculator; + + // Get weight from the weight interface. + typedef CGAL::Weights::Cotangent_weight Weight_calculator; class ARAP_visitor{ double m_nb_edges_incident; diff --git a/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies b/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies index 974b4a8f5f5..e4abdd72dbd 100644 --- a/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies +++ b/Surface_mesh_deformation/package_info/Surface_mesh_deformation/dependencies @@ -11,7 +11,6 @@ Interval_support Kernel_23 Modular_arithmetic Number_types -Polygon_mesh_processing Profiling_tools Property_map Random_numbers @@ -19,3 +18,4 @@ STL_Extension Solver_interface Stream_support Surface_mesh_deformation +Weights diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h index 3fb7edade43..33fef26c674 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/ARAP_parameterizer_3.h @@ -26,8 +26,8 @@ #include #include #include - #include +#include #include @@ -449,7 +449,7 @@ private: const Point_3& position_vj = get(ppmap, vj); const Point_3& position_vk = get(ppmap, vk); - NT cot = internal::cotangent(position_vi, position_vj, position_vk); + const NT cot = CGAL::Weights::cotangent(position_vi, position_vj, position_vk); put(ctmap, hd, cot); } @@ -489,13 +489,13 @@ private: // coefficient corresponding to the angle at vk if vk is the vertex before vj // while circulating around vi - NT c_k = get(ctmap, opposite(hd, mesh)); + const NT c_k = get(ctmap, opposite(hd, mesh)); // coefficient corresponding to the angle at vl if vl is the vertex after vj // while circulating around vi - NT c_l = get(ctmap, hd); + const NT c_l = get(ctmap, hd); - NT weight = c_k + c_l; + const NT weight = c_k + c_l; return weight; } diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h index c53c4c56d20..f311cb9396a 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Barycentric_mapping_parameterizer_3.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -180,7 +181,7 @@ protected: Vertex_around_target_circulator /* neighbor_vertex_v_j */ ) const { /// In the Tutte Barycentric Mapping algorithm, we have `w_ij = 1`, for `j` neighbor vertex of `i`. - return 1.; + return NT(1); } }; diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h index 61ca95aab95..aeb891cff92 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_authalic_parameterizer_3.h @@ -16,11 +16,10 @@ #include -#include #include #include - #include +#include #include @@ -177,34 +176,18 @@ protected: Vertex_around_target_circulator neighbor_vertex_v_j) const { const PPM ppmap = get(vertex_point, mesh); - const Point_3& position_v_i = get(ppmap, main_vertex_v_i); const Point_3& position_v_j = get(ppmap, *neighbor_vertex_v_j); - // Compute the square norm of v_j -> v_i vector - Vector_3 edge = position_v_i - position_v_j; - double square_len = edge*edge; - - // Compute cotangent of (v_k,v_j,v_i) corner (i.e. cotan of v_j corner) - // if v_k is the vertex before v_j when circulating around v_i vertex_around_target_circulator previous_vertex_v_k = neighbor_vertex_v_j; - previous_vertex_v_k--; + --previous_vertex_v_k; const Point_3& position_v_k = get(ppmap, *previous_vertex_v_k); - NT cotg_psi_ij = internal::cotangent(position_v_k, position_v_j, position_v_i); - // Compute cotangent of (v_i,v_j,v_l) corner (i.e. cotan of v_j corner) - // if v_l is the vertex after v_j when circulating around v_i vertex_around_target_circulator next_vertex_v_l = neighbor_vertex_v_j; - next_vertex_v_l++; - const Point_3& position_v_l = get(ppmap,*next_vertex_v_l); - NT cotg_theta_ij = internal::cotangent(position_v_i, position_v_j, position_v_l); + ++next_vertex_v_l; + const Point_3& position_v_l = get(ppmap, *next_vertex_v_l); - NT weight = 0.0; - CGAL_assertion(square_len != 0.0); // two points are identical! - if(square_len != 0.0) - weight = (cotg_psi_ij + cotg_theta_ij) / square_len; - - return weight; + return CGAL::Weights::authalic_weight(position_v_k, position_v_j, position_v_l, position_v_i) / NT(2); } }; diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h index 62bf4f29b3c..3d09fad861c 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Discrete_conformal_map_parameterizer_3.h @@ -16,11 +16,10 @@ #include -#include #include #include - #include +#include #if defined(CGAL_EIGEN3_ENABLED) #include @@ -173,26 +172,18 @@ protected: Vertex_around_target_circulator neighbor_vertex_v_j) const // its target is main_vertex_v_i { const PPM ppmap = get(vertex_point, mesh); - const Point_3& position_v_i = get(ppmap, main_vertex_v_i); const Point_3& position_v_j = get(ppmap, *neighbor_vertex_v_j); - // Compute cotangent of (v_i,v_k,v_j) corner (i.e. cotan of v_k corner) - // if v_k is the vertex before v_j when circulating around v_i vertex_around_target_circulator previous_vertex_v_k = neighbor_vertex_v_j; - previous_vertex_v_k--; + --previous_vertex_v_k; const Point_3& position_v_k = get(ppmap, *previous_vertex_v_k); - NT cotg_beta_ij = internal::cotangent(position_v_i, position_v_k, position_v_j); - // Compute cotangent of (v_j,v_l,v_i) corner (i.e. cotan of v_l corner) - // if v_l is the vertex after v_j when circulating around v_i vertex_around_target_circulator next_vertex_v_l = neighbor_vertex_v_j; - next_vertex_v_l++; + ++next_vertex_v_l; const Point_3& position_v_l = get(ppmap, *next_vertex_v_l); - NT cotg_alpha_ij = internal::cotangent(position_v_j, position_v_l, position_v_i); - NT weight = cotg_beta_ij + cotg_alpha_ij; - return weight; + return CGAL::Weights::cotangent_weight(position_v_k, position_v_j, position_v_l, position_v_i) / NT(2); } }; diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h index c3b9d8de956..4222d5f2244 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Fixed_border_parameterizer_3.h @@ -16,10 +16,8 @@ #include -#include #include #include - #include #include diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Iterative_authalic_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Iterative_authalic_parameterizer_3.h index 38093049023..2e475b11db8 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Iterative_authalic_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Iterative_authalic_parameterizer_3.h @@ -21,7 +21,6 @@ #include -#include #include #include #include @@ -34,7 +33,9 @@ #include #include #include -#include +// #include +#include +#include #include #if defined(CGAL_EIGEN3_ENABLED) @@ -629,7 +630,7 @@ private: /// computes `w_ij`, coefficient of matrix `A` for `j` neighbor vertex of `i`. /// - /// \param mesh a triangulated surface. + /// \param tmesh a triangulated surface. /// \param main_vertex_v_i the vertex of `mesh` with index `i` /// \param neighbor_vertex_v_j the vertex of `mesh` with index `j` NT compute_w_ij(const Triangle_mesh& tmesh, @@ -637,36 +638,28 @@ private: Vertex_around_target_circulator neighbor_vertex_v_j) const { const PPM ppmap = get(vertex_point, tmesh); - const PPM_ref position_v_i = get(ppmap, main_vertex_v_i); const PPM_ref position_v_j = get(ppmap, *neighbor_vertex_v_j); - // Compute the square norm of v_j -> v_i vector - Vector_3 edge = position_v_i - position_v_j; - NT square_len = edge*edge; + const Vector_3 edge = position_v_i - position_v_j; + const NT squared_length = edge * edge; - // Compute cotangent of (v_k,v_j,v_i) corner (i.e. cotan of v_j corner) - // if v_k is the vertex before v_j when circulating around v_i vertex_around_target_circulator previous_vertex_v_k = neighbor_vertex_v_j; --previous_vertex_v_k; const PPM_ref position_v_k = get(ppmap, *previous_vertex_v_k); -// NT cotg_psi_ij = internal::cotangent(position_v_k, position_v_j, position_v_i); - NT cotg_beta_ij = internal::cotangent(position_v_i, position_v_k, position_v_j); - // Compute cotangent of (v_i,v_j,v_l) corner (i.e. cotan of v_j corner) - // if v_l is the vertex after v_j when circulating around v_i vertex_around_target_circulator next_vertex_v_l = neighbor_vertex_v_j; ++next_vertex_v_l; + const PPM_ref position_v_l = get(ppmap, *next_vertex_v_l); - const Point_3 position_v_l = get(ppmap, *next_vertex_v_l); -// NT cotg_theta_ij = internal::cotangent(position_v_i, position_v_j, position_v_l); - NT cotg_alpha_ij = internal::cotangent(position_v_j, position_v_l, position_v_i); - - NT weight = 0; - CGAL_assertion(square_len > NT(0)); // two points are identical! - if(square_len != NT(0)) - weight = cotg_beta_ij + cotg_alpha_ij; - + NT weight = NT(0); + CGAL_assertion(squared_length > NT(0)); // two points are identical! + if(squared_length != NT(0)) { + // This version was commented out to be an alternative weight + // in the original code by authors. + // weight = CGAL::Weights::authalic_weight(position_v_k, position_v_j, position_v_l, position_v_i) / NT(2); + weight = CGAL::Weights::cotangent_weight(position_v_k, position_v_j, position_v_l, position_v_i) / NT(2); + } return weight; } @@ -730,7 +723,7 @@ private: VertexIndexMap& vimap) const { auto vpm = get_const_property_map(CGAL::vertex_point, tmesh); - CGAL::internal::Mean_value_weight compute_mvc(tmesh, vpm); + const CGAL::Weights::Edge_tangent_weight compute_mvc(tmesh, vpm); const int i = get(vimap, v); diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h index 7803a1980a4..a8053c2a9bd 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/MVC_post_processor_3.h @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -354,22 +355,6 @@ private: return OK; } - // -> -> - // Return angle (in radians) of of (P,Q,R) corner (i.e. QP,QR angle). - double compute_angle_rad(const Point_2& P, - const Point_2& Q, - const Point_2& R) const - { - Vector_2 u = P - Q; - Vector_2 v = R - Q; - - double angle = std::atan2(v.y(), v.x()) - std::atan2(u.y(), u.x()); - if(angle < 0) - angle += 2 * CGAL_PI; - - return angle; - } - // Fix vertices that are on the convex hull. template @@ -385,23 +370,6 @@ private: } while (++vc != vend); } - NT compute_w_ij_mvc(const Point_2& pi, const Point_2& pj, const Point_2& pk) const - { - // -> -> - // Compute the angle (pj, pi, pk), the angle between the vectors ij and ik - NT angle = compute_angle_rad(pj, pi, pk); - - // For flipped triangles, the connectivity is inversed and thus the angle - // computed by the previous function is not the one we need. Instead, - // we need the explementary angle. - if(angle > CGAL_PI) { // flipped triangle - angle = 2 * CGAL_PI - angle; - } - NT weight = std::tan(0.5 * angle); - - return weight; - } - void fill_linear_system_matrix_mvc_from_points(const Point_2& pi, int i, const Point_2& pj, int j, const Point_2& pk, int k, @@ -418,27 +386,25 @@ private: // The other parts of A(i,j) and A(i,k) will be added when this function // is called from the neighboring faces of F_ijk that share the vertex i - // Compute: - tan(alpha / 2) - NT w_i_base = -1.0 * compute_w_ij_mvc(pi, pj, pk); - // @fixme unefficient: lengths are computed (and inversed!) twice per edge + // Set w_i_base: - tan(alpha / 2) + // Match order of the input points to the new weight implementation. + const Point_2& p = pk; + const Point_2& q = pi; + const Point_2& r = pj; + const CGAL::Weights::Tangent_weight tangent_weight(p, q, r); + // Set w_ij in matrix - Vector_2 edge_ij = pi - pj; - double len_ij = std::sqrt(edge_ij * edge_ij); - CGAL_assertion(len_ij != 0.0); // two points are identical! - NT w_ij = w_i_base / len_ij; + const NT w_ij = tangent_weight.get_w_r(); A.add_coef(i, j, w_ij); // Set w_ik in matrix - Vector_2 edge_ik = pi - pk; - double len_ik = std::sqrt(edge_ik * edge_ik); - CGAL_assertion(len_ik != 0.0); // two points are identical! - NT w_ik = w_i_base / len_ik; + const NT w_ik = tangent_weight.get_w_p(); A.add_coef(i, k, w_ik); // Add to w_ii (w_ii = - sum w_ij) - NT w_ii = - w_ij - w_ik; + const NT w_ii = - w_ij - w_ik; A.add_coef(i, i, w_ii); } diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h index 796504c93f2..95593adf95e 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Mean_value_coordinates_parameterizer_3.h @@ -17,9 +17,9 @@ #include #include - #include #include +#include #ifdef CGAL_EIGEN3_ENABLED #include @@ -195,35 +195,18 @@ protected: Vertex_around_target_circulator neighbor_vertex_v_j) const { const PPM ppmap = get(vertex_point, mesh); - const Point_3& position_v_i = get(ppmap, main_vertex_v_i); const Point_3& position_v_j = get(ppmap, *neighbor_vertex_v_j); - // Compute the norm of v_j -> v_i vector - Vector_3 edge = position_v_i - position_v_j; - NT len = std::sqrt(edge * edge); - - // Compute angle of (v_j,v_i,v_k) corner (i.e. angle of v_i corner) - // if v_k is the vertex before v_j when circulating around v_i vertex_around_target_circulator previous_vertex_v_k = neighbor_vertex_v_j; - previous_vertex_v_k--; + --previous_vertex_v_k; const Point_3& position_v_k = get(ppmap, *previous_vertex_v_k); - NT gamma_ij = internal::compute_angle_rad(position_v_j, position_v_i, position_v_k); - // Compute angle of (v_l,v_i,v_j) corner (i.e. angle of v_i corner) - // if v_l is the vertex after v_j when circulating around v_i vertex_around_target_circulator next_vertex_v_l = neighbor_vertex_v_j; - next_vertex_v_l++; + ++next_vertex_v_l; const Point_3& position_v_l = get(ppmap, *next_vertex_v_l); - NT delta_ij = internal::compute_angle_rad(position_v_l, position_v_i, position_v_j); - NT weight = 0.0; - CGAL_assertion(len != 0.0); // two points are identical! - if(len != 0.0) - weight = (std::tan(0.5*gamma_ij) + std::tan(0.5*delta_ij)) / len; - CGAL_assertion(weight > 0); - - return weight; + return CGAL::Weights::tangent_weight(position_v_k, position_v_j, position_v_l, position_v_i) / NT(2); } }; diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h index 5d5cc9e6a54..3f8337d0660 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/Orbifold_Tutte_parameterizer_3.h @@ -16,17 +16,15 @@ #include -#include #include #include #include - #include #include #include - +#include +#include #include -#include #include #include @@ -702,17 +700,6 @@ private: CGAL_postcondition(current_line_id_in_M - initial_line_id == number_of_linear_constraints(mesh)); } - // MVC computations - NT compute_w_ij_mvc(const Point_3& pi, const Point_3& pj, const Point_3& pk) const - { - // -> -> - // Compute the angle (pj, pi, pk), the angle between the vectors ij and ik - const NT angle = internal::compute_angle_rad(pj, pi, pk); - const NT weight = std::tan(0.5 * angle); - - return weight; - } - // Computes the coefficients of the mean value Laplacian matrix for the edge. // `ij` in the face `ijk` void fill_mvc_matrix(const Point_3& pi, int i, @@ -730,29 +717,27 @@ private: // The other parts of M(i,j) and M(i,k) will be added when this function // is called from the neighboring faces of F_ijk that share the vertex i - // Compute: - tan(alpha / 2) - const NT w_i_base = 1.0 * compute_w_ij_mvc(pi, pj, pk); - // @fixme unefficient: lengths are computed (and inversed!) twice per edge + // Set w_i_base: - tan(alpha / 2) + const Point_3& p = pk; + const Point_3& q = pi; + const Point_3& r = pj; + const CGAL::Weights::Tangent_weight tangent_weight(p, q, r); + // Set w_ij in matrix - const Vector_3 edge_ij = pi - pj; - const NT len_ij = CGAL::sqrt(edge_ij * edge_ij); - CGAL_assertion(len_ij != 0.0); // two points are identical! - const NT w_ij = w_i_base / len_ij; + const NT w_ij = tangent_weight.get_w_r(); M.add_coef(2*i, 2*j, w_ij); - M.add_coef(2*i +1, 2*j + 1, w_ij); + M.add_coef(2*i + 1, 2*j + 1, w_ij); // Set w_ik in matrix - Vector_3 edge_ik = pi - pk; - const NT len_ik = CGAL::sqrt(edge_ik * edge_ik); - CGAL_assertion(len_ik != 0.0); // two points are identical! - const NT w_ik = w_i_base / len_ik; + const NT w_ik = tangent_weight.get_w_p(); M.add_coef(2*i, 2*k, w_ik); M.add_coef(2*i + 1, 2*k + 1, w_ik); // Add to w_ii (w_ii = - sum w_ij) const NT w_ii = - w_ij - w_ik; + M.add_coef(2*i, 2*i, w_ii); M.add_coef(2*i + 1, 2*i + 1, w_ii); } @@ -790,35 +775,25 @@ private: VertexIndexMap vimap, Matrix& M) const { - const PPM ppmap = get(vertex_point, mesh); + const PPM pmap = get(vertex_point, mesh); + for (const halfedge_descriptor hd : halfedges(mesh)) { - // not exactly sure which cotan weights should be used: - // 0.5 (cot a + cot b) ? 1/T1 cot a + 1/T2 cot b ? 1/Vor(i) (cot a + cot b?) - // Comparing to the matlab code, the basic Cotangent_weight gives the same results. - typedef CGAL::internal::Cotangent_weight Cotan_weights; -// typedef CGAL::internal::Cotangent_weight_with_triangle_area Cotan_weights; - - Cotan_weights cotan_weight_calculator(mesh, ppmap); - - for(halfedge_descriptor hd : halfedges(mesh)) { const vertex_descriptor vi = source(hd, mesh); const vertex_descriptor vj = target(hd, mesh); const int i = get(vimap, vi); const int j = get(vimap, vj); - if(i > j) - continue; - - // times 2 because Cotangent_weight returns 1/2 (cot alpha + cot beta)... - const NT w_ij = 2 * cotan_weight_calculator(hd); + if (i > j) continue; + const CGAL::Weights::Cotangent_weight cotangent_weight; + const NT w_ij = NT(2) * cotangent_weight(hd, mesh, pmap); // ij M.set_coef(2*i, 2*j, w_ij, true /* new coef */); - M.set_coef(2*i +1, 2*j + 1, w_ij, true /* new coef */); + M.set_coef(2*i + 1, 2*j + 1, w_ij, true /* new coef */); // ji M.set_coef(2*j, 2*i, w_ij, true /* new coef */); - M.set_coef(2*j +1, 2*i + 1, w_ij, true /* new coef */); + M.set_coef(2*j + 1, 2*i + 1, w_ij, true /* new coef */); // ii M.add_coef(2*i, 2*i, - w_ij); diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h deleted file mode 100644 index abd987d33f9..00000000000 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/internal/angles.h +++ /dev/null @@ -1,119 +0,0 @@ -// Copyright (c) 2016 GeometryFactory (France). -// All rights reserved. -// -// This file is part of CGAL (www.cgal.org). -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial -// -// Author(s) : Mael Rouxel-Labbé - -#ifndef CGAL_SURFACE_MESH_PARAMETERIZATION_ANGLES_H -#define CGAL_SURFACE_MESH_PARAMETERIZATION_ANGLES_H - -#include - -#include -#include - -#include - -namespace CGAL { - -namespace Surface_mesh_parameterization { - -namespace internal { - -// -> -> -// Returns the cotangent of the corner (P,Q,R) (i.e. the cotan of the angle (QP, QR) ). -template -typename K::FT cotangent(const typename K::Point_3& P, - const typename K::Point_3& Q, - const typename K::Point_3& R) -{ - typedef typename K::FT NT; - typedef typename K::Vector_3 Vector_3; - - Vector_3 u = P - Q; - Vector_3 v = R - Q; - NT dot = (u * v); - Vector_3 cross_vector = CGAL::cross_product(u, v); - NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); - if(cross_norm != NT(0)) - return (dot / cross_norm); - else - return 0; // undefined -} - -// -> -> -// Returns the tangent of the corner (P,Q,R) (i.e. the tangent of angle (QP, QR) ). -template -typename K::FT tangent(const typename K::Point_3& P, - const typename K::Point_3& Q, - const typename K::Point_3& R) -{ - typedef typename K::FT NT; - typedef typename K::Vector_3 Vector_3; - - Vector_3 u = P - Q; - Vector_3 v = R - Q; - NT dot = (u * v); - Vector_3 cross_vector = CGAL::cross_product(u, v); - NT cross_norm = CGAL::sqrt(cross_vector * cross_vector); - if(dot != NT(0)) - return (cross_norm / dot); - else - return 0; // undefined -} - -// Fixes the sine to be within [-1;1]. -template -typename K::FT fix_sine(typename K::FT sine) -{ - if(sine >= 1) - return 1; - else if(sine <= -1) - return -1; - else - return sine; -} - -// -> -> -// Returns the angle (in radians) of the corner (P,Q,R) (i.e. the angle (QP, QR) ). -template -typename K::FT compute_angle_rad(const typename K::Point_3& P, - const typename K::Point_3& Q, - const typename K::Point_3& R) -{ - typedef typename K::FT NT; - typedef typename K::Vector_3 Vector_3; - - Vector_3 u = P - Q; - Vector_3 v = R - Q; - - NT product = CGAL::sqrt(u * u) * CGAL::sqrt(v * v); - if(product == NT(0)) - return 0; - - // cosine - NT dot = (u * v); - NT cosine = dot / product; - - // sine - Vector_3 w = CGAL::cross_product(u, v); - NT abs_sine = CGAL::sqrt(w * w) / product; - - if(cosine >= NT(0)) - return std::asin(fix_sine(abs_sine)); - else - return CGAL_PI - std::asin(fix_sine(abs_sine)); -} - -} // namespace internal - -} // namespace Surface_mesh_parameterization - -} // namespace CGAL - -#endif // CGAL_SURFACE_MESH_PARAMETERIZATION_ANGLES_H diff --git a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h index 4243374f9d3..4b1e4ab2cc0 100644 --- a/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h +++ b/Surface_mesh_parameterization/include/CGAL/Surface_mesh_parameterization/orbifold_shortest_path.h @@ -190,8 +190,8 @@ void compute_shortest_paths_between_cones(const TriangleMesh& mesh, compute_shortest_paths_between_two_cones(mesh, *first, *next, std::back_inserter(seams)); } - std::ofstream out("shortest_path.selection.txt"); #ifdef CGAL_SMP_ORBIFOLD_DEBUG + std::ofstream out("shortest_path.selection.txt"); internal::output_shortest_paths_to_selection_file(mesh, seams, out); #endif } diff --git a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies index 6dedee5435a..0d5931b478b 100644 --- a/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies +++ b/Surface_mesh_parameterization/package_info/Surface_mesh_parameterization/dependencies @@ -26,3 +26,4 @@ Stream_support Surface_mesh_parameterization TDS_2 Triangulation_2 +Weights diff --git a/Surface_mesh_segmentation/include/CGAL/Surface_mesh_segmentation/internal/auxiliary/graph.h b/Surface_mesh_segmentation/include/CGAL/Surface_mesh_segmentation/internal/auxiliary/graph.h index 5698e0c59a0..e13471ce036 100644 --- a/Surface_mesh_segmentation/include/CGAL/Surface_mesh_segmentation/internal/auxiliary/graph.h +++ b/Surface_mesh_segmentation/include/CGAL/Surface_mesh_segmentation/internal/auxiliary/graph.h @@ -109,7 +109,7 @@ a minimum cut on the following graph: /////////////////////////////////////////////////// -#include +#include #include "graph.h" void main() @@ -125,16 +125,16 @@ void main() Graph::flowtype flow = g -> maxflow(); - printf("Flow = %d\n", flow); + std::cout << "Flow = " << flow << std::endl; printf("Minimum cut:\n"); if (g->what_segment(nodes[0]) == Graph::SOURCE) - printf("node0 is in the SOURCE set\n"); + std::cout << "node0 is in the SOURCE set\n"; else - printf("node0 is in the SINK set\n"); + std::cout << "node0 is in the SINK set\n"; if (g->what_segment(nodes[1]) == Graph::SOURCE) - printf("node1 is in the SOURCE set\n"); + std::cout << "node1 is in the SOURCE set\n"; else - printf("node1 is in the SINK set\n"); + std::cout << "node1 is in the SINK set\n"; delete g; } diff --git a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h index 81bacc0d8a8..3882180786a 100644 --- a/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h +++ b/Surface_mesh_skeletonization/include/CGAL/Mean_curvature_flow_skeletonization.h @@ -35,7 +35,7 @@ #include // Compute cotangent Laplacian -#include +#include // Compute the vertex normal #include @@ -222,12 +222,8 @@ public: typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::edge_iterator edge_iterator; - // Cotangent weight calculator - typedef internal::Cotangent_weight::type, - internal::Cotangent_value_minimum_zero::type, - internal::Cotangent_value_Meyer_secure > > Weight_calculator; + // Get weight from the weight interface. + typedef CGAL::Weights::Cotangent_weight Weight_calculator; typedef internal::Curve_skeleton #include #include +#include namespace @@ -27,7 +28,7 @@ namespace { if ( type == _CRT_ASSERT ) { - std::fprintf(stderr,msg); + std::cerr << msg << std::endl; *retval = 0 ; std::exit(255); } @@ -38,11 +39,11 @@ namespace { switch(n) { - case SIGSEGV: std::fprintf(stderr,"In CGAL_handle_signal, Program received signal SIGSEGV: Segmentation Fault."); break ; - case SIGFPE : std::fprintf(stderr,"In CGAL_handle_signal, Program received signal SIGFPE: Floating Point Execption."); break ; - case SIGILL : std::fprintf(stderr,"In CGAL_handle_signal, Program received signal SIGILL: Illegal Instruction."); break ; + case SIGSEGV: std::cerr << "In CGAL_handle_signal, Program received signal SIGSEGV: Segmentation Fault." << std::endl; break ; + case SIGFPE : std::cerr << "In CGAL_handle_signal, Program received signal SIGFPE: Floating Point Execption." << std::endl; break ; + case SIGILL : std::cerr << "In CGAL_handle_signal, Program received signal SIGILL: Illegal Instruction." << std::endl; break ; default: - std::fprintf(stderr,"In CGAL_handle_signal, Program received signal %d", n); break ; + std::cerr << "In CGAL_handle_signal, Program received signal " << n << std::endl; break ; } std::exit(128+n); diff --git a/Triangulation_3/demo/Triangulation_3/PreferenceDlg.cpp b/Triangulation_3/demo/Triangulation_3/PreferenceDlg.cpp index c922abd6fd4..122c291d048 100644 --- a/Triangulation_3/demo/Triangulation_3/PreferenceDlg.cpp +++ b/Triangulation_3/demo/Triangulation_3/PreferenceDlg.cpp @@ -12,7 +12,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QPushButton *btnVertex = new QPushButton( tr("Set Color") ); // create color label m_labelVertex = new QLabel; - m_labelVertex->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelVertex->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create size label QLabel *labelSizeV = new QLabel( tr("Set Size") ); // create lineedit @@ -38,7 +38,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QPushButton *btnDEdge = new QPushButton( tr("Set Color") ); // create color label m_labelDEdge = new QLabel; - m_labelDEdge->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelDEdge->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create size label QLabel *labelSizeDE = new QLabel( tr("Set Size") ); // create lineedit @@ -64,7 +64,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QPushButton *btnVEdge = new QPushButton( tr("Set Color") ); // create color label m_labelVEdge = new QLabel; - m_labelVEdge->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelVEdge->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create size label QLabel *labelSizeVE = new QLabel( tr("Set Size") ); // create lineedit @@ -90,7 +90,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QPushButton *btnFacet = new QPushButton( tr("Set Color") ); // create color label m_labelFacet = new QLabel; - m_labelFacet->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelFacet->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create label and spinbox QLabel *labelFacetA = new QLabel( tr("Transparency") ); m_spinAlphaF = new QSpinBox; @@ -116,7 +116,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QPushButton *btnBall = new QPushButton( tr("Set Color") ); // create color label m_labelBall = new QLabel; - m_labelBall->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelBall->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create label and spinbox QLabel *labelBallA = new QLabel( tr("Transparency") ); m_spinAlphaB = new QSpinBox; @@ -147,7 +147,7 @@ PreferenceDlg::PreferenceDlg(QWidget *parent) : QDialog(parent) QGroupBox *groupS = new QGroupBox( tr("Empty Sphere") ); // create color label m_labelSphere = new QLabel; - m_labelSphere->setFrameStyle(QFrame::Sunken | QFrame::Panel); + m_labelSphere->setFrameStyle(static_cast(QFrame::Sunken) | static_cast(QFrame::Panel)); // create button QPushButton *btnSphere = new QPushButton( tr("Set Color") ); // create label and spinbox diff --git a/Triangulation_3/demo/Triangulation_3/Viewer.cpp b/Triangulation_3/demo/Triangulation_3/Viewer.cpp index 90af7a440db..62937f5a5bc 100644 --- a/Triangulation_3/demo/Triangulation_3/Viewer.cpp +++ b/Triangulation_3/demo/Triangulation_3/Viewer.cpp @@ -69,12 +69,12 @@ void Viewer::init() glHint(GL_LINE_SMOOTH_HINT, GL_NICEST); /* Add mouse and key description */ - setKeyDescription( Qt::CTRL + Qt::Key_G, tr("Generate points") ); - setKeyDescription( Qt::CTRL + Qt::Key_O, tr("Load points") ); - setKeyDescription( Qt::CTRL + Qt::Key_S, tr("Save points") ); - setKeyDescription( Qt::CTRL + Qt::Key_Comma, tr("Preference") ); - setKeyDescription( Qt::CTRL + Qt::Key_H, tr("Hide Kernel Demo") ); - setKeyDescription( Qt::CTRL + Qt::Key_Q, tr("Quit Kernel Demo") ); + setKeyDescription( Qt::CTRL, Qt::Key_G, tr("Generate points") ); + setKeyDescription( Qt::CTRL, Qt::Key_O, tr("Load points") ); + setKeyDescription( Qt::CTRL, Qt::Key_S, tr("Save points") ); + setKeyDescription( Qt::CTRL, Qt::Key_Comma, tr("Preference") ); + setKeyDescription( Qt::CTRL, Qt::Key_H, tr("Hide Kernel Demo") ); + setKeyDescription( Qt::CTRL, Qt::Key_Q, tr("Quit Kernel Demo") ); setKeyDescription( Qt::Key_Return, tr("Insert new point to triangulation in Input-Point mode") ); setKeyDescription( Qt::Key_Escape, diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index 3b5509add2b..07518932ccc 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -446,7 +446,8 @@ private: const Self *t; public: - Infinite_tester() {} + Infinite_tester() + : t(nullptr) {} Infinite_tester(const Self *tr) : t(tr) {} diff --git a/Weights/doc/Weights/PackageDescription.txt b/Weights/doc/Weights/PackageDescription.txt index 1fc97c0ee1f..f6e5cfaf1e1 100644 --- a/Weights/doc/Weights/PackageDescription.txt +++ b/Weights/doc/Weights/PackageDescription.txt @@ -510,7 +510,7 @@ a model of `AnalyticWeightTraits_3` for 3D points \cgalPkgDescriptionBegin{Weight Interface, PkgWeightsRef} -\cgalPkgPicture{logo_120x120.png} +\cgalPkgPicture{weights_logo_120x120.png} \cgalPkgSummaryBegin \cgalPkgAuthors{Dmitry Anisimov} diff --git a/Weights/doc/Weights/fig/logo.svg b/Weights/doc/Weights/fig/weights_logo.svg similarity index 100% rename from Weights/doc/Weights/fig/logo.svg rename to Weights/doc/Weights/fig/weights_logo.svg diff --git a/Weights/doc/Weights/fig/logo_120x120.png b/Weights/doc/Weights/fig/weights_logo_120x120.png similarity index 100% rename from Weights/doc/Weights/fig/logo_120x120.png rename to Weights/doc/Weights/fig/weights_logo_120x120.png diff --git a/Weights/include/CGAL/Weights/internal/utils.h b/Weights/include/CGAL/Weights/internal/utils.h index 0786d605ff7..cfefee02d4b 100644 --- a/Weights/include/CGAL/Weights/internal/utils.h +++ b/Weights/include/CGAL/Weights/internal/utils.h @@ -187,7 +187,7 @@ namespace internal { const FT cross = cross_product_2(v1, v2); const FT length = CGAL::abs(cross); - CGAL_assertion(length != FT(0)); + // CGAL_assertion(length != FT(0)); not really necessary if (length != FT(0)) { return dot / length; } else { @@ -218,7 +218,7 @@ namespace internal { const FT cross = cross_product_2(v1, v2); const FT length = CGAL::abs(cross); - CGAL_assertion(dot != FT(0)); + // CGAL_assertion(dot != FT(0)); not really necessary if (dot != FT(0)) { return length / dot; } else { @@ -293,7 +293,11 @@ namespace internal { const auto cross = cross_product_3(v1, v2); const FT length = length_3(traits, cross); - CGAL_assertion(length != FT(0)); + // TODO: + // Not really necessary: since we handle case length = 0. Does this case happen? + // Yes, e.g. in Surface Parameterization tests. Does it affect the results? + // In current applications, not really. + // CGAL_assertion(length != FT(0)); if (length != FT(0)) { return dot / length; } else { @@ -324,7 +328,7 @@ namespace internal { const auto cross = cross_product_3(v1, v2); const FT length = length_3(traits, cross); - CGAL_assertion(dot != FT(0)); + // CGAL_assertion(dot != FT(0)); not really necessary if (dot != FT(0)) { return length / dot; } else { diff --git a/Weights/include/CGAL/Weights/mean_value_weights.h b/Weights/include/CGAL/Weights/mean_value_weights.h index d66d9bf3487..2fc9117247d 100644 --- a/Weights/include/CGAL/Weights/mean_value_weights.h +++ b/Weights/include/CGAL/Weights/mean_value_weights.h @@ -188,99 +188,6 @@ namespace Weights { } // namespace internal - // Undocumented mean value weight class. - // Its constructor takes a polygon mesh and a vertex to point map - // and its operator() is defined based on the halfedge_descriptor only. - // This version is currently used in: - // Surface_mesh_parameterizer -> Iterative_authalic_parameterizer_3.h - template< - typename PolygonMesh, - typename VertexPointMap = typename boost::property_map::type> - class Mean_value_weight { - - using GeomTraits = typename CGAL::Kernel_traits< - typename boost::property_traits::value_type>::type; - using FT = typename GeomTraits::FT; - - const PolygonMesh& m_pmesh; - const VertexPointMap m_pmap; - const GeomTraits m_traits; - - public: - using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; - using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; - - Mean_value_weight(const PolygonMesh& pmesh, const VertexPointMap pmap) : - m_pmesh(pmesh), m_pmap(pmap), m_traits() { } - - // Returns the mean-value coordinate of the specified halfedge_descriptor. - // Returns different values for different edge orientations (which is normal - // behavior according to the formula). - FT operator()(const halfedge_descriptor he) const { - - const vertex_descriptor v0 = target(he, m_pmesh); - const vertex_descriptor v1 = source(he, m_pmesh); - const auto& p0 = get(m_pmap, v0); - const auto& p1 = get(m_pmap, v1); - const FT norm = internal::distance_3(m_traits, p0, p1); - - // Only one triangle for border edges. - if (is_border_edge(he, m_pmesh)) { - const halfedge_descriptor he_cw = opposite(next(he, m_pmesh), m_pmesh); - vertex_descriptor v2 = source(he_cw, m_pmesh); - if (is_border_edge(he_cw, m_pmesh)) { - const halfedge_descriptor he_ccw = prev(opposite(he, m_pmesh), m_pmesh); - v2 = source(he_ccw, m_pmesh); - } - return half_tan_value_2(v1, v0, v2) / norm; - } else { - const halfedge_descriptor he_cw = opposite(next(he, m_pmesh), m_pmesh); - const vertex_descriptor v2 = source(he_cw, m_pmesh); - const halfedge_descriptor he_ccw = prev(opposite(he, m_pmesh), m_pmesh); - const vertex_descriptor v3 = source(he_ccw, m_pmesh); - return ( - half_tan_value_2(v1, v0, v2) / norm + - half_tan_value_2(v1, v0, v3) / norm ); - } - } - - private: - // The authors deviation built on Meyer_02. - FT half_tan_value_2( - const vertex_descriptor v0, - const vertex_descriptor v1, - const vertex_descriptor v2) const { - - using Get_sqrt = internal::Get_sqrt; - const auto sqrt = Get_sqrt::sqrt_object(m_traits); - - const auto squared_length_3 = - m_traits.compute_squared_length_3_object(); - const auto construct_vector_3 = - m_traits.construct_vector_3_object(); - - const auto& p0 = get(m_pmap, v0); - const auto& p1 = get(m_pmap, v1); - const auto& p2 = get(m_pmap, v2); - - const auto a = construct_vector_3(p1, p0); - const auto b = construct_vector_3(p1, p2); - - const FT dot_ab = a[0] * b[0] + a[1] * b[1] + a[2] * b[2]; - const FT dot_aa = squared_length_3(a); - const FT dot_bb = squared_length_3(b); - const FT dot_aa_bb = dot_aa * dot_bb; - - const FT cos_rep = dot_ab; - const FT sin_rep = sqrt(dot_aa_bb - dot_ab * dot_ab); - const FT normalizer = sqrt(dot_aa_bb); // |a| * |b| - - // The formula from [Floater04] page 4: - // tan(Q / 2) = (1 - cos(Q)) / sin(Q). - return (normalizer - cos_rep) / sin_rep; - } - }; - /// \endcond /*! diff --git a/Weights/include/CGAL/Weights/tangent_weights.h b/Weights/include/CGAL/Weights/tangent_weights.h index a7e93109a02..47a7539ae8a 100644 --- a/Weights/include/CGAL/Weights/tangent_weights.h +++ b/Weights/include/CGAL/Weights/tangent_weights.h @@ -372,6 +372,67 @@ namespace Weights { return tangent_weight(t, r, p, q, traits); } + // Undocumented tangent weight class. + // Its constructor takes a polygon mesh and a vertex to point map + // and its operator() is defined based on the halfedge_descriptor only. + // This version is currently used in: + // Surface_mesh_parameterizer -> Iterative_authalic_parameterizer_3.h + template< + typename PolygonMesh, + typename VertexPointMap = typename boost::property_map::type> + class Edge_tangent_weight { + + using GeomTraits = typename CGAL::Kernel_traits< + typename boost::property_traits::value_type>::type; + using FT = typename GeomTraits::FT; + + const PolygonMesh& m_pmesh; + const VertexPointMap m_pmap; + const GeomTraits m_traits; + + public: + using vertex_descriptor = typename boost::graph_traits::vertex_descriptor; + using halfedge_descriptor = typename boost::graph_traits::halfedge_descriptor; + + Edge_tangent_weight(const PolygonMesh& pmesh, const VertexPointMap pmap) : + m_pmesh(pmesh), m_pmap(pmap), m_traits() { } + + FT operator()(const halfedge_descriptor he) const { + + FT weight = FT(0); + if (is_border_edge(he, m_pmesh)) { + const auto h1 = next(he, m_pmesh); + + const auto v0 = target(he, m_pmesh); + const auto v1 = source(he, m_pmesh); + const auto v2 = target(h1, m_pmesh); + + const auto& p0 = get(m_pmap, v0); + const auto& p1 = get(m_pmap, v1); + const auto& p2 = get(m_pmap, v2); + + weight = internal::tangent_3(m_traits, p0, p2, p1); + + } else { + const auto h1 = next(he, m_pmesh); + const auto h2 = prev(opposite(he, m_pmesh), m_pmesh); + + const auto v0 = target(he, m_pmesh); + const auto v1 = source(he, m_pmesh); + const auto v2 = target(h1, m_pmesh); + const auto v3 = source(h2, m_pmesh); + + const auto& p0 = get(m_pmap, v0); + const auto& p1 = get(m_pmap, v1); + const auto& p2 = get(m_pmap, v2); + const auto& p3 = get(m_pmap, v3); + + weight = tangent_weight(p2, p1, p3, p0) / FT(2); + } + return weight; + } + }; + // Undocumented tangent weight class. // Its constructor takes three points either in 2D or 3D. // This version is currently used in: diff --git a/Weights/include/CGAL/Weights/utils.h b/Weights/include/CGAL/Weights/utils.h index 919b2fc2bf2..4f68b34e1ef 100644 --- a/Weights/include/CGAL/Weights/utils.h +++ b/Weights/include/CGAL/Weights/utils.h @@ -18,7 +18,6 @@ // Internal includes. #include -#include namespace CGAL { namespace Weights {