diff --git a/.github/workflows/build_doc.yml b/.github/workflows/build_doc.yml new file mode 100644 index 00000000000..6979eb86108 --- /dev/null +++ b/.github/workflows/build_doc.yml @@ -0,0 +1,93 @@ +name: Documentation + +on: + issue_comment: + types: [created] + +jobs: + build: + + runs-on: ubuntu-latest + steps: + - uses: actions/github-script@v3 + id: get_round + with: + result-encoding: string + script: | + const asso = context.payload.comment.author_association + if(asso == 'OWNER' || asso == 'MEMBER') { + const body = context.payload.comment.body + if(body.includes("build:")) { + return body.replace('build:','') + } + } + return 'stop' + - uses: actions/github-script@v3 + if: steps.get_round.outputs.result != 'stop' + id: get_pr_number + with: + result-encoding: string + script: | + //get pullrequest url + const pr_number = context.payload.issue.number + return pr_number + - uses: actions/checkout@v2 + name: "checkout branch" + if: steps.get_round.outputs.result != 'stop' + with: + repository: ${{ github.repository }} + ref: refs/pull/${{ steps.get_pr_number.outputs.result }}/merge + token: ${{ secrets.PUSH_TO_CGAL_GITHUB_IO_TOKEN }} + + + - name: install dependencies + if: steps.get_round.outputs.result != 'stop' + run: | + set -x + sudo apt-get install -y graphviz ssh + sudo pip install lxml pyquery + wget --no-verbose -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen/build_1_8_13/bin/doxygen + sudo mv doxygen_exe /usr/bin/doxygen + sudo chmod +x /usr/bin/doxygen + git config --global user.email "maxime.gimeno@geometryfactory.com" + git config --global user.name "Maxime Gimeno" + + - name: configure all + if: steps.get_round.outputs.result != 'stop' + run: | + set -ex + git clone https://CGAL:${{ secrets.PUSH_TO_CGAL_GITHUB_IO_TOKEN }}@github.com/CGAL/cgal.github.io.git --depth=5 + mkdir -p build_doc && cd build_doc && cmake ../Documentation/doc + + - name: Upload Doc + if: steps.get_round.outputs.result != 'stop' + run: | + set -ex + PR_NUMBER=${{ steps.get_pr_number.outputs.result }} + ROUND=${{ steps.get_round.outputs.result }} + wget --no-verbose cgal.github.io -O tmp.html + if ! egrep -q "\/$PR_NUMBER\/$ROUND" tmp.html; then + mkdir -p cgal.github.io/${PR_NUMBER}/$ROUND + cd build_doc && make -j2 doc && make -j2 doc_with_postprocessing + cp -r ./doc_output/* ../cgal.github.io/${PR_NUMBER}/$ROUND + cd ../cgal.github.io + egrep -v " ${PR_NUMBER}\." index.html > tmp.html + echo "
  • Manual for PR ${PR_NUMBER} ($ROUND).
  • " >> ./tmp.html + mv tmp.html index.html + git add ${PR_NUMBER}/$ROUND && git commit -q -a -m "Add ${PR_NUMBER} $ROUND" && git push -q -u origin master + else + exit 1 + fi + + - name: Post address + uses: actions/github-script@v3 + if: steps.get_round.outputs.result != 'stop' + with: + script: | + const address = "The documentation is built. You can find it here : https://cgal.github.io/${{ steps.get_pr_number.outputs.result }}/${{ steps.get_round.outputs.result }}/Manual/index.html" + github.issues.createComment({ + owner: "CGAL", + repo: "cgal", + issue_number: ${{ github.event.issue.number }}, + body: address + }); diff --git a/.github/workflows/delete_doc.yml b/.github/workflows/delete_doc.yml new file mode 100644 index 00000000000..c1152d37ca9 --- /dev/null +++ b/.github/workflows/delete_doc.yml @@ -0,0 +1,27 @@ +name: Documentation Removal + +on: + pull_request_target: + types: [closed, removed] +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2.0.0 + - name: delete directory + run: | + set -x + git config --global user.email "maxime.gimeno@geometryfactory.com" + git config --global user.name "Maxime Gimeno" + git clone https://maxGimeno:${{ secrets.PUSH_TO_CGAL_GITHUB_IO_TOKEN }}@github.com/CGAL/cgal.github.io.git --depth=5 + PR_NUMBER=$(python -c "import json; import os; y = json.load(open(os.environ['GITHUB_EVENT_PATH'])); print(y[\"number\"])") + cd cgal.github.io/ + egrep -v " ${PR_NUMBER}\." index.html > tmp.html + if [ -n "$(diff -q ./index.html ./tmp.html)" ]; then + mv tmp.html index.html + #git rm -r ${PR_NUMBER} && git commit -a -m "Remove ${PR_NUMBER}" && git push -u origin master + git commit -a -m "Remove ${PR_NUMBER}" && git push -u origin master + fi + diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 254dd2b08c7..12f6082c922 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -41,6 +41,7 @@ do continue fi cd $ROOT + #install openmesh only if necessary if [ "$ARG" = "CHECK" ] || [ "$ARG" = BGL ] || [ "$ARG" = Convex_hull_3 ] ||\ [ "$ARG" = Polygon_mesh_processing ] || [ "$ARG" = Property_map ] ||\ @@ -92,28 +93,27 @@ cd $ROOT exit 1 fi echo "Matrix is up to date." - #check if non standard cgal installation works - cd $ROOT - mkdir build_test - cd build_test - mytime cmake -DCMAKE_INSTALL_PREFIX=install/ -DCGAL_BUILD_THREE_DOC=TRUE .. - mytime make install - # test install with minimal downstream example - mkdir installtest - cd installtest - touch main.cpp - mkdir build - echo 'project(Example)' >> CMakeLists.txt - echo 'set(PROJECT_SRCS ${PROJECT_SOURCE_DIR}/main.cpp)' >> CMakeLists.txt - echo 'find_package(CGAL REQUIRED)' >> CMakeLists.txt - echo 'add_executable(${PROJECT_NAME} ${PROJECT_SRCS})' >> CMakeLists.txt - echo 'target_link_libraries(${PROJECT_NAME} CGAL::CGAL)' >> CMakeLists.txt - echo '#include "CGAL/remove_outliers.h"' >> main.cpp - cd build - mytime cmake -DCMAKE_INSTALL_PREFIX=../../install -DCGAL_BUILD_THREE_DOC=TRUE .. - cd .. exit 0 fi + + if [ "$ARG" = "Installation" ] + then + mkdir build_dir + cd build_dir + cmake -DWITH_tests=ON -DBUILD_TESTING=ON .. + ctest -j2 -L CGAL_cmake_testsuite --output-on-failure + cd .. + rm -rf ./build_dir + #==-- configure all CGAL with -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON, and then launch CTest on a few labels. --== + mkdir config_dir + cd config_dir + cmake -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON -DBUILD_TESTING=ON .. + ctest -j2 -L AABB_tree --output-on-failure + cd .. + rm -rf ./config_dir + exit 0 + fi + IFS=$old_IFS if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$ARG" != Polyhedron_demo ]; then @@ -185,6 +185,7 @@ cd $ROOT cd "$ROOT/$DEMO" build_demo fi + done IFS=$old_IFS # Local Variables: diff --git a/AABB_tree/include/CGAL/AABB_tree.h b/AABB_tree/include/CGAL/AABB_tree.h index 84a45fba132..03a6dab8354 100644 --- a/AABB_tree/include/CGAL/AABB_tree.h +++ b/AABB_tree/include/CGAL/AABB_tree.h @@ -578,7 +578,7 @@ public: #ifdef CGAL_HAS_THREADS mutable CGAL_MUTEX build_mutex; // mutex used to protect const calls inducing build() and build_kd_tree() #endif - + public: const Node* root_node() const { CGAL_assertion(size() > 1); @@ -596,7 +596,7 @@ public: } return m_p_root_node; } - + private: const Primitive& singleton_data() const { CGAL_assertion(size() == 1); return *m_primitives.begin(); diff --git a/Arrangement_on_surface_2/archive/include/CGAL/Arr_extended_rational_arc_traits_d_1.h b/Arrangement_on_surface_2/archive/include/CGAL/Arr_extended_rational_arc_traits_d_1.h index 0a710185dfe..e999643e2ed 100644 --- a/Arrangement_on_surface_2/archive/include/CGAL/Arr_extended_rational_arc_traits_d_1.h +++ b/Arrangement_on_surface_2/archive/include/CGAL/Arr_extended_rational_arc_traits_d_1.h @@ -660,23 +660,33 @@ public: return Equal_2(_traits); } - /*! A functor that divides a curve into continues (x-monotone) curves. */ + //! A functor for subdividing curves into x-monotone curves. class Make_x_monotone_2 { private: Traits& _traits; + public: Make_x_monotone_2(Traits& traits) : _traits(traits) {} - template - OutputIterator operator() (const Curve_2& cv, OutputIterator oi) const + + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. + * \param cv the curve. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return The past-the-end iterator. + */ + template + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { Object_vector res (boost::apply_visitor(Make_x_monotone_2_visitor(_traits),cv.variant())); re_cast_object_vector(res,oi); return (oi); } + private: - class Make_x_monotone_2_visitor - : public boost::static_visitor < Object_vector > + class Make_x_monotone_2_visitor : + public boost::static_visitor < Object_vector > { private: typedef boost::static_visitor Base; @@ -1787,4 +1797,3 @@ public: #endif // CGAL_DONT_SUBMIT #endif //CGAL_ARR_RATIONAL_ARC_TRAITS_D_1_H - diff --git a/Arrangement_on_surface_2/archive/include/CGAL/Arr_rational_arc_traits_2.h b/Arrangement_on_surface_2/archive/include/CGAL/Arr_rational_arc_traits_2.h index cd8d80f962f..2c25299c59b 100644 --- a/Arrangement_on_surface_2/archive/include/CGAL/Arr_rational_arc_traits_2.h +++ b/Arrangement_on_surface_2/archive/include/CGAL/Arr_rational_arc_traits_2.h @@ -80,7 +80,7 @@ public: Arr_rational_arc_traits_2 () {} - /// \name Functor definitions. + /// \name Basic functor definitions. //@{ /*! A functor that compares the x-coordinates of two points */ @@ -381,19 +381,22 @@ public: { return Equal_2(); } + //@} + + //! \name Intersections, subdivisions, and mergings + //@{ /*! A functor that divides a curve into continues (x-monotone) curves. */ class Make_x_monotone_2 { public: - /*! - * Cut the given conic curve (or conic arc) into x-monotone subcurves - * and insert them to the given output iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The returned - * objects is a wrapper for an X_monotone_curve_2 object. - * \return The past-the-end iterator. + /*! Subdivide a given rational arc into x-monotone subcurves and insert them + * into a given output iterator. + * \param cv the arc. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return the past-the-end iterator. */ template OutputIterator operator() (const Curve_2& cv, OutputIterator oi) diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestAlgebraic.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestAlgebraic.cpp index 41acec251bb..dbe9e2dd917 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestAlgebraic.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestAlgebraic.cpp @@ -25,26 +25,26 @@ typedef CGAL::Curved_kernel_via_analysis_2< Algebraic_kernel_d_2 > CKvA_2; Polynomial_2 makeParabola( ) { - Polynomial_2 x = CGAL::shift( Polynomial_2( 1 ), 1, 0 ); - Polynomial_2 y = CGAL::shift( Polynomial_2( 1 ), 1, 1 ); - Polynomial_2 parabola = y - x*x; + Polynomial_2 x = CGAL::shift( Polynomial_2( 1 ), 1, 0 ); + Polynomial_2 y = CGAL::shift( Polynomial_2( 1 ), 1, 1 ); + Polynomial_2 parabola = y - x*x; - return parabola; + return parabola; } X_monotone_curve_2 makeVerticalLine( Bound x ) { - Traits traits; - Traits::Construct_point_2 constructPoint = - traits.construct_point_2_object( ); - Traits::Construct_x_monotone_segment_2 constructSegment = - traits.construct_x_monotone_segment_2_object( ); + Traits traits; + Traits::Construct_point_2 constructPoint = + traits.construct_point_2_object( ); + Traits::Construct_x_monotone_segment_2 constructSegment = + traits.construct_x_monotone_segment_2_object( ); - std::vector< X_monotone_curve_2 > curves; - Point_2 p1 = constructPoint( Algebraic_real_1(x), Algebraic_real_1(Bound( -10000 )) ); - Point_2 p2 = constructPoint( x, Bound( +10000 ) ); - constructSegment( p1, p2, std::back_inserter( curves ) ); - return curves[ 0 ]; + std::vector< X_monotone_curve_2 > curves; + Point_2 p1 = constructPoint( Algebraic_real_1(x), Algebraic_real_1(Bound( -10000 )) ); + Point_2 p2 = constructPoint( x, Bound( +10000 ) ); + constructSegment( p1, p2, std::back_inserter( curves ) ); + return curves[ 0 ]; } typedef CGAL::Cartesian< Coefficient > Kernel; @@ -52,40 +52,38 @@ typedef Kernel::Point_2 Kernel_point_2; int main( ) { - Algebraic_real_1 real( 1 ); - //CGAL::Qt::Converter< Algebraic_kernel_d_2 > testConverter; - //CGAL::Qt::Converter< CKvA_2 > testConverter; + Algebraic_real_1 real( 1 ); + //CGAL::Qt::Converter< Algebraic_kernel_d_2 > testConverter; + //CGAL::Qt::Converter< CKvA_2 > testConverter; - //CGAL::Qt::Converter< Cartesian > testConverter; - Kernel_point_2 testPt( 1, 2 ); - Point_2 testPt2( testPt.x( ), testPt.y( ) ); - Traits traits; - Construct_curve_2 constructCurve = traits.construct_curve_2_object( ); - Curve_2 curve = constructCurve( makeParabola( ) ); - Make_x_monotone_2 mm = traits.make_x_monotone_2_object( ); - std::vector< CGAL::Object > curves; - mm( curve, std::back_inserter( curves ) ); - std::cout << curves.size( ) << std::endl; - X_monotone_curve_2 c1; - CGAL::assign( c1, curves[ 0 ] ); - double lb = -3; - double ub = 3; - double step = 6.0 / 1000; + //CGAL::Qt::Converter< Cartesian > testConverter; + Kernel_point_2 testPt( 1, 2 ); + Point_2 testPt2( testPt.x( ), testPt.y( ) ); + Traits traits; + Construct_curve_2 constructCurve = traits.construct_curve_2_object( ); + Curve_2 curve = constructCurve( makeParabola( ) ); + Make_x_monotone_2 mm = traits.make_x_monotone_2_object( ); + std::vector< CGAL::Object > curves; + mm( curve, std::back_inserter( curves ) ); + std::cout << curves.size( ) << std::endl; + X_monotone_curve_2 c1; + CGAL::assign( c1, curves[ 0 ] ); + double lb = -3; + double ub = 3; + double step = 6.0 / 1000; - for ( int i = 0; i < 1000; ++i ) - { - X_monotone_curve_2 c2 = makeVerticalLine( lb + step * i ); + for ( int i = 0; i < 1000; ++i ) { + X_monotone_curve_2 c2 = makeVerticalLine( lb + step * i ); - CGAL::Object o; - CGAL::Oneset_iterator< CGAL::Object > oi( o ); - Intersect_2 intersect = traits.intersect_2_object( ); - intersect( c1, c2, oi ); - std::pair< Point_2, Multiplicity > res; - CGAL::assign( res, o ); - std::pair< double, double > approx = res.first.to_double( ); - std::cout << approx.first << " " << approx.second << std::endl; - } + CGAL::Object o; + CGAL::Oneset_iterator< CGAL::Object > oi( o ); + Intersect_2 intersect = traits.intersect_2_object( ); + intersect( c1, c2, oi ); + std::pair< Point_2, Multiplicity > res; + CGAL::assign( res, o ); + std::pair< double, double > approx = res.first.to_double( ); + std::cout << approx.first << " " << approx.second << std::endl; + } - - return 0; + return 0; } diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestRayPL.cpp b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestRayPL.cpp index e2be25f6b52..120fdf7beea 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestRayPL.cpp +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/tests/TestRayPL.cpp @@ -6,28 +6,29 @@ #include #include -typedef CGAL::Gmpq NT; -typedef CGAL::Cartesian< NT > Kernel; -typedef CGAL::Arr_linear_traits_2< Kernel > Traits; -typedef CGAL::Arr_default_dcel< Traits > Dcel; -typedef CGAL::Arrangement_with_history_2< Traits, Dcel > Arrangement; -typedef CGAL::Arr_walk_along_line_point_location< Arrangement > WalkAlongLinePointLocationStrategy; -typedef Kernel::Point_2 Point_2; -typedef Kernel::Ray_2 Ray_2; -typedef Arrangement::Curve_2 Curve_2; +typedef CGAL::Gmpq NT; +typedef CGAL::Cartesian Kernel; +typedef CGAL::Arr_linear_traits_2 Traits; +typedef CGAL::Arr_default_dcel Dcel; +typedef CGAL::Arrangement_with_history_2< Traits, Dcel> Arrangement; +typedef CGAL::Arr_walk_along_line_point_location + Walk_along_line_pl; +typedef Kernel::Point_2 Point_2; +typedef Kernel::Ray_2 Ray_2; +typedef Arrangement::Curve_2 Curve_2; int main( ) { - Point_2 p1( 0, 0 ); - Point_2 p2( 1, 0 ); - Ray_2 ray( p1, p2 ); - Curve_2 curve( ray ); + Point_2 p1(0, 0); + Point_2 p2(1, 0); + Ray_2 ray(p1, p2); + Curve_2 curve(ray); Arrangement arr; - CGAL::insert( arr, curve ); + CGAL::insert(arr, curve); - WalkAlongLinePointLocationStrategy pl( arr ); - CGAL::Object o = pl.locate( Point_2( 1, -1 ) ); + Walk_along_line_pl pl(arr); + auto o = pl.locate(Point_2(1, -1)); return 0; } diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_polycurve_traits_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_polycurve_traits_2.h index fc41e4c1f97..16788a94596 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_polycurve_traits_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_polycurve_traits_2.h @@ -239,19 +239,17 @@ namespace CGAL { const Point_2& tgt) const; }; - /*! Subdivide the given subcurve into x-monotone subcurves and insert them - * into the given output iterator. Since the subcurves that - * constitute a general polycurve are not necessarily - * \f$x\f$-monotone, this functor may break them. + /*! Subdivide a given subcurve into x-monotone subcurves and insert them + * into a given output iterator. */ class Make_x_monotone_2 { public: /*! * \pre if `cv` is not empty then it must be continuous and well-oriented. - * \param cv The subcurve. - * \param oi The output iterator, whose value-type is Object. The output - * object is a wrapper of a X_monotone_curve_2 objects. - * \return The past-the-end iterator. + * \param cv the subcurve. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return the past-the-end iterator. */ template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const; diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_vertical_decomposition_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_vertical_decomposition_2.h index d2deb6868f4..7a39bd94d77 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_vertical_decomposition_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/CGAL/Arr_vertical_decomposition_2.h @@ -1,57 +1,52 @@ namespace CGAL { -/*! -\ingroup PkgArrangementOnSurface2Funcs - -Produces the symbolic vertical decomposition of a -given arrangement, performing a batched vertical ray-shooting query from -all arrangement vertices, such that every vertex is associated with a pair -of objects, one corresponds to the arrangement feature that lies below it, -and the other corresponds to the feature that lies above it. -The output of this function can be readily used for inserting vertical walls -and physically decomposing the arrangement into pseudo-trapezoids. To do -this, it is convenient to process the vertices in an ascending -\f$ xy\f$-lexicographic order. The visible objects are therefore returned through -an output iterator, which pairs each finite arrangement vertex with the two -features it "sees", such that the vertices are given in ascending -\f$ xy\f$-lexicographic order. - -Produces the symbolic vertical decomposition of the `arr` arrangement. -More precisely, it performs a batched vertical ray-shooting query from all -arrangement vertices, such that every vertex is associated with a pair of -objects, one corresponding to the arrangement feature that lies below it, -while the other corresponds to the feature that lies above it. -The query results are returned through the output iterator, which pairs -each finite arrangement vertex with a pair of `Object`s, the first -represents the feature below the vertex, and the second represents the -feature that lies above it. Each `Object` may be one of the following: -
      -
    • `Halfedge_const_handle`, if the vertex is located above (or -below) an edge. The given halfedge is always directed from right to left. -In case there is no concrete edge below (or above) the vertex, and -the arrangement is unbounded, then the object returned is a -fictitious halfedge. -
    • `Face_const_handle`, in case there is no edge below (or above) -the vertex, and the arrangement is bounded. -
    • `Vertex_const_handle`, in case the vertex is located vertically -above (or below) another arrangement vertex. -
    • An empty object, in case the vertex is the top end-vertex of -a vertical edge, we define there is no feature below it. Similarly, if -it is the bottom end-vertex of a vertical edge, we define that there -is no feature above it. -
    -The function returns a past-the-end iterator for its output sequence. - -\cgalHeading{Requirements} - -`OutputIterator::value_type` must be -`pair >`. - -*/ +/*! \ingroup PkgArrangementOnSurface2Funcs + * + * Produces the symbolic vertical decomposition of a given arrangement, + * performing a batched vertical ray-shooting query from all arrangement + * vertices, such that every vertex is associated with a pair of objects, one + * corresponds to the arrangement feature that lies below it, and the other + * corresponds to the feature that lies above it. The output of this function + * can be readily used for inserting vertical walls and physically decomposing + * the arrangement into pseudo-trapezoids. To do this, it is convenient to + * process the vertices in an ascending \f$ xy\f$-lexicographic order. The + * visible objects are therefore returned through an output iterator, which + * pairs each finite arrangement vertex with the two features it "sees", such + * that the vertices are given in ascending \f$ xy\f$-lexicographic order. + * + * Produces the symbolic vertical decomposition of the `arr` arrangement. More + * precisely, it performs a batched vertical ray-shooting query from all + * arrangement vertices, such that every vertex is associated with a pair of + * objects, one corresponding to the arrangement feature that lies below it, + * while the other corresponds to the feature that lies above it. The query + * results are returned through the output iterator, which pairs each finite + * arrangement vertex with a pair of objects, the first represents the feature + * below the vertex, and the second represents the feature that lies above + * it. Each object is an optional variant that wraps a handle to an arrangement + * feature. If the vertex is the top end-vertex of a vertical edge, we say that + * there is no feature below it; similarly, if it is the bottom end-vertex of a + * vertical edge, we say that there is no feature above it. In these cases the + * optional object is set to be empty; otherwise it is set as follows: + *
      + *
    • `Halfedge_const_handle`, if the vertex is located above (or below) an + * edge. The given halfedge is always directed from right to left. In case + * there is no concrete edge below (or above) the vertex, and the arrangement + * is unbounded, then the object returned is a fictitious halfedge. + *
    • `Face_const_handle`, in case there is no edge below (or above) + * the vertex, and the arrangement is bounded. + *
    • `Vertex_const_handle`, in case the vertex is located vertically above + * (or below) another arrangement vertex. + *
    The function returns a past-the-end iterator for its output sequence. + * + * \cgalHeading{Requirements} + * + * `OutputIterator::value_type` must be + * `pair >`. + * + */ template OutputIterator decompose (const Arrangement_2& arr, OutputIterator oi); } /* namespace CGAL */ - diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--MakeXMonotone_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--MakeXMonotone_2.h index 2bed5f23a61..9af5785aa0c 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--MakeXMonotone_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--MakeXMonotone_2.h @@ -16,18 +16,16 @@ public: /// A model of this concept must provide: /// @{ -/*! -subdivides the input curve `c` into \f$ x\f$-monotone subcurves and -isolated points, and inserts the results into a container through the -given output iterator. The value type of `OutputIterator` is -`CGAL::Object`, where each `Object` wraps either an -`ArrTraits::X_monotone_curve_2` object or a `ArrTraits::Point_2` -object. The operator returns a past-the-end iterator for the output -sequence. -*/ +/*! subdivides the input curve `c` into \f$ x\f$-monotone subcurves and + * isolated points, and inserts the results into a range begining at the + * given output iterator `oi`. The type `OutputIterator` dereferences a + * `boost::variant` that wraps either an `ArrTraits::Point_2` object or an + * `ArrTraits::X_monotone_curve_2` object. The operator returns a past-the-end + * iterator for the output sequence. + */ template -OutputIterator operator()( ArrTraits::Curve_2 c, -OutputIterator oi); +OutputIterator operator()(ArrTraits::Curve_2 c, + OutputIterator oi); /// @} diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/algebraic_segments.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/algebraic_segments.cpp index 96bcc9c1786..1db0e105e69 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/algebraic_segments.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/algebraic_segments.cpp @@ -25,106 +25,102 @@ typedef CORE::BigInt Integer; typedef LEDA::integer Integer; #endif -typedef CGAL::Arr_algebraic_segment_traits_2 Arr_traits_2; -typedef CGAL::Arrangement_2 Arrangement_2; -typedef Arr_traits_2::Curve_2 Curve_2; -typedef Arr_traits_2::Polynomial_2 Polynomial_2; -typedef Arr_traits_2::Algebraic_real_1 Algebraic_real_1; -typedef Arr_traits_2::X_monotone_curve_2 X_monotone_curve_2; -typedef Arr_traits_2::Point_2 Point_2; +typedef CGAL::Arr_algebraic_segment_traits_2 Arr_traits_2; +typedef CGAL::Arrangement_2 Arrangement_2; +typedef Arr_traits_2::Curve_2 Curve_2; +typedef Arr_traits_2::Polynomial_2 Polynomial_2; +typedef Arr_traits_2::Algebraic_real_1 Algebraic_real_1; +typedef Arr_traits_2::X_monotone_curve_2 X_monotone_curve_2; +typedef Arr_traits_2::Point_2 Point_2; +typedef boost::variant Make_x_monotone_result; -int main() { +int main() +{ + Arr_traits_2 arr_traits; + auto construct_curve = arr_traits.construct_curve_2_object(); + auto construct_x_monotone_segment = + arr_traits.construct_x_monotone_segment_2_object(); + auto construct_point = arr_traits.construct_point_2_object(); + auto make_x_monotone = arr_traits.make_x_monotone_2_object(); - Arr_traits_2 arr_traits; + Arrangement_2 arr(&arr_traits); - Arr_traits_2::Construct_curve_2 construct_curve - = arr_traits.construct_curve_2_object(); - Arr_traits_2::Construct_x_monotone_segment_2 construct_x_monotone_segment - = arr_traits.construct_x_monotone_segment_2_object(); - Arr_traits_2::Construct_point_2 construct_point - = arr_traits.construct_point_2_object(); - Arr_traits_2::Make_x_monotone_2 make_x_monotone - = arr_traits.make_x_monotone_2_object(); + std::vector segs; - Arrangement_2 arr(&arr_traits); + Polynomial_2 x = CGAL::shift(Polynomial_2(1),1,0); + Polynomial_2 y = CGAL::shift(Polynomial_2(1),1,1); - std::vector segs; + // Construct x^4+y^3-1 + Curve_2 cv0 = construct_curve(CGAL::ipower(x,4)+CGAL::ipower(y,3)-1); + // Construct all x-monotone segments using the Make_x_mononotone functor + std::vector pre_segs; + make_x_monotone(cv0, std::back_inserter(pre_segs)); + // Cast all CGAL::Objects into X_monotone_segment_2 + // (the vector might also contain Point_2 objects for isolated points, + // but not for this instance + for(size_t i = 0; i < pre_segs.size(); ++i) { + auto* curr_p = boost::get(&pre_segs[i]);; + CGAL_assertion(curr_p); + segs.push_back(*curr_p); + } + // Construct an ellipse with equation 2*x^2+5*y^2-7=0 + Curve_2 cv1 = construct_curve(2*CGAL::ipower(x,2)+5*CGAL::ipower(y,2)-7); - Polynomial_2 x = CGAL::shift(Polynomial_2(1),1,0); - Polynomial_2 y = CGAL::shift(Polynomial_2(1),1,1); + // Construct point on the upper arc (counting of arc numbers starts with 0! + Point_2 p11 = construct_point(Algebraic_real_1(0),cv1,1); - // Construct x^4+y^3-1 - Curve_2 cv0 = construct_curve(CGAL::ipower(x,4)+CGAL::ipower(y,3)-1); - // Construct all x-monotone segments using the Make_x_mononotone functor - std::vector pre_segs; - make_x_monotone(cv0,std::back_inserter(pre_segs)); - // Cast all CGAL::Objects into X_monotone_segment_2 - // (the vector might also contain Point_2 objects for isolated points, - // but not for this instance - for(size_t i = 0; i < pre_segs.size(); i++ ) { - X_monotone_curve_2 curr; - bool check = CGAL::assign(curr,pre_segs[i]); - assert(check); CGAL_USE(check); - segs.push_back(curr); - } - // Construct an ellipse with equation 2*x^2+5*y^2-7=0 - Curve_2 cv1 = construct_curve(2*CGAL::ipower(x,2)+5*CGAL::ipower(y,2)-7); + construct_x_monotone_segment(cv1,p11,Arr_traits_2::POINT_IN_INTERIOR, + std::back_inserter(segs)); - // Construct point on the upper arc (counting of arc numbers starts with 0! - Point_2 p11 = construct_point(Algebraic_real_1(0),cv1,1); + // Construct a vertical cusp x^2-y^3=0 + Curve_2 cv2 = construct_curve(CGAL::ipower(x,2)-CGAL::ipower(y,3)); - construct_x_monotone_segment(cv1,p11,Arr_traits_2::POINT_IN_INTERIOR, + // Construct a segment containing the cusp point. + // This adds to X_monotone_curve_2 objects to the vector, + // because the cusp is a critical point + Point_2 p21 = construct_point(Algebraic_real_1(-2),cv2,0); + Point_2 p22 = construct_point(Algebraic_real_1(2),cv2,0); + construct_x_monotone_segment(cv2,p21,p22,std::back_inserter(segs)); + + // Construct an unbounded curve, starting at x=3 + Point_2 p23 = construct_point(Algebraic_real_1(3),cv2,0); + construct_x_monotone_segment(cv2,p23,Arr_traits_2::MIN_ENDPOINT, std::back_inserter(segs)); - // Construct a vertical cusp x^2-y^3=0 - Curve_2 cv2 = construct_curve(CGAL::ipower(x,2)-CGAL::ipower(y,3)); + // Construct another conic: y^2-x^2+1 + Curve_2 cv3 = construct_curve(CGAL::ipower(y,2)-CGAL::ipower(x,2)+1); - // Construct a segment containing the cusp point. - // This adds to X_monotone_curve_2 objects to the vector, - // because the cusp is a critical point - Point_2 p21 = construct_point(Algebraic_real_1(-2),cv2,0); - Point_2 p22 = construct_point(Algebraic_real_1(2),cv2,0); - construct_x_monotone_segment(cv2,p21,p22,std::back_inserter(segs)); + Point_2 p31 = construct_point(Algebraic_real_1(2),cv3,1); + construct_x_monotone_segment(cv3,p31,Arr_traits_2::MAX_ENDPOINT, + std::back_inserter(segs)); - // Construct an unbounded curve, starting at x=3 - Point_2 p23 = construct_point(Algebraic_real_1(3),cv2,0); - construct_x_monotone_segment(cv2,p23,Arr_traits_2::MIN_ENDPOINT, - std::back_inserter(segs)); + // Construct a vertical segment + Point_2 v1 = construct_point(0,0); + Point_2 v2 = construct_point(Algebraic_real_1(0),cv1,1); + construct_x_monotone_segment(v1,v2,std::back_inserter(segs)); - // Construct another conic: y^2-x^2+1 - Curve_2 cv3 = construct_curve(CGAL::ipower(y,2)-CGAL::ipower(x,2)+1); + CGAL::insert(arr,segs.begin(),segs.end()); - Point_2 p31 = construct_point(Algebraic_real_1(2),cv3,1); - construct_x_monotone_segment(cv3,p31,Arr_traits_2::MAX_ENDPOINT, - std::back_inserter(segs)); + // Add some isolated points (must be wrapped into CGAL::Object) + std::vector isolated_points; + isolated_points.push_back + (CGAL::make_object(construct_point(Algebraic_real_1(2),cv3,0))); + isolated_points.push_back + (CGAL::make_object(construct_point(Integer(1),Integer(5)))); + isolated_points.push_back + (CGAL::make_object(construct_point(Algebraic_real_1(-1), + Algebraic_real_1(5)))); - // Construct a vertical segment - Point_2 v1 = construct_point(0,0); - Point_2 v2 = construct_point(Algebraic_real_1(0),cv1,1); - construct_x_monotone_segment(v1,v2,std::back_inserter(segs)); + CGAL::insert(arr,isolated_points.begin(), isolated_points.end()); - CGAL::insert(arr,segs.begin(),segs.end()); + // Print the arrangement size. + std::cout << "The arrangement size:" << std::endl + << " V = " << arr.number_of_vertices() + << ", E = " << arr.number_of_edges() + << ", F = " << arr.number_of_faces() << std::endl; - // Add some isolated points (must be wrapped into CGAL::Object) - std::vector isolated_points; - isolated_points.push_back - (CGAL::make_object(construct_point(Algebraic_real_1(2),cv3,0))); - isolated_points.push_back - (CGAL::make_object(construct_point(Integer(1),Integer(5)))); - isolated_points.push_back - (CGAL::make_object(construct_point(Algebraic_real_1(-1), - Algebraic_real_1(5)))); - - CGAL::insert(arr,isolated_points.begin(), isolated_points.end()); - - // Print the arrangement size. - std::cout << "The arrangement size:" << std::endl - << " V = " << arr.number_of_vertices() - << ", E = " << arr.number_of_edges() - << ", F = " << arr.number_of_faces() << std::endl; - - return 0; + return 0; } #endif diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/bounded_planar_vertical_decomposition.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/bounded_planar_vertical_decomposition.cpp index a28f94b838b..08e312a7e83 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/bounded_planar_vertical_decomposition.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/bounded_planar_vertical_decomposition.cpp @@ -8,16 +8,20 @@ #include typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; -typedef CGAL::Arr_segment_traits_2 Traits_2; -typedef Traits_2::Point_2 Point_2; -typedef Traits_2::X_monotone_curve_2 Segment_2; -typedef CGAL::Arrangement_2 Arrangement_2; -typedef Arrangement_2::Vertex_const_handle Vertex_const_handle; -typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle; -typedef Arrangement_2::Face_const_handle Face_const_handle; -typedef std::pair Object_pair; -typedef std::pair Vert_decomp_entry; -typedef std::list Vert_decomp_list; +typedef CGAL::Arr_segment_traits_2 Traits_2; +typedef Traits_2::Point_2 Point_2; +typedef Traits_2::X_monotone_curve_2 Segment_2; +typedef CGAL::Arrangement_2 Arrangement_2; +typedef Arrangement_2::Vertex_const_handle Vertex_const_handle; +typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle; +typedef Arrangement_2::Face_const_handle Face_const_handle; + +typedef boost::variant Cell_type; +typedef boost::optional Vert_decomp_type; +typedef std::pair Vert_decomp_pair; +typedef std::pair Vert_decomp_entry; +typedef std::list Vert_decomp_list; int main() { @@ -39,34 +43,41 @@ int main() CGAL::decompose(arr, std::back_inserter(vd_list)); // Print the results. - Vert_decomp_list::const_iterator vd_iter; - for (vd_iter = vd_list.begin(); vd_iter != vd_list.end(); ++vd_iter) { - const Object_pair& curr = vd_iter->second; + for (auto vd_iter = vd_list.begin(); vd_iter != vd_list.end(); ++vd_iter) { + const Vert_decomp_pair& curr = vd_iter->second; std::cout << "Vertex (" << vd_iter->first->point() << ") : "; - Vertex_const_handle vh; - Halfedge_const_handle hh; - Face_const_handle fh; - std::cout << " feature below: "; - if (CGAL::assign(hh, curr.first)) - std::cout << '[' << hh->curve() << ']'; - else if (CGAL::assign(vh, curr.first)) - std::cout << '(' << vh->point() << ')'; - else if (CGAL::assign(fh, curr.first)) - std::cout << "NONE"; - else - std::cout << "EMPTY"; + if (! curr.first) std::cout << "EMPTY"; + else { + auto* vh = boost::get(&*(curr.first)); + if (vh) std::cout << '(' << (*vh)->point() << ')'; + else { + auto* hh = boost::get(&*(curr.first)); + if (hh) std::cout << '[' << (*hh)->curve() << ']'; + else { + auto* fh = boost::get(&*(curr.first)); + CGAL_assertion(fh); + std::cout << "NONE (" << (*fh)->is_unbounded() << ")"; + } + } + } std::cout << " feature above: "; - if (CGAL::assign(hh, curr.second)) - std::cout << '[' << hh->curve() << ']' << std::endl; - else if (CGAL::assign(vh, curr.second)) - std::cout << '(' << vh->point() << ')' << std::endl; - else if (CGAL::assign(fh, curr.second)) - std::cout << "NONE" << std::endl; - else - std::cout << "EMPTY" << std::endl; + if (! curr.second) std::cout << "EMPTY" << std::endl; + else { + auto* vh = boost::get(&*(curr.second)); + if (vh) std::cout << '(' << (*vh)->point() << ')' << std::endl; + else { + auto* hh = boost::get(&*(curr.second)); + if (hh) std::cout << '[' << (*hh)->curve() << ']' << std::endl; + else { + auto* fh = boost::get(&*(curr.second)); + CGAL_assertion(fh); + std::cout << "NONE (" << (*fh)->is_unbounded() << ")" << std::endl; + } + } + } } return 0; diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_bezier.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_bezier.cpp index bed7aead09d..2ab2edbdc96 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_bezier.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/polycurve_bezier.cpp @@ -33,16 +33,18 @@ typedef CGAL::Arr_Bezier_curve_traits_2 typedef Bezier_traits::Curve_2 Bezier_curve_2; typedef Bezier_traits::X_monotone_curve_2 Bezier_x_curve_2; typedef CGAL::Arr_polycurve_traits_2 Polycurve_bezier_traits_2; +typedef Polycurve_bezier_traits_2::Point_2 Point_2; typedef Polycurve_bezier_traits_2::X_monotone_curve_2 X_mono_polycurve; typedef CGAL::Arrangement_2 Arrangement_2; +typedef boost::variant Make_x_monotone_result; + int main() { Polycurve_bezier_traits_2 pc_traits; Bezier_traits bezier_traits; - Polycurve_bezier_traits_2::Construct_x_monotone_curve_2 - construct_x_mono_polycurve = + auto construct_x_mono_polycurve = pc_traits.construct_x_monotone_curve_2_object(); std::vector x_bezier_curves; @@ -69,11 +71,11 @@ int main() // Read the current curve (specified by its control points). in_file >> B; //convert it into x-monotone bezier curve. - std::vector obj_vector; + std::vector obj_vector; bezier_traits.make_x_monotone_2_object()(B, std::back_inserter(obj_vector)); - Bezier_x_curve_2 x_seg = - CGAL::object_cast((obj_vector[0])); - x_curves.push_back(x_seg); + auto* x_seg_p = boost::get(&obj_vector[0]); + CGAL_assertion(x_seg_p); + x_curves.push_back(*x_seg_p); } X_mono_polycurve polycurve = diff --git a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/unb_planar_vertical_decomposition.cpp b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/unb_planar_vertical_decomposition.cpp index ef04deb25ce..230c6d7694b 100644 --- a/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/unb_planar_vertical_decomposition.cpp +++ b/Arrangement_on_surface_2/examples/Arrangement_on_surface_2/unb_planar_vertical_decomposition.cpp @@ -8,19 +8,22 @@ #include #include -typedef CGAL::MP_Float Number_type; -typedef CGAL::Cartesian Kernel; -typedef CGAL::Arr_linear_traits_2 Traits_2; -typedef Traits_2::Point_2 Point_2; -typedef Traits_2::X_monotone_curve_2 Segment_2; -typedef CGAL::Arrangement_2 Arrangement_2; -typedef Arrangement_2::Vertex_const_handle Vertex_const_handle; -typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle; -typedef Arrangement_2::Face_const_handle Face_const_handle; +typedef CGAL::MP_Float Number_type; +typedef CGAL::Cartesian Kernel; +typedef CGAL::Arr_linear_traits_2 Traits_2; +typedef Traits_2::Point_2 Point_2; +typedef Traits_2::X_monotone_curve_2 Segment_2; +typedef CGAL::Arrangement_2 Arrangement_2; +typedef Arrangement_2::Vertex_const_handle Vertex_const_handle; +typedef Arrangement_2::Halfedge_const_handle Halfedge_const_handle; +typedef Arrangement_2::Face_const_handle Face_const_handle; -typedef std::pair > - Vert_decomp_entry; -typedef std::list Vert_decomp_list; +typedef boost::variant Cell_type; +typedef boost::optional Vert_decomp_type; +typedef std::pair Vert_decomp_pair; +typedef std::pair Vert_decomp_entry; +typedef std::list Vert_decomp_list; int main () { @@ -43,37 +46,37 @@ int main () CGAL::decompose (arr, std::back_inserter(vd_list)); // Print the results. - Vert_decomp_list::const_iterator vd_iter; - std::pair curr; - Vertex_const_handle vh; - Halfedge_const_handle hh; - Face_const_handle fh; - - for (vd_iter = vd_list.begin(); vd_iter != vd_list.end(); ++vd_iter) { - curr = vd_iter->second; + for (auto vd_iter = vd_list.begin(); vd_iter != vd_list.end(); ++vd_iter) { + const Vert_decomp_pair& curr = vd_iter->second; std::cout << "Vertex (" << vd_iter->first->point() << ") : "; std::cout << " feature below: "; - if (CGAL::assign (vh, curr.first)) - std::cout << '(' << vh->point() << ')'; - else if (CGAL::assign (hh, curr.first)) - if (!hh->is_fictitious()) - std::cout << '[' << hh->curve() << ']'; - else - std::cout << "NONE"; - else - std::cout << "EMPTY"; + if (! curr.first) std::cout << "EMPTY"; + else { + auto* vh = boost::get(&*(curr.first));; + if (vh) std::cout << '(' << (*vh)->point() << ')'; + else { + auto* hh = boost::get(&*(curr.first)); + CGAL_assertion(hh); + if (! (*hh)->is_fictitious()) + std::cout << '[' << (*hh)->curve() << ']'; + else std::cout << "NONE"; + } + } std::cout << " feature above: "; - if (CGAL::assign (vh, curr.second)) - std::cout << '(' << vh->point() << ')' << std::endl; - else if (CGAL::assign (hh, curr.second)) - if (!hh->is_fictitious()) - std::cout << '[' << hh->curve() << ']' << std::endl; - else - std::cout << "NONE" << std::endl; - else - std::cout << "EMPTY" << std::endl; + if (! curr.second) std::cout << "EMPTY" << std::endl; + else { + auto* vh = boost::get(&*(curr.second));; + if (vh) std::cout << '(' << (*vh)->point() << ')' << std::endl; + else { + auto* hh = boost::get(&*(curr.second)); + CGAL_assertion(hh); + if (! (*hh)->is_fictitious()) + std::cout << '[' << (*hh)->curve() << ']' << std::endl; + else std::cout << "NONE" << std::endl; + } + } } return 0; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_Bezier_curve_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_Bezier_curve_traits_2.h index 36b46416572..243fbbf705a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_Bezier_curve_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_Bezier_curve_traits_2.h @@ -7,9 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Iddo Hanniel -// Waqar Khan +// Author(s): Ron Wein +// Iddo Hanniel +// Waqar Khan #ifndef CGAL_ARR_BEZIER_CURVE_TRAITS_2_H #define CGAL_ARR_BEZIER_CURVE_TRAITS_2_H @@ -163,7 +163,7 @@ public: } //@} - /// \name Functor definitions for the arrangement traits. + /// \name Basic functor definitions for the arrangement traits //@{ /*! \class Compare_x_2 @@ -473,33 +473,34 @@ public: { return (Equal_2 (p_cache)); } + //@} + + //! \name Intersections, subdivisions, and mergings + //@{ /*! \class Make_x_monotone_2 - * The Make_x_monotone_2 functor. + * A functor for subdividing a curve into x-monotone curves. */ - class Make_x_monotone_2 - { + class Make_x_monotone_2 { private: - Bezier_cache *p_cache; + Bezier_cache* p_cache; public: - /*! Constructor. */ - Make_x_monotone_2 (Bezier_cache *cache) : - p_cache (cache) - {} + Make_x_monotone_2(Bezier_cache* cache) : p_cache(cache) {} - /*! - * Cut the given Bezier curve into x-monotone subcurves and insert them - * into the given output iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The returned - * objects is a wrapper for an X_monotone_curve_2 object. - * \return The past-the-end iterator. + /*! Subdivide a given Bezier curve into x-monotone subcurves and insert them + * into a given output iterator. + * \param cv the curve. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return the past-the-end iterator. */ - template + template OutputIterator operator() (const Curve_2& B, OutputIterator oi) const { + typedef boost::variant + Make_x_monotone_result; typedef typename Bounding_traits::Vertical_tangency_point Vertical_tangency_point; @@ -512,20 +513,17 @@ public: std::back_inserter(cpts)); bound_tr.compute_vertical_tangency_points - (cpts, std::back_inserter (vpt_bounds)); + (cpts, std::back_inserter (vpt_bounds)); // Construct Point_2 from bounded tangency points. std::list vpts; bool app_ok = true; - typename std::list::const_iterator iter; - for (iter = vpt_bounds.begin(); iter != vpt_bounds.end(); ++iter) - { + for (auto iter = vpt_bounds.begin(); iter != vpt_bounds.end(); ++iter) { const typename Bounding_traits::Bez_point_bound& bound = iter->bound; const typename Bounding_traits::Bez_point_bbox& bbox = iter->bbox; - if (! bound.can_refine) - { + if (! bound.can_refine) { // If we cannot refine the vertical-tangency bound anymore, then // we failed to bound the vertical tangency point. // \todo In the future, we might want to use the info. @@ -534,28 +532,25 @@ public: } // Construct an approximate vertical tangency point. - Point_2 pt; + Point_2 pt; - if (bound.type == Bounding_traits::Bez_point_bound::RATIONAL_PT) - { + if (bound.type == Bounding_traits::Bez_point_bound::RATIONAL_PT) { CGAL_assertion (CGAL::compare (bound.t_min, bound.t_max) == EQUAL); - Rational t0 = bound.t_min; + Rational t0 = bound.t_min; pt = Point_2 (B, t0); } - else - { - pt.add_originator (typename Point_2::Originator(B, bound)); + else { + pt.add_originator(typename Point_2::Originator(B, bound)); } - pt.set_bbox (bbox); + pt.set_bbox(bbox); vpts.push_back(pt); } // If bounding the approximated vertical-tangency points went fine, // use these points as endpoint for the x-monotone subcurves. - if (app_ok) - { + if (app_ok) { // Create the x-monotone subcurves with approximate endpoints. typename std::list::const_iterator pit; unsigned int xid = 1; // Serial number of the subcurve. @@ -563,19 +558,16 @@ public: // Note: xid is needed in ctr of p0 (and of p1 below), // for handling end case of start point == end point. - for (pit = vpts.begin(); pit != vpts.end(); ++pit) - { - *oi++ = CGAL::make_object (X_monotone_curve_2 (B, xid, - p0, *pit, - *p_cache)); + for (pit = vpts.begin(); pit != vpts.end(); ++pit) { + *oi++ = Make_x_monotone_result(X_monotone_curve_2(B, xid, p0, *pit, + *p_cache)); xid++; p0 = *pit; } Point_2 p1(B, xid, Rational(1)); // A rational end point. - *oi++ = CGAL::make_object (X_monotone_curve_2 (B, xid, - p0, p1, - *p_cache)); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(B, xid, p0, p1, + *p_cache)); return (oi); } @@ -583,41 +575,34 @@ public: // points in an exact manner. We do this by considering all t-values // on B(t) = (X(t), Y(t)), such that X'(t) = 0. const typename Bezier_cache::Vertical_tangency_list& - vt_list = p_cache->get_vertical_tangencies (B.id(), - B.x_polynomial(), - B.x_norm()); + vt_list = p_cache->get_vertical_tangencies(B.id(), B.x_polynomial(), + B.x_norm()); // Create the x-monotone subcurves. - Point_2 p1; - typename Bezier_cache::Vertical_tangency_iter it; - unsigned int xid = 1; // Serial number of the subcurve. - Point_2 p0 (B, xid, Rational(0)); + Point_2 p1; + unsigned int xid = 1; // Serial number of the subcurve. + Point_2 p0(B, xid, Rational(0)); - for (it = vt_list.begin(); it != vt_list.end(); ++it) - { - p1 = Point_2 (B, *it); - *oi++ = CGAL::make_object (X_monotone_curve_2 (B, xid, - p0, p1, - *p_cache)); + for (auto it = vt_list.begin(); it != vt_list.end(); ++it) { + p1 = Point_2(B, *it); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(B, xid, p0, p1, + *p_cache)); xid++; p0 = p1; } // Create the final subcurve. - p1 = Point_2 (B, xid, Rational(1)); - *oi++ = CGAL::make_object (X_monotone_curve_2 (B, xid, - p0, p1, - *p_cache)); - return (oi); + p1 = Point_2(B, xid, Rational(1)); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(B, xid, p0, p1, + *p_cache)); + return oi; } }; /*! Get a Make_x_monotone_2 functor object. */ - Make_x_monotone_2 make_x_monotone_2_object () const - { - return (Make_x_monotone_2 (p_cache)); - } + Make_x_monotone_2 make_x_monotone_2_object() const + { return (Make_x_monotone_2 (p_cache)); } /*! \class Split_2 * The Split_2 functor. @@ -756,7 +741,6 @@ public: { return Merge_2(this); } - //@} /// \name Functor definitions for the Boolean set-operation traits. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_accessor.h b/Arrangement_on_surface_2/include/CGAL/Arr_accessor.h index 0397cd07f67..dbbc07dbad9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_accessor.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_accessor.h @@ -22,6 +22,7 @@ */ #include +#include namespace CGAL { @@ -60,6 +61,9 @@ private: typedef typename Arrangement_2::DInner_ccb DInner_ccb; typedef typename Arrangement_2::DIso_vertex DIso_vertex; + typedef Arr_point_location_result Pl_result; + typedef typename Pl_result::Type Pl_result_type; + private: Arrangement_2* p_arr; // The associated arrangement. @@ -99,33 +103,29 @@ public: * This object may wrap a Face_const_handle (the general case), * or a Halfedge_const_handle (in case of an overlap). */ - CGAL::Object locate_curve_end(const X_monotone_curve_2& cv, - Arr_curve_end ind, - Arr_parameter_space ps_x, - Arr_parameter_space ps_y) const + Pl_result_type locate_curve_end(const X_monotone_curve_2& cv, + Arr_curve_end ind, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y) const { CGAL_precondition((ps_x != ARR_INTERIOR) || (ps_y != ARR_INTERIOR)); // Use the topology traits to locate the unbounded curve end. - CGAL::Object obj = - p_arr->topology_traits()->locate_curve_end(cv, ind, ps_x, ps_y); + auto obj = p_arr->topology_traits()->locate_curve_end(cv, ind, ps_x, ps_y); // Return a handle to the DCEL feature. - DFace* f; - if (CGAL::assign(f, obj)) - return (CGAL::make_object(p_arr->_const_handle_for(f))); + DFace** f_p = boost::get(&obj); + if (f_p) return (Pl_result::make_result(p_arr->_const_handle_for(*f_p))); - DHalfedge* he; - if (CGAL::assign(he, obj)) - return (CGAL::make_object(p_arr->_const_handle_for(he))); + DHalfedge** he_p = boost::get(&obj); + if (he_p) return (Pl_result::make_result(p_arr->_const_handle_for(*he_p))); - DVertex* v; - if (CGAL::assign(v, obj)) - return (CGAL::make_object(p_arr->_const_handle_for(v))); + DVertex** v_p = boost::get(&obj); + if (v_p) return (Pl_result::make_result(p_arr->_const_handle_for(*v_p))); // We should never reach here: CGAL_error(); - return Object(); + return Pl_result::make_result(Vertex_const_handle()); } /*! diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_algebraic_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_algebraic_segment_traits_2.h index 5a3384145d2..5a3f2baa7b0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_algebraic_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_algebraic_segment_traits_2.h @@ -8,7 +8,7 @@ // SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Michael Kerber +// Author(s): Michael Kerber // // ============================================================================ @@ -264,138 +264,141 @@ public: } - template OutputIterator - x_monotone_segment (Curve_2 cv, - Point_2 p, - boost::optional start, - boost::optional end, - OutputIterator out) const { + template OutputIterator + x_monotone_segment(Curve_2 cv, + Point_2 p, + boost::optional start, + boost::optional end, + OutputIterator out) const + { + typedef boost::variant + Make_x_monotone_result; + //CGAL_assertion(is_one_one(cv,p)); - //CGAL_assertion(is_one_one(cv,p)); + std::list segs; - std::list segs; - - Is_on_2 on_arc - = this->_ckva()->is_on_2_object(); - Construct_min_vertex_2 left - = this->_ckva()->construct_min_vertex_2_object(); - Construct_max_vertex_2 right - = this->_ckva()->construct_max_vertex_2_object(); - Equal_2 equal = this->_ckva()->equal_2_object(); - - std::vector arcs; - this->_ckva()->make_x_monotone_2_object() - (cv,std::back_inserter(arcs)); - typename std::vector::const_iterator - it = arcs.begin(),helper; - X_monotone_curve_2 it_seg; - CGAL::assign(it_seg,*it); - while(it!=arcs.end()) { - if( on_arc(p,it_seg) ) { - break; - } - CGAL_assertion(it!=arcs.end()); - it++; - CGAL::assign(it_seg,*it); - } - - bool left_on_arc = start && on_arc(start.get(),it_seg); - bool right_on_arc = end && on_arc(end.get(),it_seg); - - if( left_on_arc && right_on_arc ) { - segs.push_back(it_seg.trim(start.get(),end.get())); - } - if(left_on_arc && (!right_on_arc)) { - if(!it_seg.is_finite(CGAL::ARR_MAX_END) || - !equal(start.get(),right(it_seg))) { - if(it_seg.is_finite(CGAL::ARR_MIN_END) && equal(start.get(),left(it_seg))) { - segs.push_back(it_seg); - } else { - X_monotone_curve_2 split1,split2; - it_seg.split(start.get(),split1,split2); - segs.push_back(split2); - } - } - } - if((!left_on_arc) && right_on_arc) { - if(!it_seg.is_finite(CGAL::ARR_MIN_END) || - ! equal(left(it_seg),end.get())) { - if(it_seg.is_finite(CGAL::ARR_MAX_END) && equal(end.get(),right(it_seg))) { - segs.push_back(it_seg); - } else { - X_monotone_curve_2 split1,split2; - it_seg.split(end.get(),split1,split2); - segs.push_back(split1); - } - } - } - if( (!left_on_arc) && (!right_on_arc)) { - segs.push_back(it_seg); - } - helper=it; // for later usage - - if(! left_on_arc) { - - Point_2 point_it; - while(true) { - if(it_seg.is_finite(CGAL::ARR_MIN_END) && - is_one_one(cv,left(it_seg) ) ) { - point_it=left(it_seg); - } else { - CGAL_assertion(! start); - break; - } - CGAL_assertion(it!=arcs.begin()); - it--; - CGAL::assign(it_seg,*it); - while(! on_arc(point_it,it_seg)) { - CGAL_assertion(it!=arcs.begin()); - it--; - CGAL::assign(it_seg,*it); - } - if(start && on_arc(start.get(),it_seg)) { - segs.push_front(it_seg.trim(start.get(), - right(it_seg))); - break; - } else { - segs.push_front(it_seg); - } - } - } - if(! right_on_arc) { - it=helper; // reset - CGAL::assign(it_seg,*it); - Point_2 point_it; - while(true) { - if(it_seg.is_finite(CGAL::ARR_MAX_END) && - is_one_one(cv,right(it_seg) ) ) { - point_it=right(it_seg); - } else { - CGAL_assertion(! end); - break; - } - it++; - CGAL_assertion(it!=arcs.end()); - CGAL::assign(it_seg,*it); - while(! on_arc(point_it,it_seg)) { - it++; - CGAL_assertion(it!=arcs.end()); - CGAL::assign(it_seg,*it); - } - if(end && on_arc(end.get(),it_seg)) { - segs.push_back(it_seg.trim(left(it_seg),end.get())); - break; - } else { - segs.push_back(it_seg); - } - } - } - - std::copy(segs.begin(),segs.end(),out); - return out; + Is_on_2 on_arc = this->_ckva()->is_on_2_object(); + auto left = this->_ckva()->construct_min_vertex_2_object(); + auto right = this->_ckva()->construct_max_vertex_2_object(); + Equal_2 equal = this->_ckva()->equal_2_object(); + std::vector arcs; + this->_ckva()->make_x_monotone_2_object()(cv, std::back_inserter(arcs)); + auto it = arcs.begin(); + auto helper = it; + const auto* it_seg_p = boost::get(&(*it)); + while (it != arcs.end()) { + if ( on_arc(p, *it_seg_p) ) break; + it++; + it_seg_p = boost::get(&(*it)); } + bool left_on_arc = start && on_arc(start.get(), *it_seg_p); + bool right_on_arc = end && on_arc(end.get(), *it_seg_p); + + if ( left_on_arc && right_on_arc ) { + segs.push_back(it_seg_p->trim(start.get(),end.get())); + } + if (left_on_arc && (!right_on_arc)) { + if (!it_seg_p->is_finite(CGAL::ARR_MAX_END) || + !equal(start.get(),right(*it_seg_p))) { + if (it_seg_p->is_finite(CGAL::ARR_MIN_END) && + equal(start.get(),left(*it_seg_p))) + { + segs.push_back(*it_seg_p); + } + else { + X_monotone_curve_2 split1,split2; + it_seg_p->split(start.get(),split1,split2); + segs.push_back(split2); + } + } + } + if ((!left_on_arc) && right_on_arc) { + if (!it_seg_p->is_finite(CGAL::ARR_MIN_END) || + ! equal(left(*it_seg_p), end.get())) + { + if (it_seg_p->is_finite(CGAL::ARR_MAX_END) && + equal(end.get(), right(*it_seg_p))) + { + segs.push_back(*it_seg_p); + } + else { + X_monotone_curve_2 split1,split2; + it_seg_p->split(end.get(), split1, split2); + segs.push_back(split1); + } + } + } + if ( (!left_on_arc) && (!right_on_arc)) { + segs.push_back(*it_seg_p); + } + helper = it; // for later usage + + if (! left_on_arc) { + + Point_2 point_it; + while (true) { + if (it_seg_p->is_finite(CGAL::ARR_MIN_END) && + is_one_one(cv, left(*it_seg_p) ) ) { + point_it = left(*it_seg_p); + } else { + CGAL_assertion(! start); + break; + } + CGAL_assertion(it != arcs.begin()); + it--; + it_seg_p = boost::get(&(*it)); + while (! on_arc(point_it, *it_seg_p)) { + CGAL_assertion(it != arcs.begin()); + it--; + it_seg_p = boost::get(&(*it)); + } + if (start && on_arc(start.get(),*it_seg_p)) { + segs.push_front(it_seg_p->trim(start.get(), right(*it_seg_p))); + break; + } + else { + segs.push_front(*it_seg_p); + } + } + } + if (! right_on_arc) { + it = helper; // reset + it_seg_p = boost::get(&(*it)); + Point_2 point_it; + while (true) { + if (it_seg_p->is_finite(CGAL::ARR_MAX_END) && + is_one_one(cv,right(*it_seg_p) ) ) + { + point_it=right(*it_seg_p); + } else { + CGAL_assertion(! end); + break; + } + it++; + CGAL_assertion(it != arcs.end()); + it_seg_p = boost::get(&(*it)); + while(! on_arc(point_it, *it_seg_p)) { + it++; + CGAL_assertion(it != arcs.end()); + it_seg_p = boost::get(&(*it)); + } + if(end && on_arc(end.get(),*it_seg_p)) { + segs.push_back(it_seg_p->trim(left(*it_seg_p),end.get())); + break; + } + else { + segs.push_back(*it_seg_p); + } + } + } + + std::copy(segs.begin(), segs.end(), out); + return out; + + } + public: template OutputIterator diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_batched_point_location.h b/Arrangement_on_surface_2/include/CGAL/Arr_batched_point_location.h index e526a7ae2b9..af328f1d6e6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_batched_point_location.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_batched_point_location.h @@ -41,11 +41,9 @@ namespace Ss2 = Surface_sweep_2; * \param oi Output: An output iterator for the query results. * \pre The value-type of PointsIterator is Arrangement::Point_2, * and the value-type of OutputIterator is is pair, - * where Result is either - * (i) Object or - * (ii) boost::optional >. + * where Result is boost::optional >. * It represents the arrangement feature containing the point. */ template -// Efi Fogel -// Eric Berberich +// Author(s): Ron Wein +// Efi Fogel +// Eric Berberich #ifndef CGAL_ARR_BOUNDED_PLANAR_TOPOLOGY_TRAITS_2_H #define CGAL_ARR_BOUNDED_PLANAR_TOPOLOGY_TRAITS_2_H +#include + #include #include @@ -306,17 +307,18 @@ public: * \param ps_x The boundary condition of the curve end in x. * \param ps_y The boundary condition of the curve end in y. * \pre The curve has a boundary condition in either x or y. - * \return An object that contains the curve end. + * \return An object that wraps the curve end. */ - CGAL::Object place_boundary_vertex(Face*, - const X_monotone_curve_2&, - Arr_curve_end, - Arr_parameter_space /* ps_x */, - Arr_parameter_space /* ps_y */) + boost::optional > + place_boundary_vertex(Face*, + const X_monotone_curve_2&, + Arr_curve_end, + Arr_parameter_space /* ps_x */, + Arr_parameter_space /* ps_y */) { // This function should never be called: CGAL_error(); - return Object(); + return boost::none; } /*! Locate the predecessor halfedge for the given curve around a given @@ -349,14 +351,17 @@ public: * \pre The curve end is incident to the boundary. * \return An object that contains the curve end. */ - CGAL::Object locate_curve_end(const X_monotone_curve_2&, - Arr_curve_end, - Arr_parameter_space /* ps_x */, - Arr_parameter_space /* ps_y */) + boost::variant + locate_curve_end(const X_monotone_curve_2&, + Arr_curve_end, + Arr_parameter_space /* ps_x */, + Arr_parameter_space /* ps_y */) { + typedef boost::variant Result; // This function should never be called: CGAL_error(); - return Object(); + Vertex* v(nullptr); + return Result(v); } /*! Split a fictitious edge using the given vertex. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h index 2b5a25cd5e0..8364ffc5cd3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circle_segment_traits_2.h @@ -378,46 +378,47 @@ public: } //@} - /// \name Functor definitions for supporting intersections. + /// \name Intersections, subdivisions, and mergings //@{ - class Make_x_monotone_2 - { + /*! \class + * A functor for subdividing a curve into x-monotone curves. + */ + class Make_x_monotone_2 { private: typedef Arr_circle_segment_traits_2 Self; bool m_use_cache; public: + Make_x_monotone_2(bool use_cache = false) : m_use_cache(use_cache) {} - Make_x_monotone_2(bool use_cache = false) : m_use_cache(use_cache) - {} - - /*! - * Cut the given conic curve (ocv.is_in_x_range (p)r conic arc) into x-monotone subcurves - * and insert them to the given output iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The returned - * objects are all wrcv.is_in_x_range (p)appers X_monotone_curve_2 objects. - * \return The past-the-end iterator. + /*! Subdivide a given circular arc or line segment into x-monotone subcurves + * and insert them to a given output iterator. + * \param cv the curve. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return the past-the-end iterator. */ - template - OutputIterator operator() (const Curve_2& cv, OutputIterator oi) const + template + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { + typedef boost::variant + Make_x_monotone_result; + // Increment the serial number of the curve cv, which will serve as its // unique identifier. - unsigned int index = 0; - if(m_use_cache) - index = Self::get_index(); + unsigned int index = 0; + if (m_use_cache) index = Self::get_index(); - if (cv.orientation() == COLLINEAR) - { + if (cv.orientation() == COLLINEAR) { // The curve is a line segment. - *oi = make_object (X_monotone_curve_2 (cv.supporting_line(), - cv.source(), cv.target(), - index)); - ++oi; - return (oi); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv.supporting_line(), + cv.source(), + cv.target(), + index)); + return oi; } // Check the case of a degenrate circle (a point). @@ -425,12 +426,11 @@ public: CGAL::Sign sign_rad = CGAL::sign (circ.squared_radius()); CGAL_precondition (sign_rad != NEGATIVE); - if (sign_rad == ZERO) - { + if (sign_rad == ZERO) { // Create an isolated point. - *oi = make_object (Point_2 (circ.center().x(), circ.center().y())); - ++oi; - return (oi); + *oi++ = Make_x_monotone_result(Point_2(circ.center().x(), + circ.center().y())); + return oi; } // The curve is circular: compute the to vertical tangency points @@ -438,84 +438,73 @@ public: Point_2 vpts[2]; unsigned int n_vpts = cv.vertical_tangency_points (vpts); - if (cv.is_full()) - { + if (cv.is_full()) { CGAL_assertion (n_vpts == 2); // Subdivide the circle into two arcs (an upper and a lower half). - *oi = make_object (X_monotone_curve_2 (circ, - vpts[0], vpts[1], - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + vpts[0], vpts[1], + cv.orientation(), + index)); - *oi = make_object (X_monotone_curve_2 (circ, - vpts[1], vpts[0], - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + vpts[1], vpts[0], + cv.orientation(), + index)); } - else - { + else { // Act according to the number of vertical tangency points. - if (n_vpts == 2) - { + if (n_vpts == 2) { // Subdivide the circular arc into three x-monotone arcs. - *oi = make_object (X_monotone_curve_2 (circ, - cv.source(), vpts[0], - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + cv.source(), vpts[0], + cv.orientation(), + index)); - *oi = make_object (X_monotone_curve_2 (circ, - vpts[0], vpts[1], - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + vpts[0], vpts[1], + cv.orientation(), + index)); - *oi = make_object (X_monotone_curve_2 (circ, - vpts[1], cv.target(), - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + vpts[1], + cv.target(), + cv.orientation(), + index)); } - else if (n_vpts == 1) - { + else if (n_vpts == 1) { // Subdivide the circular arc into two x-monotone arcs. - *oi = make_object (X_monotone_curve_2 (circ, - cv.source(), vpts[0], - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + cv.source(), + vpts[0], + cv.orientation(), + index)); - *oi = make_object (X_monotone_curve_2 (circ, - vpts[0], cv.target(), - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + vpts[0], + cv.target(), + cv.orientation(), + index)); } - else - { - CGAL_assertion (n_vpts == 0); + else { + CGAL_assertion(n_vpts == 0); // The arc is already x-monotone: - *oi = make_object (X_monotone_curve_2 (circ, - cv.source(), cv.target(), - cv.orientation(), - index)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(circ, + cv.source(), + cv.target(), + cv.orientation(), + index)); } } - return (oi); + return oi; } }; /*! Get a Make_x_monotone_2 functor object. */ - Make_x_monotone_2 make_x_monotone_2_object () const - { - return Make_x_monotone_2(m_use_cache); - } + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(m_use_cache); } class Split_2 { diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circular_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circular_arc_traits_2.h index a7d96844523..6827889a4f1 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circular_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circular_arc_traits_2.h @@ -27,6 +27,10 @@ * Arrangement_2 package, which it is now part of. It contains a traits * class for the arrangement package that handles circular curves. * It is based on the circular kernel. + * + * \todo Fix the circular-kernel make-x-monotone functor to use modern variant + * instead of the legacy CGAL::Object. Then, eliminate the special + * implementation here and directly use the kernel functor instead. */ #include @@ -109,7 +113,7 @@ public: typedef unsigned int Multiplicity; typedef CGAL::Tag_false Has_left_category; - typedef CGAL::Tag_false Has_merge_category; + typedef CGAL::Tag_false Has_merge_category; typedef CGAL::Tag_false Has_do_intersect_category; typedef Arr_oblivious_side_tag Left_side_category; @@ -129,7 +133,7 @@ public: typedef typename CircularKernel::Construct_circular_min_vertex_2 Construct_min_vertex_2; typedef typename CircularKernel::Equal_2 Equal_2; - typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2; + // typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2; typedef typename CircularKernel::Split_2 Split_2; typedef typename CircularKernel::Intersect_2 Intersect_2; typedef typename CircularKernel::Is_vertical_2 Is_vertical_2; @@ -149,8 +153,8 @@ public: Equal_2 equal_2_object() const { return ck.equal_2_object(); } - Make_x_monotone_2 make_x_monotone_2_object() const - { return ck.make_x_monotone_2_object(); } + // Make_x_monotone_2 make_x_monotone_2_object() const + // { return ck.make_x_monotone_2_object(); } Split_2 split_2_object() const { return ck.split_2_object(); } @@ -168,6 +172,34 @@ public: { return ck.is_vertical_2_object(); } + //! A functor for subdividing curves into x-monotone curves. + class Make_x_monotone_2 { + public: + template + OutputIterator operator()(const Curve_2& arc, OutputIterator oi) const + { + typedef boost::variant + Make_x_monotone_result; + + std::vector objs; + CircularKernel().make_x_monotone_2_object()(arc, std::back_inserter(objs)); + for (const auto& obj : objs) { + if (const auto* p = CGAL::object_cast(&obj)) { + *oi++ = Make_x_monotone_result(*p); + continue; + } + if (const auto* xcv = CGAL::object_cast(&obj)) { + *oi++ = Make_x_monotone_result(*xcv); + continue; + } + CGAL_error(); + } + return oi; + } + }; + + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(); } }; } // namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h index eb9acae74a8..db91adb57cf 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_circular_line_arc_traits_2.h @@ -27,6 +27,10 @@ * Arrangement_2 package, which it is now part of. It contains a traits * class for the arrangement package that handles circular and linear curves. * It is based on the circular kernel. + * + * \todo Fix the circular-kernel make-x-monotone functor to use modern variant + * instead of the legacy CGAL::Object. Then, eliminate the special + * implementation here and directly use the kernel functor instead. */ #include @@ -39,53 +43,35 @@ namespace CGAL { namespace VariantFunctors{ - // Takes an iterator range of Object(Line/Circular_arc), - // returns an Object(Variant(Line/Circular_arc)). - // Do nothing for Object(Endpoint). + // Takes an iterator range of Object(Line/Circular_arc/Point), + // returns a variant of Line, Circular_arc, and Point_2. template OutputIterator object_to_object_variant(const std::vector& res1, OutputIterator res2) { - for (std::vector::const_iterator it = res1.begin(); - it != res1.end(); ++it ) { - if (const Arc1 *arc = CGAL::object_cast< Arc1 >(&*it)){ - boost::variant< Arc1, Arc2 > v = *arc; - *res2++ = make_object(v); + typedef typename CK::Circular_arc_point_2 Point_2; + typedef boost::variant X_monotone_curve_2; + typedef boost::variant + Make_x_monotone_result; + + for (auto it = res1.begin(); it != res1.end(); ++it) { + if (const Arc1* arc = CGAL::object_cast(&*it)) { + boost::variant v = *arc; + *res2++ = Make_x_monotone_result(v); } - else if (const Arc2 *line = CGAL::object_cast< Arc2 >(&*it)){ - boost::variant< Arc1, Arc2 > v = *line; - *res2++ = make_object(v); + else if (const Arc2* line = CGAL::object_cast(&*it)) { + boost::variant v = *line; + *res2++ = Make_x_monotone_result(v); } - else{ - *res2++ = *it; + else if (const Point_2* p = CGAL::object_cast(&*it)) { + *res2++ = Make_x_monotone_result(*p); } + else CGAL_error(); } return res2; } - template - OutputIterator - object_to_object_variant1(const std::vector& res, - OutputIterator oi) - { - typedef IntersectionPoint Intersection_point; - typedef XMonotoneCurve X_monotone_curve_2; - typedef boost::variant - Intersection_result; - - for (auto it = res.begin(); it != res.end(); ++it) { - if (const Arc* arc = boost::get(&*it)) { - X_monotone_curve_2 cv = *arc; - *oi++ = Intersection_result(cv); - } - else *oi++ = Intersection_result(*it); - } - return oi; - } - template class Compare_y_to_right_2 { @@ -147,17 +133,12 @@ namespace CGAL { template class Equal_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 - : public - CircularKernel::Equal_2 -#endif + : public CircularKernel::Equal_2 { public: typedef boost::variant< Arc1, Arc2 > Curve_2; typedef bool result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CircularKernel::Equal_2::operator(); -#else typedef typename CircularKernel::Circular_arc_point_2 Circular_arc_point_2; typedef typename CircularKernel::Line_arc_2 Line_arc_2; @@ -185,8 +166,6 @@ namespace CGAL { operator() ( const Circular_arc_2 &a0, const Line_arc_2 &a1) const { return false; } -#endif - result_type operator()(const Curve_2 &a0, const Curve_2 &a1) const { @@ -259,6 +238,7 @@ namespace CGAL { }; + //! A functor for subdividing curves into x-monotone curves. template class Make_x_monotone_2 { @@ -268,20 +248,21 @@ namespace CGAL { template < class OutputIterator,class Not_X_Monotone > OutputIterator - operator()(const boost::variant &A, OutputIterator res) const + operator()(const boost::variant &A, + OutputIterator res) const { - if ( const Arc1* arc1 = boost::get( &A ) ){ + if ( const Arc1* arc1 = boost::get( &A ) ) { std::vector container; - CircularKernel() - .make_x_monotone_2_object()(*arc1,std::back_inserter(container)); + CircularKernel(). + make_x_monotone_2_object()(*arc1,std::back_inserter(container)); return object_to_object_variant (container, res); } else { const Arc2* arc2 = boost::get( &A ); std::vector container; - CircularKernel() - .make_x_monotone_2_object()(*arc2,std::back_inserter(container)); + CircularKernel(). + make_x_monotone_2_object()(*arc2,std::back_inserter(container)); return object_to_object_variant (container, res); } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h index cc26c045a84..45c3a903ea7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_conic_traits_2.h @@ -448,135 +448,127 @@ public: } //@} - /// \name Functor definitions for supporting intersections. + /// \name Intersections, subdivisions, and mergings //@{ - class Make_x_monotone_2 - { + /*! \class Make_x_monotone_2 + * A functor for subdividing curves into x-monotone curves. + */ + class Make_x_monotone_2 { typedef Arr_conic_traits_2 Self; - public: - /*! - * Cut the given conic curve (or conic arc) into x-monotone subcurves - * and insert them to the given output iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The returned - * objects are all wrappers X_monotone_curve_2 objects. - * \return The past-the-end iterator. + public: + /*! Subdivide a given conic curve (or conic arc) into x-monotone subcurves + * and insert them to a given output iterator. + * \param cv the curve. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return the past-the-end iterator. */ - template - OutputIterator operator() (const Curve_2& cv, OutputIterator oi) const + template + OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { + typedef boost::variant + Make_x_monotone_result; + // Increment the serial number of the curve cv, which will serve as its // unique identifier. - unsigned int index = Self::get_index(); - Conic_id conic_id (index); + auto index = Self::get_index(); + Conic_id conic_id(index); // Find the points of vertical tangency to cv and act accordingly. - typename Curve_2::Point_2 vtan_ps[2]; - int n_vtan_ps; + typename Curve_2::Point_2 vtan_ps[2]; + int n_vtan_ps; - n_vtan_ps = cv.vertical_tangency_points (vtan_ps); + n_vtan_ps = cv.vertical_tangency_points(vtan_ps); - if (n_vtan_ps == 0) - { + if (n_vtan_ps == 0) { // In case the given curve is already x-monotone: - *oi = make_object (X_monotone_curve_2 (cv, conic_id)); - ++oi; - return (oi); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, conic_id)); + return oi; } // Split the conic arc into x-monotone sub-curves. - if (cv.is_full_conic()) - { + if (cv.is_full_conic()) { // Make sure we have two vertical tangency points. CGAL_assertion(n_vtan_ps == 2); // In case the curve is a full conic, split it into two x-monotone // arcs, one going from ps[0] to ps[1], and the other from ps[1] to // ps[0]. - *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[0], vtan_ps[1], - conic_id)); - ++oi; - *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[1], vtan_ps[0], - conic_id)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[0], + vtan_ps[1], + conic_id)); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[1], + vtan_ps[0], + conic_id)); } - else - { - if (n_vtan_ps == 1) - { + else { + if (n_vtan_ps == 1) { // Split the arc into two x-monotone sub-curves: one going from the // arc source to ps[0], and the other from ps[0] to the target. - *oi = make_object (X_monotone_curve_2 (cv, cv.source(), vtan_ps[0], - conic_id)); - ++oi; - *oi = make_object (X_monotone_curve_2 (cv, vtan_ps[0], cv.target(), - conic_id)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, cv.source(), + vtan_ps[0], + conic_id)); + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, vtan_ps[0], + cv.target(), + conic_id)); } - else - { - CGAL_assertion (n_vtan_ps == 2); + else { + CGAL_assertion(n_vtan_ps == 2); // Identify the first point we encounter when going from cv's source // to its target, and the second point we encounter. Note that the // two endpoints must both be below the line connecting the two // tangnecy points (or both lies above it). - int ind_first = 0; - int ind_second = 1; - Alg_kernel_ ker; - typename Alg_kernel_::Line_2 line = - ker.construct_line_2_object() (vtan_ps[0], vtan_ps[1]); - const Comparison_result start_pos = + int ind_first = 0; + int ind_second = 1; + Alg_kernel_ ker; + typename Alg_kernel_::Line_2 line = + ker.construct_line_2_object()(vtan_ps[0], vtan_ps[1]); + const Comparison_result start_pos = ker.compare_y_at_x_2_object() (cv.source(), line); - const Comparison_result order_vpts = - ker.compare_x_2_object() (vtan_ps[0], vtan_ps[1]); + const Comparison_result order_vpts = + ker.compare_x_2_object()(vtan_ps[0], vtan_ps[1]); - CGAL_assertion (start_pos != EQUAL && - ker.compare_y_at_x_2_object() (cv.target(), - line) == start_pos); - CGAL_assertion (order_vpts != EQUAL); + CGAL_assertion(start_pos != EQUAL && + ker.compare_y_at_x_2_object()(cv.target(), + line) == start_pos); + CGAL_assertion(order_vpts != EQUAL); - if ((cv.orientation() == COUNTERCLOCKWISE && - start_pos == order_vpts) || - (cv.orientation() == CLOCKWISE && - start_pos != order_vpts)) + if (((cv.orientation() == COUNTERCLOCKWISE) && + (start_pos == order_vpts)) || + ((cv.orientation() == CLOCKWISE) && (start_pos != order_vpts))) { ind_first = 1; ind_second = 0; } // Split the arc into three x-monotone sub-curves. - *oi = make_object (X_monotone_curve_2 (cv, - cv.source(), - vtan_ps[ind_first], - conic_id)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, cv.source(), + vtan_ps[ind_first], + conic_id)); - *oi = make_object (X_monotone_curve_2 (cv, - vtan_ps[ind_first], - vtan_ps[ind_second], - conic_id)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, + vtan_ps[ind_first], + vtan_ps[ind_second], + conic_id)); - *oi = make_object (X_monotone_curve_2 (cv, - vtan_ps[ind_second], - cv.target(), - conic_id)); - ++oi; + *oi++ = Make_x_monotone_result(X_monotone_curve_2(cv, + vtan_ps[ind_second], + cv.target(), + conic_id)); } } - return (oi); + return oi; } }; /*! Get a Make_x_monotone_2 functor object. */ - Make_x_monotone_2 make_x_monotone_2_object () const - { - return Make_x_monotone_2(); - } + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(); } class Split_2 { 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 1babd65aba1..8f07fc7be36 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 @@ -101,120 +101,120 @@ public: } /*! Obtain the counter of the given operation */ - unsigned int count(Operation_id id) const + size_t count(Operation_id id) const { return m_counters[id]; } - unsigned int count_compare_x() const + size_t count_compare_x() const { return m_counters[COMPARE_X_OP]; } - unsigned int count_compare_xy() const + size_t count_compare_xy() const { return m_counters[COMPARE_XY_OP]; } - unsigned int count_construct_min_vertex() const + size_t count_construct_min_vertex() const { return m_counters[CONSTRUCT_MIN_VERTEX_OP]; } - unsigned int count_construct_max_vertex() const + size_t count_construct_max_vertex() const { return m_counters[CONSTRUCT_MAX_VERTEX_OP]; } - unsigned int count_is_vertical() const + size_t count_is_vertical() const { return m_counters[IS_VERTICAL_OP]; } - unsigned int count_compare_y_at_x() const + size_t count_compare_y_at_x() const { return m_counters[COMPARE_Y_AT_X_OP]; } - unsigned int count_equal_points() const + size_t count_equal_points() const { return m_counters[EQUAL_POINTS_OP]; } - unsigned int count_equal_curves() const + size_t count_equal_curves() const { return m_counters[EQUAL_CURVES_OP]; } - unsigned int count_compare_y_at_x_left() const + size_t count_compare_y_at_x_left() const { return m_counters[COMPARE_Y_AT_X_LEFT_OP]; } - unsigned int count_compare_y_at_x_right() const + size_t count_compare_y_at_x_right() const { return m_counters[COMPARE_Y_AT_X_RIGHT_OP]; } - unsigned int count_make_x_monotone() const + size_t count_make_x_monotone() const { return m_counters[MAKE_X_MONOTONE_OP]; } - unsigned int count_split() const + size_t count_split() const { return m_counters[SPLIT_OP]; } - unsigned int count_intersect() const + size_t count_intersect() const { return m_counters[INTERSECT_OP]; } - unsigned int count_are_mergeable() const + size_t count_are_mergeable() const { return m_counters[ARE_MERGEABLE_OP]; } - unsigned int count_merge() const + size_t count_merge() const { return m_counters[MERGE_OP]; } - unsigned int count_construct_opposite() const + size_t count_construct_opposite() const { return m_counters[CONSTRUCT_OPPOSITE_OP]; } - unsigned int count_compare_endpoints_xy() const + size_t count_compare_endpoints_xy() const { return m_counters[COMPARE_ENDPOINTS_XY_OP]; } // left-right - unsigned int count_parameter_space_in_x_curve_end() const + size_t count_parameter_space_in_x_curve_end() const { return m_counters[PARAMETER_SPACE_IN_X_CURVE_END_OP]; } - unsigned int count_parameter_space_in_x_curve() const + size_t count_parameter_space_in_x_curve() const { return m_counters[PARAMETER_SPACE_IN_X_CURVE_OP]; } - unsigned int count_parameter_space_in_x_point() const + size_t count_parameter_space_in_x_point() const { return m_counters[PARAMETER_SPACE_IN_X_POINT_OP]; } - unsigned int count_is_on_x_identification_point() const + size_t count_is_on_x_identification_point() const { return m_counters[IS_ON_X_IDENTIFICATION_POINT_OP]; } - unsigned int count_is_on_x_identification_curve() const + size_t count_is_on_x_identification_curve() const { return m_counters[IS_ON_X_IDENTIFICATION_CURVE_OP]; } - unsigned int count_compare_y_on_boundary() const + size_t count_compare_y_on_boundary() const { return m_counters[COMPARE_Y_ON_BOUNDARY_OP]; } - unsigned int count_compare_y_near_boundary() const + size_t count_compare_y_near_boundary() const { return m_counters[COMPARE_Y_NEAR_BOUNDARY_OP]; } // bottom-top - unsigned int count_parameter_space_in_y_curve_end() const + size_t count_parameter_space_in_y_curve_end() const { return m_counters[PARAMETER_SPACE_IN_Y_CURVE_END_OP]; } - unsigned int count_parameter_space_in_y_curve() const + size_t count_parameter_space_in_y_curve() const { return m_counters[PARAMETER_SPACE_IN_Y_CURVE_OP]; } - unsigned int count_parameter_space_in_y_point() const + size_t count_parameter_space_in_y_point() const { return m_counters[PARAMETER_SPACE_IN_Y_POINT_OP]; } - unsigned int count_is_on_y_identification_point() const + size_t count_is_on_y_identification_point() const { return m_counters[IS_ON_Y_IDENTIFICATION_POINT_OP]; } - unsigned int count_is_on_y_identification_curve() const + size_t count_is_on_y_identification_curve() const { return m_counters[IS_ON_Y_IDENTIFICATION_CURVE_OP]; } - unsigned int count_compare_x_at_limit_point_curve_end() const + size_t count_compare_x_at_limit_point_curve_end() const { return m_counters[COMPARE_X_AT_LIMIT_POINT_CURVE_END_OP]; } - unsigned int count_compare_x_at_limit_curve_ends() const + size_t count_compare_x_at_limit_curve_ends() const { return m_counters[COMPARE_X_AT_LIMIT_CURVE_ENDS_OP]; } - unsigned int count_compare_x_near_limit() const + size_t count_compare_x_near_limit() const { return m_counters[COMPARE_X_NEAR_LIMIT_OP]; } - unsigned int count_compare_x_on_boundary_points() const + size_t count_compare_x_on_boundary_points() const { return m_counters[COMPARE_X_ON_BOUNDARY_POINTS_OP]; } - unsigned int count_compare_x_on_boundary_point_curve_end() const + size_t count_compare_x_on_boundary_point_curve_end() const { return m_counters[COMPARE_X_ON_BOUNDARY_POINT_CURVE_END_OP]; } - unsigned int count_compare_x_on_boundary_curve_ends() const + size_t count_compare_x_on_boundary_curve_ends() const { return m_counters[COMPARE_X_ON_BOUNDARY_CURVE_ENDS_OP]; } - unsigned int count_compare_x_near_boundary() const + size_t count_compare_x_near_boundary() const { return m_counters[COMPARE_X_NEAR_BOUNDARY_OP]; } /// \name Types and functors inherited from the base @@ -242,11 +242,11 @@ public: class Compare_x_2 { private: typename Base::Compare_x_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_x_2(const Base* base, unsigned int& counter) : + Compare_x_2(const Base* base, size_t& counter) : m_object(base->compare_x_2_object()), m_counter(counter) {} /*! Operate */ @@ -258,11 +258,11 @@ public: class Compare_xy_2 { private: typename Base::Compare_xy_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_xy_2(const Base* base, unsigned int& counter) : + Compare_xy_2(const Base* base, size_t& counter) : m_object(base->compare_xy_2_object()), m_counter(counter) {} /*! Operate */ @@ -274,11 +274,11 @@ public: class Construct_min_vertex_2 { private: typename Base::Construct_min_vertex_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Construct_min_vertex_2(const Base* base, unsigned int& counter) : + Construct_min_vertex_2(const Base* base, size_t& counter) : m_object(base->construct_min_vertex_2_object()), m_counter(counter) {} /*! Operate */ @@ -290,11 +290,11 @@ public: class Construct_max_vertex_2 { private: typename Base::Construct_max_vertex_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Construct_max_vertex_2(const Base* base, unsigned int& counter) : + Construct_max_vertex_2(const Base* base, size_t& counter) : m_object(base->construct_max_vertex_2_object()), m_counter(counter) {} /*! Operate */ @@ -306,11 +306,11 @@ public: class Is_vertical_2 { private: typename Base::Is_vertical_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Is_vertical_2(const Base* base, unsigned int& counter) : + Is_vertical_2(const Base* base, size_t& counter) : m_object(base->is_vertical_2_object()), m_counter(counter) {} /*! Operate */ @@ -324,11 +324,11 @@ public: class Compare_y_at_x_2 { private: typename Base::Compare_y_at_x_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_y_at_x_2(const Base* base, unsigned int& counter) : + Compare_y_at_x_2(const Base* base, size_t& counter) : m_object(base->compare_y_at_x_2_object()), m_counter(counter) {} /*! Operate */ @@ -343,12 +343,12 @@ public: class Equal_2 { private: typename Base::Equal_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; + size_t& m_counter1; + size_t& m_counter2; public: /*! Construct */ - Equal_2(const Base* base, unsigned int& counter1, unsigned int& counter2) : + Equal_2(const Base* base, size_t& counter1, size_t& counter2) : m_object(base->equal_2_object()), m_counter1(counter1), m_counter2(counter2) {} @@ -369,11 +369,11 @@ public: class Compare_y_at_x_left_2 { private: typename Base::Compare_y_at_x_left_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_y_at_x_left_2(const Base* base, unsigned int& counter) : + Compare_y_at_x_left_2(const Base* base, size_t& counter) : m_object(base->compare_y_at_x_left_2_object()), m_counter(counter) {} /*! Operate */ @@ -389,11 +389,11 @@ public: class Compare_y_at_x_right_2 { private: typename Base::Compare_y_at_x_right_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_y_at_x_right_2(const Base* base, unsigned int& counter) : + Compare_y_at_x_right_2(const Base* base, size_t& counter) : m_object(base->compare_y_at_x_right_2_object()), m_counter(counter) {} /*! Operate */ @@ -403,19 +403,27 @@ public: { ++m_counter; return m_object(xc1, xc2, p); } }; - /*! A functor that divides a curve into x-monotone curves. */ + /*! \class Make_x_monotone_2 + * A functor that subdivides a curve into x-monotone curves. + */ class Make_x_monotone_2 { private: typename Base::Make_x_monotone_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Make_x_monotone_2(const Base* base, unsigned int& counter) : + Make_x_monotone_2(const Base* base, size_t& counter) : m_object(base->make_x_monotone_2_object()), m_counter(counter) {} - /*! Operate */ - template + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. + * \param cv the curve. + * \param oi the output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return The past-the-end iterator. + */ + template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { ++m_counter; return m_object(cv, oi); } }; @@ -424,11 +432,11 @@ public: class Split_2 { private: typename Base::Split_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Split_2(const Base* base, unsigned int& counter) : + Split_2(const Base* base, size_t& counter) : m_object(base->split_2_object()), m_counter(counter) {} /*! Operate */ @@ -441,11 +449,11 @@ public: class Intersect_2 { private: typename Base::Intersect_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Intersect_2(const Base* base, unsigned int& counter) : + Intersect_2(const Base* base, size_t& counter) : m_object(base->intersect_2_object()), m_counter(counter) {} /*! Operate */ @@ -460,11 +468,11 @@ public: class Are_mergeable_2 { private: typename Base::Are_mergeable_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Are_mergeable_2(const Base* base, unsigned int& counter) : + Are_mergeable_2(const Base* base, size_t& counter) : m_object(base->are_mergeable_2_object()), m_counter(counter) {} /*! Operate */ @@ -477,11 +485,11 @@ public: class Merge_2 { private: typename Base::Merge_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Merge_2(const Base* base, unsigned int& counter) : + Merge_2(const Base* base, size_t& counter) : m_object(base->merge_2_object()), m_counter(counter) {} /*! Operate */ @@ -495,11 +503,11 @@ public: class Construct_opposite_2 { private: typename Base::Construct_opposite_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Construct_opposite_2(const Base* base, unsigned int& counter) : + Construct_opposite_2(const Base* base, size_t& counter) : m_object(base->construct_opposite_2_object()), m_counter(counter) {} /*! Operate */ @@ -513,11 +521,11 @@ public: class Compare_endpoints_xy_2 { private: typename Base::Compare_endpoints_xy_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_endpoints_xy_2(const Base* base, unsigned int& counter) : + Compare_endpoints_xy_2(const Base* base, size_t& counter) : m_object(base->compare_endpoints_xy_2_object()), m_counter(counter) {} /*! Operate */ @@ -533,14 +541,14 @@ public: class Parameter_space_in_x_2 { private: typename Base::Parameter_space_in_x_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; - unsigned int& m_counter3; + size_t& m_counter1; + size_t& m_counter2; + size_t& m_counter3; public: /*! Construct */ - Parameter_space_in_x_2(const Base* base, unsigned int& counter1, - unsigned int& counter2, unsigned int& counter3) : + Parameter_space_in_x_2(const Base* base, size_t& counter1, + size_t& counter2, size_t& counter3) : m_object(base->parameter_space_in_x_2_object()), m_counter1(counter1), m_counter2(counter2), @@ -569,13 +577,13 @@ public: class Is_on_x_identification_2 { private: typename Base::Is_on_x_identificiation_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; + size_t& m_counter1; + size_t& m_counter2; public: /*! Construct */ Is_on_x_identification_2(const Base* base, - unsigned int& counter1, unsigned int& counter2) : + size_t& counter1, size_t& counter2) : m_object(base->is_on_x_identificiation_2_object()), m_counter1(counter1), m_counter2(counter2) {} @@ -597,11 +605,11 @@ public: class Compare_y_on_boundary_2 { private: typename Base::Compare_y_on_boundary_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_y_on_boundary_2(const Base* base, unsigned int& counter) : + Compare_y_on_boundary_2(const Base* base, size_t& counter) : m_object(base->compare_y_on_boundary_2_object()), m_counter(counter) {} @@ -617,11 +625,11 @@ public: class Compare_y_near_boundary_2 { private: typename Base::Compare_y_near_boundary_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_y_near_boundary_2(const Base* base, unsigned int& counter) : + Compare_y_near_boundary_2(const Base* base, size_t& counter) : m_object(base->compare_y_near_boundary_2_object()), m_counter(counter) {} /*! Operate */ @@ -639,14 +647,14 @@ public: class Parameter_space_in_y_2 { private: typename Base::Parameter_space_in_y_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; - unsigned int& m_counter3; + size_t& m_counter1; + size_t& m_counter2; + size_t& m_counter3; public: /*! Construct */ - Parameter_space_in_y_2(const Base* base, unsigned int& counter1, - unsigned int& counter2, unsigned int& counter3) : + Parameter_space_in_y_2(const Base* base, size_t& counter1, + size_t& counter2, size_t& counter3) : m_object(base->parameter_space_in_y_2_object()), m_counter1(counter1), m_counter2(counter2), @@ -673,13 +681,13 @@ public: class Is_on_y_identification_2 { private: typename Base::Is_on_y_identificiation_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; + size_t& m_counter1; + size_t& m_counter2; public: /*! Construct */ Is_on_y_identification_2(const Base* base, - unsigned int& counter1, unsigned int& counter2) : + size_t& counter1, size_t& counter2) : m_object(base->is_on_y_identificiation_2_object()), m_counter1(counter1), m_counter2(counter2) {} @@ -701,13 +709,13 @@ public: class Compare_x_at_limit_2 { private: typename Base::Compare_x_at_limit_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; + size_t& m_counter1; + size_t& m_counter2; public: /*! Construct */ Compare_x_at_limit_2(const Base* base, - unsigned int& counter1, unsigned int& counter2) : + size_t& counter1, size_t& counter2) : m_object(base->compare_x_at_limit_2_object()), m_counter1(counter1), m_counter2(counter2) {} @@ -733,11 +741,11 @@ public: class Compare_x_near_limit_2 { private: typename Base::Compare_x_near_limit_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ - Compare_x_near_limit_2(const Base* base, unsigned int& counter) : + Compare_x_near_limit_2(const Base* base, size_t& counter) : m_object(base->compare_x_near_limit_2_object()), m_counter(counter) {} @@ -755,14 +763,14 @@ public: class Compare_x_on_boundary_2 { private: typename Base::Compare_x_on_boundary_2 m_object; - unsigned int& m_counter1; - unsigned int& m_counter2; - unsigned int& m_counter3; + size_t& m_counter1; + size_t& m_counter2; + size_t& m_counter3; public: /*! Construct */ - Compare_x_on_boundary_2(const Base* base, unsigned int& counter1, - unsigned int& counter2, unsigned int& counter3 ) : + Compare_x_on_boundary_2(const Base* base, size_t& counter1, + size_t& counter2, size_t& counter3 ) : m_object(base->compare_x_on_boundary_2_object()), m_counter1(counter1), m_counter2(counter2), @@ -794,12 +802,12 @@ public: class Compare_x_near_boundary_2 { private: typename Base::Compare_x_near_boundary_2 m_object; - unsigned int& m_counter; + size_t& m_counter; public: /*! Construct */ Compare_x_near_boundary_2(const Base* base, - unsigned int& counter) : + size_t& counter) : m_object(base->compare_x_near_boundary_2_object()), m_counter(counter) {} @@ -945,12 +953,12 @@ public: * \param doit indicates whethet to actually inceremnt the counter or not * \return the counter at the end of the operation */ - static unsigned int increment(bool doit = true) + static size_t increment(bool doit = true) { #ifdef CGAL_NO_ATOMIC - static unsigned int counter; + static size_t counter; #else - static CGAL::cpp11::atomic counter; + static CGAL::cpp11::atomic counter; #endif if (doit) ++counter; return counter; @@ -962,7 +970,7 @@ public: private: /*! The operation counters */ - mutable unsigned int m_counters[NUMBER_OF_OPERATIONS]; + mutable size_t m_counters[NUMBER_OF_OPERATIONS]; }; template @@ -971,8 +979,8 @@ Out_stream& operator<<(Out_stream& os, const Arr_counting_traits_2& traits) { typedef Arr_counting_traits_2 Traits; - unsigned int sum = 0; - unsigned int i; + size_t sum = 0; + size_t i; for (i = 0; i < Traits::NUMBER_OF_OPERATIONS; ++i) sum += traits.count(static_cast(i)); os << "# of COMPARE_X operation = " diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h index 7ed8e459334..ca8413d47ad 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_curve_data_traits_2.h @@ -27,8 +27,8 @@ #include #include -#include #include +#include #include #include @@ -101,6 +101,12 @@ public: /// \name Overriden functors. //@{ + //! \name Intersections & subdivisions + //@{ + + /*! \class Make_x_monotone_2 + * A functor for subdividing a curve into x-monotone curves. + */ class Make_x_monotone_2 { private: const Base_traits_2& m_base; @@ -109,36 +115,36 @@ public: /*! Constructor. */ Make_x_monotone_2(const Base_traits_2& base) : m_base(base) {} - /*! Cut the given curve into x-monotone subcurves and insert them to the - * given output iterator. As segments are always x_monotone, only one - * x-monotone curve will be contained in the iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is X_monotone_curve_2. - * \return The past-the-end iterator. + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. + * \param cv the curve. + * \param oi the output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return the past-the-end iterator. */ - template + template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { + typedef boost::variant + Base_make_x_monotone_result; + typedef boost::variant + Make_x_monotone_result; + // Make the original curve x-monotone. - std::list base_objects; + std::list base_objects; m_base.make_x_monotone_2_object()(cv, std::back_inserter(base_objects)); // Attach the data to each of the resulting x-monotone curves. - const Base_x_monotone_curve_2* base_x_curve; X_monotone_curve_data xdata = Convert()(cv.data()); - for (typename std::list::const_iterator it = - base_objects.begin(); it != base_objects.end(); ++it) - { - base_x_curve = object_cast(&(*it)); - if (base_x_curve != nullptr) { - // Current object is an x-monotone curve: Attach data to it. - *oi++ = make_object(X_monotone_curve_2(*base_x_curve, xdata)); - } - else { - // Current object is an isolated point: Leave it as is. - CGAL_assertion(object_cast(&(*it)) != nullptr); - *oi++ = *it; + for (const auto& base_obj : base_objects) { + if (const auto* bxcv = boost::get(&base_obj)) { + *oi++ = Make_x_monotone_result(X_monotone_curve_2(*bxcv, xdata)); + continue; } + // Current object is an isolated point: Leave it as is. + const auto* bp = boost::get(&base_obj); + CGAL_assertion(bp); + *oi++ = Make_x_monotone_result(*bp); } return oi; @@ -359,6 +365,8 @@ public: /*! Obtain a Merge_2 functor object. */ Merge_2 merge_2_object() const { return Merge_2(*this); } + //@} + class Construct_x_monotone_curve_2 { private: const Base_traits_2& m_base; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h index 3855dee3c67..cf0b22dddd0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geodesic_arc_on_sphere_traits_2.h @@ -1358,8 +1358,9 @@ public: /// \name Functor definitions for supporting intersections. //@{ - /*! A functor that divides an arc into x-monotone arcs. That are, arcs that - * do not cross the identification arc. + /*! \class Make_x_monotone_2 + * A functor for subdividing arcs into x-monotone arcs that do not cross the + * identification arc. */ class Make_x_monotone_2 { protected: @@ -1376,21 +1377,24 @@ public: friend class Arr_geodesic_arc_on_sphere_traits_2; public: - /*! Cut the given curve into x-monotone subcurves and insert them into the - * given output iterator. As spherical_arcs are always x_monotone, only one - * object will be contained in the iterator. + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. As spherical_arcs are always x_monotone, only + * one object will be contained in the iterator. * \param xc the curve. - * \param oi the output iterator, whose value-type is Object. The output - * object is a wrapper of either an X_monotone_curve_2, or - in - * case the input spherical_arc is degenerate - a Point_2 object. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. * \return the past-the-end iterator. */ - template + template OutputIterator operator()(const Curve_2& c, OutputIterator oi) const { + typedef boost::variant + Make_x_monotone_result; + if (c.is_degenerate()) { // The spherical_arc is a degenerate point - wrap it with an object: - *oi++ = make_object(c.right()); + *oi++ = Make_x_monotone_result(c.right()); return oi; } @@ -1398,7 +1402,7 @@ public: // The spherical arc is monotone - wrap it with an object: // *oi++ = make_object(X_monotone_curve_2(c)); const X_monotone_curve_2* xc = &c; - *oi++ = make_object(*xc); + *oi++ = Make_x_monotone_result(*xc); return oi; } @@ -1410,14 +1414,14 @@ public: const Direction_3& pp = m_traits->pos_pole(); X_monotone_curve_2 xc1(np, pp, c.normal(), true, true); X_monotone_curve_2 xc2(pp, np, c.normal(), true, false); - *oi++ = make_object(xc1); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc1); + *oi++ = Make_x_monotone_result(xc2); return oi; } #if defined(CGAL_FULL_X_MONOTONE_GEODESIC_ARC_ON_SPHERE_IS_SUPPORTED) // The arc is not vertical => break it at the discontinuity arc: const X_monotone_curve_2 xc(c.normal()); - *oi++ = make_object(xc); + *oi++ = Make_x_monotone_result(xc); #else // Full x-monotone arcs are not supported! // Split the arc at the intersection point with the complement of the @@ -1428,8 +1432,8 @@ public: Direction_3 d2(normal.dz(), 0, -(normal.dx())); X_monotone_curve_2 xc1(d1, d2, normal, false, directed_right); X_monotone_curve_2 xc2(d2, d1, normal, false, directed_right); - *oi++ = make_object(xc1); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc1); + *oi++ = Make_x_monotone_result(xc2); #endif return oi; } @@ -1447,16 +1451,16 @@ public: if (source.is_min_boundary() || target.is_min_boundary()) { X_monotone_curve_2 xc1(source, pp, normal, true, true); X_monotone_curve_2 xc2(pp, target, normal, true, false); - *oi++ = make_object(xc1); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc1); + *oi++ = Make_x_monotone_result(xc2); return oi; } if (source.is_max_boundary() || target.is_max_boundary()) { X_monotone_curve_2 xc1(source, np, normal, true, false); X_monotone_curve_2 xc2(np, target, normal, true, true); - *oi++ = make_object(xc1); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc1); + *oi++ = Make_x_monotone_result(xc2); return oi; } @@ -1476,19 +1480,19 @@ public: (!plane_is_positive && !s_is_positive)); const Point_2& pole1 = (ccw) ? pp : np; X_monotone_curve_2 xc1(source, pole1, normal, true, ccw); - *oi++ = make_object(xc1); + *oi++ = Make_x_monotone_result(xc1); if (s_is_positive != t_is_positive) { // Construct 1 more arc: X_monotone_curve_2 xc2(pole1, target, normal, true, !ccw); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc2); return oi; } // Construct 2 more arcs: const Point_2& pole2 = (ccw) ? np : pp; X_monotone_curve_2 xc2(pole1, pole2, normal, true, !ccw); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc2); X_monotone_curve_2 xc3(pole2, target, normal, true, ccw); - *oi++ = make_object(xc3); + *oi++ = Make_x_monotone_result(xc3); return oi; } @@ -1514,8 +1518,8 @@ public: X_monotone_curve_2 xc1(source, p, normal, false, directed_right); X_monotone_curve_2 xc2(p, target, normal, false, directed_right); - *oi++ = make_object(xc1); - *oi++ = make_object(xc2); + *oi++ = Make_x_monotone_result(xc1); + *oi++ = Make_x_monotone_result(xc2); return oi; } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Arr_plane_3.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Arr_plane_3.h index ebfc5cef09b..7680e01d93a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Arr_plane_3.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Arr_plane_3.h @@ -197,49 +197,51 @@ public: /*! Intersect 2 planes * \param plane1 the first plane * \param plane2 the second plane - * \return a geometric object that represents the intersection. Could be - * the line of intersection, or a plane in case plane1 and plane2 coincide. + * \return a variant that represents the intersection. It wraps a line of + * intersection or a plane in case plane1 and plane2 coincide. */ -template -CGAL::Object intersect(const Arr_plane_3 & plane1, +template +boost::variant > +intersect(const Arr_plane_3 & plane1, const Arr_plane_3 & plane2) { typedef typename Kernel::Point_3 Point_3; typedef typename Kernel::Direction_3 Direction_3; typedef typename Kernel::Line_3 Line_3; typedef typename Kernel::FT FT; + typedef boost::variant > Intersection_result; // We know that the plane goes throgh the origin - const FT & a1 = plane1.a(); - const FT & b1 = plane1.b(); - const FT & c1 = plane1.c(); + const FT& a1 = plane1.a(); + const FT& b1 = plane1.b(); + const FT& c1 = plane1.c(); - const FT & a2 = plane2.a(); - const FT & b2 = plane2.b(); - const FT & c2 = plane2.c(); + const FT& a2 = plane2.a(); + const FT& b2 = plane2.b(); + const FT& c2 = plane2.c(); FT det = a1*b2 - a2*b1; if (det != 0) { Point_3 is_pt = Point_3(0, 0, 0, det); Direction_3 is_dir = Direction_3(b1*c2 - c1*b2, a2*c1 - a1*c2, det); - return make_object(Line_3(is_pt, is_dir)); + return Intersection_result(Line_3(is_pt, is_dir)); } det = a1*c2 - a2*c1; if (det != 0) { Point_3 is_pt = Point_3(0, 0, 0, det); Direction_3 is_dir = Direction_3(c1*b2 - b1*c2, det, a2*b1 - a1*b2); - return make_object(Line_3(is_pt, is_dir)); + return Intersection_result(Line_3(is_pt, is_dir)); } det = b1*c2 - c1*b2; if (det != 0) { Point_3 is_pt = Point_3(0, 0, 0, det); Direction_3 is_dir = Direction_3(det, c1*a2 - a1*c2, a1*b2 - b1*a2); - return make_object(Line_3(is_pt, is_dir)); + return Intersection_result(Line_3(is_pt, is_dir)); } // degenerate case - return make_object(plane1); + return Intersection_result(plane1); } /*! Compute the image point of the projection of p under an affine diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_bounding_rational_traits.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_bounding_rational_traits.h index 761710d8a89..bc7831ee95f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_bounding_rational_traits.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_bounding_rational_traits.h @@ -1262,36 +1262,26 @@ private: // the intersection of the two skewed bounding boxes. Bez_point_bbox ipt_bbox; Control_points aux_vec; - CGAL::Object res; - Point_2 p; - res = f_intersect (skew1a, skew2a); - if (! assign (p, res)) - { - CGAL_error(); - } - aux_vec.push_back(p); + auto res1 = f_intersect(skew1a, skew2a); + const Point_2* p1 = boost::get(&*res1); + if (! p1) CGAL_error(); + aux_vec.push_back(*p1); - res = f_intersect (skew1a, skew2b); - if (! assign(p, res)) - { - CGAL_error(); - } - aux_vec.push_back(p); + auto res2 = f_intersect(skew1a, skew2b); + const Point_2* p2 = boost::get(&*res2); + if (! p2) CGAL_error(); + aux_vec.push_back(*p2); - res = f_intersect (skew1b, skew2a); - if (! assign(p, res)) - { - CGAL_error(); - } - aux_vec.push_back(p); + auto res3 = f_intersect(skew1b, skew2a); + const Point_2* p3 = boost::get(&*res3); + if (! p3) CGAL_error(); + aux_vec.push_back(*p3); - res = f_intersect (skew1b, skew2b); - if (!assign(p, res)) - { - CGAL_error(); - } - aux_vec.push_back(p); + auto res4 = f_intersect (skew1b, skew2b); + const Point_2* p4 = boost::get(&*res4); + if (! p4) CGAL_error(); + aux_vec.push_back(*p4); construct_bbox (aux_vec, ipt_bbox); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_line_arc_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_line_arc_traits_2.h index b48cad3da36..20ccbe9c758 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_line_arc_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_line_arc_traits_2.h @@ -27,6 +27,10 @@ * Arrangement_2 package, which it is now part of. It contains a traits * class for the arrangement package that handles linear curves. * It is based on the circular kernel. + * + * \todo Fix the circular-kernel make-x-monotone functor to use modern variant + * instead of the legacy CGAL::Object. Then, eliminate the special + * implementation here and directly use the kernel functor instead. */ #include @@ -73,7 +77,7 @@ public: typedef typename CircularKernel::Compare_y_at_x_2 Compare_y_at_x_2; typedef typename CircularKernel::Compare_y_to_right_2 Compare_y_at_x_right_2; typedef typename CircularKernel::Equal_2 Equal_2; - typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2; + // typedef typename CircularKernel::Make_x_monotone_2 Make_x_monotone_2; typedef typename CircularKernel::Split_2 Split_2; typedef typename CircularKernel::Construct_circular_min_vertex_2 Construct_min_vertex_2; @@ -97,8 +101,8 @@ public: Equal_2 equal_2_object() const { return ck.equal_2_object(); } - Make_x_monotone_2 make_x_monotone_2_object() const - { return ck.make_x_monotone_2_object(); } + // Make_x_monotone_2 make_x_monotone_2_object() const + // { return ck.make_x_monotone_2_object(); } Split_2 split_2_object() const { return ck.split_2_object(); } @@ -115,7 +119,20 @@ public: Is_vertical_2 is_vertical_2_object() const { return ck.is_vertical_2_object();} + //! A functor for subdividing curves into x-monotone curves. + class Make_x_monotone_2 { + public: + template + OutputIterator operator()(const Curve_2& line, OutputIterator oi) const + { + typedef boost::variant Make_x_monotone_result; + *oi++ = Make_x_monotone_result(line); + return oi; + } + }; + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(); } }; } // namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h index 3fe62601378..7d6b3fcbb23 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_linear_traits_2.h @@ -1239,16 +1239,18 @@ public: * given output iterator. As segments are always x_monotone, only one * object will be contained in the iterator. * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The output - * object is a wrapper of an X_monotone_curve_2 which is - * essentially the same as the input curve. + * \param oi an output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. * \return The past-the-end iterator. */ template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - // Wrap the curve with an object. - *oi++ = make_object(cv); + // Wrap the segment with a variant. + typedef boost::variant + Make_x_monotone_result; + *oi++ = Make_x_monotone_result(cv); return oi; } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h index ac2220a2b5f..1190c3e1085 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_basic_traits_2.h @@ -7,14 +7,14 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Ron Wein -// (based on old version by: Iddo Hanniel, -// Eyal Flato, -// Oren Nechushtan, -// Ester Ezra, -// Shai Hirsch, -// and Eugene Lipovetsky) +// Author(s): Efi Fogel +// Ron Wein +// (based on old version by: Iddo Hanniel, +// Eyal Flato, +// Oren Nechushtan, +// Ester Ezra, +// Shai Hirsch, +// and Eugene Lipovetsky) #ifndef CGAL_ARR_NON_CACHING_SEGMENT_BASIC_TRAITS_2_H #define CGAL_ARR_NON_CACHING_SEGMENT_BASIC_TRAITS_2_H diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h index 3df642ba1e7..81852fe41ea 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_non_caching_segment_traits_2.h @@ -113,24 +113,27 @@ public: // Traits types: typedef X_monotone_curve_2 Curve_2; - /*! \class - * A functor for splitting curves into x-monotone pieces. + /*! \class Make_x_monotone_2 + * A functor for subdividing a curve into x-monotone curves. */ class Make_x_monotone_2 { public: - - /*! Cut the given segment into x-monotone subcurves and insert them into - * the given output iterator. As segments are always x_monotone, only one + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. As segments are always x_monotone, only one * x-monotone curve is inserted into the output iterator. - * \param cv The segment. - * \param oi The output iterator, whose value-type is Object. The output - * object is a wrapper of an X_monotone_curve_2 object. - * \return The past-the-end iterator. + * \param cv the segment. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return the past-the-end iterator. */ template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - *oi++ = make_object(cv); + // Wrap the segment with a variant. + typedef boost::variant + Make_x_monotone_result; + *oi++ = Make_x_monotone_result(cv); return oi; } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_batched_point_location_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_batched_point_location_traits_2.h index 103f47c670c..208ff208cfc 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_batched_point_location_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_batched_point_location_traits_2.h @@ -42,6 +42,7 @@ public: typedef typename Base_traits_2::X_monotone_curve_2 Base_x_monotone_curve_2; typedef typename Base_traits_2::Point_2 Base_point_2; + typedef typename Base_traits_2::Multiplicity Multiplicity; typedef typename Base_traits_2::Construct_min_vertex_2 Base_construct_min_vertex_2; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_landmarks_pl_impl.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_landmarks_pl_impl.h index eb9679a8883..0a6fbc736b7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_landmarks_pl_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_landmarks_pl_impl.h @@ -56,15 +56,15 @@ Arr_landmarks_point_location::locate(const Point_2& p) const const Vertex_const_handle* vh; const Halfedge_const_handle* hh; const Face_const_handle* fh; - if ( ( vh = Result().template assign(lm_location_obj) ) ) + if ( ( vh = Result().template assign(&lm_location_obj) ) ) out_obj = _walk_from_vertex(*vh, p, crossed_edges); - else if ( ( hh = Result().template assign(lm_location_obj) ) ) + else if ( ( hh = Result().template assign(&lm_location_obj) ) ) out_obj = _walk_from_edge(*hh, landmark_point, p, crossed_edges); - else if ( ( fh = Result().template assign(lm_location_obj) ) ) + else if ( ( fh = Result().template assign(&lm_location_obj) ) ) out_obj = _walk_from_face(*fh, landmark_point, p, crossed_edges); else CGAL_error_msg("lm_location_obj of an unknown type."); - if ( ( fh = Result().template assign(out_obj) ) ) { + if ( ( fh = Result().template assign(&out_obj) ) ) { // If we reached here, we did not locate the query point in any of the // holes inside the current face, so we conclude it is contained in this // face. @@ -159,7 +159,7 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex, if (new_vertex) { // We found a vertex closer to p; Continue using this vertex. const Vertex_const_handle* p_vh = - Result().template assign(obj); + Result().template assign(&obj); CGAL_assertion(p_vh != nullptr); vh = *p_vh; continue; @@ -167,11 +167,12 @@ _walk_from_vertex(Vertex_const_handle nearest_vertex, // If p is located on an edge or on a vertex, return the object // that wraps this arrangement feature. - if (Result().template assign(obj) || - Result().template assign(obj)) + if (Result().template assign(&obj) || + Result().template assign(&obj)) return obj; - const Face_const_handle* p_fh = Result().template assign(obj); + const Face_const_handle* p_fh = + Result().template assign(&obj); if (p_fh) // Walk to p from the face we have located: return _walk_from_face(*p_fh, vh->point(), p, crossed_edges); diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_simple_point_location_impl.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_simple_point_location_impl.h index 6b0820da97e..a5980967cb4 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_simple_point_location_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_simple_point_location_impl.h @@ -44,10 +44,8 @@ Arr_simple_point_location::locate(const Point_2& p) const // Go over arrangement halfedges and check whether one of them contains // the query point in its interior. - typename Traits_adaptor_2::Is_in_x_range_2 is_in_x_range = - m_geom_traits->is_in_x_range_2_object(); - typename Traits_adaptor_2::Compare_y_at_x_2 cmp_y_at_x = - m_geom_traits->compare_y_at_x_2_object(); + auto is_in_x_range = m_geom_traits->is_in_x_range_2_object(); + auto cmp_y_at_x = m_geom_traits->compare_y_at_x_2_object(); typename Arrangement::Edge_const_iterator eit; for (eit = m_arr->edges_begin(); eit != m_arr->edges_end(); ++eit) { @@ -71,14 +69,14 @@ Arr_simple_point_location::locate(const Point_2& p) const // In case the ray-shooting returned a vertex, we have to locate the first // halfedge whose source vertex is v, rotating clockwise around the vertex // from "6 o'clock", and to return its incident face. - const Vertex_const_handle* vh = Result().template assign(obj); + const auto* vh = Result::template assign(&obj); if (vh) { Halfedge_const_handle hh = _first_around_vertex(*vh); Face_const_handle fh = hh->face(); return make_result(fh); } - const Halfedge_const_handle* hh = Result().template assign(obj); + const auto* hh = Result::template assign(&obj); if (hh) { // Make sure that the edge is directed from right to left, so that p // (which lies below it) is contained in its incident face. If necessary, @@ -288,14 +286,13 @@ Arr_simple_point_location::_vertical_ray_shoot(const Point_2& p, if (! optional_empty(optional_obj)) { const Result_type& obj = optional_assign(optional_obj); - const Vertex_const_handle* p_vh = Result().template assign(obj); + const auto* p_vh = Result::template assign(&obj); if (p_vh) { found_vertex = true; closest_v = *p_vh; } else { - const Halfedge_const_handle* p_hh = - Result().template assign(obj); + const auto* p_hh = Result::template assign(&obj); CGAL_assertion(p_hh != nullptr); found_halfedge = true; closest_he = *p_hh; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h index c8971c5d1eb..7b2cc3ffd9b 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Arr_walk_along_line_pl_impl.h @@ -618,7 +618,8 @@ _is_in_connected_component (const Point_2& p, // The current curve is not vertical. Check the query point is in the // semi-open x-range (source, target] of this curve and lies below it. if (source_res != EQUAL) { - if (closest_he == invalid_he || (closest_he->twin() == curr)) { + if ((closest_he == invalid_he) || + (closest_he->twin() == Halfedge_const_handle(curr))) { // 1. If we have no closests halfedge, we have just found one. // 2. If the closest halfedge is the twin of our current halfedge, // we can take our halfedge to be the closest one. This covers the @@ -701,7 +702,7 @@ _is_in_connected_component (const Point_2& p, do { next_non_vert = next_non_vert->next(); - CGAL_assertion (next_non_vert != curr); + CGAL_assertion(next_non_vert != Halfedge_const_handle(curr)); } while ((! next_non_vert->is_fictitious() && is_vertical(next_non_vert->curve())) || diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location_result.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location_result.h index 33aeb50201b..1fae9de1d30 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location_result.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location_result.h @@ -78,32 +78,34 @@ struct Arr_point_location_result { // lead to conversion overhead, and so we rather go for the real type. // Overloads for empty returns are also provided. #if CGAL_ARR_POINT_LOCATION_VERSION < 2 - template + template static - inline CGAL::Object make_result(T t) { return CGAL::make_object(t); } + inline Type make_result(T t) { return CGAL::make_object(t); } static inline CGAL::Object empty_optional_result() { return CGAL::Object(); } - template - const T* assign(CGAL::Object obj) const { return CGAL::object_cast(&obj); } + template + static + inline const T* assign(const Type* obj) { return CGAL::object_cast(obj); } #else - template + template static inline Type make_result(T t) { return Type(t); } - inline static - boost::optional empty_optional_result() { return boost::optional(); } + inline boost::optional empty_optional_result() + { return boost::optional(); } - template - const T* assign(const Type& obj) const { return boost::get(&obj); } + template + static + inline const T* assign(const Type* obj) { return boost::get(obj); } #endif // CGAL_ARR_POINT_LOCATION_VERSION < 2 //this one is only to remove warnings in functions static inline Type default_result(){ - CGAL_error_msg("This functions should never have been called!"); + CGAL_error_msg("This functions should have never been called!"); return Type(); } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h index fa5475f7e0c..2ddca1a1809 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_basic_traits_2.h @@ -63,6 +63,7 @@ public: typedef typename Subcurve_traits_2::Point_2 Point_2; typedef typename Subcurve_traits_2::X_monotone_curve_2 X_monotone_subcurve_2; + typedef typename Subcurve_traits_2::Multiplicity Multiplicity; //@} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h index 5d430ebcafc..1adc9169184 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_polycurve_traits_2.h @@ -7,10 +7,10 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Ron Wein -// Dror Atariah -// Waqar Khan +// Author(s): Efi Fogel +// Ron Wein +// Dror Atariah +// Waqar Khan #ifndef CGAL_ARR_POLYCURVE_TRAITS_2_H #define CGAL_ARR_POLYCURVE_TRAITS_2_H @@ -160,10 +160,8 @@ public: #ifndef DOXYGEN_RUNNING class Push_back_2; #endif - /*! \class - * A functor that divides an arc into x-monotone arcs. That are, arcs that - * do not cross the identification arc. - */ + + //! A functor for subdividing curves into x-monotone curves. class Make_x_monotone_2 { protected: typedef Arr_polycurve_traits_2 Polycurve_traits_2; @@ -176,21 +174,24 @@ public: m_poly_traits(traits) {} - /*! Cut the given curve into x-monotone sub-curves and insert them into the - * given output iterator. + /*! Subdivide a given curve into x-monotone sub-curves and insert them into + * a given output iterator. * * \pre if `cv` is not empty then it must be continuous and well-oriented. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The output - * object is a wrapper of a X_monotone_curve_2. - * \return The past-the-end iterator. + * \param cv the curve. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or an X_monotone_curve_2 objects. + * \return the past-the-end iterator. */ private: template OutputIterator operator_impl(const Curve_2& cv, OutputIterator oi, Arr_all_sides_oblivious_tag) const { - typedef typename Curve_2::Subcurve_const_iterator const_seg_iterator; + typedef boost::variant + Make_x_monotone_subresult; + typedef boost::variant + Make_x_monotone_result; // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; @@ -204,33 +205,29 @@ public: m_poly_traits.subcurve_traits_2()->compare_endpoints_xy_2_object(); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - typename Subcurve_traits_2::Construct_opposite_2 ctr_seg_opposite = + auto ctr_seg_opposite = m_poly_traits.subcurve_traits_2()->construct_opposite_2_object(); #endif - // Convert the input polycurve to a sequence of CGAL objects, such - // that each Object wraps an x-monotone subcurve. - std::vector x_seg_objects; - const_seg_iterator it_segs; - for (it_segs = cv.subcurves_begin(); it_segs != cv.subcurves_end(); - ++it_segs) - make_seg_x_monotone(*it_segs, std::back_inserter(x_seg_objects)); - typename std::vector::iterator it = x_seg_objects.begin(); - X_monotone_subcurve_2 x_seg; -#if defined (CGAL_NO_ASSERTIONS) - CGAL::assign(x_seg, *it); -#else - bool assign_res = CGAL::assign(x_seg, *it); - CGAL_assertion(assign_res); + // Convert the input polycurve to a sequence of variant objects, such + // that each object wraps an x-monotone subcurve. + std::vector x_seg_objects; + for (auto its = cv.subcurves_begin(); its != cv.subcurves_end(); ++its) + make_seg_x_monotone(*its, std::back_inserter(x_seg_objects)); + auto it = x_seg_objects.begin(); + const auto* x_seg_p = boost::get(&(*it)); +#if ! defined (CGAL_NO_ASSERTIONS) + CGAL_assertion(x_seg_p != nullptr); #endif // If the polycurve consists of a single x-monotone subcurve, return. if (x_seg_objects.size() == 1) { #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT if (cmp_seg_endpts(x_seg) == LARGER) - x_seg = ctr_seg_opposite(x_seg); + *oi++ = Make_x_monotone_result(ctr_x_curve(ctr_seg_opposite(*x_seg_p))); else *oi++ = Make_x_monotone_result(ctr_x_curve(*x_seg_p)); +#else + *oi++ = Make_x_monotone_result(ctr_x_curve(*x_seg_p)); #endif - *oi++ = make_object(ctr_x_curve(x_seg)); x_seg_objects.clear(); return oi; } @@ -244,39 +241,38 @@ public: auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); auto equal = m_poly_traits.subcurve_traits_2()->equal_2_object(); - Point_2 last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? - max_seg_v(x_seg) : min_seg_v(x_seg); + Point_2 last_target = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + max_seg_v(*x_seg_p) : min_seg_v(*x_seg_p); Point_2 next_src; ); // The polycurve consists of at least 2 x-monotone subcurves: Push_back_2 push_back = m_poly_traits.push_back_2_object(); - typename Subcurve_traits_2::Is_vertical_2 is_seg_vertical = + auto is_seg_vertical = m_poly_traits.subcurve_traits_2()->is_vertical_2_object(); - bool is_start_vertical = is_seg_vertical(x_seg); - Comparison_result start_dir = cmp_seg_endpts(x_seg); + bool is_start_vertical = is_seg_vertical(*x_seg_p); + Comparison_result start_dir = cmp_seg_endpts(*x_seg_p); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT Push_front_2 push_front = m_poly_traits.push_front_2_object(); - if (cmp_seg_endpts(x_seg) == LARGER) x_seg = ctr_seg_opposite(x_seg); -#endif - X_monotone_curve_2 x_polycurve = ctr_x_curve(x_seg); - - for (++it; it != x_seg_objects.end(); ++it){ - X_monotone_subcurve_2 x_seg; -#if defined (CGAL_NO_ASSERTIONS) - CGAL::assign(x_seg, *it); + X_monotone_curve_2 x_polycurve = (cmp_seg_endpts(x_seg) == LARGER) ? + ctr_x_curve(ctr_seg_opposite(*x_seg_p)) : ctr_x_curve(*x_seg_p); #else - bool assign_res = CGAL::assign(x_seg, *it); - CGAL_assertion(assign_res); + X_monotone_curve_2 x_polycurve = ctr_x_curve(*x_seg_p); +#endif + + for (++it; it != x_seg_objects.end(); ++it) { + const auto* x_seg_p = boost::get(&(*it)); +#if ! defined (CGAL_NO_ASSERTIONS) + CGAL_assertion(x_seg_p != nullptr); #endif // Test that cv is continuous and well-oriented. CGAL_precondition_code ( - next_src = (cmp_seg_endpts(x_seg) == SMALLER) ? - min_seg_v(x_seg) : max_seg_v(x_seg); + next_src = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + min_seg_v(*x_seg_p) : max_seg_v(*x_seg_p); ); CGAL_precondition_msg ( @@ -285,46 +281,50 @@ public: ); CGAL_precondition_code ( - last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? - max_seg_v(x_seg) : min_seg_v(x_seg); + last_target = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + max_seg_v(*x_seg_p) : min_seg_v(*x_seg_p); ); - if ((cmp_seg_endpts(x_seg) != start_dir) || - (is_seg_vertical(x_seg) != is_start_vertical)) + if ((cmp_seg_endpts(*x_seg_p) != start_dir) || + (is_seg_vertical(*x_seg_p) != is_start_vertical)) { // Construct an x-monotone curve from the sub-range which was found - *oi++ = make_object(x_polycurve); - is_start_vertical = is_seg_vertical(x_seg); - start_dir = cmp_seg_endpts(x_seg); + *oi++ = Make_x_monotone_result(x_polycurve); + is_start_vertical = is_seg_vertical(*x_seg_p); + start_dir = cmp_seg_endpts(*x_seg_p); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - if (cmp_seg_endpts(x_seg) == LARGER) x_seg = ctr_seg_opposite(x_seg); + x_polycurve = (cmp_seg_endpts(*x_seg_p) == LARGER) ? + ctr_x_curve(ctr_seg_opposite(*x_seg_p)) : ctr_x_curve(*x_seg_p); +#else + x_polycurve = ctr_x_curve(*x_seg_p); #endif - x_polycurve = ctr_x_curve(x_seg); } else { #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - if (cmp_seg_endpts(x_seg) == LARGER) { - x_seg = ctr_seg_opposite(x_seg); - push_front(x_polycurve, x_seg); - } + if (cmp_seg_endpts(*x_seg_p) == LARGER) + push_front(x_polycurve, ctr_seg_opposite(*x_seg_p)); else - push_back(x_polycurve, x_seg); + push_back(x_polycurve, *x_seg_p); #else - push_back(x_polycurve, x_seg); + push_back(x_polycurve, *x_seg_p); #endif } } // for loop if (x_polycurve.number_of_subcurves() != 0) - *oi++ = make_object(x_polycurve); + *oi++ = Make_x_monotone_result(x_polycurve); x_seg_objects.clear(); return oi; } + template OutputIterator operator_impl(const Curve_2& cv, OutputIterator oi, Arr_not_all_sides_oblivious_tag) const { - typedef typename Curve_2::Subcurve_const_iterator const_seg_iterator; + typedef boost::variant + Make_x_monotone_subresult; + typedef boost::variant + Make_x_monotone_result; // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; @@ -347,29 +347,25 @@ public: m_poly_traits.subcurve_traits_2()->construct_opposite_2_object(); #endif - // Convert the input polycurve to a sequence of CGAL objects, such - // that each Object wraps an x-monotone subcurve. - std::vector x_seg_objects; - const_seg_iterator it_segs; - for (it_segs = cv.subcurves_begin(); it_segs != cv.subcurves_end(); - ++it_segs) - make_seg_x_monotone(*it_segs, std::back_inserter(x_seg_objects)); - typename std::vector::iterator it = x_seg_objects.begin(); - X_monotone_subcurve_2 x_seg; -#if defined (CGAL_NO_ASSERTIONS) - CGAL::assign(x_seg, *it); -#else - bool assign_res = CGAL::assign(x_seg, *it); - CGAL_assertion(assign_res); + // Convert the input polycurve to a sequence of objects, such that + // each object wraps an x-monotone subcurve. + std::vector x_seg_objects; + for (auto its = cv.subcurves_begin(); its != cv.subcurves_end(); ++its) + make_seg_x_monotone(*its, std::back_inserter(x_seg_objects)); + auto it = x_seg_objects.begin(); + const auto* x_seg_p = boost::get(&(*it)); +#if ! defined (CGAL_NO_ASSERTIONS) + CGAL_assertion(x_seg_p != nullptr); #endif // If the polycurve consists of a single x-monotone subcurve, return. if (x_seg_objects.size() == 1) { #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT if (cmp_seg_endpts(x_seg) == LARGER) - x_seg = ctr_seg_opposite(x_seg); + *oi++ = Make_x_monotone_result(ctr_x_curve(ctr_seg_opposite(*x_seg_p))); else *oi++ = Make_x_monotone_result(ctr_x_curve(*x_seg_p)); +#else + *oi++ = Make_x_monotone_result(ctr_x_curve(*x_seg_p)); #endif - *oi++ = make_object(ctr_x_curve(x_seg)); x_seg_objects.clear(); return oi; } @@ -383,39 +379,38 @@ public: auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); auto equal = m_poly_traits.subcurve_traits_2()->equal_2_object(); - Point_2 last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? - max_seg_v(x_seg) : min_seg_v(x_seg); + Point_2 last_target = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + max_seg_v(*x_seg_p) : min_seg_v(*x_seg_p); Point_2 next_src; ); // The polycurve consists of at least 2 x-monotone subcurves: Push_back_2 push_back = m_poly_traits.push_back_2_object(); - typename Subcurve_traits_2::Is_vertical_2 is_seg_vertical = + auto is_seg_vertical = m_poly_traits.subcurve_traits_2()->is_vertical_2_object(); - bool is_start_vertical = is_seg_vertical(x_seg); - Comparison_result start_dir = cmp_seg_endpts(x_seg); + bool is_start_vertical = is_seg_vertical(*x_seg_p); + Comparison_result start_dir = cmp_seg_endpts(*x_seg_p); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT Push_front_2 push_front = m_poly_traits.push_front_2_object(); - if (cmp_seg_endpts(x_seg) == LARGER) x_seg = ctr_seg_opposite(x_seg); -#endif - X_monotone_curve_2 x_polycurve = ctr_x_curve(x_seg); - - for (++it; it != x_seg_objects.end(); ++it){ - X_monotone_subcurve_2 x_seg; -#if defined (CGAL_NO_ASSERTIONS) - CGAL::assign(x_seg, *it); + X_monotone_curve_2 x_polycurve = (cmp_seg_endpts(x_seg) == LARGER) ? + ctr_x_curve(ctr_seg_opposite(*x_seg_p)) : ctr_x_curve(*x_seg_p); #else - bool assign_res = CGAL::assign(x_seg, *it); - CGAL_assertion(assign_res); + X_monotone_curve_2 x_polycurve = ctr_x_curve(*x_seg_p); +#endif + + for (++it; it != x_seg_objects.end(); ++it) { + const auto* x_seg_p = boost::get(&(*it)); +#if ! defined (CGAL_NO_ASSERTIONS) + CGAL_assertion(x_seg_p != nullptr); #endif // Test that cv is continuous and well-oriented. CGAL_precondition_code ( - next_src = (cmp_seg_endpts(x_seg) == SMALLER) ? - min_seg_v(x_seg) : max_seg_v(x_seg); + next_src = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + min_seg_v(*x_seg_p) : max_seg_v(*x_seg_p); ); CGAL_precondition_msg ( @@ -424,59 +419,61 @@ public: ); CGAL_precondition_code ( - last_target = (cmp_seg_endpts(x_seg) == SMALLER) ? - max_seg_v(x_seg) : min_seg_v(x_seg); + last_target = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + max_seg_v(*x_seg_p) : min_seg_v(*x_seg_p); ); - Arr_curve_end polycurve_target = - (cmp_seg_endpts(x_polycurve[0]) == SMALLER) ? - ARR_MAX_END : ARR_MIN_END; - Arr_curve_end seg_source = (cmp_seg_endpts(x_seg) == SMALLER) ? - ARR_MIN_END : ARR_MAX_END; - unsigned int num_segs = x_polycurve.number_of_subcurves(); + Arr_curve_end polycurve_target = + (cmp_seg_endpts(x_polycurve[0]) == SMALLER) ? + ARR_MAX_END : ARR_MIN_END; + Arr_curve_end seg_source = (cmp_seg_endpts(*x_seg_p) == SMALLER) ? + ARR_MIN_END : ARR_MAX_END; + auto num_segs = x_polycurve.number_of_subcurves(); - if ((cmp_seg_endpts(x_seg) != start_dir) || - (is_seg_vertical(x_seg) != is_start_vertical)) + if ((cmp_seg_endpts(*x_seg_p) != start_dir) || + (is_seg_vertical(*x_seg_p) != is_start_vertical)) { // Construct an x-monotone curve from the sub-range which was found - *oi++ = make_object(x_polycurve); - is_start_vertical = is_seg_vertical(x_seg); - start_dir = cmp_seg_endpts(x_seg); + *oi++ = Make_x_monotone_result(x_polycurve); + is_start_vertical = is_seg_vertical(*x_seg_p); + start_dir = cmp_seg_endpts(*x_seg_p); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - if (cmp_seg_endpts(x_seg) == LARGER) x_seg = ctr_seg_opposite(x_seg); + x_polycurve (cmp_seg_endpts(*x_seg_p) == LARGER) ? + ctr_x_curve(ctr_seg_opposite(*x_seg_p)) : ctr_x_curve(*x_seg_p); +#else + x_polycurve = ctr_x_curve(*x_seg_p); #endif - x_polycurve = ctr_x_curve(x_seg); } else if (ps_x(x_polycurve[num_segs-1], polycurve_target) != ARR_INTERIOR || - ps_x(x_seg, seg_source) != ARR_INTERIOR) + (ps_x(*x_seg_p, seg_source) != ARR_INTERIOR)) { - *oi++ = make_object(x_polycurve); + *oi++ = Make_x_monotone_result(x_polycurve); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - if (cmp_seg_endpts(x_seg) == LARGER) x_seg = ctr_seg_opposite(x_seg); + x_polycurve = (cmp_seg_endpts(*x_seg_p) == LARGER) ? + ctr_seg_opposite(*x_seg_p) : ctr_x_curve(*x_seg_p); #endif - x_polycurve = ctr_x_curve(x_seg); + x_polycurve = ctr_x_curve(*x_seg_p); } else { #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT - if (cmp_seg_endpts(x_seg) == LARGER) { - x_seg = ctr_seg_opposite(x_seg); - push_front(x_polycurve, x_seg); - } + if (cmp_seg_endpts(*x_seg_p) == LARGER) + push_front(x_polycurve, ctr_seg_opposite(*x_seg_p)); else - push_back(x_polycurve, x_seg); + push_back(x_polycurve, *x_seg_p); #else - push_back(x_polycurve, x_seg); + push_back(x_polycurve, *x_seg_p); #endif } } // for loop if (x_polycurve.number_of_subcurves() != 0) - *oi++ = make_object(x_polycurve); + *oi++ = Make_x_monotone_result(x_polycurve); x_seg_objects.clear(); return oi; } -public: + + public: template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { return operator_impl(cv, oi, Are_all_sides_oblivious_tag()); } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_rational_function_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_rational_function_traits_2.h index bff77f5f588..31a6186505a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_rational_function_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_rational_function_traits_2.h @@ -808,45 +808,41 @@ public: return Equal_2(this); } - /*! A functor that divides a curve into continues (x-monotone) curves. */ - class Make_x_monotone_2 - { - public: + //! \name Intersections & subdivisions + //@{ - /*! - * Cut the given conic curve (or conic arc) into x-monotone subcurves - * and insert them to the given output iterator. - * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. The returned - * objects is a wrapper for an X_monotone_curve_2 object. - * \return The past-the-end iterator. + /*! \class Make_x_monotone_2 + * A functor for subdividing a curve into continues x-monotone curves. + */ + class Make_x_monotone_2 { + public: + /*! Subdivide a given rational-function curve into x-monotone subcurves + * and insert them to a given output iterator. + * \param cv the curve. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return the past-the-end iterator. */ - template + template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - // Make the rational arc continuous. - std::list arcs; + typedef boost::variant + Make_x_monotone_result; + // Make the rational arc continuous. + std::list arcs; cv.make_continuous(std::back_inserter(arcs)); // Create objects. - typename std::list::const_iterator iter; - - for (iter = arcs.begin(); iter != arcs.end(); ++iter) - { - *oi = make_object (*iter); - ++oi; - } - - return (oi); + for (const auto& arc : arcs) *oi++ = Make_x_monotone_result(arc); + return oi; } }; /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const - { - return Make_x_monotone_2(); - } + { return Make_x_monotone_2(); } /*! A functor that splits a curve at a point. */ class Split_2 @@ -975,6 +971,8 @@ public: return Merge_2(this); } + //@} + /// \name Functor definitions to handle boundaries //@{ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h index 44f65d9b056..575f797d293 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_segment_traits_2.h @@ -543,23 +543,30 @@ public: //@} - /// \name Functor definitions for supporting intersections. + //! \name Intersections, subdivisions, and mergings //@{ + /*! \class Make_x_monotone_2 + * A functor for subdividing a curve into x-monotone curves. + */ class Make_x_monotone_2 { public: - /*! Cut the given curve into x-monotone subcurves and insert them into the - * given output iterator. As segments are always x_monotone, only one - * object will be contained in the iterator. + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. As segments are always x_monotone a single + * object is inserted. * \param cv the curve. - * \param oi the output iterator, whose value-type is variant<.... - * \return the past-the-end iterator. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return the past-the-end output iterator. */ template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - // Wrap the segment with an object. - *oi++ = make_object(cv); + // Wrap the segment with a variant. + typedef boost::variant + Make_x_monotone_result; + *oi++ = Make_x_monotone_result(cv); return oi; } }; @@ -1161,6 +1168,7 @@ public: //! \brief constructs default. template Arr_segment_traits_2::_Segment_cached_2::_Segment_cached_2() : + m_is_directed_right(false), m_is_vert(false), m_is_degen(true) {} diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_spherical_gaussian_map_3.h b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_spherical_gaussian_map_3.h index d7d20809e10..5aaf22a64a8 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_spherical_gaussian_map_3.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_spherical_gaussian_map_3.h @@ -151,23 +151,25 @@ public: OutputIterator insert(const Vector_3 & normal1, const Vector_3 & normal2, OutputIterator oi) { - std::list x_objects; + typedef boost::variant + Make_x_monotone_result; + + std::list x_objects; make_x_monotone(normal1, normal2, std::back_inserter(x_objects)); - typename std::list::iterator it = x_objects.begin(); - const X_monotone_curve_2 * xc = object_cast(&(*it)); + auto it = x_objects.begin(); + const auto* xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "1.a. insert_in_face_interior(" << *xc << ")" << std::endl; #endif - Halfedge_handle he = - m_sgm.insert_in_face_interior(*xc, m_sgm.faces_begin()); - if (!xc->is_directed_right()) he = he->twin(); + Halfedge_handle he = m_sgm.insert_in_face_interior(*xc, m_sgm.faces_begin()); + if (! xc->is_directed_right()) he = he->twin(); *oi++ = he; ++it; if (it == x_objects.end()) return oi; - xc = object_cast(&(*it)); + xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "1.b. insert_from_vertex(" << *xc << ")" << std::endl; #endif @@ -190,11 +192,14 @@ public: const Vector_3 & normal2, OutputIterator oi) { - std::list x_objects; + typedef boost::variant + Make_x_monotone_result; + + std::list x_objects; make_x_monotone(normal1, normal2, std::back_inserter(x_objects)); - typename std::list::iterator it = x_objects.begin(); - const X_monotone_curve_2 * xc = object_cast(&(*it)); + auto it = x_objects.begin(); + const auto* xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "2.a. insert_from_vertex(" << *xc << ", " << vertex1->point() << ")" << std::endl; @@ -208,7 +213,7 @@ public: ++it; if (it == x_objects.end()) return oi; - xc = object_cast(&(*it)); + xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "2.b. insert_from_vertex(" << *xc << ")" << std::endl; #endif @@ -231,12 +236,15 @@ public: const Vector_3 & normal2, Vertex_handle vertex2, OutputIterator oi) { - std::list x_objects; + typedef boost::variant + Make_x_monotone_result; + + std::list x_objects; make_x_monotone(normal1, normal2, std::back_inserter(x_objects)); - typename std::list::iterator it = x_objects.begin(); + auto it = x_objects.begin(); if (x_objects.size() == 1) { - const X_monotone_curve_2 * xc = object_cast(&(*it)); + const auto* xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "3. insert_from_vertex(" << *xc << ")" << std::endl; #endif @@ -247,8 +255,8 @@ public: return oi; } - const X_monotone_curve_2 * xc1 = object_cast(&(*it++)); - const X_monotone_curve_2 * xc2 = object_cast(&(*it)); + const X_monotone_curve_2* xc1 = boost::get(&(*it++)); + const X_monotone_curve_2* xc2 = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "3.a. insert_from_vertex(" << *xc2 << ")" << std::endl; @@ -283,11 +291,13 @@ public: const Vector_3 & normal2, Vertex_handle vertex2, OutputIterator oi) { - std::list x_objects; + typedef boost::variant + Make_x_monotone_result; + std::list x_objects; make_x_monotone(normal1, normal2, std::back_inserter(x_objects)); - typename std::list::iterator it = x_objects.begin(); + auto it = x_objects.begin(); if (x_objects.size() == 1) { - const X_monotone_curve_2 * xc = object_cast(&(*it)); + const auto* xc = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "4. insert_at_vertices(" << *xc << ")" << std::endl; #endif @@ -295,8 +305,8 @@ public: return oi; } - const X_monotone_curve_2 * xc1 = object_cast(&(*it++)); - const X_monotone_curve_2 * xc2 = object_cast(&(*it)); + const X_monotone_curve_2 * xc1 = boost::get(&(*it++)); + const X_monotone_curve_2 * xc2 = boost::get(&(*it)); #if CGAL_ARR_SPHERICAL_GAUSSIAN_MAP_3_DEBUG==1 std::cout << "4.a. insert_from_vertex(" << *xc1 diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_transform_on_sphere.h b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_transform_on_sphere.h index 1cf5b88058c..1a772864e24 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_transform_on_sphere.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_gaussian_map_3/Arr_transform_on_sphere.h @@ -35,6 +35,7 @@ void Arr_transform_on_sphere(Arrangement & arr, typedef typename Arrangement::Geometry_traits_2 Geometry_traits_2; typedef typename Arrangement::Topology_traits Topology_traits; + typedef typename Geometry_traits_2::Point_2 Point_2; typedef typename Geometry_traits_2::Curve_2 Curve_2; typedef typename Geometry_traits_2::X_monotone_curve_2 X_monotone_curve_2; @@ -45,6 +46,8 @@ void Arr_transform_on_sphere(Arrangement & arr, typedef typename Arrangement::Halfedge_around_vertex_circulator Halfedge_around_vertex_circulator; + typedef boost::variant Make_x_monotone_result; + const Geometry_traits_2 * geom_traits = arr.geometry_traits(); Topology_traits * topol_traits = arr.topology_traits(); @@ -53,8 +56,7 @@ void Arr_transform_on_sphere(Arrangement & arr, // Preprocessing loop - merge all the edges that were splited // (meaning have a common endpoint that lies on the boundary and their degree // is 2) on the identification curve. - for (Vertex_handle vi1 = arr.vertices_begin() ; vi1 != arr.vertices_end() ;) - { + for (auto vi1 = arr.vertices_begin(); vi1 != arr.vertices_end(); ) { Vertex_handle v_temp = vi1; ++vi1; @@ -63,9 +65,9 @@ void Arr_transform_on_sphere(Arrangement & arr, Arr_parameter_space by = geom_traits->parameter_space_in_y_2_object()(v_temp->point()); - // use vertex->parameter_space_in_x() != interior || vertex->parameter_space_in_y() != interior) - if ((bx != ARR_INTERIOR || by != ARR_INTERIOR) && (v_temp->degree() == 2)) - { + // use vertex->parameter_space_in_x() != interior || + // vertex->parameter_space_in_y() != interior) + if ((bx != ARR_INTERIOR || by != ARR_INTERIOR) && (v_temp->degree() == 2)) { Curve_2 merged_cv; Halfedge_around_vertex_circulator havc = v_temp->incident_halfedges(); Halfedge_around_vertex_circulator havc_next = havc; @@ -80,16 +82,13 @@ void Arr_transform_on_sphere(Arrangement & arr, // Compare the direction of the edges. bool eq_direction = havc->direction() == havc_next->twin()->direction(); - if (point_eq1 && normal_eq1 && eq_direction) - { - if (havc->source()->point() == havc->curve().source()) - { + if (point_eq1 && normal_eq1 && eq_direction) { + if (havc->source()->point() == havc->curve().source()) { merged_cv = Curve_2(havc->source()->point(), havc_next->twin()->target()->point(), havc->curve().normal()); } - else if (havc->source()->point() == havc->curve().target()) - { + else if (havc->source()->point() == havc->curve().target()) { merged_cv = Curve_2(havc_next->twin()->target()->point(), havc->source()->point(), havc->curve().normal()); @@ -111,20 +110,17 @@ void Arr_transform_on_sphere(Arrangement & arr, } //Rotate all the vertices. - for (Vertex_handle vi1 = arr.vertices_begin(); vi1 != arr.vertices_end() ; - ++vi1) - { + for (auto vi1 = arr.vertices_begin(); vi1 != arr.vertices_end(); ++vi1) { m_arr_access.modify_vertex_ex(vi1, aff.transform(vi1->point())); } - unsigned int num_of_edges = arr.number_of_edges(); + size_t num_of_edges = arr.number_of_edges(); Edge_iterator ei1 = arr.edges_begin(); // Rotate all the halfedges. // The loop is over the initial edges , since new edges are created and // added to the edges list. - for (unsigned int i=0 ; i < num_of_edges ; ++i) - { + for (size_t i = 0; i < num_of_edges; ++i) { Curve_2 new_cv; Halfedge_handle hei1 = ei1; @@ -133,8 +129,7 @@ void Arr_transform_on_sphere(Arrangement & arr, // Take only the halfedge that its source is equal to the source of // the curve. bool eq1 = hei1->source()->point() == aff.transform(hei1->curve().source()); - if (!eq1) - { + if (!eq1) { hei1 = hei1->twin(); eq1 = hei1->source()->point() == aff.transform(hei1->curve().source()); } @@ -150,31 +145,28 @@ void Arr_transform_on_sphere(Arrangement & arr, // Modify the edge with the new curve. m_arr_access.modify_edge_ex(hei1, new_cv); - std::list objects; + std::list objects; // Try to split the curve into x_monotone pieces. geom_traits->make_x_monotone_2_object()(new_cv , std::back_inserter(objects)); // If the curve is not x-monotone - split it into 2 x_monotone parts. // Since the curves were x_monotone before , can assume that it will be // splited into 2 parts max. - if (objects.size() == 2) - { - typename std::list::iterator it = objects.begin(); + if (objects.size() == 2) { + auto it = objects.begin(); // The curve that its left vertex lies on the identification curve - const X_monotone_curve_2 * sub_cv1 = - object_cast(&(*it)); + const auto* sub_cv1 = boost::get(&(*it)); ++it; //The curve that its rigth vertex lies on the identification curve - const X_monotone_curve_2 * sub_cv2 = - object_cast(&(*it)); + const auto* sub_cv2 = boost::get(&(*it)); bool eq1 = (*sub_cv1).source() == hei1->source()->point(); bool eq2 = (*sub_cv2).target() == hei1->target()->point(); if (eq1 && eq2) - m_arr_access.split_edge_ex (hei1, (*sub_cv1).target(), *sub_cv1, - *sub_cv2); + m_arr_access.split_edge_ex(hei1, (*sub_cv1).target(), *sub_cv1, + *sub_cv2); else CGAL_error_msg ("The new curve endpoints should be equal to the original ones"); @@ -183,25 +175,20 @@ void Arr_transform_on_sphere(Arrangement & arr, // Update all the vertices that located on the boundary after the rotation // with boundary conditions - for (Vertex_handle vi = arr.vertices_begin() ; vi != arr.vertices_end() ; - ++vi) - { + for (auto vi = arr.vertices_begin(); vi != arr.vertices_end(); ++vi) { Arr_parameter_space bx = geom_traits->parameter_space_in_x_2_object()(vi->point()); Arr_parameter_space by = geom_traits->parameter_space_in_y_2_object()(vi->point()); - if (bx != ARR_INTERIOR || by != ARR_INTERIOR) - { + if (bx != ARR_INTERIOR || by != ARR_INTERIOR) { // The target of the Halfedge_around_vertex_circulator is the relevant // point. Halfedge_around_vertex_circulator havc = vi->incident_halfedges(); - Arr_curve_end ind; - if (geom_traits->construct_min_vertex_2_object()(havc->curve()) == vi->point()) - ind = ARR_MIN_END; - else - ind = ARR_MAX_END; + Arr_curve_end ind = + (geom_traits->construct_min_vertex_2_object()(havc->curve()) == + vi->point()) ? ARR_MIN_END : ARR_MAX_END; // Check if it was already added. if (topol_traits->discontinuity_vertex(havc->curve(), ind)== nullptr && @@ -219,7 +206,7 @@ void Arr_transform_on_sphere(Arrangement & arr, } // Transform the faces with the suitable transformation traits. - for(Face_handle f1 = arr.faces_begin() ; f1 != arr.faces_end() ; ++f1) + for (auto f1 = arr.faces_begin(); f1 != arr.faces_end(); ++f1) tran_tr.rotate_face(f1, aff); } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_topology_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_topology_traits_2.h index 002c9e0ee81..853815756f5 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_spherical_topology_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_spherical_topology_traits_2.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Eric Berberich +// Author(s): Efi Fogel +// Eric Berberich #ifndef CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_H #define CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_H @@ -491,11 +491,12 @@ public: * \pre The curve has a boundary condition in either x or y. * \return An object that contains the curve end. */ - CGAL::Object place_boundary_vertex(Face* f, - const X_monotone_curve_2& xc, - Arr_curve_end ind, - Arr_parameter_space ps_x, - Arr_parameter_space ps_y); + boost::optional > + place_boundary_vertex(Face* f, + const X_monotone_curve_2& xc, + Arr_curve_end ind, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y); /*! Locate the predecessor halfedge for the given curve around a given * vertex with boundary conditions. @@ -522,9 +523,10 @@ public: * \pre The curve end is incident to the boundary. * \return An object that contains the curve end. */ - CGAL::Object locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ce, - Arr_parameter_space ps_x, - Arr_parameter_space ps_y); + boost::variant + locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ce, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y); /*! Split a fictitious edge using the given vertex. * \param e The edge to split (one of the pair of halfedges). diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_bounded_planar_vert_decomp_helper.h b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_bounded_planar_vert_decomp_helper.h index 71b038765b8..2170c332d80 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_bounded_planar_vert_decomp_helper.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_bounded_planar_vert_decomp_helper.h @@ -7,9 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_BOUNDED_PLANAR_VERT_DEOCMP_HELPER_H #define CGAL_ARR_BOUNDED_PLANAR_VERT_DEOCMP_HELPER_H @@ -43,9 +42,15 @@ private: typedef Geometry_traits_2 Gt2; public: + typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; typedef typename Arrangement_2::Face_const_handle Face_const_handle; typedef typename Arrangement_2::Topology_traits Topology_traits; + typedef boost::variant Cell_type; + typedef boost::optional Vert_type; + protected: // Data members: const Topology_traits* m_top_traits; // The topology-traits class. @@ -76,10 +81,10 @@ public: //@} /*! Get the current top object. */ - CGAL::Object top_object() const { return CGAL::make_object(m_unb_face); } + Vert_type top_object() const { return Vert_type(m_unb_face); } /*! Get the current bottom object. */ - CGAL::Object bottom_object() const { return CGAL::make_object(m_unb_face); } + Vert_type bottom_object() const { return Vert_type(m_unb_face); } }; } // namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_topology_traits_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_topology_traits_2_impl.h index 08b6c653034..5e51ba36a01 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_topology_traits_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_topology_traits_2_impl.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Ron Wein +// Author(s): Efi Fogel +// Ron Wein #ifndef CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_IMPL_H #define CGAL_ARR_SPHERICAL_TOPOLOGY_TRAITS_2_IMPL_H @@ -514,7 +514,10 @@ let_me_decide_the_outer_ccb(std::pair< CGAL::Sign, CGAL::Sign> signs1, * the interior of the curve, find a place for a boundary vertex that will * represent the curve end along the face boundary */ template -CGAL::Object +boost::optional + ::Vertex*, + typename Arr_spherical_topology_traits_2::Halfedge*> > Arr_spherical_topology_traits_2:: place_boundary_vertex(Face* /* f */, const X_monotone_curve_2& xc, Arr_curve_end ind, @@ -525,15 +528,18 @@ place_boundary_vertex(Face* /* f */, , Arr_parameter_space ps_y) { + typedef boost::variant Non_optional_result; + typedef boost::optional Result; + // std::cout << "place_boundary_vertex()" << std::endl; if (ps_y == ARR_BOTTOM_BOUNDARY) { - if (m_south_pole == nullptr) return Object(); - return CGAL::make_object(m_south_pole); + if (m_south_pole == nullptr) return boost::none; + return Result(Non_optional_result(m_south_pole)); } if (ps_y == ARR_TOP_BOUNDARY) { - if (m_north_pole == nullptr) return Object(); - return CGAL::make_object(m_north_pole); + if (m_north_pole == nullptr) return boost::none; + return Result(Non_optional_result(m_north_pole)); } CGAL_assertion((ps_x == ARR_LEFT_BOUNDARY) || (ps_x == ARR_RIGHT_BOUNDARY)); @@ -541,15 +547,14 @@ place_boundary_vertex(Face* /* f */, const Point_2& key = (ind == ARR_MIN_END) ? m_geom_traits->construct_min_vertex_2_object()(xc) : m_geom_traits->construct_max_vertex_2_object()(xc); - typename Vertex_map::iterator it = m_boundary_vertices.find(key); - + auto it = m_boundary_vertices.find(key); if (it != m_boundary_vertices.end()) { Vertex* v = it->second; - return CGAL::make_object(v); + return Result(Non_optional_result(v)); } // The vertex hasn't been created yet, return a null object: - return Object(); + return boost::none; } /*! \brief locate the predecessor halfedge for the given curve around a given @@ -585,7 +590,11 @@ locate_around_boundary_vertex(Vertex* v, /*! \brief locates a DCEL feature that contains a given curve end. */ template -CGAL::Object Arr_spherical_topology_traits_2:: +boost::variant +::Vertex*, + typename Arr_spherical_topology_traits_2::Halfedge*, + typename Arr_spherical_topology_traits_2::Face*> +Arr_spherical_topology_traits_2:: locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ind, Arr_parameter_space #if !defined(CGAL_NO_ASSERTIONS) @@ -594,13 +603,14 @@ locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ind, , Arr_parameter_space ps_y) { + typedef boost::variant Result; // Act according to the boundary conditions. if (ps_y == ARR_TOP_BOUNDARY) { // In case the curve end coincides with the north pole, return the vertex // representing the north pole, if one exists. Otherwise, return the face // containing this pole (the spherical face). - if (m_north_pole != nullptr) return CGAL::make_object(m_north_pole); - return CGAL::make_object(m_spherical_face); + if (m_north_pole != nullptr) return Result(m_north_pole); + return Result(m_spherical_face); } typename Vertex_map::iterator it; @@ -610,7 +620,7 @@ locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ind, // In case the curve end coincides with the south pole, return the vertex // representing the south pole, if one exists. Otherwise, search for the // face containing this pole. - if (m_south_pole != nullptr) return CGAL::make_object(m_south_pole); + if (m_south_pole != nullptr) return Result(m_south_pole); it = m_boundary_vertices.begin(); } else { @@ -625,7 +635,7 @@ locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ind, it = m_boundary_vertices.find(key); if (it != m_boundary_vertices.end()) { v = it->second; - return CGAL::make_object(v); + return Result(v); } it = m_boundary_vertices.lower_bound(key); @@ -635,11 +645,10 @@ locate_curve_end(const X_monotone_curve_2& xc, Arr_curve_end ind, // discontinuity that is strictly above the curve end. If there is none, // we know the curve end is contained in the spherical face. Otherwise, // we return the face that lies below the vertex v. - if (it == m_boundary_vertices.end()) - return CGAL::make_object(m_spherical_face); + if (it == m_boundary_vertices.end()) return Result(m_spherical_face); v = it->second; - return CGAL::make_object(_face_below_vertex_on_discontinuity(v)); + return Result(_face_below_vertex_on_discontinuity(v)); } /*! \brief determines whether a given boundary vertex is redundant */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_vert_decomp_helper.h b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_vert_decomp_helper.h index 4a8c0434211..a5600465606 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_vert_decomp_helper.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_spherical_vert_decomp_helper.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_SPHERICAL_VERT_DECOMP_HELPER_H #define CGAL_ARR_SPHERICAL_VERT_DECOMP_HELPER_H @@ -44,8 +44,13 @@ private: public: typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Arrangement_2::Face_const_handle Face_const_handle; typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arrangement_2::Face_const_handle Face_const_handle; + + typedef boost::variant Cell_type; + typedef boost::optional Vert_type; protected: typedef typename Arrangement_2::Topology_traits Topology_traits; @@ -80,17 +85,17 @@ public: //@} /*! Get the current top object. */ - CGAL::Object top_object () const + Vert_type top_object () const { return (m_valid_north_pole) ? - CGAL::make_object (m_north_pole) : CGAL::make_object (m_north_face); + Vert_type(m_north_pole) : Vert_type(m_north_face); } /*! Get the current bottom object. */ - CGAL::Object bottom_object () const + Vert_type bottom_object () const { return (m_valid_south_pole) ? - CGAL::make_object(m_south_pole) : CGAL::make_object(m_south_face); + Vert_type(m_south_pole) : Vert_type(m_south_face); } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_topology_traits_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_topology_traits_2_impl.h index d968482a1d8..5d9a91452af 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_topology_traits_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_topology_traits_2_impl.h @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_IMPL_H #define CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_IMPL_H @@ -296,27 +296,31 @@ are_equal(const Vertex *v, // represent the curve end along the face boundary. // template -CGAL::Object +boost::optional + ::Vertex*, + typename Arr_unb_planar_topology_traits_2::Halfedge*> > Arr_unb_planar_topology_traits_2:: -place_boundary_vertex(Face *f, +place_boundary_vertex(Face* f, const X_monotone_curve_2& cv, Arr_curve_end ind, Arr_parameter_space ps_x, Arr_parameter_space ps_y) { - // Get a halfedge on the outer CCB of f and start traversing the CCB. - Halfedge *first = *(f->outer_ccbs_begin()); - Halfedge *curr = first; - bool eq_source, eq_target; + typedef boost::variant Non_optional_result; + typedef boost::optional Result; - do - { + // Get a halfedge on the outer CCB of f and start traversing the CCB. + Halfedge* first = *(f->outer_ccbs_begin()); + Halfedge* curr = first; + bool eq_source, eq_target; + + do { // Note we consider only fictitious halfedges and check whether they // contain the relevant curve end. if (curr->has_null_curve() && - _is_on_fictitious_edge (cv, ind, ps_x, ps_y, curr, - eq_source, eq_target)) + _is_on_fictitious_edge(cv, ind, ps_x, ps_y, curr, eq_source, eq_target)) { - CGAL_assertion (! eq_source && ! eq_target); - return (CGAL::make_object (curr)); + CGAL_assertion(! eq_source && ! eq_target); + return Result(curr); } // Move to the next halfegde along the CCB. @@ -327,59 +331,58 @@ place_boundary_vertex(Face *f, // If we reached here, we did not find a suitable halfegde, which should // never happen. CGAL_error(); - return CGAL::Object(); + return boost::none; } //----------------------------------------------------------------------------- // Locate a DCEL feature that contains the given unbounded curve end. // template -CGAL::Object Arr_unb_planar_topology_traits_2:: +boost::variant +::Vertex*, + typename Arr_unb_planar_topology_traits_2::Halfedge*, + typename Arr_unb_planar_topology_traits_2::Face*> +Arr_unb_planar_topology_traits_2:: locate_curve_end (const X_monotone_curve_2& cv, Arr_curve_end ind, Arr_parameter_space ps_x, Arr_parameter_space ps_y) { + typedef boost::variant Result; + // Start traversing the inner CCB of the fictitious face and try to locate // a feature that contains the curve end. - Halfedge *first = *(fict_face->inner_ccbs_begin()); - Halfedge *curr = first; - bool eq_source, eq_target; + Halfedge* first = *(fict_face->inner_ccbs_begin()); + Halfedge* curr = first; + bool eq_source, eq_target; - do - { - if (_is_on_fictitious_edge (cv, ind, ps_x, ps_y, curr, - eq_source, eq_target)) + do { + if (_is_on_fictitious_edge(cv, ind, ps_x, ps_y, curr, eq_source, eq_target)) { - if (eq_source) - { + if (eq_source) { // cv's end coincides with the source vertex of the current // fictitious halfedge. This means that cv overlaps the curve that // is associated with the only non-fictitious halfedge incident to // this vertex. We therefore return a pointer to this halfedge. - Halfedge *he = curr->opposite()->next(); - - CGAL_assertion (! he->has_null_curve()); - return (CGAL::make_object (he)); + Halfedge* he = curr->opposite()->next(); + CGAL_assertion(! he->has_null_curve()); + return Result(he); } - else if (eq_target) - { + else if (eq_target) { // cv's end coincides with the target vertex of the current // fictitious halfedge. This means that cv overlaps the curve that // is associated with the only non-fictitious halfedge incident to // this vertex. We therefore return a pointer to this halfedge. - Halfedge *he = curr->opposite()->prev(); - - CGAL_assertion (! he->has_null_curve()); - return (CGAL::make_object (he)); + Halfedge* he = curr->opposite()->prev(); + CGAL_assertion(! he->has_null_curve()); + return Result(he); } // The current ficitious edge contains cv's end in its interior. // Note we use curr's twin, whose incident face is a valid // unbounded face (whereas the incident face of curr is the fictitious // face). - Face *uf = curr->opposite()->outer_ccb()->face(); - + Face* uf = curr->opposite()->outer_ccb()->face(); CGAL_assertion (uf->is_unbounded() && ! uf->is_fictitious()); - return (CGAL::make_object (uf)); + return Result(uf); } curr = curr->next(); @@ -388,7 +391,8 @@ locate_curve_end (const X_monotone_curve_2& cv, Arr_curve_end ind, // We should never reach here. CGAL_error(); - return Object(); + Vertex* v(nullptr); + return Result(v); } //----------------------------------------------------------------------------- diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_vert_decomp_helper.h b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_vert_decomp_helper.h index e0da9681994..858f9c468af 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_vert_decomp_helper.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_topology_traits/Arr_unb_planar_vert_decomp_helper.h @@ -7,9 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_UNB_PLANAR_VERT_DECOMP_HELPER_H #define CGAL_ARR_UNB_PLANAR_VERT_DECOMP_HELPER_H @@ -43,12 +42,16 @@ private: typedef Geometry_traits_2 Gt2; public: + typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; typedef typename Arrangement_2::Face_const_handle Face_const_handle; + typedef boost::variant Cell_type; + typedef boost::optional Vert_type; + protected: typedef typename Arrangement_2::Topology_traits Topology_traits; - typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; - typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; // Data members: const Topology_traits* m_top_traits; // The topology-traits class. @@ -77,10 +80,10 @@ public: //@} /*! Get the current top object. */ - CGAL::Object top_object() const { return CGAL::make_object(m_top_fict); } + Vert_type top_object() const { return Vert_type(m_top_fict); } /*! Get the current bottom object. */ - CGAL::Object bottom_object() const { return CGAL::make_object(m_bottom_fict); } + Vert_type bottom_object() const { return Vert_type(m_bottom_fict); } }; //----------------------------------------------------------------------------- diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h index 9738f6cf7f4..3ab0c03bbbf 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_tracing_traits_2.h @@ -504,7 +504,12 @@ public: } }; - /*! A functor that divides a curve into x-monotone curves. */ + //! \name Intersections & subdivisions + //@{ + + /*! \class Make_x_monotone_2 + * A functor for subdividing curves into x-monotone curves. + */ class Make_x_monotone_2 { private: typename Base::Make_x_monotone_2 m_object; @@ -515,39 +520,43 @@ public: Make_x_monotone_2(const Base * base, bool enabled = true) : m_object(base->make_x_monotone_2_object()), m_enabled(enabled) {} - /*! Operate - * \param cv the curve - * \param oi an output iterator that contains the result. It's value - * type is CGAL::Object, which wraps either an x-monotone curve or a point - * \return the output iterator + /*! Subdivide a given curve into x-monotone subcurves and insert them into + * a given output iterator. + * \param cv the curve. + * \param oi an output iterator for the result. Its value type is a variant + * that wraps Point_2 or X_monotone_curve_2 objects. + * \return the output iterator. */ - template + template OutputIterator operator()(const Curve_2 & cv, OutputIterator oi) const { - if (!m_enabled) return m_object(cv, oi); + if (! m_enabled) return m_object(cv, oi); std::cout << "make_x_monotone" << std::endl << " cv: " << cv << std::endl; - std::list container; + + typedef boost::variant + Make_x_monotone_result; + + std::list container; m_object(cv, std::back_inserter(container)); if (container.empty()) return oi; - std::list::iterator it; - unsigned int i = 0; - for (it = container.begin(); it != container.end(); ++it) { - X_monotone_curve_2 xcv; - if (assign (xcv, *it)) { - std::cout << " result[" << i++ << "]: xcv: " << xcv << std::endl; + size_t i = 0; + for (auto it = container.begin(); it != container.end(); ++it) { + if (const auto* xcv = boost::get(*it)) { + std::cout << " result[" << i++ << "]: xcv: " << *xcv << std::endl; continue; } - Point_2 p; - if (assign (p, *it)) { - std::cout << " result[" << i++ << "]: p: " << p << std::endl; + if (const Point_2* p = boost::get(*it)) { + std::cout << " result[" << i++ << "]: p: " << *p << std::endl; continue; } + + CGAL_error(); } - for (it = container.begin(); it != container.end(); ++it) *oi++ = *it; + for (auto it = container.begin(); it != container.end(); ++it) *oi++ = *it; container.clear(); return oi; } @@ -597,14 +606,14 @@ public: Intersect_2(const Base* base, bool enabled = true) : m_object(base->intersect_2_object()), m_enabled(enabled) {} - /*! Operate + /*! Compute the intersections of the two given curves and insert them into + * a given output iterator. * \param xcv1 the first curve * \param xcv2 the ssecond curve - * \param oi an output iterator that contains the result. It's value - * type is CGAL::Object, which wraps either an x-monotone overlapping - * curve or pair that consists of an intersection point and its - * multiplicity - * \return the output iterator + * \param oi the output iterator for the result. It value type is a variant + * that wraps an x-monotone overlapping curve or a pair that + * consists of the intersection point and its multiplicity + * \return the past-the-end output iterator. */ template OutputIterator operator()(const X_monotone_curve_2 & xcv1, diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_unb_planar_topology_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_unb_planar_topology_traits_2.h index bed94cdbb3f..12598f4bed7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_unb_planar_topology_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_unb_planar_topology_traits_2.h @@ -7,9 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_H #define CGAL_ARR_UNB_PLANAR_TOPOLOGY_TRAITS_2_H @@ -308,11 +307,12 @@ public: * \return An object that contains the curve end. * In our case this object always wraps a fictitious edge. */ - CGAL::Object place_boundary_vertex(Face* f, - const X_monotone_curve_2& cv, - Arr_curve_end ind, - Arr_parameter_space ps_x, - Arr_parameter_space ps_y); + boost::optional > + place_boundary_vertex(Face* f, + const X_monotone_curve_2& cv, + Arr_curve_end ind, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y); /*! Locate the predecessor halfedge for the given curve around a given * vertex with boundary conditions. @@ -346,10 +346,11 @@ public: * In our case this object may either wrap an unbounded face, * or an edge with an end-vertex at infinity (in case of an overlap). */ - CGAL::Object locate_curve_end(const X_monotone_curve_2& cv, - Arr_curve_end ind, - Arr_parameter_space ps_x, - Arr_parameter_space ps_y); + boost::variant + locate_curve_end(const X_monotone_curve_2& cv, + Arr_curve_end ind, + Arr_parameter_space ps_x, + Arr_parameter_space ps_y); /*! Split a fictitious edge using the given vertex. * \param e The edge to split (one of the pair of halfedges). diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_vertical_decomposition_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_vertical_decomposition_2.h index e58af63b2f0..c47e24f906c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_vertical_decomposition_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_vertical_decomposition_2.h @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_ARR_VERTICAL_DECOMPOSITION_2_H #define CGAL_ARR_VERTICAL_DECOMPOSITION_2_H @@ -34,14 +34,13 @@ namespace Ss2 = Surface_sweep_2; /*! Perform a vertical decomposition of an arrangement, by performing a * "batched vertical ray-shooting" query from all arrangement vertices. * \param arr The arrangement. - * \param oi Output: An output iterator of the vertices, each paired with - * a pair of arrangement features that lie below and above - * it, respectively. - * The vertices are sorted by increasing xy-order. + * \param oi An output iterator of the vertices, each paired with a pair of + * arrangement features that lie below and above it, respectively. + * The vertices are sorted by increasing xy-order. + * The OutputIterator dereferences the type \c + * pair >, where + * \c Vert_type is an optional handle to an arrangement feature. * \return A past-the-end iterator for the ordered arrangement vertices. - * \pre The value-type of OutputIterator is - * pair >, where - * the Object represents a handle to an arrangement feature. */ template diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_compute_zone_visitor.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_compute_zone_visitor.h index b32ffa842c9..1d6bc8b97cd 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_compute_zone_visitor.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_compute_zone_visitor.h @@ -8,27 +8,29 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ophir Setter +// Author(s) : Ophir Setter +// Efi Fogel // #ifndef CGAL_ARR_COMPUTE_ZONE_VISITOR_H #define CGAL_ARR_COMPUTE_ZONE_VISITOR_H #include - /*! \file * Definition of the Arr_compute_zone_visitor class. */ +#include + namespace CGAL { /*! \class - * A visitor class for Arrangement_zone_2, which outputs the - * zone of an x-monotone curve. Meaning, it output the arrangment's - * vertices, edges and faces that the x-monotone curve intersects. + * A visitor class for Arrangement_zone_2 that outputs the zone of an + * x-monotone curve. Specifically, it outputs handles to the the arrangment + * cells that the x-monotone curve intersects. * The class should be templated by an Arrangement_2 class, and by an - * output iterator of CGAL Objects, where we store all arrangement - * features the x-monotone curve intersects. + * output iterator of a variant of types of handles to the arrangement cells + * that appear in the zone, namely, vertex, halfedge, and face handles. */ template class Arr_compute_zone_visitor @@ -53,7 +55,7 @@ private: const Vertex_handle invalid_v; // Invalid vertex. OutputIterator& out_iter; // for outputing the zone objects. - // Its value type is CGAL::Object. + // Its value type is boost::variant. bool output_left; // Determines wheter we should // output the left end point of a // subcurve (to avoid outputing @@ -65,8 +67,8 @@ public: Arr_compute_zone_visitor (OutputIterator& oi) : invalid_he(), invalid_v(), - out_iter (oi), - output_left (true) + out_iter(oi), + output_left(true) {} /*! Initialize the visitor. */ @@ -90,50 +92,35 @@ public: * \return A handle to the halfedge obtained from the insertion of the * subcurve into the arrangement. */ - Result found_subcurve (const X_monotone_curve_2&, - Face_handle face, - Vertex_handle left_v, Halfedge_handle left_he, - Vertex_handle right_v, Halfedge_handle right_he) + Result found_subcurve(const X_monotone_curve_2&, + Face_handle face, + Vertex_handle left_v, Halfedge_handle left_he, + Vertex_handle right_v, Halfedge_handle right_he) { - if (output_left) - { + typedef boost::variant + Zone_result; + + if (output_left) { // Only the first subcurve should output the arrangement feature incident // to its left endpoint. This way we avoid reporting the same feature // twice. - if (left_v != invalid_v) - { - *out_iter = CGAL::make_object (left_v); - ++out_iter; - } - else if (left_he != invalid_he) - { - *out_iter = CGAL::make_object (left_he); - ++out_iter; - } + if (left_v != invalid_v) *out_iter++ = Zone_result(left_v); + else if (left_he != invalid_he) *out_iter++ = Zone_result(left_he); output_left = false; } // Report the face that contains the interior of the subcurve. - *out_iter = CGAL::make_object (face); - ++out_iter; + *out_iter++ = Zone_result(face); // If the right endpoint of the subcurve is incident to an arrangement // vertex or an arrangement edge, report this feature. - if (right_v != invalid_v) - { - *out_iter = CGAL::make_object(right_v); - ++out_iter; - } - else if (right_he != invalid_he) - { - *out_iter = CGAL::make_object(right_he); - ++out_iter; - } + if (right_v != invalid_v) *out_iter++ = Zone_result(right_v); + else if (right_he != invalid_he) *out_iter++ = Zone_result(right_he); // We did not modify the arrangement, so we return an invalid handle // and a flag indicating that the zone-computation process should continue. - return (Result (invalid_he, false)); + return Result(invalid_he, false); } /*! @@ -151,35 +138,28 @@ public: Halfedge_handle he, Vertex_handle left_v, Vertex_handle right_v) { - if (output_left) - { + typedef boost::variant + Zone_result; + + if (output_left) { // Only the first subcurve should output the arrangement feature incident // to its left endpoint. This way we avoid reporting the same feature // twice. - if (left_v != invalid_v) - { - *out_iter = CGAL::make_object (left_v); - ++out_iter; - } + if (left_v != invalid_v) *out_iter++ = Zone_result(left_v); output_left = false; } // Report the arrangement edge the curve currently overlaps. - *out_iter = CGAL::make_object(he); - ++out_iter; + *out_iter++ = Zone_result(he); // If the right endpoint of the overlapping subcurve is incident to an // arrangement vertex, report this vertex as well. - if (right_v != invalid_v) - { - *out_iter = CGAL::make_object (right_v); - ++out_iter; - } + if (right_v != invalid_v) *out_iter++ = Zone_result(right_v); // We did not modify the arrangement, so we return an invalid handle // and a flag indicating that the zone-computation process should continue. - return (Result (invalid_he, false)); + return Result(invalid_he, false); } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_traits_adaptor_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_traits_adaptor_2.h index 879ec2625ae..2140fb0630a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_traits_adaptor_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arr_traits_adaptor_2.h @@ -8,7 +8,6 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // $Date$ // -// // Author(s): Ron Wein s // Efi Fogel // Eric Berberich @@ -24,7 +23,6 @@ #include - /*! \file * Definitions of the adaptor classes for the arrangement traits class. */ @@ -50,6 +48,7 @@ public: typedef Arr_traits_basic_adaptor_2 Self; typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; typedef typename Base::Point_2 Point_2; + typedef typename Base::Multiplicity Multiplicity; // Categories typedef typename Base::Has_left_category Has_left_category; @@ -320,9 +319,12 @@ public: const X_monotone_curve_2& xcv2, Tag_false) const { - std::list intersections; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + std::list intersections; m_self->intersect_2_object()(xcv1, xcv2, back_inserter(intersections)); - return !intersections.empty(); + return ! intersections.empty(); } }; @@ -665,7 +667,7 @@ public: return parameter_space_in_y(xcv, ind, Psy_2_curve_end_tag()); } - /*! + /*! * Obtain the location of the given curve end in y. * \param xcv The curve. * \return The location of the curve end in y direction. @@ -2276,6 +2278,7 @@ public: typedef typename Base_traits_2::Curve_2 Curve_2; typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; typedef typename Base::Point_2 Point_2; + typedef typename Base::Multiplicity Multiplicity; // Categories. typedef typename Base::Has_left_category Has_left_category; @@ -2324,6 +2327,10 @@ public: * endpoint, then by the graphs, and finally by their right-most endpoint. */ class Compare_xy_2 { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + public: /*! Compare two points lexigoraphically: by x, then by y. * \param p1 the first point. @@ -2360,7 +2367,7 @@ public: Comparison_result operator()(const X_monotone_curve_2& c1, const X_monotone_curve_2& c2) const { - std::list intersections; + std::list intersections; return operator()(c1, c2, intersections, Are_all_sides_oblivious_category()); } @@ -2586,7 +2593,7 @@ public: Comparison_result compare_remainder(const X_monotone_curve_2& c1, const X_monotone_curve_2& c2, - std::list& intersections) const + std::list& intersections) const { // Right-most sections are equal. // Advance to the next respective sections: @@ -2597,9 +2604,9 @@ public: } // Verify the first intersection is an overlap, remove it, and // recursively call. - CGAL::Object first = intersections.front(); - X_monotone_curve_2 xcv; - if (!assign(xcv, first)) { + const X_monotone_curve_2* xcv = + boost::get(&(intersections.front())); + if (! xcv) { CGAL_error_msg("The first intersection is not an overlap!"); return SMALLER; } @@ -2611,10 +2618,9 @@ public: typedef typename Self::Split_2 Split_2; Split_2 split = m_self.split_2_object(); X_monotone_curve_2 c11, c12, c21, c22; - Construct_max_vertex_2 ctr_max = - m_self.construct_max_vertex_2_object(); - const Point_2& p1 = ctr_max(xcv); - const Point_2& p2 = ctr_max(xcv); + Construct_max_vertex_2 ctr_max = m_self.construct_max_vertex_2_object(); + const Point_2& p1 = ctr_max(*xcv); + const Point_2& p2 = ctr_max(*xcv); split(c1, p1, c11, c12); split(c2, p2, c21, c22); return operator()(c12, c22, intersections, @@ -2625,7 +2631,7 @@ public: */ Comparison_result operator()(const X_monotone_curve_2& c1, const X_monotone_curve_2& c2, - std::list& intersections, + std::list& intersections, Arr_all_sides_oblivious_tag) const { const Point_2& c1_min = m_self.construct_min_vertex_2_object()(c1); @@ -2646,7 +2652,7 @@ public: */ Comparison_result operator()(const X_monotone_curve_2& c1, const X_monotone_curve_2& c2, - std::list& intersections, + std::list& intersections, Arr_not_all_sides_oblivious_tag) const { typedef typename Base::Parameter_space_in_x_2 Parameter_space_in_x_2; diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_global.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_global.h index 73fcc93fccc..748dad78195 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_global.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_global.h @@ -8,9 +8,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Baruch Zukerman -// Efi Fogel +// Author(s): Ron Wein +// Baruch Zukerman +// Efi Fogel // #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_GLOBAL_H #define CGAL_ARRANGEMENT_ON_SURFACE_2_GLOBAL_H @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,10 @@ void insert(Arrangement_on_surface_2& arr, typedef Arrangement_on_surface_2 Arr; typedef ZoneVisitor Zone_visitor; + typedef typename Gt2::Point_2 Point_2; + typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2; + typedef boost::variant Make_x_monotone_result; + // Obtain an arrangement accessor. Arr_accessor arr_access(arr); @@ -88,19 +93,14 @@ void insert(Arrangement_on_surface_2& arr, Arrangement_zone_2 arr_zone(arr, &visitor); // Break the input curve into x-monotone subcurves and isolated points. - std::list x_objects; - std::list::const_iterator obj_iter; - const typename Gt2::X_monotone_curve_2* x_curve; - const typename Gt2::Point_2* iso_p; - - arr.geometry_traits()-> - make_x_monotone_2_object()(c, std::back_inserter(x_objects)); + std::list x_objects; + const auto* traits = arr.geometry_traits(); + traits->make_x_monotone_2_object()(c, std::back_inserter(x_objects)); // Insert each x-monotone curve into the arrangement. - for (obj_iter = x_objects.begin(); obj_iter != x_objects.end(); ++obj_iter) { + for (const auto& x_obj : x_objects) { // Act according to the type of the current object. - x_curve = object_cast(&(*obj_iter)); - + const auto* x_curve = boost::get(&x_obj); if (x_curve != nullptr) { // Inserting an x-monotone curve: // Initialize the zone-computation object with the given curve. @@ -116,14 +116,13 @@ void insert(Arrangement_on_surface_2& arr, // Notify the arrangement observers that the global operation has been // completed. arr_access.notify_after_global_change(); + continue; } - else { - iso_p = object_cast(&(*obj_iter)); - CGAL_assertion(iso_p != nullptr); + const auto* iso_p = boost::get(&x_obj); + CGAL_assertion(iso_p != nullptr); - // Inserting a point into the arrangement: - insert_point(arr, *iso_p, pl); - } + // Inserting a point into the arrangement: + insert_point(arr, *iso_p, pl); } } @@ -529,7 +528,9 @@ void insert(Arrangement_on_surface_2& arr, template void insert(Arrangement_on_surface_2& arr, const typename GeometryTraits_2::X_monotone_curve_2& c, - const Object& obj) + typename Arr_point_location_result< + Arrangement_on_surface_2 >::type obj) { typedef GeometryTraits_2 Gt2; typedef TopologyTraits Tt; @@ -597,7 +598,8 @@ template CGAL_DEPRECATED void insert_x_monotone_curve (Arrangement_on_surface_2& arr, const typename GeometryTraits_2::X_monotone_curve_2& c, - const Object& obj) + typename Arr_point_location_result< + Arrangement_on_surface_2 >::type obj) { insert(arr, c, obj); } @@ -658,6 +660,7 @@ insert_non_intersecting_curve Traits_adaptor_2; typedef typename Arr::Vertex_const_handle Vertex_const_handle; typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; CGAL_USE_TYPE(Halfedge_const_handle); const Traits_adaptor_2* geom_traits = @@ -666,13 +669,13 @@ insert_non_intersecting_curve // Check whether the left end has boundary conditions, and locate it in the // arrangement accordingly. - const Arr_parameter_space bx1 = - geom_traits->parameter_space_in_x_2_object()(c, ARR_MIN_END); - const Arr_parameter_space by1 = - geom_traits->parameter_space_in_y_2_object()(c, ARR_MIN_END); - CGAL::Object obj1; + auto bx1 = geom_traits->parameter_space_in_x_2_object()(c, ARR_MIN_END); + auto by1 = geom_traits->parameter_space_in_y_2_object()(c, ARR_MIN_END); const Vertex_const_handle* vh1 = nullptr; + typedef Arr_point_location_result Pl_result; + + typename Pl_result::type obj1; if ((bx1 == ARR_INTERIOR) && (by1 == ARR_INTERIOR)) { // We have a normal left endpoint with no boundary conditions: // use a point-location query. @@ -680,33 +683,26 @@ insert_non_intersecting_curve // The endpoint must not lie on an existing edge, but may coincide with // and existing vertex vh1. - CGAL_precondition_msg - (object_cast(&obj1) == nullptr, - "The curve must not intersect an existing edge."); + CGAL_precondition_msg(boost::get(&obj1) == nullptr, + "The curve must not intersect an existing edge."); - vh1 = object_cast(&obj1); } else { // We have a left end with boundary conditions. Use the accessor to locate // the feature that contains it. obj1 = arr_access.locate_curve_end(c, ARR_MIN_END, bx1, by1); - - CGAL_precondition_msg - (object_cast(&obj1) == nullptr, - "The curve must not overlap an existing edge."); - - vh1 = object_cast(&obj1); + CGAL_precondition_msg(boost::get(&obj1) == nullptr, + "The curve must not overlap an existing edge."); } + vh1 = Pl_result::template assign(&obj1); // Check whether the right end has boundary conditions, and locate it in the // arrangement accordingly. - const Arr_parameter_space bx2 = - geom_traits->parameter_space_in_x_2_object()(c, ARR_MAX_END); - const Arr_parameter_space by2 = - geom_traits->parameter_space_in_y_2_object()(c, ARR_MAX_END); - CGAL::Object obj2; + auto bx2 = geom_traits->parameter_space_in_x_2_object()(c, ARR_MAX_END); + auto by2 = geom_traits->parameter_space_in_y_2_object()(c, ARR_MAX_END); const Vertex_const_handle* vh2 = nullptr; + typename Pl_result::type obj2; if ((bx2 == ARR_INTERIOR) && (by2 == ARR_INTERIOR)) { // We have a normal right endpoint with no boundary conditions: // use a point-location query. @@ -714,11 +710,8 @@ insert_non_intersecting_curve // The endpoint must not lie on an existing edge, but may coincide with // and existing vertex vh2. - CGAL_precondition_msg - (object_cast(&obj2) == nullptr, - "The curve must not intersect an existing edge."); - - vh2 = object_cast(&obj2); + CGAL_precondition_msg(boost::get(&obj2) == nullptr, + "The curve must not intersect an existing edge."); } else { // We have a right end with boundary conditions. Use the accessor to locate @@ -728,13 +721,10 @@ insert_non_intersecting_curve // << ", by2: " << by2 // << std::endl; obj2 = arr_access.locate_curve_end(c, ARR_MAX_END, bx2, by2); - - CGAL_precondition_msg - (object_cast(&obj2) == nullptr, - "The curve must not overlap an existing edge."); - - vh2 = object_cast(&obj2); + CGAL_precondition_msg(boost::get(&obj2) == nullptr, + "The curve must not overlap an existing edge."); } + vh2 = Pl_result::template assign(&obj2); // Notify the arrangement observers that a global operation is about to // take place. @@ -776,10 +766,8 @@ insert_non_intersecting_curve // we must insert the curve in the interior of a face. // In this case insert_in_face_interior() already returns a halfedge // directed from left to right. - const typename Arr::Face_const_handle* fh1 = - object_cast(&obj1); - const typename Arr::Face_const_handle* fh2 = - object_cast(&obj2); + const Face_const_handle* fh1 = boost::get(&obj1); + const Face_const_handle* fh2 = boost::get(&obj2); // std::cout << arr << std::endl; // std::cout << "(*fh1)->number_of_outer_ccbs(): " @@ -1140,49 +1128,49 @@ insert_point(Arrangement_on_surface_2& arr, typedef Arrangement_on_surface_2 Arr; + typedef typename Arr::Vertex_const_handle Vertex_const_handle; + typedef typename Arr::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arr::Face_const_handle Face_const_handle; + // Act according to the type of arrangement feature that contains the point. - const typename Arr::Face_const_handle* fh; - const typename Arr::Halfedge_const_handle* hh; - const typename Arr::Vertex_const_handle* vh; typename Arr::Vertex_handle vh_for_p; // Locate the given point in the arrangement. - CGAL::Object obj = pl.locate (p); + auto obj = pl.locate(p); // Notify the arrangement observers that a global operation is about to // take place. - Arr_accessor arr_access (arr); + Arr_accessor arr_access(arr); arr_access.notify_before_global_change(); - if ((fh = object_cast(&obj)) != nullptr) { + const Face_const_handle* fh = boost::get(&obj); + if (fh != nullptr) { // p lies inside a face: Insert it as an isolated vertex it the interior of // this face. vh_for_p = arr.insert_in_face_interior(p, arr.non_const_handle (*fh)); } - else if ((hh = object_cast(&obj)) != - nullptr) - { - // p lies in the interior of an edge: Split this edge to create a new - // vertex associated with p. - typename Gt2::X_monotone_curve_2 sub_cv1, sub_cv2; - typename Arr::Halfedge_handle split_he; - - arr.geometry_traits()->split_2_object()((*hh)->curve(), p, - sub_cv1, sub_cv2); - - split_he = arr.split_edge(arr.non_const_handle(*hh), sub_cv1, sub_cv2); - - // The new vertex is the target of the returned halfedge. - vh_for_p = split_he->target(); - } else { - // In this case p lies on an existing vertex, so we just update this - // vertex. - vh = object_cast(&obj); - CGAL_assertion (vh != nullptr); + const Halfedge_const_handle* hh = boost::get(&obj); + if (hh != nullptr) { + // p lies in the interior of an edge: Split this edge to create a new + // vertex associated with p. + typename Gt2::X_monotone_curve_2 sub_cv1, sub_cv2; + typename Arr::Halfedge_handle split_he; - vh_for_p = arr.modify_vertex (arr.non_const_handle (*vh), p); + const auto* gt = arr.geometry_traits(); + gt->split_2_object()((*hh)->curve(), p, sub_cv1, sub_cv2); + split_he = arr.split_edge(arr.non_const_handle(*hh), sub_cv1, sub_cv2); + + // The new vertex is the target of the returned halfedge. + vh_for_p = split_he->target(); + } + else { + // p lies on an existing vertex, so we just update this vertex. + const Vertex_const_handle* vh = boost::get(&obj); + CGAL_assertion(vh != nullptr); + vh_for_p = arr.modify_vertex (arr.non_const_handle (*vh), p); + } } // Notify the arrangement observers that the global operation has been @@ -1381,60 +1369,47 @@ is_valid(const Arrangement_on_surface_2& arr) // Shoot a vertical ray from each vertex we have collected downward, and // check that this vertex is really contained in the proper face. - typename Gt2::Compare_y_at_x_right_2 comp_y_at_x_right = - traits->compare_y_at_x_right_2_object(); - typename Gt2::Compare_y_at_x_left_2 comp_y_at_x_left = - traits->compare_y_at_x_left_2_object(); + auto comp_y_at_x_right = traits->compare_y_at_x_right_2_object(); + auto comp_y_at_x_left = traits->compare_y_at_x_left_2_object(); - typename std::list >::iterator vf_iter; typename Tt::Default_point_location_strategy def_pl(arr); - Vertex_const_handle curr_v; - Object obj; - Halfedge_const_handle he_below; - Vertex_const_handle v_below; - Face_const_handle in_face; - Halfedge_around_vertex_const_circulator first, circ; - bool assign_ok; const Halfedge_const_handle invalid_he; - for (vf_iter = vf_list.begin(); vf_iter != vf_list.end(); ++vf_iter) { + Face_const_handle in_face; + for (auto vf_iter = vf_list.begin(); vf_iter != vf_list.end(); ++vf_iter) { // Perform ray-shooting from the current vertex. - curr_v = vf_iter->first; - obj = def_pl.ray_shoot_down(curr_v->point()); + Vertex_const_handle curr_v = vf_iter->first; + auto obj = def_pl.ray_shoot_down(curr_v->point()); - if (CGAL::assign(he_below, obj)) { - // Hit an edge - take the incident face of the halfedge directed to the + // if (CGAL::assign(he_below, obj)) { + if (auto* he_below_p = boost::get(&obj)) { + // Hit an edge; take the incident face of the halfedge directed to the // right. - if (he_below->direction() == ARR_RIGHT_TO_LEFT) - he_below = he_below->twin(); - - in_face = he_below->face(); + auto he_below = *he_below_p; + in_face = (he_below->direction() == ARR_RIGHT_TO_LEFT) ? + he_below->twin()->face() : he_below->face(); } - else if (CGAL::assign(v_below, obj)) { + else if (auto* v_below_p = boost::get(&obj)) { + auto v_below = *v_below_p; // Hit a vertex. if (v_below->is_isolated()) in_face = v_below->face(); else { // Get the first halfedge around v_below that is directed from left to // right and the first halfedge that is directed from right to left. - first = circ = v_below->incident_halfedges(); + Halfedge_around_vertex_const_circulator circ = + v_below->incident_halfedges(); + Halfedge_around_vertex_const_circulator first = circ; Halfedge_const_handle he_left; // A halfedge to the left of v_below. Halfedge_const_handle he_right; // A halfedge to the right of v_below. - do { - if (circ->direction() == ARR_LEFT_TO_RIGHT) { - he_left = circ; - } + if (circ->direction() == ARR_LEFT_TO_RIGHT) he_left = circ; else { he_right = circ; - if (he_left != invalid_he && he_right != invalid_he) - break; + if ((he_left != invalid_he) && (he_right != invalid_he)) break; } - ++circ; + } while(++circ != first); - } while(circ != first); - - CGAL_assertion (he_left != invalid_he || he_right != invalid_he); + CGAL_assertion((he_left != invalid_he) || (he_right != invalid_he)); if (he_left != invalid_he && he_right != invalid_he) { while (he_left->direction() == ARR_LEFT_TO_RIGHT) @@ -1460,26 +1435,24 @@ is_valid(const Arrangement_on_surface_2& arr) else { Comparison_result res; Halfedge_const_handle he_curr = he_right; - - do // as long as we have he_right halfedge which is below - { + do { + // as long as we have he_right halfedge which is below he_right = he_curr; he_curr = he_right->next()->twin(); - res = comp_y_at_x_right (he_curr->curve(), - he_right->curve(), - v_below->point()); + res = comp_y_at_x_right(he_curr->curve(), + he_right->curve(), + v_below->point()); } while(res == SMALLER); in_face = he_right->face(); } } } else { + auto* in_face_p = boost::get(&obj); + CGAL_assertion(in_face_p); + in_face = *in_face_p; // Hit nothing (an unbounded face is returned). - assign_ok = CGAL::assign(in_face, obj); - - CGAL_assertion (assign_ok && in_face->is_unbounded()); - - if (! assign_ok) return false; + CGAL_assertion(in_face->is_unbounded()); } if (vf_iter->second != in_face) { @@ -1611,35 +1584,34 @@ do_intersect(Arrangement_on_surface_2& arr, // Break the input curve into x-monotone subcurves and isolated points. typedef Arr_traits_adaptor_2 Traits_adaptor_2; + typedef typename Gt2::Point_2 Point_2; + typedef typename Gt2::X_monotone_curve_2 X_monotone_curve_2; + typedef boost::variant Make_x_monotone_result; + typedef typename Arr::Face_const_handle Face_const_handle; + const Traits_adaptor_2* traits = static_cast(arr.geometry_traits()); - std::list x_objects; - std::list::const_iterator obj_iter; - const typename Gt2::X_monotone_curve_2* x_curve; - const typename Gt2::Point_2* iso_p; - + std::list x_objects; traits->make_x_monotone_2_object()(c, std::back_inserter(x_objects)); // Insert each x-monotone curve into the arrangement. - for (obj_iter = x_objects.begin(); obj_iter != x_objects.end(); ++obj_iter) { + for (const auto& x_obj : x_objects) { // Act according to the type of the current object. - x_curve = object_cast(&(*obj_iter)); + const X_monotone_curve_2* x_curve = boost::get(&x_obj); if (x_curve != nullptr) { // Check if the x-monotone subcurve intersects the arrangement. - if (do_intersect(arr, *x_curve, pl) == true) - return true; + if (do_intersect(arr, *x_curve, pl) == true) return true; + continue; } - else { - iso_p = object_cast(&(*obj_iter)); - CGAL_assertion(iso_p != nullptr); - // Check whether the isolated point lies inside a face (otherwise, - // it conincides with a vertex or an edge). - CGAL::Object obj = pl.locate (*iso_p); + const Point_2* iso_p = boost::get(&x_obj); + CGAL_assertion(iso_p != nullptr); - return (object_cast(&obj) != nullptr); - } + // Check whether the isolated point lies inside a face (otherwise, + // it conincides with a vertex or an edge). + auto obj = pl.locate(*iso_p); + if (boost::get(&x_obj) != nullptr) return true; } // If we reached here, the curve does not intersect the arrangement. @@ -1651,8 +1623,8 @@ do_intersect(Arrangement_on_surface_2& arr, template bool -do_intersect (Arrangement_on_surface_2& arr, - const Curve& c, const PointLocation& pl) +do_intersect(Arrangement_on_surface_2& arr, + const Curve& c, const PointLocation& pl) { typedef GeometryTraits_2 Gt2; diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h index 8c3fd571803..7b714c12412 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_on_surface_2_impl.h @@ -7,16 +7,15 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein -// Efi Fogel -// Eric Berberich -// (based on old version by: Iddo Hanniel, -// Eyal Flato, -// Oren Nechushtan, -// Ester Ezra, -// Shai Hirsch, -// and Eugene Lipovetsky) +// Author(s): Ron Wein +// Efi Fogel +// Eric Berberich +// (based on old version by: Iddo Hanniel, +// Eyal Flato, +// Oren Nechushtan, +// Ester Ezra, +// Shai Hirsch, +// and Eugene Lipovetsky) #ifndef CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H #define CGAL_ARRANGEMENT_ON_SURFACE_2_IMPL_H @@ -32,6 +31,8 @@ * class-template. */ +#include + #include #include @@ -2195,16 +2196,30 @@ _place_and_set_curve_end(DFace* f, { // Use the topology traits to locate the DCEL feature that contains the // given curve end. - CGAL::Object obj = - m_topol_traits.place_boundary_vertex(f, cv, ind, ps_x, ps_y); - DVertex* v; - DHalfedge* fict_he; - + auto obj = m_topol_traits.place_boundary_vertex(f, cv, ind, ps_x, ps_y); // Act according to the result type. - if (CGAL::assign(fict_he, obj)) { + + if (! obj) { + // We have to create a new vertex that reprsents the given curve end. + DVertex* v = _create_boundary_vertex(cv, ind, ps_x, ps_y); + + // Notify the topology traits on the creation of the boundary vertex. + m_topol_traits.notify_on_boundary_vertex_creation(v, cv, ind, ps_x, ps_y); + + // There are no edges incident to v, therefore no predecessor halfedge. + *p_pred = nullptr; + + // Return the vertex that represents the curve end. + return v; + } + + DHalfedge** fict_he_p = boost::get(&*obj); + if (fict_he_p != nullptr) { + DHalfedge* fict_he = *fict_he_p; + CGAL_assertion(fict_he != nullptr); // The curve end is located on a fictitious edge. We first create a new // vertex that corresponds to the curve end. - v = _create_boundary_vertex(cv, ind, ps_x, ps_y); + DVertex* v = _create_boundary_vertex(cv, ind, ps_x, ps_y); // Split the fictitious halfedge at the newly created vertex. // The returned halfedge is the predecessor for the insertion of the curve @@ -2216,29 +2231,16 @@ _place_and_set_curve_end(DFace* f, _notify_after_split_fictitious_edge(Halfedge_handle(*p_pred), Halfedge_handle((*p_pred)->next())); + return v; } - else if (CGAL::assign(v, obj)) { - // In this case we are given an existing vertex that represents the curve - // end. We now have to locate the predecessor edge for the insertion of cv - // around this vertex. - *p_pred = - m_topol_traits.locate_around_boundary_vertex(v, cv, ind, ps_x, ps_y); - } - else { - CGAL_assertion(obj.is_empty()); - - // In this case we have to create a new vertex that reprsents the given - // curve end. - v = _create_boundary_vertex(cv, ind, ps_x, ps_y); - - // Notify the topology traits on the creation of the boundary vertex. - m_topol_traits.notify_on_boundary_vertex_creation(v, cv, ind, ps_x, ps_y); - - // There are no edges incident to v, therefore no predecessor halfedge. - *p_pred = nullptr; - } - - // Return the vertex that represents the curve end. + DVertex** v_p = boost::get(&*obj); + CGAL_assertion(v_p != nullptr); + DVertex* v = *v_p; + CGAL_assertion(v != nullptr); + // In this case we are given an existing vertex that represents the curve + // end. We now have to locate the predecessor edge for the insertion of cv + // around this vertex. + *p_pred = m_topol_traits.locate_around_boundary_vertex(v, cv, ind, ps_x, ps_y); return v; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h index 1a88af753c2..97e868c0d4a 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_2/Arrangement_zone_2_impl.h @@ -29,7 +29,7 @@ namespace CGAL { // template void Arrangement_zone_2:: -init_with_hint(const X_monotone_curve_2& cv, const Object& obj) +init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj) { // Set the curve and check whether its ends are bounded, therefore // associated with valid endpoints. @@ -95,9 +95,8 @@ void Arrangement_zone_2::compute_zone() // curve (currently m_obj stores the object containing it). const Vertex_const_handle* vh; const Halfedge_const_handle* hh; - const Face_const_handle* fh; - if ((vh = object_cast(&m_obj)) != nullptr) { + if ((vh = boost::get(&m_obj)) != nullptr) { CGAL_assertion(m_has_left_pt); // The left endpoint coincides with an existing vertex: @@ -119,7 +118,7 @@ void Arrangement_zone_2::compute_zone() #endif } - else if ((hh = object_cast(&m_obj)) != nullptr) { + else if ((hh = boost::get(&m_obj)) != nullptr) { if (m_has_left_pt) { // Obtain the right halfedge from the halfedge-pair containing m_left_pt // in their interior. @@ -160,7 +159,7 @@ void Arrangement_zone_2::compute_zone() } else { // The left endpoint lies inside a face. - fh = object_cast(&m_obj); + const Face_const_handle* fh = boost::get(&m_obj); CGAL_assertion_msg(fh != nullptr, "Invalid object returned by the point-location query."); diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h index 32a8a42a10c..fd441863314 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_on_surface_2.h @@ -2832,7 +2832,8 @@ void insert(Arrangement_on_surface_2& arr, template void insert(Arrangement_on_surface_2& arr, const typename GeomTraits::X_monotone_curve_2& c, - const Object& obj); + typename Arr_point_location_result< + Arrangement_on_surface_2 >::type obj); /*! * Insert an x-monotone curve into the arrangement, such that the curve @@ -2948,16 +2949,16 @@ remove_vertex(Arrangement_on_surface_2& arr, template bool is_valid(const Arrangement_on_surface_2& arr); -/*! - * Compute the zone of the given x-monotone curve in the existing arrangement. +/*! Compute the zone of the given x-monotone curve in the existing arrangement. * Meaning, it output the arrangment's vertices, edges and faces that the * x-monotone curve intersects. * \param arr The arrangement. - * \param c The x-monotone curve that its zone was computed. - * \param oi Output iterator of CGAL::Object to insert the zone elements to. - * \param pi The point location strategy that is used to locate the starting - * point. - * \return The output iterator that the curves were inserted to. + * \param c the x-monotone curve that its zone is computed. + * \param oi the output iterator for the resulting zone elements. Its + * dereference type is a variant that wraps a \c Vertex_handle, a + * \c Halfedge_handle, or a \c Face_handle. + * \param pl the point location strategy used to locate the starting point. + * \return the past-the-end output iterator. */ template @@ -2971,9 +2972,11 @@ OutputIterator zone(Arrangement_on_surface_2& arr, * Overloaded version with no point location object - the walk point-location * strategy is used as default. * \param arr The arrangement. - * \param c The x-monotone curve that its zone was computed. - * \param oi Output iterator of CGAL::Object to insert the zone elements to. - * \return The output iterator that the curves were inserted to. + * \param c the x-monotone curve that its zone was computed. + * \param oi the output iterator for the resulting zone elements. Its + * dereference type is a variant that wraps a \c Vertex_handle, a + * \c Halfedge_handle, or a \c Face_handle. + * \return the past-the-end output iterator. */ template OutputIterator zone(Arrangement_on_surface_2& arr, diff --git a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h index 55616307cd0..be08099796f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,9 @@ protected: typedef std::set Curves_set; typedef typename Curves_set::iterator Curves_set_iterator; + typedef Arr_point_location_result Pl_result; + typedef typename Pl_result::Type Pl_result_type; + // Data members: Arrangement_2& m_arr; // The associated arrangement. const Traits_adaptor_2* m_geom_traits; // Its associated geometry traits. @@ -127,7 +131,7 @@ protected: X_monotone_curve_2 m_cv; // The current portion of the // inserted curve. - CGAL::Object m_obj; // The location of the left endpoint. + Pl_result_type m_obj; // The location of the left endpoint. bool m_has_left_pt; // Is the left end of the curve bounded. bool m_left_on_boundary; // Is the left point on the boundary. Point_2 m_left_pt; // Its current left endpoint. @@ -247,7 +251,7 @@ public: * \param obj An object that represents the location of the left end of the * curve. */ - void init_with_hint(const X_monotone_curve_2& cv, const Object& obj); + void init_with_hint(const X_monotone_curve_2& cv, Pl_result_type obj); /*! Compute the zone of the given curve and issue the apporpriate * notifications for the visitor. diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h index de6f2e14529..b8dd6eaf6f9 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Curved_kernel_via_analysis_2_functors.h @@ -1410,9 +1410,9 @@ public: * Functor that computes the intersections of two arcs */ template < class CurvedKernelViaAnalysis_2 > -class Intersect_2 : public -Curved_kernel_via_analysis_2_functor_base< CurvedKernelViaAnalysis_2 > { - +class Intersect_2 : + public Curved_kernel_via_analysis_2_functor_base +{ public: //! this instance' first template parameter typedef CurvedKernelViaAnalysis_2 Curved_kernel_via_analysis_2; @@ -1420,13 +1420,17 @@ public: //! the base type typedef Curved_kernel_via_analysis_2_functor_base< Curved_kernel_via_analysis_2 > - Base; + Base; CGAL_CKvA_2_GRAB_BASE_FUNCTOR_TYPES + typedef unsigned int Multiplicity; + typedef std::pair Intersection_point; + typedef boost::variant Intersection_result; + //! the result type - typedef CGAL::cpp98::iterator< std::output_iterator_tag, CGAL::Object > - result_type; + typedef CGAL::cpp98::iterator + result_type; //! the arity of the functor @@ -1458,11 +1462,6 @@ public: template < class OutputIterator > OutputIterator operator()(const Arc_2& cv1, const Arc_2& cv2, OutputIterator oi) const { - - typedef unsigned int Multiplicity; - typedef std::pair Intersection_point; - typedef boost::variant Intersection_result; - CERR("\nintersect; cv1: " << cv1 << ";\n cv2:" << cv2 << ""); @@ -1860,100 +1859,110 @@ public: /*!\brief * Functor that decomposes curve into x-monotone arcs and isolated points */ -template < class CurvedKernelViaAnalysis_2 > +template class Make_x_monotone_2 : public -Curved_kernel_via_analysis_2_functor_base< CurvedKernelViaAnalysis_2 > { +Curved_kernel_via_analysis_2_functor_base { public: - //! this instance' first template parameter - typedef CurvedKernelViaAnalysis_2 Curved_kernel_via_analysis_2; + //! this instance' first template parameter + typedef CurvedKernelViaAnalysis_2 Curved_kernel_via_analysis_2; - //! the base type - typedef - Curved_kernel_via_analysis_2_functor_base< Curved_kernel_via_analysis_2 > + //! the base type + typedef + Curved_kernel_via_analysis_2_functor_base< Curved_kernel_via_analysis_2> Base; - CGAL_CKvA_2_GRAB_BASE_FUNCTOR_TYPES + CGAL_CKvA_2_GRAB_BASE_FUNCTOR_TYPES - //! the result type - typedef CGAL::cpp98::iterator< std::output_iterator_tag, CGAL::Object > + //! the result type + typedef CGAL::cpp98::iterator< std::output_iterator_tag, CGAL::Object> result_type; - //! the arity of the functor + //! the arity of the functor - /*!\brief - * Standard constructor - * - * \param kernel The kernel - */ - Make_x_monotone_2(Curved_kernel_via_analysis_2 *kernel) : - Base(kernel) { - } + /*!\brief + * Standard constructor + * + * \param kernel The kernel + */ + Make_x_monotone_2(Curved_kernel_via_analysis_2* kernel) : + Base(kernel) + {} - /*!\brief - * Decomposes a given arc into list of x-monotone arcs - * (subcurves) and insert them to the output iterator. Since \c Arc_2 - * is by definition x-monotone, an input arc is passed to the - * output iterator directly. - * - * \param cv The arc - * \param oi The output iterator, whose value-type is Object - * The returned objects are all wrappers Arc_2 objects - * \return The past-the-end iterator - */ - template < class OutputIterator > - OutputIterator operator()(const Arc_2& cv, OutputIterator oi) const { + /*!\brief + * Decomposes a given arc into list of x-monotone arcs + * (subcurves) and insert them to the output iterator. Since \c Arc_2 + * is by definition x-monotone, an input arc is passed to the + * output iterator directly. + * + * \param cv The arc + * \param oi The output iterator, whose value-type is Object + * The returned objects are all wrappers Arc_2 objects + * \return The past-the-end iterator + */ + template + OutputIterator operator()(const Arc_2& cv, OutputIterator oi) const + { + typedef typename Curved_kernel_via_analysis_2::Point_2 Point_2; + typedef typename Curved_kernel_via_analysis_2::Arc_2 Arc_2; + typedef boost::variant Make_x_monotone_result; + *oi++ = Make_x_monotone_result(cv); + return oi; + } - *oi++ = CGAL::make_object(cv); - return oi; - } + /*!\brief + * Decomposes a given curve into list of x-monotone arcs + * (subcurves) and isolated points and insert them to the output iterator. + * + * \param cv The curve + * \param oi The output iterator, whose value-type is Object. + * The returned objects either wrapper Arc_2 or Point_2 objects + * \return The past-the-end iterator + */ + template + OutputIterator operator()(const Curve_analysis_2& cv, OutputIterator oi) + const + { + CGAL::internal::Make_x_monotone_2< Curved_kernel_via_analysis_2 > + make_x_monotone(Base::_ckva()); - /*!\brief - * Decomposes a given curve into list of x-monotone arcs - * (subcurves) and isolated points and insert them to the output iterator. - * - * \param cv The curve - * \param oi The output iterator, whose value-type is Object. - * The returned objects either wrapper Arc_2 or Point_2 objects - * \return The past-the-end iterator - */ - template < class OutputIterator > - OutputIterator operator()(const Curve_analysis_2& cv, OutputIterator oi) - const { + return make_x_monotone(cv, oi); + } - CGAL::internal::Make_x_monotone_2< Curved_kernel_via_analysis_2 > - make_x_monotone(Base::_ckva()); + /*!\brief + * Splits an input object \c obj into x-monotone arcs and isolated points + * + * \param obj the polymorph input object: can represet \c Point_2, + * \c Arc_2, \c Non_x_monotone_arc_2 or \c Curve_analysis_2 + * \param oi Output iterator that stores CGAL::Object, which either + * encapsulates \c Point_2 or \c Arc_2 + * \return Past-the-end iterator of \c oi + */ + template + OutputIterator operator()(CGAL::Object obj, OutputIterator oi) + { + typedef typename Curved_kernel_via_analysis_2::Point_2 Point_2; + typedef typename Curved_kernel_via_analysis_2::Arc_2 Arc_2; + typedef typename Curved_kernel_via_analysis_2::Non_x_monotone_arc_2 + Non_x_monotone_arc_2; + typedef boost::variant + Make_x_monotone_result; - return make_x_monotone(cv, oi); - } + Curve_analysis_2 curve; + Point_2 p; + Arc_2 xcv; + Non_x_monotone_arc_2 nxarc; - /*!\brief - * Splits an input object \c obj into x-monotone arcs and isolated points - * - * \param obj the polymorph input object: can represet \c Point_2, - * \c Arc_2, \c Non_x_monotone_arc_2 or \c Curve_analysis_2 - * \param oi Output iterator that stores CGAL::Object, which either - * encapsulates \c Point_2 or \c Arc_2 - * \return Past-the-end iterator of \c oi - */ - template - OutputIterator operator()(CGAL::Object obj, OutputIterator oi) { - - typedef typename Curved_kernel_via_analysis_2::Non_x_monotone_arc_2 - Non_x_monotone_arc_2; - Curve_analysis_2 curve; - Non_x_monotone_arc_2 nxarc; - - if(CGAL::assign(curve, obj)) - oi = (*this)(curve, oi); - else if(CGAL::assign(nxarc, obj)) - std::cerr << "AU BACKE" << std::endl; - //oi = std::transform(nxarc.begin(), nxarc.end(), oi, - // std::ptr_fun(CGAL::make_object)); - else // allow the remaining objects to pass through - *oi++ = obj; - return oi; - } + if (CGAL::assign(curve, obj)) oi = (*this)(curve, oi); + else if (CGAL::assign(nxarc, obj)) + std::cerr << "AU BACKE" << std::endl; + //oi = std::transform(nxarc.begin(), nxarc.end(), oi, + // std::ptr_fun(CGAL::make_object)); + else if (CGAL::assign(xcv, obj)) *oi++ = Make_x_monotone_result(xcv); + else if (CGAL::assign(p, obj)) *oi++ = Make_x_monotone_result(p); + else CGAL_error(); + return oi; + } }; diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Filtered_curved_kernel_via_analysis_2_impl.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Filtered_curved_kernel_via_analysis_2_impl.h index 38c8eda3412..dcd4bb372a0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Filtered_curved_kernel_via_analysis_2_impl.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Filtered_curved_kernel_via_analysis_2_impl.h @@ -169,12 +169,10 @@ public: Coordinate_1 asym_info1, asym_info2; CGAL::Arr_parameter_space ps1, ps2; - obj1 = cv1.curve().asymptotic_value_of_arc( - cv1.location(ce), cv1.arcno() - ); - obj2 = cv2.curve().asymptotic_value_of_arc( - cv2.location(ce), cv2.arcno() - ); + obj1 = + cv1.curve().asymptotic_value_of_arc(cv1.location(ce), cv1.arcno()); + obj2 = + cv2.curve().asymptotic_value_of_arc(cv2.location(ce), cv2.arcno()); CGAL::Comparison_result filter_res = CGAL::EQUAL; diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Make_x_monotone_2.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Make_x_monotone_2.h index e0a51c6565a..e667c90ea23 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Make_x_monotone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Make_x_monotone_2.h @@ -42,15 +42,26 @@ namespace internal { * Isolated points are stored as \c CurvedKernelViaAnalysis_2::Point_2 objects. * * The resulting arcs and points are written to the output iterator as - * polymorphic \c CGAL::Object. Past-the-end value of the iterator is returned. + * polymorphic \c variant. Past-the-end value of the iterator is returned. + * + * EF: I believe that the inheritance from binary_function is not exploited, + * and thus redundant, but I keep it anyway. */ template < class CurvedKernelViaAnalysis_2, class ConstructArc_2 = typename CurvedKernelViaAnalysis_2::Construct_arc_2 > struct Make_x_monotone_2 : - public CGAL::cpp98::binary_function< typename CurvedKernelViaAnalysis_2::Curve_2, - CGAL::cpp98::iterator, - CGAL::cpp98::iterator > { + public CGAL::cpp98::binary_function< + typename CurvedKernelViaAnalysis_2::Curve_2, + CGAL::cpp98::iterator >, + CGAL::cpp98::iterator > > +{ //!\name Public types //!@{ @@ -87,242 +98,250 @@ struct Make_x_monotone_2 : typedef typename Curved_kernel_via_analysis_2::Non_x_monotone_arc_2 Non_x_monotone_arc_2; - //!@} + //!@} - //!\name Constructors - //!@{ + //!\name Constructors + //!@{ - /*!\brief - * Standard constructor - * - * \param kernel The kernel instance to use - */ - Make_x_monotone_2(Curved_kernel_via_analysis_2 *kernel) : - _m_curved_kernel(kernel) { - CGAL_assertion(kernel != nullptr); + /*!\brief + * Standard constructor + * + * \param kernel The kernel instance to use + */ + Make_x_monotone_2(Curved_kernel_via_analysis_2 *kernel) : + _m_curved_kernel(kernel) + { + CGAL_assertion(kernel != nullptr); + } + + //!@} + + //!\name Functor invokation + //!@{ + + // TODO add operator for non-x-monotone arc + + /*!\brief + * Splits a curve into x-monotone arcs and isolated points + * + * \param curve The input curve + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a Point_2 or an X_monotone_curve_2 objects. + * \return Past-the-end iterator of \c oi + */ + template + OutputIterator operator()(Curve_analysis_2 curve, OutputIterator oi) + { + typedef boost::variant Make_x_monotone_result; + + Construct_arc_2 construct_arc_2 = + _m_curved_kernel->construct_arc_2_object(); + // use CGAL::Total_degree ? + if (typename CGAL::Polynomial_traits_d< + typename Curve_analysis_2::Polynomial_2 >:: + Total_degree()(curve.polynomial_2()) < 1) + { + return oi; } - //!@} + Status_line_1 evt_line1, evt_line2, + int_line = curve.status_line_of_interval(0); + int total_events = curve.number_of_status_lines_with_event(); + // handle special case of a curve without any events + if(total_events == 0) { + for (int k = 0; k < int_line.number_of_events(); k++) + *oi++ = Make_x_monotone_result(construct_arc_2(curve, k)); + return oi; + } + _m_curve = curve; + typedef typename Curved_kernel_via_analysis_2:: + Curve_interval_arcno_cache CIA_cache; + const CIA_cache& map_interval_arcno = + _m_curved_kernel->interval_arcno_cache(); - //!\name Functor invokation - //!@{ + typename Curved_kernel_via_analysis_2::Construct_point_2 + construct_point = + _m_curved_kernel->construct_point_2_object(); - // TODO add operator for non-x-monotone arc + typename CIA_cache::result_type info1, info2; + std::vector min_pts, max_pts; + Coordinate_1 min_x, max_x; + int i, k, n; + Arc_2 arc; + // first handle segments before first event + evt_line1 = curve.status_line_at_event(0); + max_x = evt_line1.x(); - /*!\brief - * Splits a curve into x-monotone arcs and isolated points - * - * \param curve The input curve - * \param oi Output iterator that stores CGAL::Object, which either - * encapsulates Point_2 or Arc_2 - * \return Past-the-end iterator of \c oi - */ - template - OutputIterator operator()(Curve_analysis_2 curve, OutputIterator oi) { + for (k = 0; k < evt_line1.number_of_events(); k++) + max_pts.push_back(construct_point(max_x, curve, k)); - Construct_arc_2 construct_arc_2 = - _m_curved_kernel->construct_arc_2_object(); - // use CGAL::Total_degree ? - if (typename CGAL::Polynomial_traits_d< - typename Curve_analysis_2::Polynomial_2 >:: - Total_degree()(curve.polynomial_2()) < 1) { - return oi; - } + //std::cout << "handling events over the 1st interval\n"; + for (k = 0; k < int_line.number_of_events(); k++) { - Status_line_1 evt_line1, evt_line2, - int_line = curve.status_line_of_interval(0); - int total_events = curve.number_of_status_lines_with_event(); - // handle special case of a curve without any events - if(total_events == 0) { - for(int k = 0; k < int_line.number_of_events(); k++) - *oi++ = CGAL::make_object(construct_arc_2(curve, k)); - return oi; - } - _m_curve = curve; - typedef typename Curved_kernel_via_analysis_2:: - Curve_interval_arcno_cache CIA_cache; - const CIA_cache& map_interval_arcno = - _m_curved_kernel->interval_arcno_cache(); + info1 = map_interval_arcno(evt_line1, 1, k); + if (info1.second != CGAL::ARR_INTERIOR) { + arc = construct_arc_2(CGAL::ARR_MIN_END, max_x, + (info1.second == + CGAL::ARR_BOTTOM_BOUNDARY ? + CGAL::ARR_MIN_END : CGAL::ARR_MAX_END), + curve, k); + } + else { + arc = construct_arc_2(max_pts[info1.first], CGAL::ARR_MIN_END, + curve, k, info1.first); + } + *oi++ = Make_x_monotone_result(arc); + } + min_pts = max_pts; + max_pts.clear(); + min_x = max_x; - typename Curved_kernel_via_analysis_2::Construct_point_2 - construct_point = - _m_curved_kernel->construct_point_2_object(); + // next handle arcs between events, including isolated points + for (i = 0; i < total_events-1; i++) { + evt_line1 = curve.status_line_at_event(i); + evt_line2 = curve.status_line_at_event(i+1); + max_x = evt_line2.x(); + oi = _handle_vertical_and_isolated(evt_line1, min_x, min_pts, oi); - typename CIA_cache::result_type info1, info2; - std::vector min_pts, max_pts; - Coordinate_1 min_x, max_x; - int i, k, n; - Arc_2 arc; - // first handle segments before first event - evt_line1 = curve.status_line_at_event(0); - max_x = evt_line1.x(); + n = evt_line2.number_of_events(); + for (k = 0; k < n; k++) + max_pts.push_back(construct_point(max_x, curve, k)); - for(k = 0; k < evt_line1.number_of_events(); k++) - max_pts.push_back(construct_point(max_x, curve, k)); - - //std::cout << "handling events over the 1st interval\n"; - for(k = 0; k < int_line.number_of_events(); k++) { - - info1 = map_interval_arcno(evt_line1, 1, k); - if (info1.second != CGAL::ARR_INTERIOR) { - arc = construct_arc_2(CGAL::ARR_MIN_END, max_x, - (info1.second == - CGAL::ARR_BOTTOM_BOUNDARY ? - CGAL::ARR_MIN_END : CGAL::ARR_MAX_END), - curve, k); - } else { - arc = construct_arc_2(max_pts[info1.first], CGAL::ARR_MIN_END, - curve, k, info1.first - ); - } - *oi++ = CGAL::make_object(arc); - } - min_pts = max_pts; - max_pts.clear(); - min_x = max_x; - - // next handle arcs between events, including isolated points - for (i = 0; i < total_events-1; i++) { - evt_line1 = curve.status_line_at_event(i); - evt_line2 = curve.status_line_at_event(i+1); - max_x = evt_line2.x(); - oi = _handle_vertical_and_isolated(evt_line1, min_x, min_pts, oi); - - n = evt_line2.number_of_events(); - for(k = 0; k < n; k++) - max_pts.push_back(construct_point(max_x, curve, k)); - - n = curve.status_line_of_interval(i+1).number_of_events(); - CGAL::Arr_curve_end inf1_end, inf2_end; - for (k = 0; k < n; k++) { - - info1 = map_interval_arcno(evt_line1, 0, k); - info2 = map_interval_arcno(evt_line2, 1, k); - inf2_end = (info2.second == CGAL::ARR_BOTTOM_BOUNDARY ? + n = curve.status_line_of_interval(i+1).number_of_events(); + CGAL::Arr_curve_end inf1_end, inf2_end; + for (k = 0; k < n; k++) { + info1 = map_interval_arcno(evt_line1, 0, k); + info2 = map_interval_arcno(evt_line2, 1, k); + inf2_end = (info2.second == CGAL::ARR_BOTTOM_BOUNDARY ? CGAL::ARR_MIN_END : CGAL::ARR_MAX_END); - if (info1.second != CGAL::ARR_INTERIOR) { - inf1_end = (info1.second == CGAL::ARR_BOTTOM_BOUNDARY ? - CGAL::ARR_MIN_END : CGAL::ARR_MAX_END); - if (info2.second != CGAL::ARR_INTERIOR) { - arc = construct_arc_2(min_x, inf1_end, max_x, inf2_end, - curve, k); - } else { - arc = construct_arc_2(max_pts[info2.first], min_x, - inf1_end, curve, k, info2.first); - } - } else if (info2.second != CGAL::ARR_INTERIOR) { - arc = construct_arc_2(min_pts[info1.first], max_x, - inf2_end, curve, k, info1.first); - } else { - arc = construct_arc_2(min_pts[info1.first], - max_pts[info2.first], - curve, k, info1.first, info2.first); - } - *oi++ = CGAL::make_object(arc); - } - min_pts = max_pts; - max_pts.clear(); - min_x = max_x; + if (info1.second != CGAL::ARR_INTERIOR) { + inf1_end = (info1.second == CGAL::ARR_BOTTOM_BOUNDARY ? + CGAL::ARR_MIN_END : CGAL::ARR_MAX_END); + if (info2.second != CGAL::ARR_INTERIOR) { + arc = construct_arc_2(min_x, inf1_end, max_x, inf2_end, + curve, k); + } + else { + arc = construct_arc_2(max_pts[info2.first], min_x, + inf1_end, curve, k, info2.first); + } } - - // here: min_x/min_pts hold information about the last event line - // event_line2 - points to the last event line - // vertical line or isolated points at last event? - evt_line2 = curve.status_line_at_event(total_events-1); - min_x = evt_line2.x(); - oi = _handle_vertical_and_isolated(evt_line2, min_x, min_pts, oi); - - n = curve.status_line_of_interval(total_events).number_of_events(); - for (k = 0; k < n; k++) { - - info1 = map_interval_arcno(evt_line2, 0, k); - if (info1.second != CGAL::ARR_INTERIOR) { - arc = construct_arc_2( - CGAL::ARR_MAX_END, min_x, - (info1.second == CGAL::ARR_BOTTOM_BOUNDARY ? - CGAL::ARR_MIN_END : CGAL::ARR_MAX_END), curve, k - ); - } else { - arc = construct_arc_2(min_pts[info1.first], - CGAL::ARR_MAX_END, curve, k, - info1.first); - } - *oi++ = CGAL::make_object(arc); + else if (info2.second != CGAL::ARR_INTERIOR) { + arc = construct_arc_2(min_pts[info1.first], max_x, + inf2_end, curve, k, info1.first); } - return oi; + else { + arc = construct_arc_2(min_pts[info1.first], + max_pts[info2.first], + curve, k, info1.first, info2.first); + } + *oi++ = Make_x_monotone_result(arc); + } + min_pts = max_pts; + max_pts.clear(); + min_x = max_x; } - //!@} + + // here: min_x/min_pts hold information about the last event line + // event_line2 - points to the last event line + // vertical line or isolated points at last event? + evt_line2 = curve.status_line_at_event(total_events-1); + min_x = evt_line2.x(); + oi = _handle_vertical_and_isolated(evt_line2, min_x, min_pts, oi); + + n = curve.status_line_of_interval(total_events).number_of_events(); + for (k = 0; k < n; k++) { + info1 = map_interval_arcno(evt_line2, 0, k); + if (info1.second != CGAL::ARR_INTERIOR) { + arc = construct_arc_2(CGAL::ARR_MAX_END, min_x, + (info1.second == CGAL::ARR_BOTTOM_BOUNDARY ? + CGAL::ARR_MIN_END : CGAL::ARR_MAX_END), curve, k + ); + } + else { + arc = construct_arc_2(min_pts[info1.first], + CGAL::ARR_MAX_END, curve, k, + info1.first); + } + *oi++ = Make_x_monotone_result(arc); + } + return oi; + } + //!@} private: - //!\name Private members - //!@{ + //!\name Private members + //!@{ - /*!\brief - * Constructs vertical arcs and isolated points at event line - * - * \param cv_line The event line in focus - * \param x x-coordinate of event - * \param pts Points at event line - * \param oi Output iterator that stores CGAL::Object, which either - * encapsulates Point_2 or Arc_2 - * \return Past-the-end iterator of \c oi - */ - template - OutputIterator _handle_vertical_and_isolated( - Status_line_1 cv_line, - Coordinate_1 x, std::vector pts, - OutputIterator oi) const { + /*!\brief + * Constructs vertical arcs and isolated points at event line + * + * \param cv_line The event line in focus + * \param x x-coordinate of event + * \param pts Points at event line + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a Point_2 or an X_monotone_curve_2 objects. + * \return Past-the-end iterator of \c oi + */ + template + OutputIterator + _handle_vertical_and_isolated(Status_line_1 cv_line, + Coordinate_1 x, std::vector pts, + OutputIterator oi) const + { + typedef boost::variant Make_x_monotone_result; - Construct_arc_2 construct_arc_2 = - _m_curved_kernel->construct_arc_2_object(); + Construct_arc_2 construct_arc_2 = + _m_curved_kernel->construct_arc_2_object(); - int n = cv_line.number_of_events(), j; - if(cv_line.covers_line()) { // look for vertical arcs - if(n > 0) { - // the first vertical ray - *oi++ = CGAL::make_object( - construct_arc_2(pts[0], CGAL::ARR_MIN_END, _m_curve) - ); - for(j = 0; j < n-1; j++) // interior bounded arcs - *oi++ = CGAL::make_object(construct_arc_2(pts[j], pts[j+1], - _m_curve)); - // the last vertical ray - *oi++ = CGAL::make_object(construct_arc_2(pts[n-1], - CGAL::ARR_MAX_END, _m_curve)); - } else // unbounded vertical line - *oi++ = CGAL::make_object(construct_arc_2(x, _m_curve)); - return oi; - } - // look for isolated points - std::pair ipair; - for(j = 0; j < n; j++) { - ipair = cv_line.number_of_incident_branches(j); - if(ipair.first == 0&&ipair.second == 0) { - //std::cout << "isolated point found\n"; - typename Curved_kernel_via_analysis_2::Construct_point_2 - construct_point = - _m_curved_kernel->construct_point_2_object(); - - *oi++ = CGAL::make_object(construct_point(x, _m_curve, j)); - } - } - return oi; + int n = cv_line.number_of_events(), j; + if (cv_line.covers_line()) { // look for vertical arcs + if (n > 0) { + // the first vertical ray + *oi++ = + Make_x_monotone_result(construct_arc_2(pts[0], CGAL::ARR_MIN_END, + _m_curve)); + for (j = 0; j < n-1; j++) // interior bounded arcs + *oi++ = Make_x_monotone_result(construct_arc_2(pts[j], pts[j+1], + _m_curve)); + // the last vertical ray + *oi++ = + Make_x_monotone_result(construct_arc_2(pts[n-1], CGAL::ARR_MAX_END, + _m_curve)); + } + else // unbounded vertical line + *oi++ = Make_x_monotone_result(construct_arc_2(x, _m_curve)); + return oi; } + // look for isolated points + std::pair ipair; + for (j = 0; j < n; j++) { + ipair = cv_line.number_of_incident_branches(j); + if (ipair.first == 0&&ipair.second == 0) { + //std::cout << "isolated point found\n"; + typename Curved_kernel_via_analysis_2::Construct_point_2 + construct_point = _m_curved_kernel->construct_point_2_object(); - //!@} + *oi++ = Make_x_monotone_result(construct_point(x, _m_curve, j)); + } + } + return oi; + } - //!\name Private data - //!@{ + //!@} - //! pointer to \c Curved_kernel_via_analysis_2 - Curved_kernel_via_analysis_2 *_m_curved_kernel; + //!\name Private data + //!@{ - //! to avoid passing curve as a parameter - Curve_analysis_2 _m_curve; + //! pointer to \c Curved_kernel_via_analysis_2 + Curved_kernel_via_analysis_2 *_m_curved_kernel; - //!@} -}; // struct Make_x_monotone + //! to avoid passing curve as a parameter + Curve_analysis_2 _m_curve; + + //!@} +}; // struct Make_x_monotone } // namespace internal diff --git a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Sweep_curves_adapter_2.h b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Sweep_curves_adapter_2.h index fbd39ef99d0..3d1bdff6e91 100644 --- a/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Sweep_curves_adapter_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Curved_kernel_via_analysis_2/Sweep_curves_adapter_2.h @@ -699,13 +699,14 @@ public: * is by definition x-monotone, an input arc is passed to the * output iterator directly. * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. - * The returned objects are all wrappers X_monotone_curve_2 objects. - * \return The past-the-end iterator. + * \param oi The output iteratorfor the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects.. + * \return The past-the-end output iterator. */ template - OutputIterator operator()(const Generic_arc_2& cv, - OutputIterator oi) const { + OutputIterator operator()(const Generic_arc_2& cv, OutputIterator oi) const + { *oi++ = cv; return oi; } @@ -714,32 +715,32 @@ public: * decompose a given curve into list of x-monotone pieces * (subcurves) and insert them to the output iterator. * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. - * The returned objects are all wrappers X_monotone_curve_2 objects. - * \return The past-the-end iterator. + * \param oi the output iterator for the result. Its dereference type is a + * variant that wraps a \c Point_2 or an \c X_monotone_curve_2 + * objects. + * \return The past-the-end output iterator. */ template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { - typedef typename SweepCurvesAdapter_2::Native_arc_2 Native_arc_2; - typedef typename SweepCurvesAdapter_2::Native_point_2 Native_point_2; - typedef typename SweepCurvesAdapter_2::Generic_point_2 Generic_point_2; + typedef typename SweepCurvesAdapter_2::Native_arc_2 Native_arc_2; + typedef typename SweepCurvesAdapter_2::Native_point_2 Native_point_2; + typedef typename SweepCurvesAdapter_2::Generic_point_2 Generic_point_2; + typedef boost::variant + Make_x_monotone_result; - typedef std::vector Objects; - Objects objs; - _m_adapter->kernel().make_x_monotone_2_object()(cv, - std::back_inserter(objs)); + std::vector objs; + auto make_x_monotone = _m_adapter->kernel().make_x_monotone_2_object(); + make_x_monotone(cv, std::back_inserter(objs)); // sort out normal and degenerate arcs - for(typename Objects::const_iterator it = objs.begin(); - it != objs.end(); it++) { - Native_arc_2 arc; - Native_point_2 pt; - if(CGAL::assign(arc, *it)) - *oi++ = Generic_arc_2(arc); - else if(CGAL::assign(pt, *it)) - *oi++ = Generic_arc_2(Generic_point_2(pt)); - else - CGAL_error_msg("Bogus object..\n"); + for (auto& obj : objs) { + if (auto* arc = boost::get(&obj)) { + *oi++ = Generic_arc_2(*arc); + continue; + } + auto* pt = boost::get(&obj); + CGAL_assertion(pt); + *oi++ = Generic_arc_2(Generic_point_2(*pt)); } return oi; } diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_basic_insertion_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_basic_insertion_traits_2.h index 970f6a45227..ffa3d6eea01 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_basic_insertion_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_basic_insertion_traits_2.h @@ -23,7 +23,6 @@ * Defintion of the Arr_basic_insertion_traits_2 class. */ -#include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_batched_pl_ss_visitor.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_batched_pl_ss_visitor.h index 4bd9e6acdff..e562f2be4ee 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_batched_pl_ss_visitor.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_batched_pl_ss_visitor.h @@ -23,7 +23,6 @@ */ #include -#include #include #include diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_no_intersection_insertion_ss_visitor.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_no_intersection_insertion_ss_visitor.h index 2ff277817d9..aee0a956eb2 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_no_intersection_insertion_ss_visitor.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_no_intersection_insertion_ss_visitor.h @@ -8,9 +8,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Baruch Zukerman -// Ron Wein -// Efi Fogel +// Author(s): Baruch Zukerman +// Ron Wein +// Efi Fogel #ifndef CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H #define CGAL_ARR_NO_INTERSECTION_INSERTION_SS_VISITOR_H diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h index c94ecf40913..48815d767f6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_overlay_traits_2.h @@ -26,7 +26,6 @@ #include #include -#include namespace CGAL { diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_vert_decomp_ss_visitor.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_vert_decomp_ss_visitor.h index 1798658e6d3..807096c6fdc 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_vert_decomp_ss_visitor.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_vert_decomp_ss_visitor.h @@ -7,9 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein -// Efi Fogel +// Author(s): Ron Wein +// Efi Fogel #ifndef CGAL_ARR_VERT_DECOMP_SS_VISITOR_H #define CGAL_ARR_VERT_DECOMP_SS_VISITOR_H @@ -21,10 +20,11 @@ * Definition of the Arr_vert_decomp_ss_visitor class-template. */ +#include + namespace CGAL { #include -#include #include /*! \class Arr_vert_decomp_ss_visitor @@ -63,13 +63,18 @@ private: public: typedef typename Helper::Arrangement_2 Arrangement_2; typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arrangement_2::Face_const_handle Face_const_handle; - typedef std::pair Vert_pair; + typedef boost::variant + Cell_type; + typedef boost::optional Vert_type; + typedef std::pair Vert_pair; typedef std::pair Vert_entry; protected: typedef typename Base::Status_line_iterator Status_line_iterator; - typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; //typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; typedef typename Arrangement_2::Halfedge_around_vertex_const_circulator Halfedge_around_vertex_const_circulator; @@ -84,8 +89,8 @@ protected: // An invalid vertex handle. Vertex_const_handle m_prev_vh; // The previous vertex. - CGAL::Object m_prev_obj_below; // The object this vertex sees below it. - CGAL::Object m_prev_obj_above; // The object this vertex sees above it. + Vert_type m_prev_obj_below; // The object this vertex sees below it. + Vert_type m_prev_obj_above; // The object this vertex sees above it. Output_iterator* m_out; // An output iterator for the result. @@ -155,7 +160,7 @@ after_handle_event(Event* event, // Get the vertex handle associated with the current event (stored with // the point). Vertex_const_handle vh = event->point().vertex_handle(); - CGAL::Object obj_above, obj_below; + Vert_type obj_above, obj_below; // Check the feature from above. if (above == this->status_line_end()) { @@ -166,8 +171,7 @@ after_handle_event(Event* event, else { // We have a valid subcurve above the event: get its halfedge handle // and associate it with the vertex. - obj_above = - CGAL::make_object((*above)->last_curve().halfedge_handle()); + obj_above = Vert_type((*above)->last_curve().halfedge_handle()); } // Check if the previous vertex we handled has the same x-coordinate @@ -206,12 +210,12 @@ after_handle_event(Event* event, } if (! vert_connected) { - obj_below = CGAL::make_object(m_prev_vh); - m_prev_obj_above = CGAL::make_object(vh); + obj_below = Vert_type(m_prev_vh); + m_prev_obj_above = Vert_type(vh); } else { - obj_below = CGAL::Object(); - m_prev_obj_above = CGAL::Object(); + obj_below = Vert_type(); + m_prev_obj_above = Vert_type(); } } else { @@ -260,19 +264,18 @@ after_handle_event(Event* event, } if (! vert_connected) { - obj_below = CGAL::make_object(m_prev_vh); - m_prev_obj_above = CGAL::make_object(vh); + obj_below = Vert_type(m_prev_vh); + m_prev_obj_above = Vert_type(vh); } else { - obj_below = CGAL::Object(); - m_prev_obj_above = CGAL::Object(); + obj_below = Vert_type(); + m_prev_obj_above = Vert_type(); } } else { // Get the halfedge handle of the subcurve below the current event and // associate it with its vertex. - obj_below = - CGAL::make_object((*below)->last_curve().halfedge_handle()); + obj_below = Vert_type((*below)->last_curve().halfedge_handle()); } } diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Batched_point_location_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Batched_point_location_test.h index 963f4cdc8f1..256d101a386 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Batched_point_location_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Batched_point_location_test.h @@ -208,8 +208,7 @@ verify(InputIterator begin, InputIterator end) typename TopolTraits::Default_point_location_strategy pl(m_arr); for (InputIterator it = begin; it != end; ++it) { - if (m_verbose_level > 1) - print(*it); + if (m_verbose_level > 1) print(*it); // Perform (single) point location. Result_type obj = pl.locate(it->first); diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h index 7adb505ef02..c1f95b8e4bc 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/IO_base_test.h @@ -71,10 +71,10 @@ read_xcurve(InputStream_& is, typename GeomTraits_::X_monotone_curve_2& xcv) typedef GeomTraits_ Geom_traits; Basic_number_type x1, y1, x2, y2; is >> x1 >> y1 >> x2 >> y2; - CGAL_assertion(!is.fail()); + assert(!is.fail()); Point_2 p1(x1, y1); Point_2 p2(x2, y2); - CGAL_assertion(p1 != p2); + assert(p1 != p2); xcv = typename Geom_traits::X_monotone_curve_2(p1, p2); return true; } @@ -89,7 +89,7 @@ read_curve(InputStream_& is, typename GeomTraits_::Curve_2& cv) is >> x1 >> y1 >> x2 >> y2; Point_2 p1(x1, y1); Point_2 p2(x2, y2); - CGAL_assertion(p1 != p2); + assert(p1 != p2); cv = typename Geom_traits::Curve_2(p1, p2); return true; } @@ -690,21 +690,20 @@ bool IO_base_test::read_xsegment(InputStream_& is, point_vector.push_back(Control_point_2(point_x, point_y)); } //get the non x-monotone bezier segment - Subcurve_2 seg (point_vector.begin(), point_vector.end()); + Subcurve_2 seg(point_vector.begin(), point_vector.end()); //convert it into x-monotone bezier segment. - std::vector obj_vector; - bezier_traits.make_x_monotone_2_object()(seg, - std::back_inserter(obj_vector)); - X_monotone_subcurve_2 x_segment = - CGAL::object_cast((obj_vector[0])); - - xseg = x_segment; + typedef boost::variant Make_x_monotone_result; + std::vector objs; + bezier_traits.make_x_monotone_2_object()(seg, std::back_inserter(objs)); + assert(! objs.empty()); + const auto* x_seg_p = boost::get(&(objs[0])); + assert(x_seg_p); + xseg = *x_seg_p; return true; } - template <> template bool IO_base_test::read_xcurve(InputStream_& is, @@ -721,6 +720,8 @@ bool IO_base_test::read_xcurve(InputStream_& is, unsigned int number_of_segments; is >> number_of_segments; + typedef boost::variant Make_x_monotone_result; + auto make_x_monotone = bezier_traits.make_x_monotone_2_object(); if ((type == 'x') || (type == 'X')) { for (unsigned int i=0; i::read_xcurve(InputStream_& is, Subcurve_2 seg(point_vector.begin(), point_vector.end()); //convert it into x-monotone bezier segment. - std::vector obj_vector; - bezier_traits.make_x_monotone_2_object()(seg, - std::back_inserter(obj_vector)); - X_monotone_subcurve_2 x_seg = - CGAL::object_cast((obj_vector[0])); - - x_segments.push_back(x_seg); + std::vector objs; + make_x_monotone(seg, std::back_inserter(objs)); + assert(! objs.empty()); + const auto* x_seg_p = boost::get(&(objs[0])); + assert(x_seg_p); + x_segments.push_back(*x_seg_p); } //for loop (number of segments) } @@ -1470,8 +1470,8 @@ bool IO_base_test::read_xcurve(InputStream_& is, X_monotone_curve_2& xcv) { std::cout << std::endl; - std::list x_objs; - std::list::const_iterator xoit; + typedef boost::variant Make_x_monotone_result; + std::list x_objs; Curve_2 tmp_cv; is >> tmp_cv; Rational B_psx = Rational(tmp_cv.control_point(0).x()); @@ -1482,15 +1482,15 @@ bool IO_base_test::read_xcurve(InputStream_& is, Rational(tmp_cv.control_point(tmp_cv.number_of_control_points()-1).y()); Point_2 B_ps(B_psx, B_psy); Point_2 B_pt(B_ptx, B_pty); - Base_geom_traits::Make_x_monotone_2 make_x_monotone = - this->m_geom_traits.make_x_monotone_2_object(); - make_x_monotone(tmp_cv, std::front_inserter (x_objs)); - xoit = x_objs.begin(); + auto make_x_monotone = this->m_geom_traits.make_x_monotone_2_object(); + make_x_monotone(tmp_cv, std::front_inserter(x_objs)); + auto xoit = x_objs.begin(); size_t id(0); - if (!is.eof()) is >> id; + if (! is.eof()) is >> id; std::advance(xoit, id); - if (CGAL::assign(xcv, *xoit)) - return true; + const auto* xcv_p = boost::get(&*xoit); + assert(xcv_p); + xcv = *xcv_p; return false; } @@ -1546,9 +1546,8 @@ bool IO_base_test::read_point(InputStream_& is, Point_2& p) { is >> x; Base_geom_traits::X_monotone_curve_2 xcv; CGAL::swallow(is, '('); - CGAL_assertion_code(bool check = ) - read_xcurve(is, xcv); - CGAL_assertion(check); + bool check = read_xcurve(is, xcv); + assert(check); CGAL::swallow(is, ')'); p = construct_point_2(x, xcv); @@ -1558,9 +1557,8 @@ bool IO_base_test::read_point(InputStream_& is, Point_2& p) { Base_geom_traits::Algebraic_real_1 x; is >> x; Base_geom_traits::Curve_2 c; - CGAL_assertion_code(bool check = ) - read_curve(is, c); - CGAL_assertion(check); + bool check = read_curve(is, c); + assert(check); int arcno = 0; is >> arcno; p = construct_point_2(x, c, arcno); @@ -1589,36 +1587,31 @@ bool IO_base_test::read_xcurve(InputStream_& is, switch (type) { case '1': { Curve_2 cv; - Point_2 end_left,end_right; - CGAL_assertion_code(bool check = ) - read_curve(is,cv); - CGAL_assertion(check); + Point_2 end_left, end_right; + bool check = read_curve(is,cv); + assert(check); CGAL::swallow(is, '('); - CGAL_assertion_code(check = ) - read_point(is,end_left); - CGAL_assertion(check); + check = read_point(is,end_left); + assert(check); CGAL::swallow(is, ')'); CGAL::swallow(is, '('); - CGAL_assertion_code(check = ) - read_point(is,end_right); - CGAL_assertion(check); + check = read_point(is,end_right); + assert(check); CGAL::swallow(is, ')'); std::vector xcvs; construct_segment_2(cv, end_left, end_right, std::back_inserter(xcvs)); - CGAL_assertion(xcvs.size() == 1); + assert(xcvs.size() == 1); xcv = xcvs[0]; break; } case '2': { Curve_2 cv; Point_2 p; - CGAL_assertion_code(bool check = ) - read_curve(is, cv); - CGAL_assertion(check); + bool check = read_curve(is, cv); + assert(check); CGAL::swallow(is, '('); - CGAL_assertion_code(check = ) - read_point(is, p); - CGAL_assertion(check); + check = read_point(is, p); + assert(check); CGAL::swallow(is, ')'); std::string site_of_p_string; Base_geom_traits::Site_of_point site_of_p; @@ -1630,12 +1623,12 @@ bool IO_base_test::read_xcurve(InputStream_& is, site_of_p = Base_geom_traits::MAX_ENDPOINT; } else { - CGAL_assertion(site_of_p_string == "POINT_IN_INTERIOR"); + assert(site_of_p_string == "POINT_IN_INTERIOR"); site_of_p = Base_geom_traits::POINT_IN_INTERIOR; } std::vector xcvs; construct_segment_2(cv, p, site_of_p, std::back_inserter(xcvs)); - CGAL_assertion(xcvs.size() == 1); + assert(xcvs.size() == 1); xcv = xcvs[0]; break; } @@ -1685,7 +1678,7 @@ bool IO_base_test::read_xcurve(InputStream_& is, Point_2 p1, p2; read_point(is, p1); read_point(is, p2); - CGAL_assertion(p1 != p2); + assert(p1 != p2); unsigned int flag; is >> flag; @@ -1707,7 +1700,7 @@ bool IO_base_test::read_curve(InputStream_& is, Curve_2& cv) Point_2 p1, p2; read_point(is, p1); read_point(is, p2); - CGAL_assertion(p1 != p2); + assert(p1 != p2); unsigned int flag; is >> flag; if (flag == 1) { diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Point_location_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Point_location_test.h index d80c295becc..c60a9a0cdad 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Point_location_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Point_location_test.h @@ -262,7 +262,7 @@ private: void allocate_pl() { Strategy* locator = new Strategy(); - CGAL_assertion(locator); + assert(locator); m_locators[id].m_variant = locator; } diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_base_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_base_test.h index 1d95d3eefef..0ac8100431c 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_base_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_base_test.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h index a519c90b1e1..40514e39260 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Traits_test.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -931,22 +930,22 @@ template bool Traits_test:: make_x_monotone_wrapper(std::istringstream& str_stream) { - typedef Geom_traits_T Traits; - typedef typename Traits::Point_2 Point_2; - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef Geom_traits_T Traits; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef boost::variant Make_x_monotone_result; CGAL_USE_TYPE(typename Traits::Curve_2); unsigned int id; str_stream >> id; - std::cout << "Test: make_x_monotone( " << this->m_curves[id] - << " ) ? "; - std::vector object_vec; + std::cout << "Test: make_x_monotone( " << this->m_curves[id] << " ) ? "; + std::vector objs; this->m_geom_traits.make_x_monotone_2_object()(this->m_curves[id], - std::back_inserter(object_vec)); + std::back_inserter(objs)); size_t num; str_stream >> num; - if (!this->compare(num, object_vec.size(), "size")) return false; + if (!this->compare(num, objs.size(), "size")) return false; for (size_t i = 0; i < num; ++i) { unsigned int type; // 0 - point, 1 - x-monotone curve @@ -955,20 +954,19 @@ make_x_monotone_wrapper(std::istringstream& str_stream) unsigned int id; // The id of the point or x-monotone str_stream >> id; // ... curve respectively - const X_monotone_curve_2 * xcv_ptr = - CGAL::object_cast (&(object_vec[i])); - if (xcv_ptr != NULL) { + const auto* xcv_ptr = boost::get(&(objs[i])); + if (xcv_ptr != nullptr) { if (!this->compare(type, 1u, "type")) return false; if (!this->compare_curves(this->m_xcurves[id], *xcv_ptr)) return false; continue; } - const Point_2 * pt_ptr = CGAL::object_cast (&(object_vec[i])); - assert (pt_ptr != NULL); + const auto* pt_ptr = boost::get(&(objs[i])); + assert(pt_ptr != nullptr); if (!this->compare(type, 0u, "type")) return false; if (!this->compare_points(this->m_points[id], *pt_ptr)) return false; } - object_vec.clear(); + objs.clear(); return true; } diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Vertical_decomposition_test.h b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Vertical_decomposition_test.h index dbe744c9fdd..1c70c873eae 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Vertical_decomposition_test.h +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/Vertical_decomposition_test.h @@ -12,11 +12,11 @@ #include "IO_test.h" /*! Point location test */ -template -class Vertical_decomposition_test : public IO_test { +template +class Vertical_decomposition_test : public IO_test { public: - typedef GeomTraits_T Geom_traits; - typedef TopolTraits_T Topol_traits; + typedef GeomTraits_2 Geom_traits; + typedef TopolTraits Topol_traits; private: typedef IO_test Base; @@ -44,8 +44,11 @@ public: typedef typename Arrangement::Edge_const_iterator Edge_const_iterator; typedef typename Arrangement::Vertex_const_iterator Vertex_const_iterator; - typedef typename std::pair Object_pair; - typedef typename std::pair + typedef boost::variant Cell_type; + typedef boost::optional Vert_type; + typedef typename std::pair Vert_pair; + typedef typename std::pair Vert_decomp_entry; typedef typename std::list Vert_decomp_list; @@ -69,7 +72,7 @@ protected: /*! Compare the results. */ - bool compare(const Result_type& expected, const CGAL::Object& actual); + bool compare(const Result_type& expected, Vert_type actual); /*! print the results. */ @@ -104,8 +107,8 @@ public: /*! * Constructor from a geometry traits object. */ -template -Vertical_decomposition_test:: +template +Vertical_decomposition_test:: Vertical_decomposition_test(const Geom_traits& geom_traits) : Base(geom_traits), m_geom_traits(geom_traits), @@ -113,24 +116,24 @@ Vertical_decomposition_test(const Geom_traits& geom_traits) : {} //! \brief sets the verbosity level. -template -void Vertical_decomposition_test:: +template +void Vertical_decomposition_test:: set_verbose_level(size_t verbose_level) { m_verbose_level = verbose_level; } /*! Clear the data structures */ -template -void Vertical_decomposition_test::clear() +template +void Vertical_decomposition_test::clear() { m_arr.clear(); Base::clear(); } -template -bool Vertical_decomposition_test::init() +template +bool Vertical_decomposition_test::init() { // Initialize the input. - if (!Base::init()) return false; + if (! Base::init()) return false; // Insert all into the arrangement CGAL::insert(m_arr, this->m_xcurves.begin(), this->m_xcurves.end()); @@ -147,8 +150,8 @@ bool Vertical_decomposition_test::init() } //! \brief performs the test. -template -bool Vertical_decomposition_test::perform() +template +bool Vertical_decomposition_test::perform() { // Apply vertical decomposition. Vert_decomp_list results; @@ -159,51 +162,48 @@ bool Vertical_decomposition_test::perform() } //! \brief verifies the results. -template +template template -bool Vertical_decomposition_test:: +bool Vertical_decomposition_test:: verify(InputIterator begin, InputIterator end) { - typedef TopolTraits_T TopolTraits; - - InputIterator it; - if (m_verbose_level > 1) for (it = begin; it != end; ++it) print(*it); + if (m_verbose_level > 1) for (auto it = begin; it != end; ++it) print(*it); // Compare the results. typename TopolTraits::Default_vertical_ray_shooting_strategy vs(m_arr); - for (it = begin; it != end; ++it) { + for (auto it = begin; it != end; ++it) { Vertex_const_handle vh = it->first; - const Object_pair& res = it->second; - const CGAL::Object& obj_below_actual = res.first; - const CGAL::Object& obj_above_actual = res.second; + const auto& res = it->second; + auto obj_below_actual = res.first; + auto obj_above_actual = res.second; Result_type obj_below_expected = vs.ray_shoot_down(vh->point()); Result_type obj_above_expected = vs.ray_shoot_up(vh->point()); - if (!compare(obj_below_expected, obj_below_actual)) return false; - if (!compare(obj_above_expected, obj_above_actual)) return false; + if (! compare(obj_below_expected, obj_below_actual)) return false; + if (! compare(obj_above_expected, obj_above_actual)) return false; } return true; } -template -bool Vertical_decomposition_test:: -compare(const Result_type& expected, const CGAL::Object& actual) +template +bool Vertical_decomposition_test:: +compare(const Result_type& expected, Vert_type actual) { + // This test does not test the case where the result is empty! + if (! actual) return false; + + auto obj = *actual; // Assign object to a fase. - const Face_const_handle* fh_expected = - boost::get(&(expected)); - if (fh_expected) { - Vertex_const_handle vh_actual; - if (CGAL::assign(vh_actual, actual)) { + if (const auto* fh_expected = boost::get(&(expected))) { + if (boost::get(&obj)) { std::cout << "Error: vertical decomposition!" << std::endl; std::cout << "Expected: a face." << std::endl; std::cout << "Actual: a vertex." << std::endl; return false; } - Halfedge_const_handle hh_actual; - if (CGAL::assign(hh_actual, actual)) { + if (boost::get(&obj)) { std::cout << "Error: vertical decomposition!" << std::endl; std::cout << "Expected: a face." << std::endl; std::cout << "Actual: a halfedge." << std::endl; @@ -213,17 +213,15 @@ compare(const Result_type& expected, const CGAL::Object& actual) } // Assign object to a halfedge. - const Halfedge_const_handle* hh_expected = - boost::get(&(expected)); + const auto* hh_expected = boost::get(&(expected)); if (hh_expected) { - Halfedge_const_handle hh_actual; - if (CGAL::assign(hh_actual, actual)) { - if (*hh_expected == hh_actual) return true; + if (const auto* hh_actual = boost::get(&obj)) { + if (*hh_expected == *hh_actual) return true; std::cout << "Error: vertical decomposition!" << std::endl; std::cout << "Expected: a halfedge, " << (*hh_expected)->curve() << std::endl; - std::cout << "Actual: a different halfedge." << hh_actual->curve() + std::cout << "Actual: a different halfedge." << (*hh_actual)->curve() << std::endl; return false; } @@ -232,14 +230,13 @@ compare(const Result_type& expected, const CGAL::Object& actual) std::cout << "Expected: a halfedge, " << (*hh_expected)->curve() << std::endl; - Vertex_const_handle vh_actual; - if (CGAL::assign(vh_actual, actual)) { - std::cout << "Actual: a vertex, " << vh_actual->point() << std::endl; + if (const auto* vh_actual = boost::get(&obj)) { + std::cout << "Actual: a vertex, " << (*vh_actual)->point() << std::endl; return false; } Face_const_handle fh_actual; - if (CGAL::assign(fh_actual, actual)) { + if (boost::get(&obj)) { std::cout << "Actual: a face." << std::endl; return false; } @@ -248,17 +245,15 @@ compare(const Result_type& expected, const CGAL::Object& actual) } // Assign object to a vertex. - const Vertex_const_handle* vh_expected = - boost::get(&(expected)); + const auto* vh_expected = boost::get(&(expected)); if (vh_expected) { - Vertex_const_handle vh_actual; - if (CGAL::assign(vh_actual, actual)) { - if (*vh_expected == vh_actual) return true; + if (const auto* vh_actual = boost::get(&obj)) { + if (*vh_expected == *vh_actual) return true; std::cout << "Error: vertical decomposition!" << std::endl; std::cout << "Expected: a vertex, " << (*vh_expected)->point() << std::endl; - std::cout << "Actual: a different vertex, " << vh_actual->point() + std::cout << "Actual: a different vertex, " << (*vh_actual)->point() << std::endl; return false; } @@ -266,14 +261,12 @@ compare(const Result_type& expected, const CGAL::Object& actual) std::cout << "Error: vertical decomposition!" << std::endl; std::cout << "Expected: a vertex, " << (*vh_expected)->point() << std::endl; - Halfedge_const_handle hh_actual; - if (CGAL::assign(hh_actual, actual)) { - std::cout << "Actual: a halfedge, " << hh_actual->curve() << std::endl; + if (const auto* hh_actual = boost::get(&obj)) { + std::cout << "Actual: a halfedge, " << (*hh_actual)->curve() << std::endl; return false; } - Face_const_handle fh_actual; - if (CGAL::assign(fh_actual, actual)) { + if (boost::get(&obj)) { std::cout << "Actual: a face." << std::endl; return false; } @@ -285,28 +278,36 @@ compare(const Result_type& expected, const CGAL::Object& actual) } //! \brief prints the results. -template -void Vertical_decomposition_test:: +template +void Vertical_decomposition_test:: print(const Vert_decomp_entry& result) { - // Print the result. - Vertex_const_handle vh; - Halfedge_const_handle hh; - Face_const_handle fh; + const auto& res = result.second; + auto obj_below = res.first; + auto obj_above = res.second; - const Object_pair& res = result.second; std::cout << "Vertex (" << result.first->point() << ") : "; + assert(obj_below); + auto obj = *obj_below; std::cout << " feature below: "; - if (CGAL::assign(hh, res.first)) std::cout << '[' << hh->curve() << ']'; - else if (CGAL::assign(vh, res.first)) std::cout << '(' << vh->point() << ')'; - else if (CGAL::assign(fh, res.first)) std::cout << "NONE"; + if (const auto* hh = boost::get(&obj)) + std::cout << '[' << (*hh)->curve() << ']'; + else if (const auto* vh = boost::get(&obj)) + std::cout << '(' << (*vh)->point() << ')'; + else if (const auto* fh = boost::get(&obj)) + std::cout << "NONE"; else std::cout << "EMPTY"; + assert(obj_above); + obj = *obj_above; std::cout << " feature above: "; - if (CGAL::assign(hh, res.second)) std::cout << '[' << hh->curve() << ']'; - else if (CGAL::assign(vh, res.second)) std::cout << '(' << vh->point() << ')'; - else if (CGAL::assign(fh, res.second)) std::cout << "NONE"; + if (const auto* hh = boost::get(&obj)) + std::cout << '[' << (*hh)->curve() << ']'; + else if (const auto* vh = boost::get(&obj)) + std::cout << '(' << (*vh)->point() << ')'; + else if (const auto* vh = boost::get(&obj)) + std::cout << "NONE"; else std::cout << "EMPTY"; std::cout << std::endl; diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_arc_polycurve.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_arc_polycurve.cpp index 56ff34ec53b..f92cd22854a 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_arc_polycurve.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_arc_polycurve.cpp @@ -1,64 +1,48 @@ - -// Constructing an arrangement of polycurves. - -#include -#ifndef CGAL_USE_CORE -#include -int main() -{ - std::cout << "Sorry, this example needs CORE ..." << std::endl; - return 0; -} - -#else - -#include -#include -#include -#include #include #include +#include +#include +#include +#include #include #include -#include - /////////////// //circle segment traits ////////////// typedef CGAL::Quotient Number_type; typedef CGAL::Cartesian Kernel; -typedef CGAL::Arr_circle_segment_traits_2 Arc_traits_2; -typedef CGAL::Arr_polyline_traits_2 Polycurve_arc_traits_2; -typedef Arc_traits_2::CoordNT CoordNT; -typedef Arc_traits_2::Point_2 Arc_point_2; -typedef Arc_traits_2::Curve_2 Arc_section_2; -typedef Arc_traits_2::X_monotone_curve_2 Arc_section_x_monotone_2; -typedef CGAL::Arrangement_2 Arc_arrangment_2; +typedef CGAL::Arr_circle_segment_traits_2 Sub_traits_2; +typedef CGAL::Arr_polyline_traits_2 Traits_2; +typedef Sub_traits_2::CoordNT CoordNT; +typedef Sub_traits_2::Point_2 Point_2; +typedef Sub_traits_2::Curve_2 Subcurve_2; +typedef Sub_traits_2::X_monotone_curve_2 Subcurve_x_monotone_2; +typedef boost::variant + Make_sub_x_monotone_result; void check_equal() { - Polycurve_arc_traits_2 Polycurve_traits_2; - Polycurve_arc_traits_2::Equal_2 equal_2 = Polycurve_traits_2.equal_2_object(); - Polycurve_arc_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = + Traits_2 Polycurve_traits_2; + auto equal_2 = Polycurve_traits_2.equal_2_object(); + auto construct_x_monotone_curve_2 = Polycurve_traits_2.construct_x_monotone_curve_2_object(); - Arc_section_2 curve1, curve2, curve3; + Subcurve_2 curve1, curve2, curve3; Kernel::Point_2 p1 = Kernel::Point_2(-5, 0); Kernel::Point_2 mid = Kernel::Point_2(0, 5); Kernel::Point_2 p2 = Kernel::Point_2(5, 0); - curve1= Arc_section_2(p1, mid, p2); - curve2= Arc_section_2(p1, mid, p2); + curve1= Subcurve_2(p1, mid, p2); + curve2= Subcurve_2(p1, mid, p2); // //make x_monotone - // Polycurve_arc_traits_2::X_monotone_curve_2 xmc1 = + // Traits_2::X_monotone_curve_2 xmc1 = // construct_x_monotone_curve_2(curve1); - // Polycurve_arc_traits_2::X_monotone_curve_2 xmc2 = + // Traits_2::X_monotone_curve_2 xmc2 = // construct_x_monotone_curve_2(curve2); - // Polycurve_arc_traits_2::X_monotone_curve_2 xmc3 = + // Traits_2::X_monotone_curve_2 xmc3 = // construct_x_monotone_curve_2(curve3); // //simple equal @@ -71,11 +55,11 @@ void check_equal() // << ((Are_equal) ? "Equal" : "Not equal") << std::endl; } -void check_intersect(Polycurve_arc_traits_2::Make_x_monotone_2 +void check_intersect(Traits_2::Make_x_monotone_2 make_x_monotone_2, - Polycurve_arc_traits_2::Intersect_2 intersect_2) + Traits_2::Intersect_2 intersect_2) { - Arc_section_2 curve1, curve2, curve3; + Subcurve_2 curve1, curve2, curve3; // Create a circular arc that correspond to the upper half of the // circle centered at (1,1) with squared radius 3. We create the @@ -85,24 +69,22 @@ void check_intersect(Polycurve_arc_traits_2::Make_x_monotone_2 Kernel::Circle_2 circ1 = Kernel::Circle_2(c1, 3, CGAL::CLOCKWISE); CoordNT one_minus_sqrt_3 = CoordNT(1, -1, 3); CoordNT one_plus_sqrt_3 = CoordNT(1, 1, 3); - Arc_point_2 s1 = Arc_point_2(one_minus_sqrt_3, CoordNT(1)); - Arc_point_2 t1 = Arc_point_2(one_plus_sqrt_3, CoordNT(1)); - curve1 = Arc_section_2(circ1, s1, t1); - curve2 = Arc_section_2(circ1, s1, t1); + Point_2 s1 = Point_2(one_minus_sqrt_3, CoordNT(1)); + Point_2 t1 = Point_2(one_plus_sqrt_3, CoordNT(1)); + curve1 = Subcurve_2(circ1, s1, t1); + curve2 = Subcurve_2(circ1, s1, t1); //push the same semi circle again - //curves.push_back(Arc_section_2(circ1, s1, t1)); + //curves.push_back(Subcurve_2(circ1, s1, t1)); //make x_monotone - std::vector X_monotone_curves; - make_x_monotone_2(curve1, std::back_inserter(X_monotone_curves)); - make_x_monotone_2(curve2, std::back_inserter(X_monotone_curves)); + std::vector x_monotone_curves; + make_x_monotone_2(curve1, std::back_inserter(x_monotone_curves)); + make_x_monotone_2(curve2, std::back_inserter(x_monotone_curves)); - Arc_section_x_monotone_2 X_monotone_curve1, X_monotone_curve2, - X_monotone_curve3 ; - CGAL::assign(X_monotone_curve1, X_monotone_curves[0]); - CGAL::assign(X_monotone_curve2, X_monotone_curves[1]); + const auto* x_curve1 = boost::get(curves[0]); + const auto* x_curve2 = boost::get(curves[1]); - std::vector Points_of_intersection; + std::vector Points_of_intersection; //intersect_2(X_monotone_curve1, X_monotone_curve2, // std::back_inserter(Points_of_intersection)); @@ -113,12 +95,12 @@ void check_intersect(Polycurve_arc_traits_2::Make_x_monotone_2 Kernel::Point_2 c6 = Kernel::Point_2(0, 0); CoordNT sqrt_3_div_2 = CoordNT(Number_type(0), Number_type(1,2), Number_type(3)); - Arc_point_2 s6 = Arc_point_2(Number_type(-1, 2), sqrt_3_div_2); - Arc_point_2 t6 = Arc_point_2(Number_type(1, 2), sqrt_3_div_2); + Point_2 s6 = Point_2(Number_type(-1, 2), sqrt_3_div_2); + Point_2 t6 = Point_2(Number_type(1, 2), sqrt_3_div_2); - curve3 = Arc_section_2(c6, 1, CGAL::CLOCKWISE, s6, t6); - make_x_monotone_2(curve3, std::back_inserter(X_monotone_curves)); - CGAL::assign(X_monotone_curve2, X_monotone_curves[2]); + curve3 = Subcurve_2(c6, 1, CGAL::CLOCKWISE, s6, t6); + make_x_monotone_2(curve3, std::back_inserter(x_curves)); + const auto* x_curve2 = boost::get<>(&x_curves[2]); Points_of_intersection.clear(); //intersect_2(X_monotone_curve1, X_monotone_curve2, @@ -126,12 +108,12 @@ void check_intersect(Polycurve_arc_traits_2::Make_x_monotone_2 } void -check_compare_end_points_xy_2(Polycurve_arc_traits_2::Compare_endpoints_xy_2 +check_compare_end_points_xy_2(Traits_2::Compare_endpoints_xy_2 compare_endpoints_xy_2, - Polycurve_arc_traits_2::Make_x_monotone_2 + Traits_2::Make_x_monotone_2 make_x_monotone_2) { - Arc_section_2 curve1, curve2; + Subcurve_2 curve1, curve2; // Create a circular arc that correspond to the upper half of the // circle centered at (1,1) with squared radius 3. We create the @@ -141,39 +123,37 @@ check_compare_end_points_xy_2(Polycurve_arc_traits_2::Compare_endpoints_xy_2 Kernel::Circle_2 circ1 = Kernel::Circle_2(c1, 3, CGAL::CLOCKWISE); CoordNT one_minus_sqrt_3 = CoordNT(1, -1, 3); CoordNT one_plus_sqrt_3 = CoordNT(1, 1, 3); - Arc_point_2 s1 = Arc_point_2(one_minus_sqrt_3, CoordNT(1)); - Arc_point_2 t1 = Arc_point_2(one_plus_sqrt_3, CoordNT(1)); - curve1= Arc_section_2(circ1, s1, t1); + Point_2 s1 = Point_2(one_minus_sqrt_3, CoordNT(1)); + Point_2 t1 = Point_2(one_plus_sqrt_3, CoordNT(1)); + curve1= Subcurve_2(circ1, s1, t1); //make x_monotone - std::vector X_monotone_curves; - make_x_monotone_2(curve1, std::back_inserter(X_monotone_curves)); + std::vector x_curves; + make_x_monotone_2(curve1, std::back_inserter(x_curves)); - Arc_section_x_monotone_2 X_monotone_curve1, X_monotone_curve2 ; - CGAL::assign(X_monotone_curve1, X_monotone_curves[ 0 ]); - - int res = compare_endpoints_xy_2(X_monotone_curve1); + const auto* x_curve1 = boost::get(&x_curves[0]); + const auto* x_curve2 = boost::get(&x_curves[1]); + auto res = compare_endpoints_xy_2(x_curve1); std::cout<< "The first result is: " << res << std::endl; Kernel::Point_2 c2 = Kernel::Point_2(1, 1); Kernel::Circle_2 circ2 = Kernel::Circle_2(c2, 3, CGAL::COUNTERCLOCKWISE); - Arc_point_2 t2 = Arc_point_2(one_minus_sqrt_3, CoordNT(1)); - Arc_point_2 s2 = Arc_point_2(one_plus_sqrt_3, CoordNT(1)); - curve2= Arc_section_2(circ2, s1, t1); + Point_2 t2 = Point_2(one_minus_sqrt_3, CoordNT(1)); + Point_2 s2 = Point_2(one_plus_sqrt_3, CoordNT(1)); + curve2 = Subcurve_2(circ2, s1, t1); + make_x_monotone_2(curve2, std::back_inserter(x_curves)); + const auto* x_curve2 = boost::get(&x_curves[1]); - make_x_monotone_2(curve2, std::back_inserter(X_monotone_curves)); - CGAL::assign(X_monotone_curve2, X_monotone_curves[ 1 ]); - - res = compare_endpoints_xy_2(X_monotone_curve2); + res = compare_endpoints_xy_2(x_curve2); std::cout<< "The second result is: " << res << std::endl; } -void check_split(Polycurve_arc_traits_2::Split_2 split_2, - Polycurve_arc_traits_2::Make_x_monotone_2 make_x_monotone_2) +void check_split(Traits_2::Split_2 split_2, + Traits_2::Make_x_monotone_2 make_x_monotone_2) { - Arc_section_2 curve; + Subcurve_2 curve; // Create a circular arc that correspond to the upper half of the // circle centered at (1,1) with squared radius 3. We create the @@ -183,64 +163,59 @@ void check_split(Polycurve_arc_traits_2::Split_2 split_2, Kernel::Circle_2 circ1 = Kernel::Circle_2(c1, 3, CGAL::CLOCKWISE); CoordNT one_minus_sqrt_3 = CoordNT(1, -1, 3); CoordNT one_plus_sqrt_3 = CoordNT(1, 1, 3); - Arc_point_2 s1 = Arc_point_2(one_minus_sqrt_3, CoordNT(1)); - Arc_point_2 t1 = Arc_point_2(one_plus_sqrt_3, CoordNT(1)); - curve= Arc_section_2(circ1, s1, t1); + Point_2 s1 = Point_2(one_minus_sqrt_3, CoordNT(1)); + Point_2 t1 = Point_2(one_plus_sqrt_3, CoordNT(1)); + curve= Subcurve_2(circ1, s1, t1); //make x_monotone - std::vector X_monotone_curves; - make_x_monotone_2(curve, std::back_inserter(X_monotone_curves)); - - Arc_section_x_monotone_2 X_monotone_curve, split_x_monotone_curve1, - split_x_monotone_curve2 ; - CGAL::assign(X_monotone_curve, X_monotone_curves[0]); + std::vector x_curves; + make_x_monotone_2(curve, std::back_inserter(x_curves)); + const auto* x_curve1 = boost::get(&x_curves[0]); + // Subcurve_x_monotone_2 split_x_monotone_curve1, split_x_monotone_curve2 ; //split_2(X_monotone_curve, Kernel::Point_2::Kernel::Point_2(1, 4), // split_x_monotone_curve1, split_x_monotone_curve2); } -void check_is_vertical(Polycurve_arc_traits_2::Make_x_monotone_2 +void check_is_vertical(Traits_2::Make_x_monotone_2 make_x_monotone_2, - Polycurve_arc_traits_2::Is_vertical_2 is_vertical) + Traits_2::Is_vertical_2 is_vertical) { - std::vector curves; + std::vector curves; // Create a circular arc defined by two endpoints and a midpoint, // all having rational coordinates. This arc is the upper-right // quarter of a circle centered at the origin with radius 5. - Kernel::Point_2 p1 = Kernel::Point_2(0, 5); - Kernel::Point_2 mid = Kernel::Point_2(3, 4); - Kernel::Point_2 p2 = Kernel::Point_2(5, 0); - Kernel::Point_2 p3 = Kernel::Point_2(0, -5); - curves.push_back(Arc_section_2(p1, mid, p2)); //quarter of a circle - curves.push_back(Arc_section_2(p1, mid, p3)); //semi-circle + Kernel::Point_2 p1 = Kernel::Point_2(0, 5); + Kernel::Point_2 mid = Kernel::Point_2(3, 4); + Kernel::Point_2 p2 = Kernel::Point_2(5, 0); + Kernel::Point_2 p3 = Kernel::Point_2(0, -5); + curves.push_back(Subcurve_2(p1, mid, p2)); //quarter of a circle + curves.push_back(Subcurve_2(p1, mid, p3)); //semi-circle //convert all curves to x-monotone curves - std::vector X_monotone_curves; - for(int i = 0; i < curves.size(); ++i) - make_x_monotone_2(curves[i], std::back_inserter(X_monotone_curves)); + std::vector x_curves; + for (const auto& cv : curves) + make_x_monotone_2(cv, std::back_inserter(x_curves)); - //std::vector x_monotone_polycurves; + //std::vector x_monotone_polycurves; - Arc_section_x_monotone_2 x_monotone_polycurve1, x_monotone_polycurve2; - CGAL::assign(x_monotone_polycurve1, X_monotone_curves[0]); - CGAL::assign(x_monotone_polycurve2, X_monotone_curves[1]); + const auto* x_polycurve1 = boost::get(&x_curves[0]); + const auto* x_polycurve2 = boost::get(&x_curves[1]); - bool res = is_vertical(x_monotone_polycurve1); + bool res = is_vertical(x_polycurve1); std::cout << "Is_verticle:: The xmonotone curve (quarter circle) is : " << ((res)? "vertical" : "not vertical") << std::endl; - res = is_vertical(x_monotone_polycurve2); + res = is_vertical(x_polycurve2); std::cout << "Is_verticle:: The xmonotone curve (Smi-circle) is : " << ((res)? "vertical" : "not vertical") << std::endl; } -void check_compare_y_at_x_2(Polycurve_arc_traits_2::Make_x_monotone_2 - make_x_monotone_2, - Polycurve_arc_traits_2::Compare_y_at_x_2 - cmp_y_at_x_2) +void check_compare_y_at_x_2(Traits_2::Make_x_monotone_2 make_x_monotone_2, + Traits_2::Compare_y_at_x_2 cmp_y_at_x_2) { - std::vector curves; + std::vector curves; // Create a circular arc defined by two endpoints and a midpoint, // all having rational coordinates. This arc is the upper-right @@ -249,30 +224,29 @@ void check_compare_y_at_x_2(Polycurve_arc_traits_2::Make_x_monotone_2 Kernel::Point_2 mid = Kernel::Point_2(4, 4); Kernel::Point_2 p2 = Kernel::Point_2(7, 1); Kernel::Point_2 p3 = Kernel::Point_2(1, 4); - curves.push_back(Arc_section_2(p1, mid, p2)); //quarter of a circle - curves.push_back(Arc_section_2(p1, mid, p3)); //semi-circle + curves.push_back(Subcurve_2(p1, mid, p2)); //quarter of a circle + curves.push_back(Subcurve_2(p1, mid, p3)); //semi-circle //convert all curves to x-monotone curves - std::vector X_monotone_curves; - for (int i = 0; i < curves.size(); ++i) - make_x_monotone_2(curves[i], std::back_inserter(X_monotone_curves)); + std::vector x_curves; + for (const auto& cv : curves) + make_x_monotone_2(cv, std::back_inserter(x_curves)); - Arc_section_x_monotone_2 x_monotone_polycurve1, x_monotone_polycurve2; - CGAL::assign(x_monotone_polycurve1, X_monotone_curves[ 0 ]); - CGAL::assign(x_monotone_polycurve2, X_monotone_curves[ 1 ]); + const auto* x_polycurve1 = boost::get(&x_curves[0]); + const auto* x_polycurve2 = boost::get(&x_curves[1]); - Kernel::Point_2 p_test = Kernel::Point_2(3, 1); + Kernel::Point_2 p_test = Kernel::Point_2(3, 1); // int res = cmp_y_at_x_2(p_test, x_monotone_polycurve1); // cmp_y_at_x_2(x_monotone_polycurve1, CGAL::ARR_MIN_END, // x_monotone_polycurve2); } -void check_push_back(Polycurve_arc_traits_2::Make_x_monotone_2 +void check_push_back(Traits_2::Make_x_monotone_2 make_x_monotone_2, - Polycurve_arc_traits_2::Push_back_2 push_back_2) + Traits_2::Push_back_2 push_back_2) { - std::vector curves; + std::vector curves; //check if segment is pushed in empty curve. Kernel::Point_2 p1 = Kernel::Point_2(1, 1); @@ -282,10 +256,10 @@ void check_push_back(Polycurve_arc_traits_2::Make_x_monotone_2 Kernel::Point_2 mid2 = Kernel::Point_2(10, 3); Kernel::Point_2 p3 = Kernel::Point_2(7, 7); - curves.push_back(Arc_section_2(p1, mid, p2)); - curves.push_back(Arc_section_2(p2, mid2, p3)); + curves.push_back(Subcurve_2(p1, mid, p2)); + curves.push_back(Subcurve_2(p2, mid2, p3)); - CGAL::internal::Polycurve_2 polycurve; + CGAL::internal::Polycurve_2 polycurve; ////pushing segments in polycurve push_back_2(polycurve, curves[0]); @@ -300,87 +274,70 @@ void check_push_back(Polycurve_arc_traits_2::Make_x_monotone_2 int main() { - Polycurve_arc_traits_2 Polycurve_traits_2; + Traits_2 Polycurve_traits_2; // Compare_x_2 - // Polycurve_arc_traits_2::Compare_x_2 compare_x_2 = + // Traits_2::Compare_x_2 compare_x_2 = // Polycurve_traits_2.compare_xy_2_object(); // number of points - // Polycurve_arc_traits_2::Number_of_points_2 num_of_points = + // Traits_2::Number_of_points_2 num_of_points = // Polycurve_traits_2.number_of_points_2_object(); //construct min vertex - Polycurve_arc_traits_2::Construct_min_vertex_2 cnst_min_vertex = - Polycurve_traits_2.construct_min_vertex_2_object(); + auto cnst_min_vertex = Polycurve_traits_2.construct_min_vertex_2_object(); //construct max vertex - Polycurve_arc_traits_2::Construct_max_vertex_2 cnst_max_vertex_2 = - Polycurve_traits_2.construct_max_vertex_2_object(); + auto cnst_max_vertex_2 = Polycurve_traits_2.construct_max_vertex_2_object(); //is vertical (return bool) - Polycurve_arc_traits_2::Is_vertical_2 is_vertical = - Polycurve_traits_2.is_vertical_2_object(); + auto is_vertical = Polycurve_traits_2.is_vertical_2_object(); //Compare y at x 2 (return comparison_result) - Polycurve_arc_traits_2::Compare_y_at_x_2 cmp_y_at_x_2 = - Polycurve_traits_2.compare_y_at_x_2_object(); + auto cmp_y_at_x_2 = Polycurve_traits_2.compare_y_at_x_2_object(); //compare y at x left - Polycurve_arc_traits_2::Compare_y_at_x_left_2 cmp_y_at_x_left_2 = - Polycurve_traits_2.compare_y_at_x_left_2_object(); + auto cmp_y_at_x_left_2 = Polycurve_traits_2.compare_y_at_x_left_2_object(); //compare y at x right - Polycurve_arc_traits_2::Compare_y_at_x_right_2 cmp_y_at_x_right_2 = - Polycurve_traits_2.compare_y_at_x_right_2_object(); + auto cmp_y_at_x_right_2 = Polycurve_traits_2.compare_y_at_x_right_2_object(); //equal_2 - Polycurve_arc_traits_2::Equal_2 equal_2 = - Polycurve_traits_2.equal_2_object(); + auto equal_2 = Polycurve_traits_2.equal_2_object(); //compare end points xy_2 - Polycurve_arc_traits_2::Compare_endpoints_xy_2 compare_endpoints_xy_2 = + auto compare_endpoints_xy_2 = Polycurve_traits_2.compare_endpoints_xy_2_object(); //construct opposite - Polycurve_arc_traits_2::Construct_opposite_2 construct_opposite_2 = - Polycurve_traits_2.construct_opposite_2_object(); + auto construct_opposite_2 = Polycurve_traits_2.construct_opposite_2_object(); //make x_monotone - Polycurve_arc_traits_2::Make_x_monotone_2 make_x_monotone_2 = - Polycurve_traits_2.make_x_monotone_2_object(); + auto make_x_monotone_2 = Polycurve_traits_2.make_x_monotone_2_object(); //push back - Polycurve_arc_traits_2::Push_back_2 push_back_2 = - Polycurve_traits_2.push_back_2_object(); + auto push_back_2 = Polycurve_traits_2.push_back_2_object(); //push front - Polycurve_arc_traits_2::Push_front_2 push_front_2 = - Polycurve_traits_2.push_front_2_object(); + auto push_front_2 = Polycurve_traits_2.push_front_2_object(); //split_2 - Polycurve_arc_traits_2::Split_2 split_2 = - Polycurve_traits_2.split_2_object(); + auto split_2 = Polycurve_traits_2.split_2_object(); //Intersect_2 - Polycurve_arc_traits_2::Intersect_2 intersect_2 = - Polycurve_traits_2.intersect_2_object(); + auto intersect_2 = Polycurve_traits_2.intersect_2_object(); //Are_mergable - Polycurve_arc_traits_2::Are_mergeable_2 are_mergeable_2 = - Polycurve_traits_2.are_mergeable_2_object(); + auto are_mergeable_2 = Polycurve_traits_2.are_mergeable_2_object(); //Merge_2 - Polycurve_arc_traits_2::Merge_2 merge_2 = - Polycurve_traits_2.merge_2_object(); + auto merge_2 = Polycurve_traits_2.merge_2_object(); //construct_curve_2 - Polycurve_arc_traits_2::Construct_curve_2 construct_curve_2 = - Polycurve_traits_2.construct_curve_2_object(); + auto construct_curve_2 = Polycurve_traits_2.construct_curve_2_object(); //construct x_monotone curve_2 - Polycurve_arc_traits_2::Construct_x_monotone_curve_2 - construct_x_monotone_curve_2 = + auto construct_x_monotone_curve_2 = Polycurve_traits_2.construct_x_monotone_curve_2_object(); //check_equal(); @@ -393,4 +350,3 @@ int main() return 0; } -#endif diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_bezier_polycurve.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_bezier_polycurve.cpp index 134fbbcc011..9936d4648ec 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_bezier_polycurve.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_bezier_polycurve.cpp @@ -23,15 +23,19 @@ typedef CGAL::Cartesian Alg_kernel; typedef Rat_kernel::Point_2 Rat_point_2; //bezier traits -typedef CGAL::Arr_Bezier_curve_traits_2 Bezier_traits_2; -typedef Bezier_traits_2::Curve_2 Bezier_curve; -typedef Bezier_traits_2::X_monotone_curve_2 Bezier_x_monotone_curve; +typedef CGAL::Arr_Bezier_curve_traits_2 + Bezier_traits_2; +typedef Bezier_traits_2::Point_2 Bezier_point; +typedef Bezier_traits_2::Curve_2 Bezier_curve; +typedef Bezier_traits_2::X_monotone_curve_2 Bezier_x_monotone_curve; //polyline traits -typedef CGAL::Arr_polyline_traits_2 Bezier_polycurve_traits; -typedef Bezier_polycurve_traits::Curve_2 Polycurve_bezier; -typedef Bezier_polycurve_traits::X_monotone_curve_2 X_polycurve_bezier; +typedef CGAL::Arr_polyline_traits_2 Bezier_polycurve_traits; +typedef Bezier_polycurve_traits::Curve_2 Polycurve_bezier; +typedef Bezier_polycurve_traits::X_monotone_curve_2 X_polycurve_bezier; +typedef boost::variant + Make_x_monotone_result; int main (int argc, char *argv[]) { @@ -51,35 +55,40 @@ int main (int argc, char *argv[]) points_vector.push_back( Rat_point_2(900,0) ); Bezier_curve curve_1 (points_vector.begin(), points_vector.end()); - std::vector obj_vector; + std::vector objs; //creating x-mono bezier - bezier_traits.make_x_monotone_2_object()( curve_1, std::back_inserter(obj_vector)); + bezier_traits.make_x_monotone_2_object()(curve_1, std::back_inserter(objs)); //std::cout << "number of x_curves: " << obj_vector.size() << std::endl; - Bezier_x_monotone_curve x_curve_1 = CGAL::object_cast( (obj_vector[0]) ); + const auto* x_curve_1 = boost::get(&(obj_vector[0])); + assert(x_curve_1); //std::cout << x_curve << std::endl; points_vector.clear(); - points_vector.push_back( Rat_point_2(900,0) ); - points_vector.push_back( Rat_point_2(1000,400) ); - points_vector.push_back( Rat_point_2(1500,200) ); - points_vector.push_back( Rat_point_2(2000,0) ); - Bezier_curve curve_2 (points_vector.begin(), points_vector.end()); + points_vector.push_back(Rat_point_2(900,0)); + points_vector.push_back(Rat_point_2(1000,400)); + points_vector.push_back(Rat_point_2(1500,200)); + points_vector.push_back(Rat_point_2(2000,0)); + Bezier_curve curve_2(points_vector.begin(), points_vector.end()); //creating x-monotne obj_vector.clear(); - bezier_traits.make_x_monotone_2_object()( curve_2, std::back_inserter(obj_vector)); - Bezier_x_monotone_curve x_curve_2 = CGAL::object_cast( (obj_vector[0]) ); + bezier_traits.make_x_monotone_2_object()( curve_2, std::back_inserter(objs)); + const auto* x_curve_2 = boost::get(&(obj_vector[0])); //push curves into polyline vectors curves_vector.push_back(curve_1); curves_vector.push_back(curve_2); - x_curves_vector.push_back(x_curve_1); - x_curves_vector.push_back(x_curve_2); + x_curves_vector.push_back(*x_curve_1); + x_curves_vector.push_back(*x_curve_2); //create polycurves - Polycurve_bezier polycurve_1 = poly_traits.construct_curve_2_object()(curves_vector.begin(), curves_vector.end()); - X_polycurve_bezier x_polycurve_1 = poly_traits.construct_x_monotone_curve_2_object()(x_curves_vector.begin(), x_curves_vector.end()); + auto ctr_curve = poly_traits.construct_curve_2_object(); + Polycurve_bezier + polycurve_1 = ctr_curve(curves_vector.begin(), curves_vector.end()); + auto ctr_x_monotone_curve = poly_traits.construct_x_monotone_curve_2_object(); + X_polycurve_bezier x_polycurve_1 = + ctr_x_monotone_curve(x_curves_vector.begin(), x_curves_vector.end()); std::cout << "polycurve : " << polycurve_1 << std::endl; std::cout << "x_polycurve : " << x_polycurve_1 << std::endl; diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_circular_arc_polycurve.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_circular_arc_polycurve.cpp index 1cf5a0e06f8..32395799ae5 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_circular_arc_polycurve.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_circular_arc_polycurve.cpp @@ -73,25 +73,31 @@ bool check_compare_y_at_x_2(Curve& cv) return true; } -template -void check_intersect(const Curve& cv1, const Curve& cv2) +template +void check_intersect(const typename GeometryTraits_2::X_monotone_curve_2& cv1, + const typename GeometryTraits_2::X_monotone_curve_2& cv2, + const GeometryTraits_2& traits) { // Polycurve_arc_traits_2 traits; - - // std::vector object_vec; - // traits.intersect_2_object()(cv1, cv2, object_vec); - // std::cout<< "number of intersections is: " << object_vec.size(); + // std::vector objs; + // traits.intersect_2_object()(cv1, cv2, std::back_inserter(objs)); + // std::cout<< "number of intersections is: " << objs.size(); } -template -void check_make_x_monotone(Curve cv) +template +void check_make_x_monotone(typename GeometryTraits::Curve_2 cv, + const GeometryTraits_2& traits) { - Polycurve_arc_traits_2 traits; - std::vector object_vec; + typedef GeometryTraits_2 Geometry_traits_2; + typedef typename Geometry_traits_2::Point_2 Point_2; + typedef typename Geometry_traits_2::X_monotone_traits_2 X_monotone_traits_2; - traits.make_x_monotone_2_object()(cv, std::back_inserter(object_vec)); - std::cout << "Number of x-monotone curves: " - << object_vec.size() << std::endl; + typedef boost::variant + Make_x_monotone_result; + + std::vector objs; + traits.make_x_monotone_2_object()(cv, std::back_inserter(objs)); + std::cout << "Number of x-monotone curves: " << objs.size() << std::endl; } template @@ -198,8 +204,8 @@ int main(int argc, char* argv[]) ////////////////////// // check_compare_y_at_x_2(x_polycurve_1); - // check_intersect(x_polycurve_1, x_polycurve_2); - //check_make_x_monotone(curve_1); + // check_intersect(x_polycurve_1, x_polycurve_2, traits); + //check_make_x_monotone(curve_1, traits); //checking if the cgal_assertion for curve construction for two points work //or not. diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp index eab53350ab6..84c33b4d914 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_conic_polycurve.cpp @@ -11,19 +11,19 @@ int main() #else +#include +#include + +#include + #include #include #include #include -#include -#include - #include #include -#include #include #include -#include //////////////////// //conic traits @@ -43,7 +43,7 @@ typedef Conic_traits_2::Curve_2 Conic_curve_2; typedef Conic_traits_2::X_monotone_curve_2 Conic_x_monotone_curve_2; typedef CGAL::Arr_polyline_traits_2 Polycurve_conic_traits_2; typedef Polycurve_conic_traits_2::X_monotone_curve_2 Pc_x_monotone_curve_2; -// typedef Polycurve_conic_traits_2::Point_2 polypoint; +typedef Polycurve_conic_traits_2::Point_2 Pc_point_2; // typedef CGAL::Arr_polyline_traits_2< // CGAL::Arr_conic_traits_2, @@ -102,27 +102,36 @@ void check_equal() << ((are_equal) ? "equal" : "Not equal") << std::endl; } - template - void check_intersect(curve_type &xcv1, curve_type &xcv2) + template + void check_intersect(typename Traits::X_monotone_curve_2& xcv1, + typename Traits::X_monotone_curve_2& xcv2, + const Traits& traits) { - Polycurve_conic_traits_2 traits; - std::vector intersection_points; - traits.intersect_2_object()(xcv1, xcv2, std::back_inserter(intersection_points)); - std::cout<< "Number of intersection Points: " << intersection_points.size() - << std::endl; + typedef typename Traits::Multiplicity Multiplicity; + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; - //dynamic cast the cgal_objects - // std::vector< std::pair > pm_vector; - // for(int i=0; i pm = - // CGAL::object_cast > - // (&(intersection_points[i])); - // pm_vector.push_back(pm); - // } + std::vector intersection_points; + traits.intersect_2_object()(xcv1, xcv2, + std::back_inserter(intersection_points)); + std::cout<< "Number of intersection Points: " << intersection_points.size() + << std::endl; + + //dynamic cast the cgal_objects + // std::vector< std::pair > pm_vector; + // for(int i=0; i pm = + // CGAL::object_cast > + // (&(intersection_points[i])); + // pm_vector.push_back(pm); + // } } void check_compare_end_points_xy_2() @@ -151,7 +160,7 @@ void check_compare_end_points_xy_2() 0, 0, 0, 0, 1, 3, // The line: y = -3. Conic_point_2(1.41, -2), // Approximation of the target. 0, 0, 0, 0, 1, 2); // The line: y = -2. - CGAL_assertion(c2.is_valid()); + assert(c2.is_valid()); //make polyline x-monotone curves Polycurve_conic_traits_2::X_monotone_curve_2 polyline_xmc1 = @@ -631,22 +640,23 @@ void check_compare_y_at_x_left() (result == CGAL::LARGER ? "Larger" : "equal")) << std::endl; } -template -void check_make_x_monotne_curve(Curve_type c1) +template +void check_make_x_monotne_curve(const typename GeometryTraits::Curve_2& c1) { + typename GeometryTraits::Point_2 Point_2; + typename GeometryTraits::X_monotone_curve_2 X_monotone_curve_2; + typedef boost::variant Make_x_monotone_result; Polycurve_conic_traits_2 traits; - std::vector obj_vec; - traits.make_x_monotone_2_object()(c1, std::back_inserter(obj_vec)); - + std::vector objs; + traits.make_x_monotone_2_object()(c1, std::back_inserter(objs)); std::cout << "The polycurve is: " << c1 << std::endl; - - std::cout<< "The poly curve have been split into " << obj_vec.size() + std::cout<< "The poly curve have been split into " << objs.size() << " polycurves" << std::endl; //const Pc_x_monotone_curve_2 *split_curve_1 = - // CGAL::object_cast (&(obj_vec[0])); + // CGAL::object_cast (&(objs[0])); //const Pc_x_monotone_curve_2 *split_curve_2 = - // CGAL::object_cast (&(obj_vec[1])); + // CGAL::object_cast (&(objs[1])); //std::cout << "The split curve 1 is: " << *split_curve_1 << std::endl; //std::cout << "The split curve 2 is: " << *split_curve_2 << std::endl; @@ -726,10 +736,8 @@ int main(int argc, char* argv[]) { Polycurve_conic_traits_2 traits; //polycurve constructors - Polycurve_conic_traits_2::Construct_x_monotone_curve_2 - construct_x_mono_polycurve = traits.construct_x_monotone_curve_2_object(); - Polycurve_conic_traits_2::Construct_curve_2 construct_polycurve = - traits.construct_curve_2_object(); + auto construct_x_mono_polycurve = traits.construct_x_monotone_curve_2_object(); + auto construct_polycurve = traits.construct_curve_2_object(); //create a curve @@ -886,7 +894,7 @@ int main(int argc, char* argv[]) //check_split(conic_x_mono_polycurve_1, conic_x_mono_polycurve_2); // std::cout<< std::endl; - //check_make_x_monotne_curve(conic_polycurve_2); + //check_make_x_monotne_curve(conic_polycurve_2); //std::cout<< std::endl; // check_is_vertical(); diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_vert_ray_shoot_vert_segments.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_vert_ray_shoot_vert_segments.cpp index e4a024fe4b9..07cfc97e199 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_vert_ray_shoot_vert_segments.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_vert_ray_shoot_vert_segments.cpp @@ -1,146 +1,131 @@ -#include +#include #include #include #include #include #include -template +template void vertical_ray_shooting_query - (const VerticalRayShoot& vrs, bool shoot_up, - const typename VerticalRayShoot::Arrangement_2::Point_2& q) +(const VerticalRayShoot& vrs, bool shoot_up, + const typename VerticalRayShoot::Arrangement_2::Point_2& q) { // Perform the point-location query. - CGAL::Object obj = (shoot_up) ? vrs.ray_shoot_up (q) : - vrs.ray_shoot_down (q); + auto obj = (shoot_up) ? vrs.ray_shoot_up(q) : vrs.ray_shoot_down(q); // Print the result. - typedef typename VerticalRayShoot::Arrangement_2 Arrangement_2; + typedef typename VerticalRayShoot::Arrangement_2 Arrangement_2; + typedef typename Arrangement_2::Vertex_const_handle Vertex_const_handle; + typedef typename Arrangement_2::Halfedge_const_handle Halfedge_const_handle; + typedef typename Arrangement_2::Face_const_handle Face_const_handle; - typename Arrangement_2::Vertex_const_handle v; - typename Arrangement_2::Halfedge_const_handle e; - typename Arrangement_2::Face_const_handle f; + if (shoot_up) std::cout << " Shooting up from (" << q << ") : "; + else std::cout << " Shooting down from (" << q << ") : "; - if (shoot_up) - std::cout << " Shooting up from (" << q << ") : "; - else - std::cout << " Shooting down from (" << q << ") : "; - - if (CGAL::assign (e, obj)) - { + if (auto* e_p = boost::get(&obj)) { // We hit an edge: - std::cout << "hit an edge: " << e->curve() << std::endl; + std::cout << "hit an edge: " << (*e_p)->curve() << std::endl; } - else if (CGAL::assign (v, obj)) - { + else if (auto* v_p = boost::get(&obj)) { // We hit a vertex: - if (v->is_isolated()) - std::cout << "hit an isolated vertex: " << v->point() << std::endl; - else - std::cout << "hit a vertex: " << v->point() << std::endl; + if ((*v_p)->is_isolated()) + std::cout << "hit an isolated vertex: " << (*v_p)->point() << std::endl; + else std::cout << "hit a vertex: " << (*v_p)->point() << std::endl; } - else if (CGAL::assign (f, obj)) - { + else if (auto* f_p = boost::get(&obj)) { // We did not hit anything: - assert (f->is_unbounded()); + assert((*f_p)->is_unbounded()); std::cout << "hit nothing." << std::endl; } - else - { - CGAL_error_msg( "Invalid object."); - } - - return; + else CGAL_error_msg( "Invalid object."); } +typedef CGAL::Exact_predicates_exact_constructions_kernel Kernel; +typedef Kernel::FT Number_type; +typedef CGAL::Arr_segment_traits_2 Traits_2; +typedef Traits_2::Point_2 Point_2; +typedef Traits_2::X_monotone_curve_2 Segment_2; +typedef CGAL::Arrangement_2 Arrangement_2; +typedef CGAL::Arr_simple_point_location Simple_pl; +typedef CGAL::Arr_walk_along_line_point_location Walk_pl; +typedef CGAL::Arr_trapezoid_ric_point_location RIC_pl; -typedef int Number_type; -typedef CGAL::Cartesian Kernel; -typedef CGAL::Arr_segment_traits_2 Traits_2; -typedef Traits_2::Point_2 Point_2; -typedef Traits_2::X_monotone_curve_2 Segment_2; -typedef CGAL::Arrangement_2 Arrangement_2; -typedef CGAL::Arr_simple_point_location Simple_pl; -typedef CGAL::Arr_walk_along_line_point_location Walk_pl; -typedef CGAL::Arr_trapezoid_ric_point_location RIC_pl; - -int main () +int main() { // Construct the arrangement. - Arrangement_2 arr; - Simple_pl simple_pl (arr); - Walk_pl walk_pl (arr); - RIC_pl ric_pl (arr); + Arrangement_2 arr; + Simple_pl simple_pl(arr); + Walk_pl walk_pl(arr); + RIC_pl ric_pl(arr); - insert (arr, Segment_2 (Point_2 (0, 0), Point_2 (0, 1))); - insert (arr, Segment_2 (Point_2 (0, 3), Point_2 (0, 4))); - insert (arr, Segment_2 (Point_2 (-1, -1), Point_2 (1, -1))); - insert (arr, Segment_2 (Point_2 (-1, 5), Point_2 (1, 5))); + insert(arr, Segment_2(Point_2(0, 0), Point_2(0, 1))); + insert(arr, Segment_2(Point_2(0, 3), Point_2(0, 4))); + insert(arr, Segment_2(Point_2(-1, -1), Point_2(1, -1))); + insert(arr, Segment_2(Point_2(-1, 5), Point_2(1, 5))); // Perform the vertical ray-shooting queries. std::cout << "First round of queries: " << std::endl; - Point_2 q1 (0, 2); + Point_2 q1(0, 2); - vertical_ray_shooting_query (simple_pl, true, q1); - vertical_ray_shooting_query (walk_pl, true, q1); - vertical_ray_shooting_query (ric_pl, true, q1); + vertical_ray_shooting_query(simple_pl, true, q1); + vertical_ray_shooting_query(walk_pl, true, q1); + vertical_ray_shooting_query(ric_pl, true, q1); - vertical_ray_shooting_query (simple_pl, false, q1); - vertical_ray_shooting_query (walk_pl, false, q1); - vertical_ray_shooting_query (ric_pl, false, q1); + vertical_ray_shooting_query(simple_pl, false, q1); + vertical_ray_shooting_query(walk_pl, false, q1); + vertical_ray_shooting_query(ric_pl, false, q1); - Point_2 q2 (0, 1); + Point_2 q2(0, 1); - vertical_ray_shooting_query (simple_pl, true, q2); - vertical_ray_shooting_query (walk_pl, true, q2); - vertical_ray_shooting_query (ric_pl, true, q2); + vertical_ray_shooting_query(simple_pl, true, q2); + vertical_ray_shooting_query(walk_pl, true, q2); + vertical_ray_shooting_query(ric_pl, true, q2); - vertical_ray_shooting_query (simple_pl, false, q2); - vertical_ray_shooting_query (walk_pl, false, q2); - vertical_ray_shooting_query (ric_pl, false, q2); + vertical_ray_shooting_query(simple_pl, false, q2); + vertical_ray_shooting_query(walk_pl, false, q2); + vertical_ray_shooting_query(ric_pl, false, q2); - Point_2 q3 (0, 3); + Point_2 q3(0, 3); - vertical_ray_shooting_query (simple_pl, true, q3); - vertical_ray_shooting_query (walk_pl, true, q3); - vertical_ray_shooting_query (ric_pl, true, q3); + vertical_ray_shooting_query(simple_pl, true, q3); + vertical_ray_shooting_query(walk_pl, true, q3); + vertical_ray_shooting_query(ric_pl, true, q3); - vertical_ray_shooting_query (simple_pl, false, q3); - vertical_ray_shooting_query (walk_pl, false, q3); - vertical_ray_shooting_query (ric_pl, false, q3); + vertical_ray_shooting_query(simple_pl, false, q3); + vertical_ray_shooting_query(walk_pl, false, q3); + vertical_ray_shooting_query(ric_pl, false, q3); // Insert additional curves and perform the ray-shooting queries again. - insert (arr, Segment_2 (Point_2 (-1, 0), Point_2 (1, 0))); - insert (arr, Segment_2 (Point_2 (-1, 4), Point_2 (1, 4))); + insert (arr, Segment_2(Point_2(-1, 0), Point_2(1, 0))); + insert (arr, Segment_2(Point_2(-1, 4), Point_2(1, 4))); std::cout << "Second round of queries: " << std::endl; - vertical_ray_shooting_query (simple_pl, true, q1); - vertical_ray_shooting_query (walk_pl, true, q1); - vertical_ray_shooting_query (ric_pl, true, q1); + vertical_ray_shooting_query(simple_pl, true, q1); + vertical_ray_shooting_query(walk_pl, true, q1); + vertical_ray_shooting_query(ric_pl, true, q1); - vertical_ray_shooting_query (simple_pl, false, q1); - vertical_ray_shooting_query (walk_pl, false, q1); - vertical_ray_shooting_query (ric_pl, false, q1); + vertical_ray_shooting_query(simple_pl, false, q1); + vertical_ray_shooting_query(walk_pl, false, q1); + vertical_ray_shooting_query(ric_pl, false, q1); - vertical_ray_shooting_query (simple_pl, true, q2); - vertical_ray_shooting_query (walk_pl, true, q2); - vertical_ray_shooting_query (ric_pl, true, q2); + vertical_ray_shooting_query(simple_pl, true, q2); + vertical_ray_shooting_query(walk_pl, true, q2); + vertical_ray_shooting_query(ric_pl, true, q2); - vertical_ray_shooting_query (simple_pl, false, q2); - vertical_ray_shooting_query (walk_pl, false, q2); - vertical_ray_shooting_query (ric_pl, false, q2); + vertical_ray_shooting_query(simple_pl, false, q2); + vertical_ray_shooting_query(walk_pl, false, q2); + vertical_ray_shooting_query(ric_pl, false, q2); - vertical_ray_shooting_query (simple_pl, true, q3); - vertical_ray_shooting_query (walk_pl, true, q3); - vertical_ray_shooting_query (ric_pl, true, q3); + vertical_ray_shooting_query(simple_pl, true, q3); + vertical_ray_shooting_query(walk_pl, true, q3); + vertical_ray_shooting_query(ric_pl, true, q3); - vertical_ray_shooting_query (simple_pl, false, q3); - vertical_ray_shooting_query (walk_pl, false, q3); - vertical_ray_shooting_query (ric_pl, false, q3); + vertical_ray_shooting_query(simple_pl, false, q3); + vertical_ray_shooting_query(walk_pl, false, q3); + vertical_ray_shooting_query(ric_pl, false, q3); return (0); } - diff --git a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_zone.cpp b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_zone.cpp index 7595a3e305a..54291b4bf5a 100644 --- a/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_zone.cpp +++ b/Arrangement_on_surface_2/test/Arrangement_on_surface_2/test_zone.cpp @@ -8,13 +8,17 @@ #include #include -typedef CGAL::Quotient Number_type; -typedef CGAL::Simple_cartesian Kernel; -typedef CGAL::Arr_segment_traits_2 Traits_2; -typedef Traits_2::Point_2 Point_2; -typedef Traits_2::X_monotone_curve_2 Segment_2; -typedef CGAL::Arrangement_2 Arrangement_2; -typedef Arrangement_2::Halfedge_handle Halfedge_handle; +typedef CGAL::Quotient Number_type; +typedef CGAL::Simple_cartesian Kernel; +typedef CGAL::Arr_segment_traits_2 Traits_2; +typedef Traits_2::Point_2 Point_2; +typedef Traits_2::X_monotone_curve_2 Segment_2; +typedef CGAL::Arrangement_2 Arrangement_2; +typedef Arrangement_2::Vertex_handle Vertex_handle; +typedef Arrangement_2::Halfedge_handle Halfedge_handle; +typedef Arrangement_2::Face_handle Face_handle; +typedef boost::variant + Zone_result; #define N_SEGMENTS 3 @@ -40,7 +44,7 @@ int main () for (k = 0; k < N_SEGMENTS; k++) { - std::list zone_elems; + std::list zone_elems; zone(arr, segs[k], std::back_inserter(zone_elems)); std::size_t zone_actual_comp = zone_elems.size(); diff --git a/BGL/doc/BGL/NamedParameters.txt b/BGL/doc/BGL/NamedParameters.txt index 9c51ba730b6..d0a492fd54a 100644 --- a/BGL/doc/BGL/NamedParameters.txt +++ b/BGL/doc/BGL/NamedParameters.txt @@ -38,8 +38,9 @@ CGAL::copy_face_graph(g1, g2); // specifying named parameters for the second graph CGAL::copy_face_graph(g1, g2, - CGAL::parameters::all_default(), - CGAL::parameters::vertex_point_map(vpm_2)); + CGAL::parameters::vertex_point_map(vpm) //parameter for g1 + .vertex_to_vertex_map(v2v), //other parameter for g1 + CGAL::parameters::all_default()); //parameter for g2 \endcode */ Ë› diff --git a/BGL/doc/BGL/PackageDescription.txt b/BGL/doc/BGL/PackageDescription.txt index 4266bfefa15..8a5d946cd9e 100644 --- a/BGL/doc/BGL/PackageDescription.txt +++ b/BGL/doc/BGL/PackageDescription.txt @@ -443,7 +443,7 @@ the requirement for traversal of all faces in a graph. /// \defgroup PkgBGLPropertiesDynamic Dynamic Properties /// \ingroup PkgBGLRef -/// \defgroup PkgBGLGraphExternalIndices External Indices +/// \defgroup BGLGraphExternalIndices External Indices /// \ingroup PkgBGLRef /// \defgroup PkgBGLHelperFct Helper Functions diff --git a/BGL/examples/BGL_LCC/normals_lcc.cpp b/BGL/examples/BGL_LCC/normals_lcc.cpp index 3cdd3580bef..7487e1876a0 100644 --- a/BGL/examples/BGL_LCC/normals_lcc.cpp +++ b/BGL/examples/BGL_LCC/normals_lcc.cpp @@ -77,7 +77,7 @@ int main(int argc, char** argv) // http://www.boost.org/libs/property_map/doc/vector_property_map.html // for details. boost::vector_property_map - normals(get(CGAL::face_index, lcc)); + normals(static_cast(num_faces(lcc)), get(CGAL::face_index, lcc)); calculate_face_normals( lcc // Graph diff --git a/BGL/examples/BGL_polyhedron_3/normals.cpp b/BGL/examples/BGL_polyhedron_3/normals.cpp index 5de0ba63f70..b74b56183f1 100644 --- a/BGL/examples/BGL_polyhedron_3/normals.cpp +++ b/BGL/examples/BGL_polyhedron_3/normals.cpp @@ -82,7 +82,7 @@ int main(int argc, char** argv) // http://www.boost.org/libs/property_map/doc/vector_property_map.html // for details. boost::vector_property_map - normals(get(CGAL::face_index, P)); + normals(static_cast(num_faces(P)), get(CGAL::face_index, P)); calculate_face_normals( P // Graph diff --git a/BGL/include/CGAL/boost/graph/Euler_operations.h b/BGL/include/CGAL/boost/graph/Euler_operations.h index d575de0f17a..8d5268da6e0 100644 --- a/BGL/include/CGAL/boost/graph/Euler_operations.h +++ b/BGL/include/CGAL/boost/graph/Euler_operations.h @@ -13,6 +13,8 @@ #define CGAL_EULER_OPERATIONS_H #include +#include +#include #include #include @@ -558,6 +560,127 @@ add_edge(typename boost::graph_traits::vertex_descriptor s, return e; } + +/** +* checks whether a new face defined by a range of vertices (identified by their descriptors, +* `boost::graph_traits::%vertex_descriptor`) can be added. +*/ +template +bool can_add_face(const VertexRange& vrange, const PMesh& sm) +{ + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + std::vector::vertex_descriptor> face(vrange.begin(), vrange.end()); + + std::size_t N = face.size(); + std::vector f2(face); + std::sort(f2.begin(), f2.end()); + + typename std::vector::iterator it = std::unique(f2.begin(),f2.end()); + + if((N > 0) && (it != f2.end())){ + return false; + } + + if(N < 3){ + return false; + } + + face.push_back(face.front()); + + for(std::size_t i=0; i < N; ++i){ + halfedge_descriptor hd; + bool found; + boost::tie(hd,found) = halfedge(face[i],face[i+1],sm); + if(found && (! is_border(hd,sm))){ + return false; + } + } + + for(std::size_t i=0; i < N; ++i){ + if(halfedge(face[i],sm) == boost::graph_traits::null_halfedge()){ + continue; + } + + if(! is_border(face[i],sm)){ + return false; + } + } + //Test if all halfedges of the new face + //are possibly consecutive border halfedges in the HDS. + //Possibly because it may be not directly encoded in the HDS + //(using next() function ). This situation can occur when one or + //more facets share only a vertex: For example, the new facet we try to add + //would make the vertex indices[i] a manifold but this should be forbidden + //if a facet only incident to that vertex has already been inserted. + //We check this for each vertex of the sequence. + for(std::size_t i = 0; i < N; ++i) { + std::size_t prev_index= (i-1+N)%N; + std::size_t next_index= (i+1)%N; + vertex_descriptor previous_vertex = face[ prev_index ]; + vertex_descriptor next_vertex = face[ next_index ]; + + halfedge_descriptor halfedge_around_vertex = halfedge(face[i],sm); + + if ( halfedge_around_vertex == boost::graph_traits::null_halfedge() || + halfedge(previous_vertex,sm) == boost::graph_traits::null_halfedge()|| + halfedge(next_vertex,sm) == boost::graph_traits::null_halfedge() + ) continue; + + halfedge_descriptor start=halfedge_around_vertex; + //halfedges pointing to/running out from vertex indices[i] + //and that need to be possibly consecutive + halfedge_descriptor prev_hd= boost::graph_traits::null_halfedge(),next_hd= boost::graph_traits::null_halfedge(); + + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + //look for a halfedge incident to vertex indices[i] + //and which opposite is incident to previous_vertex + do{ + if(target(opposite(halfedge_around_vertex,sm),sm)==previous_vertex){ + prev_hd=halfedge_around_vertex; + CGAL_precondition(is_border(prev_hd,sm)); + break; + } + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + } + while (halfedge_around_vertex!=start); + + if (prev_hd != boost::graph_traits::null_halfedge()){ + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + //prev_hd and next are already consecutive in the HDS + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex) continue; + + //look for a border halfedge which opposite is + //incident to next_vertex: set next halfedge + do + { + if (target(opposite(halfedge_around_vertex,sm),sm)==next_vertex){ + next_hd = opposite(halfedge_around_vertex,sm); + break; + } + halfedge_around_vertex = opposite(next(halfedge_around_vertex,sm),sm); + } + while(halfedge_around_vertex != prev_hd); + if (next_hd==boost::graph_traits::null_halfedge()) continue; + + //check if no constraint prevents + //prev_hd and next_hd to be adjacent: + do{ + halfedge_around_vertex = opposite(next(halfedge_around_vertex, sm),sm); + if ( is_border(opposite(halfedge_around_vertex,sm),sm) ) break; + } + while (halfedge_around_vertex != prev_hd); + if (halfedge_around_vertex == prev_hd) return false; + start = halfedge_around_vertex; + } + } + + return true; +} + + + /** * adds a new face defined by a range of vertices (identified by their descriptors, * `boost::graph_traits::%vertex_descriptor`). diff --git a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h index d7771588560..a9bc5749a21 100644 --- a/BGL/include/CGAL/boost/graph/Face_filtered_graph.h +++ b/BGL/include/CGAL/boost/graph/Face_filtered_graph.h @@ -104,6 +104,66 @@ struct Face_filtered_graph typedef Face_filtered_graph Self; + /*! + * \brief constructs an empty face filtered graph (no face is selected) + * + * \tparam NamedParameters a sequence of named parameters + * + * \param graph the underlying graph. + * + * \param np optional sequence of named parameters among the ones listed below + * + * \cgalNamedParamsBegin + * \cgalParamNBegin{vertex_index_map} + * \cgalParamDescription{a property map associating to each vertex of `graph` a unique index between `0` and `num_vertices(graph) - 1`} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%vertex_descriptor` + * as key type and `std::size_t` as value type} + * \cgalParamDefault{an automatically indexed internal map} + * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize + * a face index property map, either using the internal property map if it exists + * or using an external map. The latter might result in - slightly - worsened performance + * in case of non-constant complexity for index access.} + * \cgalParamNEnd + * + * \cgalParamNBegin{halfedge_index_map} + * \cgalParamDescription{a property map associating to each halfedge of `graph` a unique index between `0` and `num_halfedges(graph) - 1`} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%halfedge_descriptor` + * as key type and `std::size_t` as value type} + * \cgalParamDefault{an automatically indexed internal map} + * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize + * a face index property map, either using the internal property map if it exists + * or using an external map. The latter might result in - slightly - worsened performance + * in case of non-constant complexity for index access.} + * \cgalParamNEnd + * + * \cgalParamNBegin{face_index_map} + * \cgalParamDescription{a property map associating to each face of `graph` a unique index between `0` and `num_faces(graph) - 1`} + * \cgalParamType{a class model of `ReadablePropertyMap` with `boost::graph_traits::%face_descriptor` + * as key type and `std::size_t` as value type} + * \cgalParamDefault{an automatically indexed internal map} + * \cgalParamExtra{If this parameter is not passed, internal machinery will create and initialize + * a face index property map, either using the internal property map if it exists + * or using an external map. The latter might result in - slightly - worsened performance + * in case of non-constant complexity for index access.} + * \cgalParamNEnd + * \cgalNamedParamsEnd + */ + template + Face_filtered_graph(const Graph& graph, + const CGAL_BGL_NP_CLASS& np) + : _graph(const_cast(graph)) + , fimap(CGAL::get_initialized_face_index_map(graph, np)) + , vimap(CGAL::get_initialized_vertex_index_map(graph, np)) + , himap(CGAL::get_initialized_halfedge_index_map(graph, np)) + , selected_faces(num_faces(graph), 0) + , selected_vertices(num_vertices(graph), 0) + , selected_halfedges(num_halfedges(graph), 0) + {} + + Face_filtered_graph(const Graph& graph) + :Face_filtered_graph(graph, parameters::all_default()) + {} + /*! * \brief Constructor where the set of selected faces is specified as a range of patch ids. * diff --git a/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h index 7fcdf24039a..6d5a321abf4 100644 --- a/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h +++ b/BGL/include/CGAL/boost/graph/alpha_expansion_graphcut.h @@ -1,4 +1,3 @@ -#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H // Copyright (c) 2014 GeometryFactory (France). All rights reserved. // // This file is part of CGAL (www.cgal.org) @@ -10,6 +9,7 @@ // // Author(s) : Ilker O. Yaz, Simon Giraudot +#ifndef CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H #define CGAL_BOOST_GRAPH_ALPHA_EXPANSION_GRAPHCUT_H #include diff --git a/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.h b/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.h index 0afdfdb1856..9ac84628c7b 100644 --- a/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.h +++ b/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.h @@ -15,21 +15,6 @@ // This will push/pop a VC15 warning #include - -#include -#include - -#if BOOST_VERSION == 105400 - #ifdef BOOST_GRAPH_DIJKSTRA_HPP - # pragma message \ - "Warning: the header file boost/graph/dijkstra_shortest_paths.hpp " \ - "of boost 1.54 contains a bug that may impact some functions in CGAL. " \ - "Please consider including CGAL/boost/graph/dijkstra_shortest_paths.hpp " \ - "before boost header" - #endif - #include -#else - #include -#endif +#include #endif // CGAL_BOOST_GRAPH_DIJKSTRA_SHORTEST_PATHS_H diff --git a/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.hpp b/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.hpp deleted file mode 100644 index 5b5e0bd472f..00000000000 --- a/BGL/include/CGAL/boost/graph/dijkstra_shortest_paths.hpp +++ /dev/null @@ -1,633 +0,0 @@ -// This file is a copy of the file distributed with boost 1.55 -// It is distributed with CGAL to work around a bug in boost 1.54 -// and must be used only with boost 1.54 by including -// CGAL/boost/graph/dijkstra_shortest_paths.hpp - - -//======================================================================= -// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. -// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) -//======================================================================= -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: BSL-1.0 -// -// Revision History: -// 04 April 2001: Added named parameter variant. (Jeremy Siek) -// 01 April 2001: Modified to use new header. (JMaddock) -// -#ifndef BOOST_GRAPH_DIJKSTRA_HPP -#define BOOST_GRAPH_DIJKSTRA_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING -# include -#endif // BOOST_GRAPH_DIJKSTRA_TESTING - -namespace boost { - - /** - * @brief Updates a particular value in a queue used by Dijkstra's - * algorithm. - * - * This routine is called by Dijkstra's algorithm after it has - * decreased the distance from the source vertex to the given @p - * vertex. By default, this routine will just call @c - * Q.update(vertex). However, other queues may provide more - * specialized versions of this routine. - * - * @param Q the queue that will be updated. - * @param vertex the vertex whose distance has been updated - * @param old_distance the previous distance to @p vertex - */ - template - inline void - dijkstra_queue_update(Buffer& Q, Vertex vertex, DistanceType old_distance) - { - (void)old_distance; - Q.update(vertex); - } - -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING - // This is a misnomer now: it now just refers to the "default heap", which is - // currently d-ary (d=4) but can be changed by a #define. - static bool dijkstra_relaxed_heap = true; -#endif - - template - struct DijkstraVisitorConcept { - void constraints() { -// commented to avoid an unused vaiable warning -// BOOST_CONCEPT_ASSERT(( CopyConstructibleConcept )); - vis.initialize_vertex(u, g); - vis.discover_vertex(u, g); - vis.examine_vertex(u, g); - vis.examine_edge(e, g); - vis.edge_relaxed(e, g); - vis.edge_not_relaxed(e, g); - vis.finish_vertex(u, g); - } - Visitor vis; - Graph g; - typename graph_traits::vertex_descriptor u; - typename graph_traits::edge_descriptor e; - }; - - template - class dijkstra_visitor : public bfs_visitor { - public: - dijkstra_visitor() { } - dijkstra_visitor(Visitors vis) - : bfs_visitor(vis) { } - - template - void edge_relaxed(Edge e, Graph& g) { - invoke_visitors(this->m_vis, e, g, on_edge_relaxed()); - } - template - void edge_not_relaxed(Edge e, Graph& g) { - invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); - } - private: - template - void tree_edge(Edge /* u */, Graph& /* g */) { } - }; - template - dijkstra_visitor - make_dijkstra_visitor(Visitors vis) { - return dijkstra_visitor(vis); - } - typedef dijkstra_visitor<> default_dijkstra_visitor; - - namespace detail { - - template - struct dijkstra_bfs_visitor - { - typedef typename property_traits::value_type D; - typedef typename property_traits::value_type W; - - dijkstra_bfs_visitor(UniformCostVisitor vis, UpdatableQueue& Q, - WeightMap w, PredecessorMap p, DistanceMap d, - BinaryFunction combine, BinaryPredicate compare, - D zero) - : m_vis(vis), m_Q(Q), m_weight(w), m_predecessor(p), m_distance(d), - m_combine(combine), m_compare(compare), m_zero(zero) { } - - template - void tree_edge(Edge e, Graph& g) { - bool decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); - if (decreased) - m_vis.edge_relaxed(e, g); - else - m_vis.edge_not_relaxed(e, g); - } - template - void gray_target(Edge e, Graph& g) { - D old_distance = get(m_distance, target(e, g)); - - bool decreased = relax(e, g, m_weight, m_predecessor, m_distance, - m_combine, m_compare); - if (decreased) { - dijkstra_queue_update(m_Q, target(e, g), old_distance); - m_vis.edge_relaxed(e, g); - } else - m_vis.edge_not_relaxed(e, g); - } - - template - void initialize_vertex(Vertex u, Graph& g) - { m_vis.initialize_vertex(u, g); } - template - void non_tree_edge(Edge, Graph&) { } - template - void discover_vertex(Vertex u, Graph& g) { m_vis.discover_vertex(u, g); } - template - void examine_vertex(Vertex u, Graph& g) { m_vis.examine_vertex(u, g); } - template - void examine_edge(Edge e, Graph& g) { - // Test for negative-weight edges: - // - // Reasons that other comparisons do not work: - // - // m_compare(e_weight, D(0)): - // m_compare only needs to work on distances, not weights, and those - // types do not need to be the same (bug 8398, - // https://svn.boost.org/trac/boost/ticket/8398). - // m_compare(m_combine(source_dist, e_weight), source_dist): - // if m_combine is project2nd (as in prim_minimum_spanning_tree), - // this test will claim that the edge weight is negative whenever - // the edge weight is less than source_dist, even if both of those - // are positive (bug 9012, - // https://svn.boost.org/trac/boost/ticket/9012). - // m_compare(m_combine(e_weight, source_dist), source_dist): - // would fix project2nd issue, but documentation only requires that - // m_combine be able to take a distance and a weight (in that order) - // and return a distance. - - // W e_weight = get(m_weight, e); - // sd_plus_ew = source_dist + e_weight. - // D sd_plus_ew = m_combine(source_dist, e_weight); - // sd_plus_2ew = source_dist + 2 * e_weight. - // D sd_plus_2ew = m_combine(sd_plus_ew, e_weight); - // The test here is equivalent to e_weight < 0 if m_combine has a - // cancellation law, but always returns false when m_combine is a - // projection operator. - if (m_compare(m_combine(m_zero, get(m_weight, e)), m_zero)) - boost::throw_exception(negative_edge()); - // End of test for negative-weight edges. - - m_vis.examine_edge(e, g); - - } - template - void black_target(Edge, Graph&) { } - template - void finish_vertex(Vertex u, Graph& g) { m_vis.finish_vertex(u, g); } - - UniformCostVisitor m_vis; - UpdatableQueue& m_Q; - WeightMap m_weight; - PredecessorMap m_predecessor; - DistanceMap m_distance; - BinaryFunction m_combine; - BinaryPredicate m_compare; - D m_zero; - }; - - } // namespace detail - - namespace detail { - template - struct vertex_property_map_generator_helper {}; - - template - struct vertex_property_map_generator_helper { - typedef boost::iterator_property_map type; - static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) { - array_holder.reset(new Value[num_vertices(g)]); - std::fill(array_holder.get(), array_holder.get() + num_vertices(g), Value()); - return make_iterator_property_map(array_holder.get(), index); - } - }; - - template - struct vertex_property_map_generator_helper { - typedef boost::vector_property_map type; - static type build(const Graph& /* g */, const IndexMap& index, boost::scoped_array& /* array_holder */) { - return boost::make_vector_property_map(index); - } - }; - - template - struct vertex_property_map_generator { - typedef boost::is_base_and_derived< - boost::vertex_list_graph_tag, - typename boost::graph_traits::traversal_category> - known_num_vertices; - typedef vertex_property_map_generator_helper helper; - typedef typename helper::type type; - static type build(const Graph& g, const IndexMap& index, boost::scoped_array& array_holder) { - return helper::build(g, index, array_holder); - } - }; - } - - namespace detail { - template - struct default_color_map_generator_helper {}; - - template - struct default_color_map_generator_helper { - typedef boost::two_bit_color_map type; - static type build(const Graph& g, const IndexMap& index) { - size_t nv = num_vertices(g); - return boost::two_bit_color_map(nv, index); - } - }; - - template - struct default_color_map_generator_helper { - typedef boost::vector_property_map type; - static type build(const Graph& /* g */, const IndexMap& index) { - return boost::make_vector_property_map(index); - } - }; - - template - struct default_color_map_generator { - typedef boost::is_base_and_derived< - boost::vertex_list_graph_tag, - typename boost::graph_traits::traversal_category> - known_num_vertices; - typedef default_color_map_generator_helper helper; - typedef typename helper::type type; - static type build(const Graph& g, const IndexMap& index) { - return helper::build(g, index); - } - }; - } - - // Call breadth first search with default color map. - template - inline void - dijkstra_shortest_paths_no_init - (const Graph& g, - SourceInputIter s_begin, SourceInputIter s_end, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistZero zero, - DijkstraVisitor vis) - { - typedef - detail::default_color_map_generator - ColorMapHelper; - typedef typename ColorMapHelper::type ColorMap; - ColorMap color = - ColorMapHelper::build(g, index_map); - dijkstra_shortest_paths_no_init( g, s_begin, s_end, predecessor, distance, weight, - index_map, compare, combine, zero, vis, - color); - } - - // Call breadth first search with default color map. - template - inline void - dijkstra_shortest_paths_no_init - (const Graph& g, - typename graph_traits::vertex_descriptor s, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistZero zero, - DijkstraVisitor vis) - { - dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, - weight, index_map, compare, combine, zero, - vis); - } - - // Call breadth first search - template - inline void - dijkstra_shortest_paths_no_init - (const Graph& g, - SourceInputIter s_begin, SourceInputIter s_end, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistZero zero, - DijkstraVisitor vis, ColorMap color) - { - typedef indirect_cmp IndirectCmp; - IndirectCmp icmp(distance, compare); - - typedef typename graph_traits::vertex_descriptor Vertex; - -#ifdef BOOST_GRAPH_DIJKSTRA_TESTING - if (!dijkstra_relaxed_heap) { - typedef mutable_queue, IndirectCmp, IndexMap> - MutableQueue; - - MutableQueue Q(num_vertices(g), icmp, index_map); - detail::dijkstra_bfs_visitor - bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - - breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); - return; - } -#endif // BOOST_GRAPH_DIJKSTRA_TESTING - -#ifdef BOOST_GRAPH_DIJKSTRA_USE_RELAXED_HEAP - typedef relaxed_heap MutableQueue; - MutableQueue Q(num_vertices(g), icmp, index_map); -#else // Now the default: use a d-ary heap - boost::scoped_array index_in_heap_map_holder; - typedef - detail::vertex_property_map_generator - IndexInHeapMapHelper; - typedef typename IndexInHeapMapHelper::type IndexInHeapMap; - IndexInHeapMap index_in_heap = - IndexInHeapMapHelper::build(g, index_map, index_in_heap_map_holder); - typedef d_ary_heap_indirect - MutableQueue; - MutableQueue Q(distance, index_in_heap, compare); -#endif // Relaxed heap - - detail::dijkstra_bfs_visitor - bfs_vis(vis, Q, weight, predecessor, distance, combine, compare, zero); - - breadth_first_visit(g, s_begin, s_end, Q, bfs_vis, color); - } - - // Call breadth first search - template - inline void - dijkstra_shortest_paths_no_init - (const Graph& g, - typename graph_traits::vertex_descriptor s, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistZero zero, - DijkstraVisitor vis, ColorMap color) - { - dijkstra_shortest_paths_no_init(g, &s, &s + 1, predecessor, distance, - weight, index_map, compare, combine, - zero, vis, color); - } - - // Initialize distances and call breadth first search with default color map - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - SourceInputIter s_begin, SourceInputIter s_end, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis, - const bgl_named_params& - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) - { - boost::two_bit_color_map color(num_vertices(g), index_map); - dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, weight, - index_map, compare, combine, inf, zero, vis, - color); - } - - // Initialize distances and call breadth first search with default color map - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis, - const bgl_named_params& - BOOST_GRAPH_ENABLE_IF_MODELS_PARM(VertexListGraph,vertex_list_graph_tag)) - { - dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, - index_map, compare, combine, inf, zero, vis); - } - - // Initialize distances and call breadth first search - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - SourceInputIter s_begin, SourceInputIter s_end, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis, ColorMap color) - { - typedef typename property_traits::value_type ColorValue; - typedef color_traits Color; - typename graph_traits::vertex_iterator ui, ui_end; - for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) { - vis.initialize_vertex(*ui, g); - put(distance, *ui, inf); - put(predecessor, *ui, *ui); - put(color, *ui, Color::white()); - } - for (SourceInputIter it = s_begin; it != s_end; ++it) { - put(distance, *it, zero); - } - - dijkstra_shortest_paths_no_init(g, s_begin, s_end, predecessor, distance, - weight, index_map, compare, combine, zero, vis, - color); - } - - // Initialize distances and call breadth first search - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis, ColorMap color) - { - dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, weight, - index_map, compare, combine, inf, zero, - vis, color); - } - - // Initialize distances and call breadth first search - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - SourceInputIter s_begin, SourceInputIter s_end, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis) - { - dijkstra_shortest_paths(g, s_begin, s_end, predecessor, distance, - weight, index_map, - compare, combine, inf, zero, vis, - no_named_parameters()); - } - - // Initialize distances and call breadth first search - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - PredecessorMap predecessor, DistanceMap distance, WeightMap weight, - IndexMap index_map, - Compare compare, Combine combine, DistInf inf, DistZero zero, - DijkstraVisitor vis) - { - dijkstra_shortest_paths(g, &s, &s + 1, predecessor, distance, - weight, index_map, - compare, combine, inf, zero, vis); - } - - namespace detail { - - // Handle defaults for PredecessorMap and - // Distance Compare, Combine, Inf and Zero - template - inline void - dijkstra_dispatch2 - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - DistanceMap distance, WeightMap weight, IndexMap index_map, - const Params& params) - { - // Default for predecessor map - dummy_property_map p_map; - - typedef typename property_traits::value_type D; - D inf = choose_param(get_param(params, distance_inf_t()), - (std::numeric_limits::max)()); - - dijkstra_shortest_paths - (g, s, - choose_param(get_param(params, vertex_predecessor), p_map), - distance, weight, index_map, - choose_param(get_param(params, distance_compare_t()), - std::less()), - choose_param(get_param(params, distance_combine_t()), - closed_plus(inf)), - inf, - choose_param(get_param(params, distance_zero_t()), - D()), - choose_param(get_param(params, graph_visitor), - make_dijkstra_visitor(null_visitor())), - params); - } - - template - inline void - dijkstra_dispatch1 - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - DistanceMap distance, WeightMap weight, IndexMap index_map, - const Params& params) - { - // Default for distance map - typedef typename property_traits::value_type D; - typename std::vector::size_type - n = is_default_param(distance) ? num_vertices(g) : 1; - std::vector distance_map(n); - - detail::dijkstra_dispatch2 - (g, s, choose_param(distance, make_iterator_property_map - (distance_map.begin(), index_map, - distance_map[0])), - weight, index_map, params); - } - } // namespace detail - - // Named Parameter Variant - template - inline void - dijkstra_shortest_paths - (const VertexListGraph& g, - typename graph_traits::vertex_descriptor s, - const bgl_named_params& params) - { - // Default for edge weight and vertex index map is to ask for them - // from the graph. Default for the visitor is null_visitor. - detail::dijkstra_dispatch1 - (g, s, - get_param(params, vertex_distance), - choose_const_pmap(get_param(params, edge_weight), g, edge_weight), - choose_const_pmap(get_param(params, vertex_index), g, vertex_index), - params); - } - -} // namespace boost - -#ifdef BOOST_GRAPH_USE_MPI -# include -#endif - -#endif // BOOST_GRAPH_DIJKSTRA_HPP diff --git a/BGL/include/CGAL/boost/graph/io.h b/BGL/include/CGAL/boost/graph/io.h index fcb9f0d83ed..ad6b83dd31a 100644 --- a/BGL/include/CGAL/boost/graph/io.h +++ b/BGL/include/CGAL/boost/graph/io.h @@ -20,13 +20,6 @@ #include #include #include - \param os the output stream - \param g the graph to be written - \param os the output stream - \param g the graph to be written - \param is the input stream - \param g the graph to be read - #include #endif // CGAL_BOOST_GRAPH_IO_H diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index 49fae3a8270..0993fb05d69 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -1,18 +1,8 @@ -//======================================================================= -// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. -// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek -// -// This file is part of the Boost Graph Library -// -// Distributed under the Boost Software License, Version 1.0. (See -// accompanying file LICENSE_1_0.txt or copy at -// https://www.boost.org/LICENSE_1_0.txt) -//======================================================================= // Copyright (c) 2007-2015 GeometryFactory (France). All rights reserved. // // $URL$ // $Id$ -// SPDX-License-Identifier: BSL-1.0 +// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Andreas Fabri, Fernando Cacciola, Jane Tournois @@ -299,7 +289,6 @@ CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face, typename boost::graph_traits::fa > ::type type; }; - namespace internal { BOOST_MPL_HAS_XXX_TRAIT_NAMED_DEF(Has_nested_type_iterator, iterator, false) } diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 3bfff7f0856..89f67233943 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -15,7 +15,7 @@ CGAL_add_named_parameter(halfedge_index_t, halfedge_index, halfedge_index_map) CGAL_add_named_parameter(edge_index_t, edge_index, edge_index_map) CGAL_add_named_parameter(face_index_t, face_index, face_index_map) CGAL_add_named_parameter(vertex_index_t, vertex_index, vertex_index_map) -CGAL_add_named_parameter(graph_visitor_t, graph_visitor, visitor) +CGAL_add_named_parameter(visitor_t, visitor, visitor) CGAL_add_named_parameter(point_t, point_map, point_map) @@ -186,7 +186,6 @@ CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) CGAL_add_named_parameter(remesh_boundaries_t, remesh_boundaries, remesh_boundaries) CGAL_add_named_parameter(cell_selector_t, cell_selector, cell_selector) CGAL_add_named_parameter(facet_is_constrained_t, facet_is_constrained, facet_is_constrained_map) -CGAL_add_named_parameter(remeshing_visitor_t, remeshing_visitor, remeshing_visitor) CGAL_add_named_parameter(smooth_constrained_edges_t, smooth_constrained_edges, smooth_constrained_edges) // output parameters diff --git a/BGL/test/BGL/CMakeLists.txt b/BGL/test/BGL/CMakeLists.txt index af374c341bb..e6bee2de3f5 100644 --- a/BGL/test/BGL/CMakeLists.txt +++ b/BGL/test/BGL/CMakeLists.txt @@ -83,6 +83,8 @@ create_single_source_cgal_program( "test_Face_filtered_graph.cpp" ) create_single_source_cgal_program( "test_Euler_operations.cpp" ) +create_single_source_cgal_program( "test_test_face.cpp" ) + create_single_source_cgal_program( "test_Collapse_edge.cpp" ) create_single_source_cgal_program( "test_graph_traits.cpp" ) diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index f5aa989a4ff..506a2a00aed 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -28,7 +28,7 @@ void test(const NamedParameters& np) // Named parameters that we use in CGAL assert(get_parameter(np, CGAL::internal_np::vertex_index).v == 0); - assert(get_parameter(np, CGAL::internal_np::graph_visitor).v == 1); + assert(get_parameter(np, CGAL::internal_np::visitor).v == 1); assert(get_parameter(np, CGAL::internal_np::vertex_point).v == 2); assert(get_parameter(np, CGAL::internal_np::halfedge_index).v == 3); assert(get_parameter(np, CGAL::internal_np::edge_index).v == 4); @@ -130,7 +130,7 @@ void test(const NamedParameters& np) // Named parameters that we use in CGAL check_same_type<0>(get_parameter(np, CGAL::internal_np::vertex_index)); - check_same_type<1>(get_parameter(np, CGAL::internal_np::graph_visitor)); + check_same_type<1>(get_parameter(np, CGAL::internal_np::visitor)); check_same_type<2>(get_parameter(np, CGAL::internal_np::vertex_point)); check_same_type<3>(get_parameter(np, CGAL::internal_np::halfedge_index)); check_same_type<4>(get_parameter(np, CGAL::internal_np::edge_index)); diff --git a/BGL/test/BGL/test_test_face.cpp b/BGL/test/BGL/test_test_face.cpp new file mode 100644 index 00000000000..e69f7e3176e --- /dev/null +++ b/BGL/test/BGL/test_test_face.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#include +#include + +typedef CGAL::Simple_cartesian K; +typedef K::Point_3 Point_3; +typedef CGAL::Surface_mesh SM; + +typedef boost::graph_traits::vertex_descriptor vertex_descriptor; +typedef boost::graph_traits::vertex_iterator vertex_iterator; +typedef std::vector V; +int main() +{ + { + SM sm; + + vertex_descriptor vp = CGAL::add_vertex(sm); + vertex_descriptor vq = CGAL::add_vertex(sm); + vertex_descriptor vr = CGAL::add_vertex(sm); + vertex_descriptor vs = CGAL::add_vertex(sm); + std::array face0; + assert( ! CGAL::Euler::can_add_face(face0,sm) ); + std::array face1; + assert( ! CGAL::Euler::can_add_face(face1,sm) ); + std::array face2; + assert( ! CGAL::Euler::can_add_face(face2,sm) ); + + std::array face = { vp, vq, vr }; + CGAL::Euler::add_face(face, sm); + + assert( ! CGAL::Euler::can_add_face(face,sm) ); + std::swap(face[0],face[1]); + assert( CGAL::Euler::can_add_face(face,sm) ); + + face[2] = vs; + assert( CGAL::Euler::can_add_face(face,sm) ); + std::swap(face[0],face[1]); + assert( ! CGAL::Euler::can_add_face(face,sm) ); + } + + { + SM sm; + Point_3 p(0,0,0), q(1,0,0), r(0,1,0), s(0,0,1); + CGAL::make_tetrahedron(p, q, r, s, sm); + std::array face; + vertex_iterator it = vertices(sm).first; + face[0] = *it; + ++it; + face[1] = *it; + face[2] = CGAL::add_vertex(sm); + assert( ! CGAL::Euler::can_add_face(face,sm) ); + std::swap(face[0],face[1]); + assert( ! CGAL::Euler::can_add_face(face,sm) ); + } + + return 0; +} diff --git a/Bounding_volumes/doc/Bounding_volumes/Bounding_volumes.txt b/Bounding_volumes/doc/Bounding_volumes/Bounding_volumes.txt index 55116f807f7..dd52a223038 100644 --- a/Bounding_volumes/doc/Bounding_volumes/Bounding_volumes.txt +++ b/Bounding_volumes/doc/Bounding_volumes/Bounding_volumes.txt @@ -9,37 +9,16 @@ namespace CGAL { \authors Kaspar Fischer, Bernd Gärtner, Thomas Herrmann, Michael Hoffmann, and Sven Schönherr \image html ball.png -\image latex ball.png This chapter describes algorithms which for a given point set compute the best circumscribing object from a specific class. If the class consists of all spheres in \f$ d\f$-dimensional Euclidean space and best is defined as having smallest radius, -then we obtain the smallest enclosing sphere problem already mentioned -above. +then we obtain the smallest enclosing sphere. -In the following example a smallest enclosing circle -(`Min_circle_2`) is constructed from points -on a line and written to standard output. The example -shows that it is advisable to switch on random shuffling -in order to deal with a bad order of the input points. -\cgalExample{Min_circle_2/min_circle_2.cpp} -Other classes for which we provide solutions are ellipses -(`Min_ellipse_2`), rectangles -(`min_rectangle_2()`), parallelograms -(`min_parallelogram_2()`) and strips (`min_strip_2()`) -in the plane, with appropriate optimality criteria. For arbitrary -dimensions we provide smallest enclosing spheres for points -(`Min_sphere_d`) and spheres for spheres -(`Min_sphere_of_spheres_d`), smallest enclosing -annuli (`Min_annulus_d`), and approximate -minimum-volume enclosing ellipsoid with user-specified -approximation ratio (`Approximate_min_ellipsoid_d`). - -\image html annulus.png -\image latex annulus.png +\section SectBoundingIntroduction Introduction Bounding volumes can be used to obtain simple approximations of complicated objects. For example, consider the problem of deciding @@ -60,13 +39,74 @@ geometric properties of objects. For example, the smallest enclosing annulus of a point set can be used to test whether a set of points is approximately cospherical. Here, the width of the annulus (or its area, or still another criterion that we use) is a good measure for -this property. The largest area triangle is for example used in -heuristics for matching archaeological aerial photographs. Largest -perimeter triangles are used in scoring cross country soaring flights, -where the goal is basically to fly as far as possible, but still -return to the departure airfield. To score simply based on the total -distance flown is not a good measure, since circling in thermals -allows to increase it easily. +this property. + +\section SectBoundingSphere Bounding Spheres in dD + +We provide the class `Min_sphere_of_spheres_d` for arbitrary dimensions +to compute the smallest enclosing spheres for points as well as for spheres. +The dimension as well as the input type depend on the chosen traits class. + +The following example is for 2D points + +\cgalExample{Min_circle_2/min_circle_2.cpp} + +The example for 2D circles as input looks rather similar. + + +\cgalExample{Min_sphere_of_spheres_d/min_sphere_of_spheres_d_2.cpp} + + + +\subsection SectBoundingSphereHomogeneous Bounding Spheres for the Homogeneous Kernel + +In the previous section we saw that we used `Min_sphere_of_spheres_d` +to compute the smallest circle for points. This package also provides +the classes `Min_circle_2` and `Min_sphere_d`, but they are slower, +and they should only be used in case of homogeneous coordinates which +are not supported by `Min_sphere_of_spheres_d`. + +In the following example a smallest enclosing circle +(`Min_circle_2`) is constructed from points +on a line and written to standard output. The example +shows that it is advisable to switch on random shuffling +in order to deal with a bad order of the input points. + +\cgalExample{Min_circle_2/min_circle_homogeneous_2.cpp} + + +\section SectBoundingAnnulus Bounding Annulus in dD + +We provide the class `Min_annulus_d` for arbitrary dimensions +to compute the smalles enclosing annulus for a set of points. +In 2D the annulus consists of two concentric circles, in 3D of +two concentric spheres. + +\image html annulus.png + + + + +\section SectBounding2D Various Bounding Areas in 2D + +Other classes for which we provide solutions are ellipses +(`Min_ellipse_2`), rectangles +(`min_rectangle_2()`), parallelograms +(`min_parallelogram_2()`) and strips (`min_strip_2()`) +in the plane, with appropriate optimality criteria. + + +\section SectBoundingEllipsoid Approximate Bounding Ellipsoid in dD + +While this package provides an exact smallest 2D ellipse, it also +provides the class `Approximate_min_ellipsoid_d` to compute +an approximate minimum-volume enclosing ellipsoid with user-specified +approximation ratio. + + + + +\section SectBoundingPcenter Rectangular P-Center Bounding volumes also define geometric "center points" of objects. For example, if two objects are to be matched (approximately), one @@ -81,8 +121,6 @@ planar point set with between two and four minimal boxes three boxes; the center points are shown in red. \image html pcenter.png -\image latex pcenter.png */ } /* namespace CGAL */ - diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h index 46fe14ad267..8f33d597b83 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Approximate_min_ellipsoid_d.h @@ -191,7 +191,7 @@ to iterate over the %Cartesian coordinates of the direction of a fixed axis of the computed ellipsoid, see `axis_direction_cartesian_begin()`. */ -typedef unspecified_type Axis_direction_iterator; +typedef unspecified_type Axes_direction_coordinate_iterator; /// @} diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_annulus_d.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_annulus_d.h index 71cd4b1bf73..6c4a6e03ace 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_annulus_d.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_annulus_d.h @@ -24,17 +24,17 @@ The underlying algorithm can cope with all kinds of input, e.g. \f$ P\f$ may be empty or points may occur more than once. The algorithm computes a support set \f$ S\f$ which remains fixed until the next set, insert, or clear operation. -\tparam Traits must be a model for `OptimisationDTraits`. +\tparam Traits must be a model for `MinSphereAnnulusDTraits`. -We provide the models `Optimisation_d_traits_2`, -`Optimisation_d_traits_3`, and `Optimisation_d_traits_d` using the +We provide the models `Min_sphere_annulus_d_traits_2`, +`Min_sphere_annulus_d_traits_3`, and `Min_sphere_annulus_d_traits_d` using the two-, three-, and \f$ d\f$-dimensional \cgal kernel, respectively. \sa `CGAL::Min_sphere_d` -\sa `CGAL::Optimisation_d_traits_2` -\sa `CGAL::Optimisation_d_traits_3` -\sa `CGAL::Optimisation_d_traits_d` -\sa `OptimisationDTraits` +\sa `CGAL::Min_sphere_annulus_d_traits_2` +\sa `CGAL::Min_sphere_annulus_d_traits_3` +\sa `CGAL::Min_sphere_annulus_d_traits_d` +\sa `MinSphereAnnulusDTraits` \cgalHeading{Implementation} diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_circle_2.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_circle_2.h index 9e7d6900a2f..c2b373057f8 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_circle_2.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_circle_2.h @@ -23,9 +23,9 @@ The underlying algorithm can cope with all kinds of input, e.g. \f$ P\f$ may be empty or points may occur more than once. The algorithm computes a support set \f$ S\f$ which remains fixed until the next insert or clear operation. -Please note: This class is (almost) obsolete. The class +\note This class is (almost) obsolete. The class `CGAL::Min_sphere_of_spheres_d` solves a more general problem -and is faster then `Min_circle_2` even if used only for points in two +and is faster than `Min_circle_2` even if used only for points in two dimensions as input. Most importantly, `CGAL::Min_sphere_of_spheres_d` has a specialized implementation for floating-point arithmetic which diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_d.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_d.h index 61511c5aee6..82b106c9971 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_d.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_d.h @@ -22,9 +22,9 @@ The algorithm computes a support set \f$ S\f$ which remains fixed until the next insert or clear operation. -Please note: This class is (almost) obsolete. The class +\note This class is (almost) obsolete. The class `CGAL::Min_sphere_of_spheres_d` solves a more general problem -and is faster then `Min_sphere_d` even if used only for points +and is faster than `Min_sphere_d` even if used only for points as input. Most importantly, `CGAL::Min_sphere_of_spheres_d` has a specialized implementation for floating-point arithmetic which ensures correct results in a large number of cases (including @@ -38,17 +38,17 @@ divide. \tparam Traits must be a model of the concept -`OptimisationDTraits` as its template argument. +`MinSphereAnnulusDTraits` as its template argument. -We provide the models `CGAL::Optimisation_d_traits_2`, -`CGAL::Optimisation_d_traits_3` and -`CGAL::Optimisation_d_traits_d` +We provide the models `CGAL::Min_sphere_annulus_d_traits_2`, +`CGAL::Min_sphere_annulus_d_traits_3` and +`CGAL::Min_sphere_annulus_d_traits_d` for two-, three-, and \f$ d\f$-dimensional points respectively. -\sa `CGAL::Optimisation_d_traits_2` -\sa `CGAL::Optimisation_d_traits_3` -\sa `CGAL::Optimisation_d_traits_d` -\sa `OptimisationDTraits` +\sa `CGAL::Min_sphere_annulus_d_traits_2` +\sa `CGAL::Min_sphere_annulus_d_traits_3` +\sa `CGAL::Min_sphere_annulus_d_traits_d` +\sa `MinSphereAnnulusDTraits` \sa `CGAL::Min_circle_2` \sa `CGAL::Min_sphere_of_spheres_d` \sa `CGAL::Min_annulus_d` @@ -68,7 +68,7 @@ each take linear time. \cgalHeading{Example} -\cgalExample{Min_sphere_d/min_sphere_d.cpp} +\cgalExample{Min_sphere_d/min_sphere_homogeneous_3.cpp} */ template< typename Traits > diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_of_spheres_d.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_of_spheres_d.h index f640780487c..3d77b9a4d88 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_of_spheres_d.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/Min_sphere_of_spheres_d.h @@ -50,7 +50,7 @@ minsphere can be described by the number \f$ t\f$, which is called the sphere's discriminant, and by \f$ d+1\f$ pairs \f$ (a_i,b_i)\in\Q^2\f$ (one for the radius and \f$ d\f$ for the center coordinates). -Note: This class (almost) replaces +\note This class (almost) replaces `CGAL::Min_sphere_d`, which solves the less general problem of finding the smallest enclosing ball of a set of points. `Min_sphere_of_spheres_d` is faster than diff --git a/Bounding_volumes/doc/Bounding_volumes/CGAL/min_quadrilateral_2.h b/Bounding_volumes/doc/Bounding_volumes/CGAL/min_quadrilateral_2.h index 8d5a65a2046..1197eebf4bb 100644 --- a/Bounding_volumes/doc/Bounding_volumes/CGAL/min_quadrilateral_2.h +++ b/Bounding_volumes/doc/Bounding_volumes/CGAL/min_quadrilateral_2.h @@ -3,6 +3,11 @@ namespace CGAL { /*! \ingroup PkgBoundingVolumesRef +computes a minimum area enclosing parallelogram of the point set +described by [`points_begin`, `points_end`), writes its +vertices (counterclockwise) to `o` and returns the past-the-end +iterator of this sequence. + The function computes a minimum area enclosing parallelogram \f$ A(P)\f$ of a given convex point set \f$ P\f$. Note that \f$ R(P)\f$ is not necessarily axis-parallel, and it is in general not @@ -11,10 +16,6 @@ parallelogram enclosing \f$ P\f$ - as a convex set - contains the convex hull of \f$ P\f$. For general point sets one has to compute the convex hull as a preprocessing step. -computes a minimum area enclosing parallelogram of the point set -described by [`points_begin`, `points_end`), writes its -vertices (counterclockwise) to `o` and returns the past-the-end -iterator of this sequence. If the input range is empty, `o` remains unchanged. If the input range consists of one element only, this point is written @@ -74,6 +75,11 @@ namespace CGAL { /*! \ingroup PkgBoundingVolumesRef +computes a minimum area enclosing rectangle of the point set described +by [`points_begin`, `points_end`), writes its vertices +(counterclockwise) to `o`, and returns the past-the-end iterator +of this sequence. + The function computes a minimum area enclosing rectangle \f$ R(P)\f$ of a given convex point set \f$ P\f$. Note that \f$ R(P)\f$ is not necessarily axis-parallel, and it is in general not unique. The focus @@ -81,10 +87,6 @@ on convex sets is no restriction, since any rectangle enclosing \f$ P\f$ - as a convex set - contains the convex hull of \f$ P\f$. For general point sets one has to compute the convex hull as a preprocessing step. -computes a minimum area enclosing rectangle of the point set described -by [`points_begin`, `points_end`), writes its vertices -(counterclockwise) to `o`, and returns the past-the-end iterator -of this sequence. If the input range is empty, `o` remains unchanged. @@ -143,6 +145,10 @@ namespace CGAL { /*! \ingroup PkgBoundingVolumesRef +computes a minimum enclosing strip of the point set described by +[`points_begin`, `points_end`), writes its two bounding lines +to `o` and returns the past-the-end iterator of this sequence. + The function computes a minimum width enclosing strip \f$ S(P)\f$ of a given convex point set \f$ P\f$. A strip is the closed region bounded by two parallel lines in the plane. Note that \f$ S(P)\f$ is not @@ -151,10 +157,6 @@ parallelogram enclosing \f$ P\f$ - as a convex set - contains the convex hull of \f$ P\f$. For general point sets one has to compute the convex hull as a preprocessing step. -computes a minimum enclosing strip of the point set described by -[`points_begin`, `points_end`), writes its two bounding lines -to `o` and returns the past-the-end iterator of this sequence. - If the input range is empty or consists of one element only, `o` remains unchanged. @@ -205,4 +207,3 @@ OutputIterator o, Traits& t = Default_traits); } /* namespace CGAL */ - diff --git a/Bounding_volumes/doc/Bounding_volumes/Concepts/MinQuadrilateralTraits_2.h b/Bounding_volumes/doc/Bounding_volumes/Concepts/MinQuadrilateralTraits_2.h index 692849cba12..be4ba5f5a2d 100644 --- a/Bounding_volumes/doc/Bounding_volumes/Concepts/MinQuadrilateralTraits_2.h +++ b/Bounding_volumes/doc/Bounding_volumes/Concepts/MinQuadrilateralTraits_2.h @@ -5,8 +5,8 @@ The concept `MinQuadrilateralTraits_2` defines types and operations needed to compute minimum enclosing quadrilaterals of a planar point -set using the functions `min_rectangle_2`, -`min_parallelogram_2` and `min_strip_2`. +set using the functions `min_rectangle_2()`, +`min_parallelogram_2()` and `min_strip_2()`. \cgalHasModel `CGAL::Min_quadrilateral_default_traits_2` @@ -262,4 +262,3 @@ const ; /// @} }; /* end MinQuadrilateralTraits_2 */ - diff --git a/Bounding_volumes/doc/Bounding_volumes/Concepts/MinSphereOfSpheresTraits.h b/Bounding_volumes/doc/Bounding_volumes/Concepts/MinSphereOfSpheresTraits.h index fc53bdb32b9..4a59d4c3390 100644 --- a/Bounding_volumes/doc/Bounding_volumes/Concepts/MinSphereOfSpheresTraits.h +++ b/Bounding_volumes/doc/Bounding_volumes/Concepts/MinSphereOfSpheresTraits.h @@ -10,6 +10,9 @@ following constants, types, predicates and operations. \cgalHasModel `CGAL::Min_sphere_of_spheres_d_traits_3` \cgalHasModel `CGAL::Min_sphere_of_spheres_d_traits_d` +\cgalHasModel `CGAL::Min_sphere_of_points_d_traits_2` +\cgalHasModel `CGAL::Min_sphere_of_points_d_traits_3` +\cgalHasModel `CGAL::Min_sphere_of_points_d_traits_d` */ class MinSphereOfSpheresTraits { @@ -112,4 +115,3 @@ Cartesian_const_iterator center_cartesian_begin(const Sphere& s); /// @} }; /* end MinSphereOfSpheresTraits */ - diff --git a/Bounding_volumes/doc/Bounding_volumes/Concepts/RectangularPCenterTraits_2.h b/Bounding_volumes/doc/Bounding_volumes/Concepts/RectangularPCenterTraits_2.h index fefd3538e5b..9c0727d44bd 100644 --- a/Bounding_volumes/doc/Bounding_volumes/Concepts/RectangularPCenterTraits_2.h +++ b/Bounding_volumes/doc/Bounding_volumes/Concepts/RectangularPCenterTraits_2.h @@ -5,7 +5,7 @@ The concept `RectangularPCenterTraits_2` defines types and operations needed to compute rectilinear \f$ p\f$-centers of a planar point set -using the function `CGAL::rectangular_p_center_2`. +using the function `CGAL::rectangular_p_center_2()`. \cgalHasModel `CGAL::Rectangular_p_center_default_traits_2` @@ -193,4 +193,3 @@ construct_iso_rectangle_2_above_right_point_2_object() const; /// @} }; /* end RectangularPCenterTraits_2 */ - diff --git a/Bounding_volumes/doc/Bounding_volumes/examples.txt b/Bounding_volumes/doc/Bounding_volumes/examples.txt index 0cdfa3636b6..4b4d2ef68bd 100644 --- a/Bounding_volumes/doc/Bounding_volumes/examples.txt +++ b/Bounding_volumes/doc/Bounding_volumes/examples.txt @@ -4,11 +4,13 @@ \example Min_annulus_d/min_annulus_d.cpp \example Min_annulus_d/min_annulus_d_fast_exact.cpp \example Min_circle_2/min_circle_2.cpp +\example Min_circle_2/min_circle_homogeneous_2.cpp \example Min_ellipse_2/min_ellipse_2.cpp \example Min_quadrilateral_2/minimum_enclosing_parallelogram_2.cpp \example Min_quadrilateral_2/minimum_enclosing_rectangle_2.cpp \example Min_quadrilateral_2/minimum_enclosing_strip_2.cpp -\example Min_sphere_d/min_sphere_d.cpp +\example Min_sphere_d/min_sphere_3.cpp +\example Min_sphere_d/min_sphere_homogeneous_3.cpp \example Min_sphere_of_spheres_d/benchmark.cpp \example Min_sphere_of_spheres_d/min_sphere_of_spheres_d_2.cpp \example Min_sphere_of_spheres_d/min_sphere_of_spheres_d_3.cpp diff --git a/Bounding_volumes/examples/Min_circle_2/min_circle_2.cpp b/Bounding_volumes/examples/Min_circle_2/min_circle_2.cpp index 0645bf979cc..e45b00c7b87 100644 --- a/Bounding_volumes/examples/Min_circle_2/min_circle_2.cpp +++ b/Bounding_volumes/examples/Min_circle_2/min_circle_2.cpp @@ -1,30 +1,33 @@ -#include -#include -#include +#include +#include +#include +#include + #include -// typedefs -typedef CGAL::Exact_predicates_exact_constructions_kernel K; -typedef CGAL::Min_circle_2_traits_2 Traits; -typedef CGAL::Min_circle_2 Min_circle; - -typedef K::Point_2 Point; +typedef CGAL::Simple_cartesian K; +typedef CGAL::Min_sphere_of_points_d_traits_2 Traits; +typedef CGAL::Min_sphere_of_spheres_d Min_circle; +typedef K::Point_2 Point; int main( int, char**) { const int n = 100; Point P[n]; + CGAL::Random r; // random number generator - for ( int i = 0; i < n; ++i) - P[ i] = Point( (i%2 == 0 ? i : -i), 0); - // (0,0), (-1,0), (2,0), (-3,0), ... + for ( int i = 0; i < n; ++i){ + P[ i] = Point(r.get_double(), r.get_double()); + } - Min_circle mc1( P, P+n, false); // very slow - Min_circle mc2( P, P+n, true); // fast - - CGAL::set_pretty_mode( std::cout); - std::cout << mc2; + Min_circle mc( P, P+n); + Min_circle::Cartesian_const_iterator ccib = mc.center_cartesian_begin(), ccie = mc.center_cartesian_end(); + std::cout << "center:"; + for( ; ccib != ccie; ++ccib){ + std::cout << " " << *ccib; + } + std::cout << std::endl << "radius: " << mc.radius() << std::endl; return 0; } diff --git a/Bounding_volumes/examples/Min_circle_2/min_circle_homogeneous_2.cpp b/Bounding_volumes/examples/Min_circle_2/min_circle_homogeneous_2.cpp new file mode 100644 index 00000000000..aac519412db --- /dev/null +++ b/Bounding_volumes/examples/Min_circle_2/min_circle_homogeneous_2.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include + +#include + +// typedefs +typedef CGAL::Exact_integer RT; +typedef CGAL::Simple_homogeneous K; +typedef CGAL::Min_circle_2_traits_2 Traits; +typedef CGAL::Min_circle_2 Min_circle; +typedef K::Point_2 Point; + +int +main( int, char**) +{ + const int n = 100; + Point P[n]; + + for ( int i = 0; i < n; ++i){ + P[i] = Point( (i%2 == 0 ? i : -i), 0, 1); + // (0,0), (-1,0), (2,0), (-3,0), ... + } + + Min_circle mc1( P, P+n, false); // very slow + Min_circle mc2( P, P+n, true); // fast + + CGAL::set_pretty_mode( std::cout); + std::cout << mc2; + + return 0; +} diff --git a/Bounding_volumes/examples/Min_sphere_d/min_sphere_3.cpp b/Bounding_volumes/examples/Min_sphere_d/min_sphere_3.cpp new file mode 100644 index 00000000000..32e92903271 --- /dev/null +++ b/Bounding_volumes/examples/Min_sphere_d/min_sphere_3.cpp @@ -0,0 +1,38 @@ +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Simple_cartesian K; +typedef CGAL::Min_sphere_of_points_d_traits_3 Traits; +typedef CGAL::Min_sphere_of_spheres_d Min_sphere; +typedef K::Point_3 Point; + +const int n = 10; // number of points +const int d = 3; // dimension of points + +int main () +{ + Point P[n]; // n points + CGAL::Random r; // random number generator + + for (int i=0; i -#include -#include -#include -#include -#include - -typedef CGAL::Cartesian_d K; -typedef CGAL::Min_sphere_annulus_d_traits_d Traits; -typedef CGAL::Min_sphere_d Min_sphere; -typedef K::Point_d Point; - -const int n = 10; // number of points -const int d = 5; // dimension of points - -int main () -{ - Point P[n]; // n points - double coord[d]; // d coordinates - CGAL::Random r; // random number generator - - for (int i=0; i +#include +#include +#include +#include + +#include +#include + +typedef CGAL::Homogeneous K; +typedef CGAL::Min_sphere_annulus_d_traits_3 Traits; +typedef CGAL::Min_sphere_d Min_sphere; +typedef K::Point_3 Point; + +int +main () +{ + const int n = 10; // number of points + Point P[n]; // n points + CGAL::Random r; // random number generator + + for (int i=0; i #include diff --git a/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_3.cpp b/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_3.cpp index 1a6e4fb29c3..c0b8b978e0c 100644 --- a/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_3.cpp +++ b/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_3.cpp @@ -1,6 +1,4 @@ // Computes the minsphere of some random spheres. -// This example illustrates how to use CGAL::Point_3 and CGAL:: -// Weighted_point with the Min_sphere_of_spheres_d package. #include #include diff --git a/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_d.cpp b/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_d.cpp index 9321fad638c..0ddbe825fba 100644 --- a/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_d.cpp +++ b/Bounding_volumes/examples/Min_sphere_of_spheres_d/min_sphere_of_spheres_d_d.cpp @@ -1,6 +1,4 @@ // Computes the minsphere of some random spheres. -// This example illustrates how to use CGAL::Point_d and CGAL:: -// Weighted_point with the Min_sphere_of_spheres_d package. #include #include diff --git a/CGAL_Core/include/CGAL/CORE/Gmp_impl.h b/CGAL_Core/include/CGAL/CORE/Gmp_impl.h index 901f5204b2b..479dc0dd0fa 100644 --- a/CGAL_Core/include/CGAL/CORE/Gmp_impl.h +++ b/CGAL_Core/include/CGAL/CORE/Gmp_impl.h @@ -198,10 +198,6 @@ io_read (std::istream &i, mpq_ptr q) ok = true; } - if (i.flags() & ios::skipws) - while (isspace(c) && i.get(c)) // skip whitespace - ; - if (c == '/') // there's a denominator { bool zero2 = false; diff --git a/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h index fe78f2e6e5c..997911312b5 100644 --- a/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h +++ b/Circular_kernel_2/include/CGAL/Circular_kernel_2/function_objects_polynomial_circular.h @@ -33,9 +33,7 @@ namespace CircularFunctors { template < class CK > class Compare_x_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Compare_x_2 -#endif { typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; typedef typename CK::Point_2 Point_2; @@ -43,45 +41,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Compare_x_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Compare_x_2::operator(); -#else - typedef typename CK::Linear_kernel LK; - typedef typename LK::Compare_x_2 LK_Compare_x_2; - typedef typename CK::Line_2 Line_2; - - result_type - operator() (const Point_2 &p0, - const Point_2 &p1) const - { - return LK_Compare_x_2()(p0, p1); - } - - result_type - operator() (const Point_2 &p0, - const Line_2 &p1, - const Line_2 &p2) const - { - return LK_Compare_x_2()(p0, p1,p2); - } - - result_type - operator() (const Line_2 &p0, - const Line_2 &p1, - const Line_2 &p2) const - { - return LK_Compare_x_2()(p0, p1,p2); - } - - result_type - operator() (const Line_2 &p0, - const Line_2 &p1, - const Line_2 &p2, - const Line_2 &p3) const - { - return LK_Compare_x_2()(p0, p1,p2,p3); - } -#endif result_type operator() (const Circular_arc_point_2 &p0, @@ -93,9 +53,7 @@ namespace CircularFunctors { template < class CK > class Compare_y_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Compare_y_2 -#endif { typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; typedef typename CK::Point_2 Point_2; @@ -103,46 +61,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Compare_y_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Compare_y_2::operator(); -#else - - typedef typename CK::Linear_kernel LK; - typedef typename LK::Compare_y_2 LK_Compare_y_2; - typedef typename CK::Line_2 Line_2; - - result_type - operator() (const Point_2 &p0, - const Point_2 &p1) const - { - return LK_Compare_y_2()(p0, p1); - } - - result_type - operator() (const Point_2 &p0, - const Line_2 &p1, - const Line_2 &p2) const - { - return LK_Compare_y_2()(p0, p1,p2); - } - - result_type - operator() (const Line_2 &p0, - const Line_2 &p1, - const Line_2 &p2) const - { - return LK_Compare_y_2()(p0, p1,p2); - } - - result_type - operator() (const Line_2 &p0, - const Line_2 &p1, - const Line_2 &p2, - const Line_2 &p3) const - { - return LK_Compare_y_2()(p0, p1,p2,p3); - } -#endif result_type operator() (const Circular_arc_point_2 &p0, @@ -153,9 +72,7 @@ namespace CircularFunctors { template < class CK > class Compare_xy_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Compare_xy_2 -#endif { typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; typedef typename CK::Point_2 Point_2; @@ -163,19 +80,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Compare_xy_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Compare_xy_2::operator(); -#else - - result_type - operator() (const Point_2 &p0, - const Point_2 &p1) const - { - typedef typename CK::Linear_kernel LK; - typedef typename LK::Compare_xy_2 LK_Compare_xy_2; - return LK_Compare_xy_2()(p0, p1); - } -#endif result_type operator() (const Circular_arc_point_2 &p0, @@ -279,9 +184,7 @@ namespace CircularFunctors { template < class CK > class Equal_2 - #ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Equal_2 -#endif { typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; typedef typename CK::Circular_arc_2 Circular_arc_2; @@ -303,71 +206,7 @@ namespace CircularFunctors { typedef typename CK::Linear_kernel::Equal_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Equal_2::operator(); -#else - - result_type - operator() (const Point_2 &p0, - const Point_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - result_type - operator() (const Vector_2 &p0, - const Vector_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - result_type - operator() (const Vector_2 &p0, - const Null_vector &p1) const - { return LK_Equal_2()(p0,p1); } - - result_type - operator() (const Null_vector &p0, - const Vector_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - result_type - operator() (const Direction_2 &p0, - const Direction_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - - result_type - operator() (const Segment_2 &p0, - const Segment_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - - result_type - operator() (const Ray_2 &p0, - const Ray_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - result_type - operator() (const Line_2 &p0, - const Line_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - - - result_type - operator() (const Triangle_2 &p0, - const Triangle_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - - result_type - operator() (const Iso_rectangle_2 &p0, - const Iso_rectangle_2 &p1) const - { return LK_Equal_2()(p0,p1); } - - - result_type - operator() (const Circle_2 &p0, - const Circle_2 &p1) const - { return LK_Equal_2()(p0,p1); } -#endif result_type operator() (const Circular_arc_point_2 &p0, @@ -1029,9 +868,7 @@ namespace CircularFunctors { template class Construct_bbox_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Construct_bbox_2 -#endif { typedef typename CK::Circular_arc_2 Circular_arc_2; typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; @@ -1041,40 +878,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Construct_bbox_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Construct_bbox_2::operator(); -#else - typedef typename CK::Linear_kernel LK; - typedef typename LK::Construct_bbox_2 LK_Construct_bbox_2; - typedef typename CK::Point_2 Point_2; - typedef typename CK::Segment_2 Segment_2; - typedef typename CK::Triangle_2 Triangle_2 ; - typedef typename CK::Iso_rectangle_2 Iso_rectangle_2 ; - - result_type operator() (const Circle_2 & a) const - { - return LK_Construct_bbox_2()(a); - } - - result_type operator() (const Point_2 & a) const - { - return LK_Construct_bbox_2()(a); - } - - result_type operator() (const Segment_2 & a) const - { - return LK_Construct_bbox_2()(a); - } - - result_type operator() (const Triangle_2 & a) const - { - return LK_Construct_bbox_2()(a); - } - result_type operator() (const Iso_rectangle_2 & a) const - { - return LK_Construct_bbox_2()(a); - } -#endif result_type operator() (const Circular_arc_point_2 & a) const { @@ -1095,9 +899,7 @@ namespace CircularFunctors { template class Bounded_side_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Bounded_side_2 -#endif { typedef typename CK::Circle_2 Circle_2; typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; @@ -1105,28 +907,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Bounded_side_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Bounded_side_2::operator(); -#else - typedef typename CK::Point_2 Point_2; - typedef typename CK::Triangle_2 Triangle_2; - typedef typename CK::Iso_rectangle_2 Iso_rectangle_2; - typedef typename CK::Linear_kernel LK; - typedef typename LK::Bounded_side_2 LK_Bounded_side_2; - - result_type - operator()(const Circle_2& c, const Point_2& p) const - { return LK_Bounded_side_2()(c,p); } - - result_type - operator()(const Triangle_2& c, const Point_2& p) const - { return LK_Bounded_side_2()(c,p); } - - result_type - operator()(const Iso_rectangle_2& c, const Point_2& p) const - { return LK_Bounded_side_2()(c,p); } - -#endif result_type operator()(const Circle_2& c, const Circular_arc_point_2& p) const @@ -1136,9 +917,7 @@ namespace CircularFunctors { template class Has_on_bounded_side_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Has_on_bounded_side_2 -#endif { typedef typename CK::Circle_2 Circle_2; typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; @@ -1146,27 +925,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Has_on_bounded_side_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Has_on_bounded_side_2::operator(); -#else - typedef typename CK::Point_2 Point_2; - typedef typename CK::Triangle_2 Triangle_2; - typedef typename CK::Iso_rectangle_2 Iso_rectangle_2; - typedef typename CK::Linear_kernel LK; - typedef typename LK::Has_on_bounded_side_2 LK_Has_on_bounded_side_2; - - result_type - operator()(const Circle_2& c, const Point_2& p) const - { return LK_Has_on_bounded_side_2()(c,p); } - - result_type - operator()(const Triangle_2& c, const Point_2& p) const - { return LK_Has_on_bounded_side_2()(c,p); } - - result_type - operator()(const Iso_rectangle_2& c, const Point_2& p) const - { return LK_Has_on_bounded_side_2()(c,p); } -#endif result_type operator()(const Circle_2& c, const Circular_arc_point_2& p) const @@ -1176,9 +935,7 @@ namespace CircularFunctors { template class Has_on_unbounded_side_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Has_on_unbounded_side_2 -#endif { typedef typename CK::Circle_2 Circle_2; typedef typename CK::Circular_arc_point_2 Circular_arc_point_2; @@ -1186,27 +943,7 @@ namespace CircularFunctors { public: typedef typename CK::Linear_kernel::Has_on_unbounded_side_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using CK::Linear_kernel::Has_on_unbounded_side_2::operator(); -#else - typedef typename CK::Point_2 Point_2; - typedef typename CK::Triangle_2 Triangle_2; - typedef typename CK::Iso_rectangle_2 Iso_rectangle_2; - typedef typename CK::Linear_kernel LK; - typedef typename LK::Has_on_unbounded_side_2 LK_Has_on_unbounded_side_2; - - result_type - operator()(const Circle_2& c, const Point_2& p) const - { return LK_Has_on_unbounded_side_2()(c,p); } - - result_type - operator()(const Triangle_2& c, const Point_2& p) const - { return LK_Has_on_unbounded_side_2()(c,p); } - - result_type - operator()(const Iso_rectangle_2& c, const Point_2& p) const - { return LK_Has_on_unbounded_side_2()(c,p); } -#endif result_type operator()(const Circle_2& c, const Circular_arc_point_2& p) const @@ -1252,28 +989,13 @@ namespace CircularFunctors { template class Construct_center_2 - #ifndef CGAL_CFG_MATCHING_BUG_6 : public CK::Linear_kernel::Construct_center_2 - #endif { typedef typename CK::Circular_arc_2 Circular_arc_2; public: typedef typename CK::Linear_kernel::Construct_center_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 - using CK::Linear_kernel::Construct_center_2::operator(); -#else + using CK::Linear_kernel::Construct_center_2::operator(); - typedef typename CK::Linear_kernel LK; - typedef typename LK::Construct_center_2 LK_Construct_center_2; - typedef typename CK::Point_2 Point_2; - typedef typename CK::Circle_2 Circle_2; - - public: - result_type - operator()( const Circle_2& c) const - { return LK_Construct_center_2()(c); } - -#endif result_type operator()(const Circular_arc_2& c) const { return c.rep().center(); } diff --git a/Circular_kernel_2/include/CGAL/Filtered_bbox_circular_kernel_2/bbox_filtered_predicates.h b/Circular_kernel_2/include/CGAL/Filtered_bbox_circular_kernel_2/bbox_filtered_predicates.h index e7535752db0..90fbdc38534 100644 --- a/Circular_kernel_2/include/CGAL/Filtered_bbox_circular_kernel_2/bbox_filtered_predicates.h +++ b/Circular_kernel_2/include/CGAL/Filtered_bbox_circular_kernel_2/bbox_filtered_predicates.h @@ -43,31 +43,7 @@ public: typedef typename CK_Compare_x_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3) const - { - return Base()(t1,t2,t3); - } - - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const - { - return Base()(t1,t2,t3,t4); - } - -#endif - result_type operator()( const Circular_arc_point_2 &a, const Circular_arc_point_2 &b) const @@ -105,29 +81,7 @@ public: return CK_Compare_y_2()(p0, p1); } -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3) const - { - return Base()(t1,t2,t3); - } - - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const - { - return Base()(t1,t2,t3,t4); - } -#endif result_type operator()( const Circular_arc_point_2 &a, const Circular_arc_point_2 &b) const @@ -158,17 +112,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif public: result_type @@ -201,16 +145,8 @@ public: typedef typename CK_In_x_range_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif + private: template @@ -273,37 +209,8 @@ public: typedef typename CK_Compare_y_at_x_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3) const - { - return Base()(t1,t2,t3); - } - - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const - { - return Base()(t1,t2,t3,t4); - } - - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) const - { - return Base()(t1,t2,t3,t4,t5); - } -#endif private: template @@ -353,16 +260,9 @@ class Has_on_2 : public BK::Circular_kernel:: template Base< BK >::Type::Has_on_ public: typedef typename CK_Has_on_2::result_type result_type; - #ifndef CGAL_CFG_MATCHING_BUG_6 + using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif + private: template @@ -395,9 +295,7 @@ public: template class Equal_2 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public BK::Circular_kernel:: template Base< BK >::Type::Equal_2 -#endif { typedef typename BK::Circular_kernel:: template Base< BK >::Type::Equal_2 CK_Equal_2; @@ -420,16 +318,7 @@ public: typedef typename CK_Equal_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif private: @@ -519,16 +408,7 @@ public: typedef typename CK_Do_overlap_2::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif private: diff --git a/Circular_kernel_3/include/CGAL/Circular_kernel_3/function_objects_polynomial_sphere.h b/Circular_kernel_3/include/CGAL/Circular_kernel_3/function_objects_polynomial_sphere.h index 694705639c3..30cd1bd3236 100644 --- a/Circular_kernel_3/include/CGAL/Circular_kernel_3/function_objects_polynomial_sphere.h +++ b/Circular_kernel_3/include/CGAL/Circular_kernel_3/function_objects_polynomial_sphere.h @@ -40,7 +40,6 @@ namespace CGAL { namespace SphericalFunctors { -#ifndef CGAL_CFG_MATCHING_BUG_6 #define CGAL_SPHERICAL_KERNEL_MACRO_FUNCTOR_COMPARE_(V)\ template < class SK > \ class Compare_ ##V## _3: public SK::Linear_kernel::Compare_ ##V## _3{\ @@ -63,38 +62,6 @@ template < class SK > \ { return SphericalFunctors::compare_ ##V (p0, p1); }\ };\ -#else -#define CGAL_SPHERICAL_KERNEL_MACRO_FUNCTOR_COMPARE_(V)\ -template < class SK > \ - class Compare_ ##V## _3 {\ - typedef typename SK::Circular_arc_point_3 Circular_arc_point_3;\ - typedef typename SK::Point_3 Point_3;\ - public:\ - typedef typename SK::Linear_kernel::Compare_ ##V## _3 LK_Compare_ ##V## _3;\ - typedef typename SK::Linear_kernel::Compare_ ##V## _3::result_type result_type;\ - \ - result_type\ - operator() (const Circular_arc_point_3 &p0,\ - const Circular_arc_point_3 &p1) const\ - { return SphericalFunctors::compare_ ##V (p0, p1); }\ - \ - result_type\ - operator() (const Circular_arc_point_3 &p0,\ - const Point_3 &p1) const\ - { return SphericalFunctors::compare_ ##V (p0, p1); }\ - \ - result_type\ - operator() (const Point_3 &p0,\ - const Circular_arc_point_3 &p1) const\ - { return SphericalFunctors::compare_ ##V (p0, p1); }\ - \ - result_type\ - operator() (const Point_3 &p0,\ - const Point_3 &p1) const\ - { return LK_Compare_ ##V## _3 ()(p0, p1); }\ - }; -#endif - CGAL_SPHERICAL_KERNEL_MACRO_FUNCTOR_COMPARE_(x) CGAL_SPHERICAL_KERNEL_MACRO_FUNCTOR_COMPARE_(y) CGAL_SPHERICAL_KERNEL_MACRO_FUNCTOR_COMPARE_(z) @@ -145,9 +112,7 @@ template < class SK > \ template < class SK > class Equal_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Equal_3 -#endif { typedef typename SK::Linear_kernel LK; typedef typename LK::Equal_3 LK_Equal_3; @@ -173,72 +138,7 @@ template < class SK > \ typedef typename SK::Linear_kernel::Equal_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Equal_3::operator(); -#else - - result_type - operator() (const Point_3 &p0, - const Point_3 &p1) const - { return LK_Equal_3()(p0,p1); } - - result_type - operator() (const Vector_3 &d0, - const Vector_3 &d1) const - { return LK_Equal_3()(d0,d1); } - - result_type - operator() (const Direction_3 &d0, - const Direction_3 &d1) const - { return LK_Equal_3()(d0,d1); } - - result_type - operator() (const Line_3 &l0, - const Line_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Segment_3 &l0, - const Segment_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Ray_3 &l0, - const Ray_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Triangle_3 &l0, - const Triangle_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - - result_type - operator() (const Tetrahedron_3 &l0, - const Tetrahedron_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Iso_cuboid_3 &l0, - const Iso_cuboid_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Plane_3 &l0, - const Plane_3 &l1) const - { return LK_Equal_3()(l0,l1); } - - result_type - operator() (const Circle_3 &c0, - const Circle_3 &c1) const - { return LK_Equal_3()(c0, c1); } - - result_type - operator() (const Sphere_3 &c0, - const Sphere_3 &c1) const - { return LK_Equal_3()(c0, c1); } - -#endif result_type operator() (const Circular_arc_point_3 &c0, @@ -951,9 +851,7 @@ template < class SK > \ template < class SK > class Has_on_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Has_on_3 -#endif { typedef typename SK::Point_3 Point_3; typedef typename SK::Sphere_3 Sphere_3; @@ -971,54 +869,7 @@ template < class SK > \ public: typedef typename SK::Linear_kernel::Has_on_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Has_on_3::operator(); -#else - typedef typename SK::Linear_kernel::Has_on_3 LK_Has_on_3; - - result_type - operator()( const Line_3& l, const Point_3& p) const - { return LK_Has_on_3()(l,p); } - - result_type - operator()( const Ray_3& r, const Point_3& p) const - { return LK_Has_on_3()(r,p); } - - result_type - operator()( const Segment_3& s, const Point_3& p) const - { return LK_Has_on_3()(s,p); } - - result_type - operator()( const Plane_3& pl, const Point_3& p) const - { return LK_Has_on_3()(pl,p); } - - result_type - operator()( const Plane_3& pl, const Line_3& l) const - { return LK_Has_on_3()(pl,l); } - - result_type - operator()( const Triangle_3& t, const Point_3& p) const - { - return LK_Has_on_3()(t,p); - } - - result_type - operator()(const Sphere_3 &a, const Point_3 &p) const - { return LK_Has_on_3()(a,p); } - - result_type - operator()(const Circle_3 &a, const Point_3 &p) const - { return LK_Has_on_3()(a,p); } - - result_type - operator()(const Sphere_3 &a, const Circle_3 &p) const - { return LK_Has_on_3()(a,p); } - - result_type - operator()(const Plane_3 &a, const Circle_3 &p) const - { return LK_Has_on_3()(a,p); } - -#endif result_type operator()(const Sphere_3 &a, const Circular_arc_point_3 &p) const @@ -1468,9 +1319,7 @@ template < class SK > \ template class Construct_bbox_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Construct_bbox_3 -#endif { typedef typename SK::Circular_arc_point_3 Circular_arc_point_3; typedef typename SK::Circular_arc_3 Circular_arc_3; @@ -1487,57 +1336,7 @@ template < class SK > \ typedef typename SK::Linear_kernel::Construct_bbox_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Construct_bbox_3::operator(); -#else - typedef typename SK::Linear_kernel LK; - typedef typename LK::Construct_bbox_3 LK_Construct_bbox_3; - - result_type - operator()(const Point_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - result_type - operator()(const Segment_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - result_type - operator()(const Triangle_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - - result_type - operator()(const Iso_cuboid_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - result_type - operator()(const Tetrahedron_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - result_type - operator()(const Sphere_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - result_type - operator()(const Circle_3& p) const - { - return LK_Construct_bbox_3()(p); - } - - -#endif result_type operator() (const Circular_arc_point_3 & c) const { return c.rep().bbox(); } @@ -1552,9 +1351,7 @@ template < class SK > \ template class Compute_approximate_squared_length_3 - #ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Compute_approximate_squared_length_3 -#endif { typedef typename SK::Circle_3 Circle_3; typedef typename SK::Circular_arc_3 Circular_arc_3; @@ -1563,13 +1360,7 @@ template < class SK > \ public: typedef double result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Compute_approximate_squared_length_3::operator(); -#else - result_type - operator() (const Circle_3 & c) const - { return CGAL_PI * CGAL_PI * 4.0 * to_double(c.squared_radius()); } -#endif result_type operator() (const Circular_arc_3 & c) const { return c.rep().approximate_squared_length(); } @@ -1578,9 +1369,7 @@ template < class SK > \ template class Compute_approximate_angle_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Compute_approximate_angle_3 -#endif { typedef typename SK::Point_3 Point_3; typedef typename SK::Vector_3 Vector_3; @@ -1591,22 +1380,8 @@ template < class SK > \ typedef double result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Compute_approximate_angle_3::operator(); -#else - typedef typename SK::Linear_kernel::Compute_approximate_angle_3 LK_Compute_approximate_angle_3; - FT operator()(const Point_3& p, const Point_3& q, const Point_3& r) const - { - return LK_Compute_approximate_angle_3()(p,q,r); - } - - FT operator()(const Vector_3& u, const Vector_3& v) const - { - return LK_Compute_approximate_angle_3()(u,v); - } - -#endif result_type operator() (const Circular_arc_3 & c) const { return c.rep().approximate_angle(); } @@ -1614,9 +1389,7 @@ template < class SK > \ template class Bounded_side_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Bounded_side_3 -#endif { typedef typename SK::Sphere_3 Sphere_3; typedef typename SK::Circle_3 Circle_3; @@ -1626,29 +1399,7 @@ template < class SK > \ public: typedef typename SK::Linear_kernel::Bounded_side_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Bounded_side_3::operator(); -#else - typedef typename SK::Tetrahedron_3 Tetrahedron_3; - typedef typename SK::Iso_cuboid_3 Iso_cuboid_3; - typedef typename SK::Linear_kernel::Bounded_side_3 LK_Bounded_side_3; - - result_type - operator()( const Sphere_3& s, const Point_3& p) const - { return LK_Bounded_side_3()(s,p); } - - result_type - operator()( const Tetrahedron_3& t, const Point_3& p) const - { return LK_Bounded_side_3()(t,p); } - - result_type - operator()( const Iso_cuboid_3& c, const Point_3& p) const - { return LK_Bounded_side_3()(c,p); } - - result_type - operator()(const Circle_3& c, const Point_3& p) const - { return LK_Bounded_side_3()(c,p); } -#endif result_type operator()( const Sphere_3& s, const Circular_arc_point_3& p) const @@ -1664,9 +1415,7 @@ template < class SK > \ template class Has_on_bounded_side_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Has_on_bounded_side_3 -#endif { typedef typename SK::Sphere_3 Sphere_3; typedef typename SK::Circle_3 Circle_3; @@ -1676,29 +1425,7 @@ template < class SK > \ public: typedef typename SK::Linear_kernel::Has_on_bounded_side_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Has_on_bounded_side_3::operator(); -#else - typedef typename SK::Tetrahedron_3 Tetrahedron_3; - typedef typename SK::Iso_cuboid_3 Iso_cuboid_3; - typedef typename SK::Linear_kernel::Has_on_bounded_side_3 LK_Has_on_bounded_side_3; - - result_type - operator()( const Sphere_3& s, const Point_3& p) const - { return LK_Has_on_bounded_side_3()(s,p); } - - result_type - operator()( const Tetrahedron_3& t, const Point_3& p) const - { return LK_Has_on_bounded_side_3()(t,p); } - - result_type - operator()( const Iso_cuboid_3& c, const Point_3& p) const - { return LK_Has_on_bounded_side_3()(c,p); } - - result_type - operator()(const Circle_3& c, const Point_3& p) const - { return LK_Has_on_bounded_side_3()(c,p); } -#endif result_type operator()( const Sphere_3& s, const Circular_arc_point_3& p) const @@ -1714,9 +1441,7 @@ template < class SK > \ template class Has_on_unbounded_side_3 -#ifndef CGAL_CFG_MATCHING_BUG_6 : public SK::Linear_kernel::Has_on_unbounded_side_3 -#endif { typedef typename SK::Sphere_3 Sphere_3; typedef typename SK::Circle_3 Circle_3; @@ -1726,29 +1451,7 @@ template < class SK > \ public: typedef typename SK::Linear_kernel::Has_on_unbounded_side_3::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using SK::Linear_kernel::Has_on_unbounded_side_3::operator(); -#else - typedef typename SK::Tetrahedron_3 Tetrahedron_3; - typedef typename SK::Iso_cuboid_3 Iso_cuboid_3; - typedef typename SK::Linear_kernel::Has_on_unbounded_side_3 LK_Has_on_unbounded_side_3; - - result_type - operator()( const Sphere_3& s, const Point_3& p) const - { return LK_Has_on_unbounded_side_3()(s,p); } - - result_type - operator()( const Tetrahedron_3& t, const Point_3& p) const - { return LK_Has_on_unbounded_side_3()(t,p); } - - result_type - operator()( const Iso_cuboid_3& c, const Point_3& p) const - { return LK_Has_on_unbounded_side_3()(c,p); } - - result_type - operator()(const Circle_3& c, const Point_3& p) const - { return LK_Has_on_unbounded_side_3()(c,p); } -#endif result_type operator()( const Sphere_3& s, const Circular_arc_point_3& p) const diff --git a/Classification/examples/Classification/gis_tutorial_example.cpp b/Classification/examples/Classification/gis_tutorial_example.cpp index 0037212b88e..996ec59ea9e 100644 --- a/Classification/examples/Classification/gis_tutorial_example.cpp +++ b/Classification/examples/Classification/gis_tutorial_example.cpp @@ -669,7 +669,7 @@ int main (int argc, char** argv) } std::size_t nb_vertices - = std::accumulate (polylines.begin(), polylines.end(), 0, + = std::accumulate (polylines.begin(), polylines.end(), 0u, [](std::size_t size, const std::vector& poly) -> std::size_t { return size + poly.size(); }); diff --git a/Documentation/doc/Documentation/Usage.txt b/Documentation/doc/Documentation/Usage.txt index 247348cab68..eba087fdaa6 100644 --- a/Documentation/doc/Documentation/Usage.txt +++ b/Documentation/doc/Documentation/Usage.txt @@ -10,7 +10,7 @@ However, some dependencies of \cgal might still need to be installed. Assuming that you have obtained \cgal through one of the package managers offering \cgal on your platform (see Section \ref secgettingcgal), you can download \cgal examples ( -CGAL-\cgalReleaseNumber-examples.tar.xz) +CGAL-\cgalReleaseNumber-examples.tar.xz) and the compilation of an example is as simple as: cd $HOME/CGAL-\cgalReleaseNumber/examples/Triangulation_2 # go to an example directory @@ -51,7 +51,7 @@ acquire these dependencies. The examples and demos of \cgal are not included when you install \cgal with a package manager, and must be downloaded -here. +here. \subsection secusingpkgman Using a Package Manager diff --git a/Documentation/doc/Documentation/windows.txt b/Documentation/doc/Documentation/windows.txt index 7963b3d12b2..77021a27a28 100644 --- a/Documentation/doc/Documentation/windows.txt +++ b/Documentation/doc/Documentation/windows.txt @@ -60,7 +60,7 @@ Note that \cgal is a header-only library, and there are therefore no `lib` or `d In this section we show how to compile a program that uses \cgal. The examples you find in these User Manual pages are not downloaded when you install \cgal with the Vcpkg library manager. You must download them separately from the following download page: -CGAL-\cgalReleaseNumber-examples.zip +CGAL-\cgalReleaseNumber-examples.zip Assuming you have unzipped this file in your home directory `C:\Users\Me`, we will next compile an example from the 2D Triangulation package. diff --git a/Envelope_2/doc/Envelope_2/CGAL/envelope_2.h b/Envelope_2/doc/Envelope_2/CGAL/envelope_2.h index 5dd0d75a15f..7a07ab96e3b 100644 --- a/Envelope_2/doc/Envelope_2/CGAL/envelope_2.h +++ b/Envelope_2/doc/Envelope_2/CGAL/envelope_2.h @@ -40,6 +40,28 @@ namespace CGAL { /*! \ingroup PkgEnvelope2Ref +Computes the lower envelope of a set of \f$ x\f$-monotone curves in +\f$ \mathbb{R}^2\f$, as given by the range `[begin, end)` with the help +of the arrangement traits object `traits` responsible for their creation. +Reusing the same traits object improves speed if the traits class caches data. +The lower envelope is represented using the output minimization diagram `diag`. + +\tparam InputIterator must be an input iterator with value type `EnvelopeDiagram::X_monotone_curve_2`. +\tparam EnvelopeDiagram must be a model of the concept `EnvelopeDiagram_1`. +\tparam Traits must be a model of the concept `ArrangementXMonotoneTraits_2`. +*/ +template +void lower_envelope_x_monotone_2 +(InputIterator begin, InputIterator end, +EnvelopeDiagram& diag, const Traits& traits); + +} /* namespace CGAL */ + +namespace CGAL { + +/*! +\ingroup PkgEnvelope2Ref + Computes the upper envelope of a set of curves in \f$ \mathbb{R}^2\f$, as given by the range `[begin, end)`. The upper envelope is represented using the output maximization diagram `diag`. @@ -71,3 +93,25 @@ void upper_envelope_x_monotone_2 EnvelopeDiagram& diag); } /* namespace CGAL */ + +namespace CGAL { + +/*! +\ingroup PkgEnvelope2Ref + +Computes the upper envelope of a set of \f$ x\f$-monotone curves in +\f$ \mathbb{R}^2\f$, as given by the range `[begin, end)` with the help +of the arrangement traits object `traits` responsbile for their creation. +Reusing the same traits object improves speed if the traits class caches data. +The upper envelope is represented using the output maximization diagram `diag`. + +\tparam InputIterator must be an input iterator with value type `EnvelopeDiagram::X_monotone_curve_2`. +\tparam EnvelopeDiagram must be a model of the concept `EnvelopeDiagram_1`. +\tparam Traits must be a model of the concept `ArrangementXMonotoneTraits_2`. +*/ +template +void upper_envelope_x_monotone_2 +(InputIterator begin, InputIterator end, +EnvelopeDiagram& diag, const Traits& traits); + +} /* namespace CGAL */ diff --git a/Envelope_2/include/CGAL/Envelope_2/Env_divide_and_conquer_2.h b/Envelope_2/include/CGAL/Envelope_2/Env_divide_and_conquer_2.h index bc72cace257..fc2f04a27ec 100644 --- a/Envelope_2/include/CGAL/Envelope_2/Env_divide_and_conquer_2.h +++ b/Envelope_2/include/CGAL/Envelope_2/Env_divide_and_conquer_2.h @@ -62,9 +62,9 @@ protected: typedef Arr_traits_adaptor_2 Traits_adaptor_2; // Data members: - Traits_adaptor_2 *traits; // The traits object. - bool own_traits; // Whether we own the traits object. - Envelope_type env_type; // Either LOWER or UPPER. + const Traits_adaptor_2 *traits; // The traits object. + bool own_traits; // Whether we own the traits object. + Envelope_type env_type; // Either LOWER or UPPER. // Copy constructor and assignment operator - not supported. Envelope_divide_and_conquer_2 (const Self& ); diff --git a/Envelope_2/include/CGAL/envelope_2.h b/Envelope_2/include/CGAL/envelope_2.h index 7eb007edc94..6d23f724393 100644 --- a/Envelope_2/include/CGAL/envelope_2.h +++ b/Envelope_2/include/CGAL/envelope_2.h @@ -93,6 +93,30 @@ void lower_envelope_x_monotone_2 (InputIterator begin, InputIterator end, return; } +/*! + * Compute the lower envelope of a range of x-monotone curves. + * \param begin An iterator for the first x-monotone curve. + * \param end A past-the-end iterator for the x-monotone curves. + * \param diag Output: The minimization diagram. + * \param traits The arrangement traits responsible for the x-monotone curves. + * \pre The value-type of the iterator is Traits::X_monotone_curve_2. + */ +template +void lower_envelope_x_monotone_2 (InputIterator begin, InputIterator end, + EnvelopeDiagram& diag, const Traits& traits) +{ + typedef typename EnvelopeDiagram::Traits_2 Traits_2; + typedef Envelope_divide_and_conquer_2 Envelope_2; + + Envelope_2 env{&traits}; + + env.insert_x_monotone_curves (begin, end, + true, // Lower envelope. + diag); + + return; +} + /*! * Compute the upper envelope of a range of x-monotone curves. * \param begin An iterator for the first x-monotone curve. @@ -116,6 +140,30 @@ void upper_envelope_x_monotone_2 (InputIterator begin, InputIterator end, return; } +/*! + * Compute the upper envelope of a range of x-monotone curves. + * \param begin An iterator for the first x-monotone curve. + * \param end A past-the-end iterator for the x-monotone curves. + * \param diag Output: The maximization diagram. + * \param traits The arrangement traits responsible for the x-monotone curves. + * \pre The value-type of the iterator is Traits::X_monotone_curve_2. + */ +template +void upper_envelope_x_monotone_2 (InputIterator begin, InputIterator end, + EnvelopeDiagram& diag, const Traits& traits) +{ + typedef typename EnvelopeDiagram::Traits_2 Traits_2; + typedef Envelope_divide_and_conquer_2 Envelope_2; + + Envelope_2 env{&traits}; + + env.insert_x_monotone_curves (begin, end, + false, // Upper envelope. + diag); + + return; +} + } //namespace CGAL #endif diff --git a/Filtered_kernel/include/CGAL/Lazy_kernel.h b/Filtered_kernel/include/CGAL/Lazy_kernel.h index 97c1ea349fb..696b81556f7 100644 --- a/Filtered_kernel/include/CGAL/Lazy_kernel.h +++ b/Filtered_kernel/include/CGAL/Lazy_kernel.h @@ -373,18 +373,7 @@ public: typedef typename Kernel_::Point_2 Point_2; typedef typename Kernel_::Weighted_point_2 Weighted_point_2; -#ifndef CGAL_CFG_MATCHING_BUG_6 using BaseClass::Construct_point_2::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - - - template - Point_2 operator()(const T& ...t) const - { - return BaseClass().construct_point_2_object()(t...); - } - -#endif // CGAL_CFG_MATCHING_BUG_6 const Point_2& operator()(const Point_2& p) const { @@ -437,17 +426,7 @@ public: typedef typename Kernel_::Point_3 Point_3; typedef typename Kernel_::Weighted_point_3 Weighted_point_3; -#ifndef CGAL_CFG_MATCHING_BUG_6 - using BaseClass::Construct_point_3::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - - template - Point_3 operator()(const T& ...t) const - { - return BaseClass().construct_point_3_object()(t...); - } - -#endif // CGAL_CFG_MATCHING_BUG_6 + using BaseClass::Construct_point_3::operator(); const Point_3& operator()(const Point_3& p) const { diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Angle_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Angle_3.h index 50895045807..d1bbf6e61bd 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Angle_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Angle_3.h @@ -41,25 +41,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } - - template - result_type - operator()(const T1& t1, const T2& t2, const T3& t3, const T4& t4) const - { - return Base()(t1,t2,t3,t4); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - Sign sign_with_error(const double x, const double error) const { if(x > error) return POSITIVE; diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_squared_radius_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_squared_radius_3.h index cc7dc9f3580..87fe56a9f7b 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_squared_radius_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_squared_radius_3.h @@ -30,16 +30,7 @@ namespace CGAL { namespace internal { namespace Static_filters_predicates { public: typedef typename Base::result_type result_type; - #ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); - #else - result_type - operator()(const Point_3& p, const FT& w) const - { - return Base::operator()(p,w); - } - #endif - result_type operator() ( const Point_3& p, diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_weighted_squared_radius_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_weighted_squared_radius_3.h index 9137774a3b8..a43617746cb 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_weighted_squared_radius_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_weighted_squared_radius_3.h @@ -33,16 +33,7 @@ namespace CGAL { namespace internal { namespace Static_filters_predicates { public: typedef typename Base::result_type result_type; - #ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); - #else - result_type - operator()(const Weighted_point_3& p, const FT& w) const - { - return Base::operator()(p,w); - } - #endif - result_type operator() ( const Weighted_point_3& p, diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_x_2.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_x_2.h index 550bea11b1e..ae1fd1e6c68 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_x_2.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_x_2.h @@ -39,31 +39,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T& t1, const T& t2, const T& t3) const - { - return Base()(t1,t2,t3); - } - - template - result_type - operator()(const T& t1, const T& t2, const T& t3, const T& t4) const - { - return Base()(t1,t2,t3, t4); - } - - result_type - operator()(const Point_2& p, const Line_2& l1, const Line_2& l2) const - { - return Base()(p,l1,l2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - result_type operator()(const Point_2 &p, const Point_2& q) const { diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_y_2.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_y_2.h index 6d1ccbcb69f..adf7d8738ea 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_y_2.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Compare_y_2.h @@ -39,31 +39,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T& t1, const T& t2, const T& t3) const - { - return Base()(t1,t2,t3); - } - - template - result_type - operator()(const T& t1, const T& t2, const T& t3, const T& t4) const - { - return Base()(t1,t2,t3, t4); - } - - result_type - operator()(const Point_2& p, const Line_2& l1, const Line_2& l2) const - { - return Base()(p,l1,l2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - result_type operator()(const Point_2 &p, const Point_2& q) const { diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_2.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_2.h index 4715e8c5681..a5533c253fa 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_2.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_2.h @@ -38,17 +38,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 // The internal::do_intersect(..) function // only performs orientation tests on the vertices diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h index ffc661b636d..92cbd3ebf3f 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Do_intersect_3.h @@ -50,18 +50,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T1& t1, const T2& t2) const - { - return Base()(t1,t2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - Sign sign_with_error(const double x, const double error) const { if(x > error) return POSITIVE; diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_2.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_2.h index 1af2cde1bc8..539a22f5bdd 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_2.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_2.h @@ -40,18 +40,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T& t1, const T& t2) const - { - return Base()(t1,t2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - result_type operator()(const Point_2 &p, const Point_2& q) const { diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_3.h index 1fa95c42457..102199d5633 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Equal_3.h @@ -39,18 +39,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T& t1, const T& t2) const - { - return Base()(t1,t2); - } -#endif // CGAL_CFG_MATCHING_BUG_6 - result_type operator()(const Point_3 &p, const Point_3& q) const { diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Is_degenerate_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Is_degenerate_3.h index 852da37cef9..a4af481f7e1 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Is_degenerate_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Is_degenerate_3.h @@ -38,18 +38,7 @@ public: typedef typename Base::result_type result_type; - -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - template - result_type - operator()(const T& t) const - { - return Base()(t); - } -#endif // end CGAL_CFG_MATCHING_BUG_6 - result_type operator()(const Segment_3& s) const diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_2.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_2.h index 1b684bef511..e4a8ca0f13c 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_2.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_2.h @@ -35,21 +35,8 @@ public: typedef typename Base::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - result_type - operator()(const Vector_2& u, const Vector_2& v) const - { - return Base::operator()(u,v); - } - result_type - operator()(const Circle_2& c) const - { - return Base::operator()(c); - } -#endif Orientation operator()(const Point_2 &p, const Point_2 &q, const Point_2 &r) const diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_3.h index 9fa66cf9aa7..611aa89d344 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Orientation_3.h @@ -36,27 +36,7 @@ class Orientation_3 public: typedef typename Base::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - result_type - operator()(const Vector_3& u, const Vector_3& v, const Vector_3& w) const - { - return Base::operator()(u,v,w); - } - - result_type - operator()(const Sphere_3& s) const - { - return Base::operator()(s); - } - - result_type - operator()(const Tetrahedron_3& t) const - { - return Base::operator()(t); - } -#endif result_type operator()(const Point_3 &p, const Point_3 &q, diff --git a/Filtered_kernel/include/CGAL/internal/Static_filters/Power_side_of_oriented_power_sphere_3.h b/Filtered_kernel/include/CGAL/internal/Static_filters/Power_side_of_oriented_power_sphere_3.h index a72b22ad205..588414ddc72 100644 --- a/Filtered_kernel/include/CGAL/internal/Static_filters/Power_side_of_oriented_power_sphere_3.h +++ b/Filtered_kernel/include/CGAL/internal/Static_filters/Power_side_of_oriented_power_sphere_3.h @@ -32,16 +32,7 @@ namespace CGAL { namespace internal { namespace Static_filters_predicates { public: typedef typename Base::result_type result_type; - #ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); - #else - result_type - operator()(const Weighted_point_3& p, const Weighted_point_3& q) const - { - return Base::operator()(p,q); - } - #endif - void msvc_workaround(double& max1, double& max2, double& max3, double& max4, double& max5, double& RT_tmp_result, diff --git a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp index 3b5cd7cf76b..483a8ab3d27 100644 --- a/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp +++ b/GraphicsView/demo/Triangulation_2/Regular_triangulation_2.cpp @@ -94,6 +94,7 @@ MainWindow::MainWindow() dgi, SLOT(modelChanged())); dgi->setVerticesPen(QPen(Qt::red, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); + dgi->setEdgesPen(QPen(Qt::black, 0, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin)); scene.addItem(dgi); // Add a GraphicItem for the Powerdiagram diagram diff --git a/GraphicsView/demo/Triangulation_2/TriangulationPointInputAndConflictZone.h b/GraphicsView/demo/Triangulation_2/TriangulationPointInputAndConflictZone.h index ce85d87d9c2..b387e314025 100644 --- a/GraphicsView/demo/Triangulation_2/TriangulationPointInputAndConflictZone.h +++ b/GraphicsView/demo/Triangulation_2/TriangulationPointInputAndConflictZone.h @@ -37,6 +37,7 @@ protected: Converter convert; QGraphicsScene *scene_; Point p; + bool do_insert; }; @@ -44,7 +45,7 @@ template TriangulationPointInputAndConflictZone::TriangulationPointInputAndConflictZone(QGraphicsScene* s, T * dt_, QObject* parent) - : GraphicsViewInput(parent), dt(dt_), scene_(s) + : GraphicsViewInput(parent), dt(dt_), scene_(s), do_insert(true) {} @@ -54,6 +55,12 @@ template void TriangulationPointInputAndConflictZone::mousePressEvent(QGraphicsSceneMouseEvent *event) { + if(event->modifiers() & ::Qt::ShiftModifier){ + do_insert = false; + return; + } + else + do_insert = true; p = convert(event->scenePos()); if(dt->dimension() < 2 || event->modifiers() != 0 || @@ -91,7 +98,8 @@ TriangulationPointInputAndConflictZone::mouseReleaseEvent(QGraphicsSceneMouse delete *it; } qfaces.clear(); - Q_EMIT( generate(CGAL::make_object(p))); + if(do_insert) + Q_EMIT( generate(CGAL::make_object(p))); } diff --git a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h index 547cff022b8..20dcc461798 100644 --- a/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h +++ b/GraphicsView/include/CGAL/Qt/Basic_viewer_qt.h @@ -252,7 +252,8 @@ public: bool inverse_normal=false, bool draw_rays=true, bool draw_lines=true, - bool draw_text=true) : + bool draw_text=true, + bool no_2D_mode=false) : CGAL::QGLViewer(parent), m_draw_vertices(draw_vertices), m_draw_edges(draw_edges), @@ -263,6 +264,7 @@ public: m_use_mono_color(use_mono_color), m_inverse_normal(inverse_normal), m_draw_text(draw_text), + m_no_2D_mode(no_2D_mode), m_size_points(7.), m_size_edges(3.1), m_size_rays(3.1), @@ -979,7 +981,8 @@ protected: // Returns true if the data structure lies on a plane bool is_two_dimensional() { - return (!is_empty() && (has_zero_x() || has_zero_y() || has_zero_z())); + return (!is_empty() && !m_no_2D_mode && + (has_zero_x() || has_zero_y() || has_zero_z())); } virtual void draw() @@ -988,6 +991,28 @@ protected: if(!m_are_buffers_initialized) { initialize_buffers(); } + if (is_two_dimensional()) + { + camera()->setType(CGAL::qglviewer::Camera::ORTHOGRAPHIC); + // Camera Constraint: + constraint.setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::AXIS); + constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE); + + double cx=0., cy=0., cz=0.; + if (has_zero_x()) { cx=1.; } + else if (has_zero_y()) { cy=1.; } + else { cz=1.; } + + camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz)); + constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz)); + camera()->frame()->setConstraint(&constraint); + } + else + { + camera()->setType(CGAL::qglviewer::Camera::PERSPECTIVE); + camera()->frame()->setConstraint(nullptr); + } + QColor color; attrib_buffers(this); @@ -1168,23 +1193,6 @@ protected: rendering_program_face.release(); } - if (is_two_dimensional()) - { - camera()->setType(CGAL::qglviewer::Camera::ORTHOGRAPHIC); - // Camera Constraint: - constraint.setRotationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::AXIS); - constraint.setTranslationConstraintType(CGAL::qglviewer::AxisPlaneConstraint::FREE); - - double cx=0., cy=0., cz=0.; - if (has_zero_x()) { cx=1.; } - else if (has_zero_y()) { cy=1.; } - else { cz=1.; } - - camera()->setViewDirection(CGAL::qglviewer::Vec(-cx,-cy,-cz)); - constraint.setRotationConstraintDirection(CGAL::qglviewer::Vec(cx, cy, cz)); - camera()->frame()->setConstraint(&constraint); - } - if (m_draw_text) { glDisable(GL_LIGHTING); @@ -1231,6 +1239,7 @@ protected: setKeyDescription(::Qt::Key_Minus+::Qt::ControlModifier, "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"); // Light default parameters glLineWidth(m_size_edges); @@ -1279,15 +1288,6 @@ protected: displayMessage(QString("Draw edges=%1.").arg(m_draw_edges?"true":"false")); update(); } - else if ((e->key()==::Qt::Key_S) && (modifiers==::Qt::NoButton)) - { - m_flatShading=!m_flatShading; - if (m_flatShading) - displayMessage("Flat shading."); - else - displayMessage("Gouraud shading."); - redraw(); - } else if ((e->key()==::Qt::Key_M) && (modifiers==::Qt::NoButton)) { m_use_mono_color=!m_use_mono_color; @@ -1301,6 +1301,15 @@ protected: negate_all_normals(); redraw(); } + else if ((e->key()==::Qt::Key_S) && (modifiers==::Qt::NoButton)) + { + m_flatShading=!m_flatShading; + if (m_flatShading) + displayMessage("Flat shading."); + else + displayMessage("Gouraud shading."); + redraw(); + } else if ((e->key()==::Qt::Key_T) && (modifiers==::Qt::NoButton)) { m_draw_text=!m_draw_text; @@ -1439,6 +1448,18 @@ protected: arg(m_ambient_color.x()).arg(m_ambient_color.y()).arg(m_ambient_color.z())); update(); } + else if ((e->key()==::Qt::Key_O) && (modifiers==::Qt::NoButton)) + { + bool old_2D=is_two_dimensional(); + m_no_2D_mode=!m_no_2D_mode; + if (old_2D!=is_two_dimensional()) + { + if (is_two_dimensional()) + { displayMessage(QString("Viewer is in 2D mode.")); } + else { displayMessage(QString("Viewer is in 3D mode.")); } + update(); + } + } else CGAL::QGLViewer::keyPressEvent(e); } @@ -1488,6 +1509,7 @@ protected: bool m_use_mono_color; bool m_inverse_normal; bool m_draw_text; + bool m_no_2D_mode; double m_size_points; double m_size_edges; diff --git a/GraphicsView/include/CGAL/Qt/GraphicsViewCircleInput.h b/GraphicsView/include/CGAL/Qt/GraphicsViewCircleInput.h index 214de4ffe40..9d8dbd490c0 100644 --- a/GraphicsView/include/CGAL/Qt/GraphicsViewCircleInput.h +++ b/GraphicsView/include/CGAL/Qt/GraphicsViewCircleInput.h @@ -28,6 +28,7 @@ #include #include + #include #include @@ -71,6 +72,7 @@ GraphicsViewCircleInput::GraphicsViewCircleInput(QObject *parent, QGraphicsSc : GraphicsViewInput(parent), m_pointsOnCircle(pointsOnCircle), count(0), qcircle(new QGraphicsEllipseItem()), scene_(s) { + qcircle->setPen(QPen(::Qt::red, 0, ::Qt::SolidLine, ::Qt::RoundCap, ::Qt::RoundJoin)); qcircle->hide(); s->addItem(qcircle); } @@ -194,6 +196,13 @@ GraphicsViewCircleInput::eventFilter(QObject *obj, QEvent *event) QKeyEvent *keyEvent = static_cast(event); keyPressEvent(keyEvent); return true; + } else if(event->type() == QEvent::GraphicsSceneMouseDoubleClick) { + QGraphicsSceneMouseEvent *mouseEvent = static_cast(event); + qp = mouseEvent->scenePos(); + p = convert(qp); + Q_EMIT generate(CGAL::make_object(std::make_pair(p, 0.0))); + count = 0; + return true; } else{ // standard event processing return QObject::eventFilter(obj, event); diff --git a/GraphicsView/include/CGAL/Qt/camera_impl.h b/GraphicsView/include/CGAL/Qt/camera_impl.h index 6629dd99994..d79ce8af56d 100644 --- a/GraphicsView/include/CGAL/Qt/camera_impl.h +++ b/GraphicsView/include/CGAL/Qt/camera_impl.h @@ -895,13 +895,17 @@ Vec Camera::pointUnderPixel(const QPoint &pixel, bool &found) const { /*! Moves the Camera so that the entire scene is visible. - Simply calls fitSphere() on a sphere defined by sceneCenter() and - sceneRadius(). + Calls fitSphere() on a sphere defined by sceneCenter() and + sceneRadius(), and resets the default FOV. You will typically use this method in CGAL::QGLViewer::init() after you defined a new sceneRadius(). */ CGAL_INLINE_FUNCTION -void Camera::showEntireScene() { fitSphere(sceneCenter(), sceneRadius()); } +void Camera::showEntireScene() +{ + setFieldOfView(CGAL_PI/4.0); + fitSphere(sceneCenter(), sceneRadius()); +} /*! Moves the Camera so that its sceneCenter() is projected on the center of the window. The orientation() and fieldOfView() are unchanged. @@ -2115,7 +2119,7 @@ void Camera::initFromDOMElement(const QDomElement &element) { while (!child.isNull()) { if (child.tagName() == "Parameters") { // #CONNECTION# Default values set in constructor - setFieldOfView(DomUtils::qrealFromDom(child, "fieldOfView", CGAL_PI / 4.0)); + //setFieldOfView(DomUtils::qrealFromDom(child, "fieldOfView", CGAL_PI / 4.0)); setZNearCoefficient( DomUtils::qrealFromDom(child, "zNearCoefficient", 0.005)); setZClippingCoefficient( diff --git a/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h b/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h index 3dfb1bf5e55..c3cae0c5b71 100644 --- a/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h +++ b/GraphicsView/include/CGAL/Qt/manipulatedCameraFrame_impl.h @@ -371,8 +371,7 @@ void ManipulatedCameraFrame::mouseMoveEvent(QMouseEvent *const event, break; } - case ZOOM_ON_REGION: - case NO_MOUSE_ACTION: + default: break; } @@ -424,6 +423,23 @@ void ManipulatedCameraFrame::wheelEvent(QWheelEvent *const event, inverseTransformOf(Vec(0.0, 0.0, 0.2 * flySpeed() * event->angleDelta().y()))); Q_EMIT manipulated(); break; + case ZOOM_FOV: + { + qreal delta = - wheelDelta(event);//- sign to keep the same behavior as for the ZOOM action. + qreal new_fov = delta/100 + camera->fieldOfView(); + if(new_fov > CGAL_PI/180.0) + { + new_fov = delta + camera->fieldOfView(); + } + if(new_fov > CGAL_PI/4.0) + new_fov = CGAL_PI/4.0; + if( new_fov >= 0.0) + { + camera->setFieldOfView(new_fov); + } + Q_EMIT manipulated(); + break; + } default: break; } @@ -447,7 +463,10 @@ void ManipulatedCameraFrame::wheelEvent(QWheelEvent *const event, // isManipulated() returns false. But then fastDraw would not be used with // wheel. Detecting the last wheel event and forcing a final draw() is done // using the timer_. - action_ = NO_MOUSE_ACTION; + if(action_ != ZOOM_FOV) + action_ = NO_MOUSE_ACTION; + //else done after postDraw(). + } //////////////////////////////////////////////////////////////////////////////// diff --git a/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h b/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h index 11a68ce0c08..e99c1acb99e 100644 --- a/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h +++ b/GraphicsView/include/CGAL/Qt/manipulatedFrame_impl.h @@ -458,7 +458,7 @@ void ManipulatedFrame::mouseMoveEvent(QMouseEvent *const event, // These MouseAction values make no sense for a manipulatedFrame break; - case NO_MOUSE_ACTION: + default: // Possible when the ManipulatedFrame is a MouseGrabber. This method is then // called without startAction because of mouseTracking. break; diff --git a/GraphicsView/include/CGAL/Qt/qglviewer_impl.h b/GraphicsView/include/CGAL/Qt/qglviewer_impl.h index b097030d1ea..ee33a8e0ed1 100644 --- a/GraphicsView/include/CGAL/Qt/qglviewer_impl.h +++ b/GraphicsView/include/CGAL/Qt/qglviewer_impl.h @@ -598,6 +598,33 @@ void CGAL::QGLViewer::postDraw() { if (displayMessage_) drawText(10, height() - 10, message_); + //zoom region + if(camera()->frame()->action_ == qglviewer::ZOOM_ON_REGION) + { + QPainter painter(this); + painter.setPen(QColor(120,120,120)); + painter.drawRect(QRect(camera()->frame()->pressPos_, mapFromGlobal(QCursor::pos()))); + painter.end(); + } + + //zoom_fov indicator + if(camera()->frame()->action_ == qglviewer::ZOOM_FOV) + { + QPainter painter(this); + QPoint bot(width()-30,height()/2-0.33*height()), + top(width()-30, height()/2+0.33*height()); + int fov_height = (top.y()-bot.y())*camera()->fieldOfView()*4.0/CGAL_PI + bot.y(); + + + painter.setPen(QColor(120,120,120)); + painter.drawLine(bot, top); + painter.fillRect(QRect(QPoint(width()-40, fov_height+10), + QPoint(width()-20, fov_height-10)), + QColor(120,120,120)); + painter.end(); + camera()->frame()->action_= qglviewer::NO_MOUSE_ACTION; + } + } @@ -732,6 +759,7 @@ void CGAL::QGLViewer::setDefaultMouseBindings() { setWheelBinding(modifiers, mh, qglviewer::ZOOM); } + setWheelBinding(::Qt::Key_Z, ::Qt::NoModifier, qglviewer::CAMERA, qglviewer::ZOOM_FOV); // Z o o m o n r e g i o n setMouseBinding(::Qt::ShiftModifier, ::Qt::MidButton, qglviewer::CAMERA, qglviewer::ZOOM_ON_REGION); @@ -753,6 +781,7 @@ void CGAL::QGLViewer::setDefaultMouseBindings() { setMouseBinding(::Qt::Key_Z, ::Qt::NoModifier, ::Qt::LeftButton, qglviewer::ZOOM_ON_PIXEL); setMouseBinding(::Qt::Key_Z, ::Qt::NoModifier, ::Qt::RightButton, qglviewer::ZOOM_TO_FIT); + #ifdef Q_OS_MAC // Specific Mac bindings for touchpads. Two fingers emulate a wheelEvent which // zooms. There is no right button available : make Option key + left emulate @@ -1636,6 +1665,8 @@ QString CGAL::QGLViewer::mouseActionString(qglviewer::MouseAction ma) { "SCREEN_TRANSLATE mouse action"); case CGAL::qglviewer::ZOOM_ON_REGION: return CGAL::QGLViewer::tr("Zooms on region for", "ZOOM_ON_REGION mouse action"); + case CGAL::qglviewer::ZOOM_FOV: + return CGAL::QGLViewer::tr("Changes the FOV to emulate an optical zoom for ", "ZOOM_FOV mouse action"); } return QString(); } @@ -2722,14 +2753,16 @@ void CGAL::QGLViewer::setWheelBinding(::Qt::Key key, ::Qt::KeyboardModifiers mod bool withConstraint) { //#CONNECTION# ManipulatedFrame::wheelEvent and // ManipulatedCameraFrame::wheelEvent switches - if ((action != qglviewer::ZOOM) && (action != qglviewer::MOVE_FORWARD) && - (action != qglviewer::MOVE_BACKWARD) && (action != qglviewer::NO_MOUSE_ACTION)) { + if ((action != qglviewer::ZOOM) && (action != qglviewer::ZOOM_FOV) && + (action != qglviewer::MOVE_FORWARD) && (action != qglviewer::MOVE_BACKWARD) + && (action != qglviewer::NO_MOUSE_ACTION)) { qWarning("Cannot bind %s to wheel", mouseActionString(action).toLatin1().constData()); return; } - if ((handler == qglviewer::FRAME) && (action != qglviewer::ZOOM) && (action != qglviewer::NO_MOUSE_ACTION)) { + if ((handler == qglviewer::FRAME) && (action != qglviewer::ZOOM) + && (action != qglviewer::NO_MOUSE_ACTION)) { qWarning("Cannot bind %s to FRAME wheel", mouseActionString(action).toLatin1().constData()); return; @@ -3840,18 +3873,13 @@ void CGAL::QGLViewer::initFromDOMElement(const QDomElement &element) { setAxisIsDrawn(DomUtils::boolFromDom(child, "axisIsDrawn", false)); setGridIsDrawn(DomUtils::boolFromDom(child, "gridIsDrawn", false)); setFPSIsDisplayed(DomUtils::boolFromDom(child, "FPSIsDisplayed", false)); - // See comment below. - tmpCameraIsEdited = DomUtils::boolFromDom(child, "cameraIsEdited", false); - // setTextIsEnabled(DomUtils::boolFromDom(child, "textIsEnabled", true)); } if (child.tagName() == "Geometry") { setFullScreen(DomUtils::boolFromDom(child, "fullScreen", false)); - if (isFullScreen()) { - prevPos_.setX(DomUtils::intFromDom(child, "prevPosX", 0)); - prevPos_.setY(DomUtils::intFromDom(child, "prevPosY", 0)); - } else { + if (!isFullScreen()) + { int width = DomUtils::intFromDom(child, "width", 600); int height = DomUtils::intFromDom(child, "height", 400); topLevelWidget()->resize(width, height); @@ -3864,15 +3892,6 @@ void CGAL::QGLViewer::initFromDOMElement(const QDomElement &element) { } } - if (child.tagName() == "Camera") { - connectAllCameraKFIInterpolatedSignals(false); - camera()->initFromDOMElement(child); - connectAllCameraKFIInterpolatedSignals(); - } - - if ((child.tagName() == "ManipulatedFrame") && (manipulatedFrame())) - manipulatedFrame()->initFromDOMElement(child); - child = child.nextSibling().toElement(); } diff --git a/GraphicsView/include/CGAL/Qt/viewer_actions.h b/GraphicsView/include/CGAL/Qt/viewer_actions.h index f349b90d9ae..98cc1f25727 100644 --- a/GraphicsView/include/CGAL/Qt/viewer_actions.h +++ b/GraphicsView/include/CGAL/Qt/viewer_actions.h @@ -79,7 +79,8 @@ enum MouseAction { ROLL, DRIVE, SCREEN_TRANSLATE, - ZOOM_ON_REGION + ZOOM_ON_REGION, + ZOOM_FOV }; enum SnapShotBackground { diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index 5a9dac235c6..549c50ddc29 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -1,8 +1,8 @@ Release History =============== + [Release 5.2](https://github.com/CGAL/cgal/releases/tag/v5.2) ------------ Release date: December 2020 @@ -10,16 +10,47 @@ Release date: December 2020 - Added the convenience header `CGAL/boost/graph/graph_traits_inheritance_macros.h` that allows to easily make any class inheriting from a model of a face graph concept, a model of the same concept. +- Added the function `can_add_face()`, which tests whether a new face defined by a range of vertices can be added. ### [3D Convex Hulls](https://doc.cgal.org/5.2/Manual/packages.html#PkgConvexHull3) - Added the function `CGAL::halfspace_intersection_interior_point_3()` that can be used to retrieve the point that is the most interior a convex closed volume defined by the intersection of a set of halfspaces. +### [2D Arrangements](https://doc.cgal.org/5.2/Manual/packages.html#PkgArrangementOnSurface2) + +- Replaced the use of legacy + [`CGAL::Object`](https://doc.cgal.org/5.2/STL_Extension/classCGAL_1_1Object.html) + to modern `boost::variant` + - Changed make-x-monotone return type from legacy + [`CGAL::Object`](https://doc.cgal.org/5.2/STL_Extension/classCGAL_1_1Object.html) + to `boost::variant` in all traits concepts and models. + As there exists an implicit conversion from `boost::variant` to `CGAL::Object`, + the new code is backward compatible. However, it is recommended that all calls + to the make-x-monotone functions are fixed to use the new return type. + - Changed `decompose()` interface to use `boost::variant` instead of legacy + [`CGAL::Object`](https://doc.cgal.org/5.1/STL_Extension/classCGAL_1_1Object.html) + As explained above, the code is backward compatible. However, it is recommended + that all calls to `decompose()` are fixed to use the new interface. + ### [Polygon Mesh Processing](https://doc.cgal.org/5.2/Manual/packages.html#PkgPolygonMeshProcessing) +- Added a visitor to the functions + [`CGAL::Polygon_mesh_processing::triangulate_face()`](https://doc.cgal.org/5.2/Polygon_mesh_processing/group__PMP__meshing__grp.html#ga70d65044f8c7309c24ade88fa280124a) + and [`CGAL::Polygon_mesh_processing::triangulate_faces()`](https://doc.cgal.org/5.2/Polygon_mesh_processing/group__PMP__meshing__grp.html#gacaaff4d520500c530d9c3d5ebe2a0760), + that enables the user to keep track of the newly created faces through the triangulation process. + - Added an option in `corefine()`, `split()` and `clip()` functions that enables the operation to be done on a mesh with self-intersections present in the intersection area. -[Release 5.1](https://github.com/CGAL/cgal/releases/tag/releases%2FCGAL-5.1) +### [dD Geometry Kernel](https://doc.cgal.org/5.2/Manual/packages.html#PkgKernelD) + +- The kernels [`Epick_d`](https://doc.cgal.org/5.2/Kernel_d/structCGAL_1_1Epick__d.html) + and [`Epeck_d`](https://doc.cgal.org/5.2/Kernel_d/structCGAL_1_1Epeck__d.html) gain two new functors: + [`Compute_power_product_d`](https://doc.cgal.org/5.2/Kernel_d/classCGAL_1_1Epeck__d_1_1Compute__power__product__d.html) + and [`Construct_power_sphere_d`](https://doc.cgal.org/5.2/Kernel_d/classCGAL_1_1Epeck__d_1_1Construct__power__sphere__d.html), + to deal with weighted points. + + +[Release 5.1](https://github.com/CGAL/cgal/releases/tag/v5.1) ----------- Release date: September 2020 diff --git a/Installation/cmake/modules/CGAL_Qt5_moc_and_resource_files.cmake b/Installation/cmake/modules/CGAL_Qt5_moc_and_resource_files.cmake index 45f531f7f93..2ff6bb7276a 100644 --- a/Installation/cmake/modules/CGAL_Qt5_moc_and_resource_files.cmake +++ b/Installation/cmake/modules/CGAL_Qt5_moc_and_resource_files.cmake @@ -18,7 +18,7 @@ if(NOT CGAL_HEADER_ONLY AND CGAL_BUILDING_LIBS) ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/include/CGAL/Qt/image_interface.h TARGET CGAL_Qt5 ) -endif()#CGAL_HEADER_ONLY +endif()#CGAL_HEADER_ONLY # qrc files (resources files, that contain icons, at least) if(EXISTS ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/demo/resources/CGAL.qrc) @@ -29,11 +29,15 @@ if(EXISTS ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/demo/resources/CGAL.qrc) ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/demo/icons/Triangulation_2.qrc) else() # Installed version, in CMake resources + file ( COPY + ${CGAL_MODULES_DIR}/demo/resources + ${CGAL_MODULES_DIR}/demo/icons + DESTINATION ${CMAKE_BINARY_DIR}) qt5_add_resources (_CGAL_Qt5_RESOURCE_FILES_private - ${CGAL_MODULES_DIR}/demo/resources/CGAL.qrc - ${CGAL_MODULES_DIR}/demo/icons/Input.qrc - ${CGAL_MODULES_DIR}/demo/icons/File.qrc - ${CGAL_MODULES_DIR}/demo/icons/Triangulation_2.qrc) + ${CMAKE_BINARY_DIR}/resources/CGAL.qrc + ${CMAKE_BINARY_DIR}/icons/Input.qrc + ${CMAKE_BINARY_DIR}/icons/File.qrc + ${CMAKE_BINARY_DIR}/icons/Triangulation_2.qrc) endif() qt5_wrap_ui(_CGAL_Qt5_UI_FILES ${CGAL_GRAPHICSVIEW_PACKAGE_DIR}/include/CGAL/Qt/resources/ImageInterface.ui) diff --git a/Installation/cmake/modules/FindITT.cmake b/Installation/cmake/modules/FindITT.cmake new file mode 100644 index 00000000000..1406b04186d --- /dev/null +++ b/Installation/cmake/modules/FindITT.cmake @@ -0,0 +1,204 @@ +# CGAL note: copy from https://raw.githubusercontent.com/dmitry-gurulev/cmake/104ca4a6c462e3d5a1c217571212238c6446cfca/FindITT.cmake +# +# Distributed under the OSI-approved BSD 3-Clause License. See accompanying +# file Copyright.txt or https://cmake.org/licensing for details. + +#.rst: +# FindITT +# --------- +# +# Find Instrumentation and Tracing Technology (ITT) API include dirs and libraries +# +# Use this module by invoking find_package with the form +# +# :: +# +# find_package(ITT +# [REQUIRED] # Fail with error if ITT is not found +# ) +# +# This module finds headers and libraries +# For the former case results are reported in variables +# +# :: +# +# ITT_FOUND - True if headers and requested libraries were found +# ITT_INCLUDE_DIRS - ITT include directories +# ITT_LIBRARIES - ITT libraries to be linked +# +# This module reads hints about search locations from variables +# +# :: +# +# SEAPI_ROOT - Preferred installation path for Intel® Single Event API (Intel® SEAPI) +# (https://github.com/intel/IntelSEAPI) +# ITT_ROOT/ +# CMAKE_ITT_HOME - Preferred installation path for standalone ITT library +# INTEL_LIBITTNOTIFY32/ +# INTEL_LIBITTNOTIFY64 - Preferred ITT library directory +# VTUNE_AMPLIFIER__DIR - VTune Amplifier XE installation path which is set by amplxe-vars.sh/bat script +# See notes about [ITT_NO_VTUNE_PATH] below +# CMAKE_VTUNE_HOME - Explicitly defined VTune Amplifier XE installation path +# +# Other variables one may set to control this module are +# +# :: +# +# ITT_DEBUG - Set to ON to enable debug output from FindITT. +# Please enable this before filing any bug report. +# ITT_NO_VTUNE_PATH - Set to ON to not try to find VTUNE_AMPLIFIER__DIR environment variable +# +# Example to find ITT headers and libraries +# +# :: +# +# find_package(ITT) +# if (ITT_FOUND) +# include_directories(${ITT_INCLUDE_DIRS}) +# add_executable(foo foo.cc) +# target_link_libraries(foo ${ITT_LIBRARIES}) +# endif() +# +# Example to find ITT library and use imported targets:: +# +# :: +# +# find_package(ITT REQUIRED) +# add_executable(foo foo.cc) +# target_link_libraries(foo ITT::ITT) + +unset (_itt_INC_DIR_HINT) +unset (_itt_LIB_DIR_HINT) + +set (_itt_ARC "") +if (${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} MATCHES "x86") + set (_itt_ARC "64") +elseif (${CMAKE_CXX_COMPILER_ARCHITECTURE_ID} MATCHES "x64") + set (_itt_ARC "64") +endif() + +if ("x${_itt_ARC}" STREQUAL "x") + if (CMAKE_SIZEOF_VOID_P EQUAL 8) + set (_itt_ARC "64") + else() + set (_itt_ARC "32") + endif() +endif() + +list (APPEND _itt_INC_DIR_HINT + $ENV{ITT_ROOT} + $ENV{SEAPI_ROOT}/ittnotify + ${CMAKE_ITT_HOME} + ${CMAKE_VTUNE_HOME} +) + +set (_itt_LIBITTNOTIFY $ENV{INTEL_LIBITTNOTIFY${_itt_ARC}}) +if (_itt_LIBITTNOTIFY) + get_filename_component (_itt_LIB_DIR_HINT ${_itt_LIBITTNOTIFY} DIRECTORY) + get_filename_component (_itt_INC_DIR_HINT ${_itt_LIB_DIR_HINT} DIRECTORY) +endif() + +list (APPEND _itt_INC_DIR_HINT + ${_itt_INC_DIR_HINT}/ittnotify +) + +if (NOT ITT_NO_VTUNE_PATH) + execute_process (COMMAND "${CMAKE_COMMAND}" "-E" "environment" + OUTPUT_VARIABLE _itt_ENV_LIST + ) + + string (REGEX MATCH "VTUNE_AMPLIFIER_[0-9]+_DIR" + _itt_VTUNE_DIR ${_itt_ENV_LIST} + ) +endif() + +if (_itt_VTUNE_DIR) + list (APPEND _itt_INC_DIR_HINT $ENV{${_itt_VTUNE_DIR}}) +endif() + +if (ITT_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_itt_INC_DIR_HINT = ${_itt_INC_DIR_HINT}") +endif() + +find_path (ITT_INCLUDE_DIR + NAMES ittnotify.h + HINTS + ${_itt_INC_DIR_HINT} + PATH_SUFFIXES + include +) + +if (ITT_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ITT_INCLUDE_DIR = ${ITT_INCLUDE_DIR}") +endif() + +if (ITT_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_itt_ARC = ${_itt_ARC}") +endif() + +if (ITT_INCLUDE_DIR) + get_filename_component (_itt_INC_DIR_HINT ${ITT_INCLUDE_DIR} DIRECTORY) + list (APPEND _itt_LIB_DIR_HINT ${_itt_INC_DIR_HINT}) +endif() + +list (APPEND _itt_LIB_DIR_HINT + $ENV{ITT_ROOT} + $ENV{SEAPI_ROOT} +) + +if (ITT_DEBUG) + message (STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "_itt_LIB_DIR_HINT = ${_itt_LIB_DIR_HINT}") +endif() + +find_library (ITT_LIBRARY + NAMES + libittnotify + libittnotify${_itt_ARC} + ittnotify + ittnotify${_itt_ARC} + HINTS + ${_itt_LIB_DIR_HINT} + PATH_SUFFIXES + lib${_itt_ARC} + lib + bin +) + +if (ITT_DEBUG) + message(STATUS "[ ${CMAKE_CURRENT_LIST_FILE}:${CMAKE_CURRENT_LIST_LINE} ] " + "ITT_LIBRARY = ${ITT_LIBRARY}") +endif() + +# handle the QUIETLY and REQUIRED arguments and set MFX_FOUND to TRUE if +# all listed variables are TRUE +include (${CMAKE_ROOT}/Modules/FindPackageHandleStandardArgs.cmake) +FIND_PACKAGE_HANDLE_STANDARD_ARGS (ITT + REQUIRED_VARS ITT_INCLUDE_DIR ITT_LIBRARY +) + +mark_as_advanced(ITT_INCLUDE_DIR ITT_LIBRARY) + +if (ITT_FOUND) + set (ITT_INCLUDE_DIRS ${ITT_INCLUDE_DIR}) + set (ITT_LIBRARIES ${ITT_LIBRARY}) + + if (NOT TARGET ITT::ITT) + add_library(ITT::ITT UNKNOWN IMPORTED) + + set_target_properties(ITT::ITT PROPERTIES + INTERFACE_INCLUDE_DIRECTORIES "${ITT_INCLUDE_DIRS}" + ) + + set_target_properties(ITT::ITT PROPERTIES + IMPORTED_LOCATION "${ITT_LIBRARIES}" + ) + + set_target_properties(ITT::ITT PROPERTIES + INTERFACE_LINK_LIBRARIES "${CMAKE_DL_LIBS}" + ) + endif() +endif() diff --git a/Installation/include/CGAL/MSVC_compiler_config.h b/Installation/include/CGAL/MSVC_compiler_config.h deleted file mode 100644 index e144342afd7..00000000000 --- a/Installation/include/CGAL/MSVC_compiler_config.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2016 GeometryFactory (France). All rights reserved. -// -// This file is part of CGAL (www.cgal.org) -// -// $URL$ -// $Id$ -// SPDX-License-Identifier: LGPL-3.0-or-later OR LicenseRef-Commercial -// -// -// Author(s) : Laurent Rineau - -#ifndef CGAL_MSVC_COMPILER_CONFIG_H -#define CGAL_MSVC_COMPILER_CONFIG_H - -// For all known version of MSVC. Actually we do not really have a -// test for that bug. -#define CGAL_CFG_MATCHING_BUG_6 1 - -// Fixed since MSVC 2015 -#define CGAL_CFG_MATCHING_BUG_7 1 - -// for all known version of MSVC -#define CGAL_CFG_MATCHING_BUG_8 1 - -// Should be only for MSVC 2012 and 2013 in Release -#define CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG 1 - -#endif // CGAL_MSVC_COMPILER_CONFIG_H diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index 47397199b09..e34187ffffb 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -159,9 +159,6 @@ #if CGAL_HEADER_ONLY # include -# if(BOOST_MSVC) -# include -# endif #else # include #endif diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index eeb855c2b3f..1cefac9ba03 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -2,7 +2,7 @@ # This is the CMake script for compiling a CGAL application. -cmake_minimum_required(VERSION 3.1...3.15) +cmake_minimum_required(VERSION 3.11...3.15) project( Installation_Tests ) @@ -86,6 +86,10 @@ if ( CGAL_FOUND ) target_link_libraries(test_gmp_mpfr_dll version) CGAL_add_test(test_gmp_mpfr_dll) add_to_cached_list( CGAL_EXECUTABLE_TARGETS test_gmp_mpfr_dll ) + string(RANDOM RDM_DIR)#5 random chars to avoid conflicts in parallel testsuites + set(NON_STANDARD_INSTALL_PREFIX $ENV{TEMP}/${RDM_DIR}) + else() + set(NON_STANDARD_INSTALL_PREFIX ${CMAKE_BINARY_DIR}) endif() find_package( LEDA QUIET) @@ -101,6 +105,18 @@ else() endif() +if("$ENV{CMAKE_GENERATOR}" STREQUAL "") + set(GENERATOR ) + else() + set(GENERATOR $ENV{CMAKE_GENERATOR}) + endif() + + if("$ENV{INIT_FILE}" STREQUAL "") + set(INIT_FILE ) + else() + set(INIT_FILE -C$ENV{INIT_FILE}) + endif() + function(CGAL_installation_test_find_package_version mode) set(EXACT) if(mode STREQUAL "less") @@ -123,10 +139,16 @@ function(CGAL_installation_test_find_package_version mode) file(REMOVE_RECURSE "${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}") file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}) + configure_file(test_find_package.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode}/CMakeLists.txt) + add_test(NAME test_find_package_version_${mode} - COMMAND ${CMAKE_COMMAND} -S ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} -B ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode} -DCGAL_DO_NOT_WARN_ABOUT_CMAKE_BUILD_TYPE=ON) + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release ${CMAKE_CURRENT_BINARY_DIR}/test_find_package_version_${mode} + ) cgal_setup_test_properties(test_find_package_version_${mode}) + set_property(TEST test_find_package_version_${mode} + PROPERTY + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/build-test_find_package_version_${mode}) endfunction() CGAL_installation_test_find_package_version(less) @@ -135,8 +157,149 @@ CGAL_installation_test_find_package_version(equal) CGAL_installation_test_find_package_version(greater) CGAL_installation_test_find_package_version(exact) CGAL_installation_test_find_package_version(fail-exact) + set_tests_properties( test_find_package_version_greater test_find_package_version_less_major test_find_package_version_fail-exact PROPERTIES WILL_FAIL TRUE) + +find_package(CGAL COMPONENTS Qt5) + +file(MAKE_DIRECTORY "${NON_STANDARD_INSTALL_PREFIX}/non_standard_install") +file(MAKE_DIRECTORY ${NON_STANDARD_INSTALL_PREFIX}/non_standard_build) +file(MAKE_DIRECTORY ${NON_STANDARD_INSTALL_PREFIX}/test_config_file) + +if(CGAL_Qt5_FOUND) + file(MAKE_DIRECTORY ${NON_STANDARD_INSTALL_PREFIX}/non_standard_install_qt5) + file(MAKE_DIRECTORY ${NON_STANDARD_INSTALL_PREFIX}/non_standard_build_qt5) + file(MAKE_DIRECTORY ${NON_STANDARD_INSTALL_PREFIX}/test_config_file_qt5) + configure_file(test_configuration_qt5.cmake.in ${CMAKE_BINARY_DIR}/test_config_file_qt5/CMakeLists.txt @ONLY) +endif()#CGAL_Qt5_FOUND + +#If ctest is ran from a global config, CGAL_SOURCE_DIR exists, but from Installation/test it doesn't. In that case, however, there is a CGAL_DIR. +if("${CGAL_SOURCE_DIR}" STREQUAL "") + if("$ENV{CGAL_RELEASE_DIR}" STREQUAL "") + set(CGAL_SOURCE_DIR ${CGAL_DIR}) + else() + set(CGAL_SOURCE_DIR $ENV{CGAL_RELEASE_DIR}) + endif() +endif() +string(REGEX REPLACE "/cygdrive/c/" "C:/" CGAL_SOURCE_DIR ${CGAL_SOURCE_DIR}) + +configure_file(test_configuration.cmake.in ${CMAKE_BINARY_DIR}/test_config_file/CMakeLists.txt @ONLY) + +#test CGAL_DIR = source_dir (Git_root or CGAL-5.x dir. +get_filename_component(CGAL_DIR_CORRECT_PATH "${CGAL_SOURCE_DIR}/CGALConfig.cmake" DIRECTORY) +add_test(NAME test_config_file + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} + "${CMAKE_BINARY_DIR}/test_config_file" #src + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file") #build +list(APPEND test_config_lst "test_config_file") + +if(RUNNING_CGAL_AUTO_TEST OR CGAL_TEST_SUITE)#CGAL_BRANCH_BUILD + #test CGAL_DIR = CGAL-5.x/lib/cmake/CGAL + get_filename_component(CGAL_DIR_CORRECT_PATH "${CGAL_SOURCE_DIR}/lib/cmake/CGAL/CGALConfig.cmake" DIRECTORY) + add_test(NAME test_config_file_2 + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} + "${CMAKE_BINARY_DIR}/test_config_file" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file_2") +else()#CGAL_BRANCH_BUILD + #use the CGAL_DIR + get_filename_component(CGAL_DIR_CORRECT_PATH "${CGAL_SOURCE_DIR}/Installation/lib/cmake/CGAL/CGALConfig.cmake" DIRECTORY) + add_test(NAME test_config_file_2 + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} + "${CMAKE_BINARY_DIR}/test_config_file" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file_2") +endif()#CGAL_BRANCH_BUILD +list(APPEND test_config_lst "test_config_file_2") + +#configure cgal for a non standard install without qt5 +get_filename_component(CORRECT_INSTALL_PATH "${NON_STANDARD_INSTALL_PREFIX}/non_standard_install/dummy.txt" DIRECTORY) +add_test(NAME config_non_standard_cgal + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${CORRECT_INSTALL_PATH} -DCGAL_INSTALL_LIB_DIR=lib + "${CGAL_SOURCE_DIR}" + WORKING_DIRECTORY "${NON_STANDARD_INSTALL_PREFIX}/non_standard_build") +#install cgal in the non standard place +add_test(NAME install_non_standard_cgal + COMMAND ${CMAKE_COMMAND} --build "${NON_STANDARD_INSTALL_PREFIX}/non_standard_build" --target "install" --config "$") + +#test CGAL_DIR=non standard place without cgal_qt5 +get_filename_component(CGAL_DIR_CORRECT_PATH "${NON_STANDARD_INSTALL_PREFIX}/non_standard_install/lib/cmake/CGAL/CGALConfig.cmake" DIRECTORY) +add_test(NAME test_config_file_3 +COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} +"${CMAKE_BINARY_DIR}/test_config_file" +WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file_3") +list(APPEND test_config_lst "test_config_file_3") + +if(CGAL_Qt5_FOUND) + #configure cgal for a non standard install with qt5 + add_test(NAME config_non_standard_cgal_qt5 + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=${NON_STANDARD_INSTALL_PREFIX}/non_standard_install_qt5 -DCGAL_INSTALL_LIB_DIR=lib -DWITH_CGAL_Qt5=ON + "${CGAL_SOURCE_DIR}" + WORKING_DIRECTORY "${NON_STANDARD_INSTALL_PREFIX}/non_standard_build_qt5") + #install cgal in the non standard place + add_test(NAME install_non_standard_cgal_qt5 + COMMAND ${CMAKE_COMMAND} --build "${NON_STANDARD_INSTALL_PREFIX}/non_standard_build_qt5" --target "install" --config "$") + + #test CGAL_DIR=non standard place with cgal_qt5 + get_filename_component(CGAL_DIR_CORRECT_PATH "${NON_STANDARD_INSTALL_PREFIX}/non_standard_install_qt5/lib/cmake/CGAL/CGALConfig.cmake" DIRECTORY) + add_test(NAME test_config_file_4 + COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} + "${CMAKE_BINARY_DIR}/test_config_file_qt5" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file_4") + list(APPEND test_config_lst "test_config_file_4") +endif()#CGAL_Qt5_FOUND + +#test CGAL_DIR=non standard build +get_filename_component(CGAL_DIR_CORRECT_PATH "${NON_STANDARD_INSTALL_PREFIX}/non_standard_build/CGALConfig.cmake" DIRECTORY) +add_test(NAME test_config_file_5 +COMMAND ${CMAKE_COMMAND} ${GENERATOR} ${INIT_FILE} -DCMAKE_BUILD_TYPE=Release -DCGAL_DIR=${CGAL_DIR_CORRECT_PATH} -DCGAL_GIVEN_DIR=${CGAL_DIR_CORRECT_PATH} + "${CMAKE_BINARY_DIR}/test_config_file" + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-test_config_file_5") +list(APPEND test_config_lst "test_config_file_5") + +foreach(tgt ${test_config_lst}) + #add_custom_target(${tgt}_target) + add_test(NAME "${tgt}_SetupFixture" COMMAND ${CMAKE_COMMAND} -E make_directory "${CMAKE_BINARY_DIR}/build-${tgt}") + add_test(NAME "${tgt}_CleanupFixture" COMMAND ${CMAKE_COMMAND} -E remove_directory "${CMAKE_BINARY_DIR}/build-${tgt}") + add_test(NAME compile__${tgt} + COMMAND ${CMAKE_COMMAND} --build "${CMAKE_BINARY_DIR}/build-${tgt}" --config "$") + add_test(NAME exec__${tgt} + COMMAND ./test_configuration + WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/build-${tgt}") + + set_property(TEST "${tgt}_SetupFixture" APPEND PROPERTY FIXTURES_SETUP ${tgt}_target) + set_property(TEST "${tgt}_CleanupFixture" APPEND PROPERTY FIXTURES_CLEANUP ${tgt}_target) + set_property(TEST ${tgt} APPEND PROPERTY FIXTURES_REQUIRED ${tgt}_target) + set_property(TEST compile__${tgt} APPEND PROPERTY FIXTURES_REQUIRED ${tgt}_target) + set_property(TEST compile__${tgt} APPEND PROPERTY DEPENDS ${tgt}) + set_property(TEST exec__${tgt} APPEND PROPERTY FIXTURES_REQUIRED ${tgt}_target) + set_property(TEST exec__${tgt} APPEND PROPERTY DEPENDS compile__${tgt}) + + set_property(TEST "${tgt}_SetupFixture" APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + set_property(TEST "${tgt}_CleanupFixture" APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + set_property(TEST ${tgt} APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + set_property(TEST compile__${tgt} APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + set_property(TEST exec__${tgt} APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + +endforeach() + +set_property(TEST install_non_standard_cgal APPEND PROPERTY DEPENDS config_non_standard_cgal) +set_property(TEST config_non_standard_cgal APPEND PROPERTY FIXTURES_SETUP test_config_file_3_target) +set_property(TEST install_non_standard_cgal APPEND PROPERTY FIXTURES_SETUP test_config_file_3_target) +set_property(TEST test_config_file_3 test_config_file_5 APPEND PROPERTY FIXTURES_REQUIRED test_config_file_3_target) + +set_property(TEST install_non_standard_cgal APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) +set_property(TEST config_non_standard_cgal APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + +if(CGAL_Qt5_FOUND) + set_property(TEST install_non_standard_cgal_qt5 APPEND PROPERTY DEPENDS config_non_standard_cgal_qt5) + set_property(TEST config_non_standard_cgal_qt5 APPEND PROPERTY FIXTURES_SETUP test_config_file_4_target) + set_property(TEST install_non_standard_cgal_qt5 APPEND PROPERTY FIXTURES_SETUP test_config_file_4_target) + set_property(TEST test_config_file_4 APPEND PROPERTY FIXTURES_REQUIRED test_config_file_4_target) + + set_property(TEST install_non_standard_cgal_qt5 APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) + set_property(TEST config_non_standard_cgal_qt5 APPEND PROPERTY LABELS Installation_Tests CGAL_cmake_testsuite) +endif()#CGAL_Qt5_FOUND + diff --git a/Installation/test/Installation/cgal_test_with_cmake b/Installation/test/Installation/cgal_test_with_cmake new file mode 100755 index 00000000000..1180ebb0d1c --- /dev/null +++ b/Installation/test/Installation/cgal_test_with_cmake @@ -0,0 +1,53 @@ +#! /bin/sh + +# This is a script for the CGAL test suite. Such a script must obey +# the following rules: +# +# - the name of the script is cgal_test_with_cmake +# - for every target two one line messages are written to the file 'error.txt' +# the first one indicates if the compilation was successful +# the second one indicates if the execution was successful +# if one of the two was not successful, the line should start with 'ERROR:' +# - running the script should not require any user interaction +# - the script should clean up object files and executables + + ERRORFILE=error.txt + +#---------------------------------------------------------------------# +# remove the previous error file +#---------------------------------------------------------------------# + +rm -f ../$ERRORFILE +touch ../$ERRORFILE + +#---------------------------------------------------------------------# +# compile_and_run +#---------------------------------------------------------------------# +echo "Configuring... " +mkdir build_dir +cd build_dir +if eval 'cmake --no-warn-unused-cli ${INIT_FILE:+"-C${INIT_FILE}"} "$CMAKE_GENERATOR" -DRUNNING_CGAL_AUTO_TEST=TRUE \ + -DCGAL_DIR="$CGAL_RELEASE_DIR" -DBUILD_TESTING=ON -DWITH_tests=ON \ + ..' ; then + + echo " successful configuration" >> ../$ERRORFILE +else + echo " ERROR: configuration" >> ../$ERRORFILE +fi +cd .. + +#---------------------------------------------------------------------# +# configure, compile and run the tests +#---------------------------------------------------------------------# + +cd build_dir +ctest -L Installation_Tests -VV |tee res.txt +SUCCES="y" +FAILED=$(cat res.txt|grep "\*\*\*Failed") +if [ -z "$FAILED" ]; then + echo " successful run of Installation tests" >> ../$ERRORFILE +else + echo " ERROR: run of Installation tests" >> ../$ERRORFILE + SUCCES="" +fi +cat ../$ERRORFILE diff --git a/Installation/test/Installation/test_configuration.cmake.in b/Installation/test/Installation/test_configuration.cmake.in new file mode 100644 index 00000000000..c6b1a0074b9 --- /dev/null +++ b/Installation/test/Installation/test_configuration.cmake.in @@ -0,0 +1,14 @@ +project(test_configuration) +cmake_minimum_required(VERSION 3.1...3.15) +find_package(CGAL) +add_definitions(-DQT_NO_KEYWORDS) + +get_filename_component(CGAL_DIR_PATH "${CGAL_DIR}/CMakeConfig.cmake" DIRECTORY) +get_filename_component(CGAL_GIVEN_DIR_PATH "${CGAL_GIVEN_DIR}/CMakeConfig.cmake" DIRECTORY) + +if(NOT ${CGAL_DIR_PATH} STREQUAL ${CGAL_GIVEN_DIR_PATH}) + message("${CGAL_DIR_PATH} != ${CGAL_GIVEN_DIR_PATH}") + message( FATAL_ERROR "The CGAL_DIR is wrong !") +endif() +add_executable(test_configuration @CMAKE_CURRENT_SOURCE_DIR@/test_configuration.cpp) +target_link_libraries(test_configuration PUBLIC CGAL::CGAL) diff --git a/Installation/test/Installation/test_configuration.cpp b/Installation/test/Installation/test_configuration.cpp new file mode 100644 index 00000000000..8d38a435bc3 --- /dev/null +++ b/Installation/test/Installation/test_configuration.cpp @@ -0,0 +1,32 @@ +#include +#include +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_2 Point_2; +typedef Kernel::Segment_2 Segment_2; +int main() +{ + Point_2 p(1,1), q(10,10); + std::cout << "p = " << p << std::endl; + std::cout << "q = " << q.x() << " " << q.y() << std::endl; + std::cout << "sqdist(p,q) = " + << CGAL::squared_distance(p,q) << std::endl; + Segment_2 s(p,q); + Point_2 m(5, 9); + std::cout << "m = " << m << std::endl; + std::cout << "sqdist(Segment_2(p,q), m) = " + << CGAL::squared_distance(s,m) << std::endl; + std::cout << "p, q, and m "; + switch (CGAL::orientation(p,q,m)){ + case CGAL::COLLINEAR: + std::cout << "are collinear\n"; + break; + case CGAL::LEFT_TURN: + std::cout << "make a left turn\n"; + break; + case CGAL::RIGHT_TURN: + std::cout << "make a right turn\n"; + break; + } + std::cout << " midpoint(p,q) = " << CGAL::midpoint(p,q) << std::endl; + return 0; +} diff --git a/Installation/test/Installation/test_configuration_qt5.cmake.in b/Installation/test/Installation/test_configuration_qt5.cmake.in new file mode 100644 index 00000000000..0d99e60144d --- /dev/null +++ b/Installation/test/Installation/test_configuration_qt5.cmake.in @@ -0,0 +1,14 @@ +project(test_configuration) +cmake_minimum_required(VERSION 3.1...3.15) +find_package(CGAL COMPONENTS Qt5) +add_definitions(-DCGAL_USE_BASIC_VIEWER -DQT_NO_KEYWORDS) + +get_filename_component(CGAL_DIR_PATH "${CGAL_DIR}/CMakeConfig.cmake" DIRECTORY) +get_filename_component(CGAL_GIVEN_DIR_PATH "${CGAL_GIVEN_DIR}/CMakeConfig.cmake" DIRECTORY) + +if(NOT ${CGAL_DIR_PATH} STREQUAL ${CGAL_GIVEN_DIR_PATH}) + message("${CGAL_DIR_PATH} != ${CGAL_GIVEN_DIR_PATH}") + message( FATAL_ERROR "The CGAL_DIR is wrong !") +endif() +add_executable(test_configuration @CMAKE_CURRENT_SOURCE_DIR@/test_configuration_qt5.cpp) +target_link_libraries(test_configuration PUBLIC CGAL::CGAL CGAL::CGAL_Qt5) diff --git a/Installation/test/Installation/test_configuration_qt5.cpp b/Installation/test/Installation/test_configuration_qt5.cpp new file mode 100644 index 00000000000..af10e898b98 --- /dev/null +++ b/Installation/test/Installation/test_configuration_qt5.cpp @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include +#include +#include +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Triangulation_2 Triangulation; +typedef Triangulation::Point Point; + +template +typename CGAL::Coercion_traits::Type +binary_func(const A& a , const B& b){ + typedef CGAL::Coercion_traits CT; + CGAL_static_assertion((CT::Are_explicit_interoperable::value)); + typename CT::Cast cast; + return cast(a)*cast(b); +} + +int main(int argc, char**) { + std::cout<< binary_func(double(3), int(5)) << std::endl; + std::cout<< binary_func(int(3), double(5)) << std::endl; + std::ifstream in("data/triangulation_prog1.cin"); + std::istream_iterator begin(in); + std::istream_iterator end; + Triangulation t; + t.insert(begin, end); + if(argc == 3) // do not test Qt5 at runtime + CGAL::draw(t); + std::cout<<"OK."< class Line_2_Line_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, LINE}; + enum Intersection_results {NOT_COMPUTED_YET, NO_INTERSECTION, POINT, LINE}; Line_2_Line_2_pair(typename K::Line_2 const *line1, typename K::Line_2 const *line2) - : _line1(line1), _line2(line2), _known(false) {} + : _line1(line1), _line2(line2), _result(NOT_COMPUTED_YET) {} Intersection_results intersection_type() const; @@ -48,7 +48,6 @@ public: protected: typename K::Line_2 const* _line1; typename K::Line_2 const * _line2; - mutable bool _known; mutable Intersection_results _result; mutable typename K::Point_2 _intersection_point; }; @@ -141,11 +140,10 @@ typename Line_2_Line_2_pair::Intersection_results Line_2_Line_2_pair::intersection_type() const { typedef typename K::RT RT; - if (_known) + if (_result != NOT_COMPUTED_YET) return _result; RT nom1, nom2, denom; // The non const this pointer is used to cast away const. - _known = true; denom = _line1->a()*_line2->b() - _line2->a()*_line1->b(); if (denom == RT(0)) { if (RT(0) == (_line1->a()*_line2->c() - _line2->a()*_line1->c()) && @@ -180,7 +178,7 @@ template typename K::Point_2 Line_2_Line_2_pair::intersection_point() const { - if (!_known) + if (_result == NOT_COMPUTED_YET) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -190,7 +188,7 @@ template typename K::Line_2 Line_2_Line_2_pair::intersection_line() const { - if (!_known) + if (_result == NOT_COMPUTED_YET) 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 bfd102da8de..eada9a07ec2 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,10 +35,13 @@ namespace internal { template class Ray_2_Line_2_pair { public: - enum Intersection_results {NO_INTERSECTION, POINT, RAY}; + enum Intersection_results {NOT_COMPUTED_YET, NO_INTERSECTION, POINT, RAY}; + 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), _known(false) {} + : _ray(ray), _line(line), _result(NOT_COMPUTED_YET), + _intersection_point(K().construct_point_2_object()(ORIGIN)) + {} Intersection_results intersection_type() const; @@ -47,7 +50,6 @@ public: protected: typename K::Ray_2 const * _ray; typename K::Line_2 const * _line; - mutable bool _known; mutable Intersection_results _result; mutable typename K::Point_2 _intersection_point; }; @@ -94,7 +96,7 @@ intersection(const typename K::Line_2 &line, const typename K::Ray_2 &ray, const K& k) { - return internal::intersection(ray, line, k); + return internal::intersection(ray, line, k); } @@ -115,14 +117,14 @@ template typename Ray_2_Line_2_pair::Intersection_results Ray_2_Line_2_pair::intersection_type() const { - if (_known) + if (_result != NOT_COMPUTED_YET) return _result; // The non const this pointer is used to cast away const. - _known = true; const typename K::Line_2 &l1 = _ray->supporting_line(); Line_2_Line_2_pair linepair(&l1, _line); switch ( linepair.intersection_type()) { case Line_2_Line_2_pair::NO_INTERSECTION: + default: _result = NO_INTERSECTION; break; case Line_2_Line_2_pair::POINT: @@ -142,7 +144,7 @@ template typename K::Point_2 Ray_2_Line_2_pair::intersection_point() const { - if (!_known) + if (_result == NOT_COMPUTED_YET) intersection_type(); CGAL_kernel_assertion(_result == POINT); return _intersection_point; @@ -152,7 +154,7 @@ template typename K::Ray_2 Ray_2_Line_2_pair::intersection_ray() const { - if (!_known) + if (_result == NOT_COMPUTED_YET) intersection_type(); CGAL_kernel_assertion(_result == RAY); return *_ray; 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 663361e4eb9..ba3d8b9567c 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 @@ -308,6 +308,7 @@ Segment_2_Segment_2_pair::intersection_type() const Line_2_Line_2_pair linepair(&l1, &l2); switch ( linepair.intersection_type()) { case Line_2_Line_2_pair::NO_INTERSECTION: + default: _result = NO_INTERSECTION; break; case Line_2_Line_2_pair::POINT: diff --git a/Intersections_2/include/CGAL/Intersections_2/internal/Straight_2.h b/Intersections_2/include/CGAL/Intersections_2/internal/Straight_2.h index 47424bb3122..fa63e699475 100644 --- a/Intersections_2/include/CGAL/Intersections_2/internal/Straight_2.h +++ b/Intersections_2/include/CGAL/Intersections_2/internal/Straight_2.h @@ -275,6 +275,7 @@ cut_right_off(typename K::Line_2 const & cutter) Line_2_Line_2_pair pair(&support_, &cutter); switch (pair.intersection_type()) { case Line_2_Line_2_pair::NO_INTERSECTION: + default: if (cutter.has_on_negative_side(support_.point())) bound_state_ = LINE_EMPTY; break; diff --git a/Intersections_3/test/Intersections_3/tetrahedron.cpp b/Intersections_3/test/Intersections_3/tetrahedron.cpp index edcbc30a24f..2696eeef178 100644 --- a/Intersections_3/test/Intersections_3/tetrahedron.cpp +++ b/Intersections_3/test/Intersections_3/tetrahedron.cpp @@ -22,7 +22,16 @@ int main() { Point p(0,0,0), q(10,0,0), r(10,10,0), s(0, 10,10); Point p2(1,1,1), q2(20,20,20), r2(0,0,20); - Tetrahedron tet(p,q,r,s); + Tetrahedron tet(p,q,r,s), + tet2(p, Point(9,0,0), Point(15, 15, 0), Point(0, 15, 10)), + v_v(p,Point(-10,0,0),Point(-10,-10,0), Point(0,-10,-10)), + v_e(Point(-10,0,0), Point(0,0,10), Point(0,0,-10), Point(-10,10,0)), + v_f(Point(-10,0,0), Point(0,-10,-10), Point(0,-10,10), Point(0,10,0)), + e_e(Point(-10,0,0), Point(-15,0,0), Point(0,5,10), Point(0,10,5)), + e_f(Point(0,15,15), Point(-15,0,0), Point(0,-11,10), Point(0,10,-11)), + f_f(Point(10,10,10), q, r, s), + tet3(Point(-1,0,0), Point(-10,0,0), Point(-10,-10,0), Point(0,-10,-10)); + Sphere sp(p2,1.0); CGAL::do_intersect(tet,Triangle(p2,q2,r2)); @@ -52,5 +61,16 @@ int main() CGAL::do_intersect(Ray(p2,q2), sp); CGAL::do_intersect(Segment(p2,q2), sp); + CGAL_assertion(CGAL::do_intersect(tet, v_e)); + CGAL_assertion(CGAL::do_intersect(tet, v_f)); + CGAL_assertion(CGAL::do_intersect(tet, v_v)); + CGAL_assertion(CGAL::do_intersect(tet, tet2)); + CGAL_assertion(CGAL::do_intersect(tet, e_e)); + CGAL_assertion(CGAL::do_intersect(tet, e_f)); + CGAL_assertion(CGAL::do_intersect(tet, f_f)); + + CGAL_assertion(!CGAL::do_intersect(tet, tet3)); + + return 0; } diff --git a/Kernel_23/examples/Kernel_23/MyPointC2.h b/Kernel_23/examples/Kernel_23/MyPointC2.h index de1c7ee6cd6..e4b2f3ff0ce 100644 --- a/Kernel_23/examples/Kernel_23/MyPointC2.h +++ b/Kernel_23/examples/Kernel_23/MyPointC2.h @@ -21,7 +21,6 @@ public: *(vec+1) = 0; } - MyPointC2(const double x, const double y, int c = 0) : col(c) { diff --git a/Kernel_23/include/CGAL/enum.h b/Kernel_23/include/CGAL/enum.h index 0a6651bdf68..a27ff99662d 100644 --- a/Kernel_23/include/CGAL/enum.h +++ b/Kernel_23/include/CGAL/enum.h @@ -99,29 +99,11 @@ enum Box_parameter_space_2 EXTERIOR }; - - -#ifdef CGAL_CFG_MATCHING_BUG_5 - -template < typename T, typename U > -inline -T enum_cast_bug(const U& u, const T*) -{ return static_cast(u); } - -template < typename T, typename U > -inline -typename Same_uncertainty::type enum_cast(const U& u) -{ return enum_cast_bug(u, (const T*)0); } - -#else - template < typename T, typename U > inline T enum_cast(const U& u) { return static_cast(u); } -#endif - } //namespace CGAL #endif // CGAL_ENUM_H diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h index eb43e4c69e9..61c3fb800c5 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epeck_d.h @@ -149,9 +149,26 @@ public: template Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Weighted_point_d&p); }; +class Construct_power_sphere_d { +public: +/*! returns a weighted point on the affine hull of the weighted points of `A=tuple[first,last)` at power distance 0 of each of them. In other words, this returns the smallest sphere orthogonal to the spheres of A. + \pre A is affinely independent. + \tparam ForwardIterator has `Epeck_d::Weighted_point_d` as value type. + */ +template +Weighted_point_d operator()(ForwardIterator first, ForwardIterator last); +}; +class Compute_power_product_d { +public: +/*! returns the power product (aka power distance) of the weighted points `pw` and `qw`, that is, the squared Euclidean distance between the points minus their weights. + */ +FT operator()(Weighted_point_d pw, Weighted_point_d qw); +}; Construct_circumcenter_d construct_circumcenter_d_object(); +Compute_power_product_d compute_power_product_d_object(); Compute_squared_radius_d compute_squared_radius_d_object(); Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object(); +Construct_power_sphere_d construct_power_sphere_d_object(); Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object(); }; /* end Epeck_d */ } /* end namespace CGAL */ diff --git a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h index 50295d58d96..4d682670ebf 100644 --- a/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h +++ b/Kernel_d/doc/Kernel_d/CGAL/Epick_d.h @@ -138,9 +138,26 @@ public: template Bounded_side operator()(ForwardIterator first, ForwardIterator last, const Weighted_point_d&p); }; +class Construct_power_sphere_d { +public: +/*! returns a weighted point on the affine hull of the weighted points of `A=tuple[first,last)` at power distance 0 of each of them. In other words, this returns the smallest sphere orthogonal to the spheres of A. + \pre A is affinely independent. + \tparam ForwardIterator has `Epick_d::Weighted_point_d` as value type. + */ +template +Weighted_point_d operator()(ForwardIterator first, ForwardIterator last); +}; +class Compute_power_product_d { +public: +/*! returns the power product (aka power distance) of the weighted points `pw` and `qw`, that is, the squared Euclidean distance between the points minus their weights. + */ +FT operator()(Weighted_point_d pw, Weighted_point_d qw); +}; Construct_circumcenter_d construct_circumcenter_d_object(); +Compute_power_product_d compute_power_product_d_object(); Compute_squared_radius_d compute_squared_radius_d_object(); Compute_squared_radius_smallest_orthogonal_sphere_d compute_squared_radius_smallest_orthogonal_sphere_d_object(); +Construct_power_sphere_d construct_power_sphere_d_object(); Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object(); }; /* end Epick_d */ } /* end namespace CGAL */ diff --git a/Mesh_3/examples/Mesh_3/CMakeLists.txt b/Mesh_3/examples/Mesh_3/CMakeLists.txt index a97ae6fcb26..21f3eba968c 100644 --- a/Mesh_3/examples/Mesh_3/CMakeLists.txt +++ b/Mesh_3/examples/Mesh_3/CMakeLists.txt @@ -64,6 +64,12 @@ target_link_libraries(mesh_cubes_intersection_with_features PUBLIC CGAL::Eigen_s create_single_source_cgal_program( "mesh_implicit_domains.cpp" "implicit_functions.cpp" ) target_link_libraries(mesh_implicit_domains PUBLIC CGAL::Eigen_support) +find_package( ITT QUIET ) +if(TARGET ITT::ITT) + target_link_libraries(mesh_implicit_domains PRIVATE ITT::ITT) + target_compile_definitions(mesh_implicit_domains PRIVATE CGAL_MESH_3_USE_INTEL_ITT) +endif() + create_single_source_cgal_program( "mesh_polyhedral_domain.cpp" ) target_link_libraries(mesh_polyhedral_domain PUBLIC CGAL::Eigen_support) @@ -129,6 +135,7 @@ if( TARGET CGAL::CGAL_ImageIO) else() message( STATUS "NOTICE: The examples mesh_3D_image.cpp, mesh_3D_image_variable_size.cpp, mesh_optimization_example.cpp and mesh_optimization_lloyd_example.cpp need CGAL_ImageIO to be configured with ZLIB support, and will not be compiled." ) endif() + else() message( STATUS "NOTICE: Some examples need the CGAL_ImageIO library, and will not be compiled." ) endif() diff --git a/Mesh_3/examples/Mesh_3/mesh_implicit_domains.cpp b/Mesh_3/examples/Mesh_3/mesh_implicit_domains.cpp index 6f0823b6f8c..efb5ea0f743 100644 --- a/Mesh_3/examples/Mesh_3/mesh_implicit_domains.cpp +++ b/Mesh_3/examples/Mesh_3/mesh_implicit_domains.cpp @@ -14,6 +14,12 @@ using namespace CGAL::parameters; +#ifdef CGAL_CONCURRENT_MESH_3 +typedef CGAL::Parallel_tag Concurrency_tag; +#else +typedef CGAL::Sequential_tag Concurrency_tag; +#endif + // Domain typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef FT_to_point_function_wrapper Function; @@ -23,7 +29,7 @@ typedef Function_wrapper::Function_vector Function_vector; typedef CGAL::Labeled_mesh_domain_3 Mesh_domain; // Triangulation -typedef CGAL::Mesh_triangulation_3::type Tr; +typedef CGAL::Mesh_triangulation_3::type Tr; typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; // Mesh Criteria diff --git a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h index 42b0de9a66f..13fd9f70083 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -98,12 +98,9 @@ namespace CGAL { // Base for Compact_mesh_cell_base_3, with specializations // for different values of Concurrency_tag // Sequential -template +template class Compact_mesh_cell_base_3_base { - typedef typename GT::Point_3 Point_3; - typedef typename GT::Weighted_point_3 Point; - protected: Compact_mesh_cell_base_3_base() : bits_(0) @@ -176,11 +173,9 @@ protected: #ifdef CGAL_LINKED_WITH_TBB // Class Compact_mesh_cell_base_3_base // Specialization for parallel -template -class Compact_mesh_cell_base_3_base +template +class Compact_mesh_cell_base_3_base { - typedef typename GT::Point_3 Point_3; - protected: Compact_mesh_cell_base_3_base() { @@ -260,14 +255,16 @@ protected: // Class Compact_mesh_cell_base_3 // Cell base class used in 3D meshing process. // Adds information to Cb about the cell of the input complex containing it -template< class GT, - class MD, - class TDS = void > -class Compact_mesh_cell_base_3 - : public Compact_mesh_cell_base_3_base +template< class Point_3, + class Weighted_point_3, + class Subdomain_index_, + class Surface_patch_index_, + class Index_, + class TDS> +class Compact_mesh_cell_3 + : public Compact_mesh_cell_base_3_base { - typedef typename GT::FT FT; - typedef Compact_mesh_cell_base_3_base Base; + typedef Compact_mesh_cell_base_3_base Base; using Base::weighted_circumcenter_; public: @@ -279,20 +276,12 @@ public: typedef typename TDS::Cell_data TDS_data; - template - struct Rebind_TDS { - typedef Compact_mesh_cell_base_3 Other; - }; - - // Index Type - typedef typename MD::Subdomain_index Subdomain_index; - typedef typename MD::Surface_patch_index Surface_patch_index; - typedef typename MD::Index Index; + typedef Subdomain_index_ Subdomain_index; + typedef Surface_patch_index_ Surface_patch_index; + typedef Index_ Index; - typedef GT Geom_traits; - typedef typename GT::Point_3 Point_3; - typedef typename GT::Weighted_point_3 Point; + typedef Weighted_point_3 Point; typedef Point* Point_container; @@ -310,20 +299,10 @@ public: public: // Constructors - Compact_mesh_cell_base_3() - : surface_index_table_() - , surface_center_table_() -#ifdef CGAL_INTRUSIVE_LIST - , next_intrusive_() - , previous_intrusive_() -#endif - , surface_center_index_table_() - , sliver_value_(FT(0.)) - , subdomain_index_() - , sliver_cache_validity_(false) + Compact_mesh_cell_3() {} - Compact_mesh_cell_base_3(const Compact_mesh_cell_base_3& rhs) + Compact_mesh_cell_3(const Compact_mesh_cell_3& rhs) : N(rhs.N) , V(rhs.V) #ifdef CGAL_INTRUSIVE_LIST @@ -342,49 +321,29 @@ public: } } - Compact_mesh_cell_base_3 (Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3) - : surface_index_table_() - , surface_center_table_() - , V(CGAL::make_array(v0, v1, v2, v3)) -#ifdef CGAL_INTRUSIVE_LIST - , next_intrusive_() - , previous_intrusive_() -#endif - , surface_center_index_table_() - , sliver_value_(FT(0.)) - , subdomain_index_() - , sliver_cache_validity_(false) + Compact_mesh_cell_3 (Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3) + : V(CGAL::make_array(v0, v1, v2, v3)) { } - Compact_mesh_cell_base_3 (Vertex_handle v0, - Vertex_handle v1, - Vertex_handle v2, - Vertex_handle v3, - Cell_handle n0, - Cell_handle n1, - Cell_handle n2, - Cell_handle n3) - : surface_index_table_() - , surface_center_table_() - , N(CGAL::make_array(n0, n1, n2, n3)) + Compact_mesh_cell_3 (Vertex_handle v0, + Vertex_handle v1, + Vertex_handle v2, + Vertex_handle v3, + Cell_handle n0, + Cell_handle n1, + Cell_handle n2, + Cell_handle n3) + : N(CGAL::make_array(n0, n1, n2, n3)) , V(CGAL::make_array(v0, v1, v2, v3)) -#ifdef CGAL_INTRUSIVE_LIST - , next_intrusive_() - , previous_intrusive_() -#endif - , surface_center_index_table_() - , sliver_value_(FT(0.)) - , subdomain_index_() - , sliver_cache_validity_(false) { } - ~Compact_mesh_cell_base_3() + ~Compact_mesh_cell_3() { if(!internal_tbb::is_null(weighted_circumcenter_)){ internal_tbb::delete_circumcenter(weighted_circumcenter_); @@ -550,11 +509,6 @@ public: return *weighted_circumcenter_; } - const Point_3& weighted_circumcenter() const - { - return weighted_circumcenter(Geom_traits()); - } - // Returns the index of the cell of the input complex that contains the cell Subdomain_index subdomain_index() const { return subdomain_index_; } @@ -562,13 +516,13 @@ public: void set_subdomain_index(const Subdomain_index& index) { subdomain_index_ = index; } - void set_sliver_value(const FT& value) + void set_sliver_value(double value) { sliver_cache_validity_ = true; sliver_value_ = value; } - const FT& sliver_value() const + double sliver_value() const { CGAL_assertion(is_cache_valid()); return sliver_value_; @@ -646,6 +600,7 @@ public: static std::string io_signature() { + using Geom_traits = typename Kernel_traits::type; return Get_io_signature()() + "+" + Get_io_signature >()() @@ -683,81 +638,81 @@ private: /// Stores surface_index for each facet of the cell - std::array surface_index_table_; + std::array surface_index_table_ = {}; /// Stores surface center of each facet of the cell - std::array surface_center_table_; + std::array surface_center_table_ = {}; /// Stores surface center index of each facet of the cell std::array N; std::array V; #ifdef CGAL_INTRUSIVE_LIST - Cell_handle next_intrusive_, previous_intrusive_; + Cell_handle next_intrusive_ = {}, previous_intrusive_ = {}; #endif std::size_t time_stamp_; - std::array surface_center_index_table_; + std::array surface_center_index_table_ = {}; /// Stores visited facets (4 first bits) // Point_container _hidden; - FT sliver_value_; + double sliver_value_ = 0.; // The index of the cell of the input complex that contains me - Subdomain_index subdomain_index_; + Subdomain_index subdomain_index_ = {}; TDS_data _tds_data; - mutable bool sliver_cache_validity_; + mutable bool sliver_cache_validity_ = false; +public: -}; // end class Compact_mesh_cell_base_3 - -template < class GT, class MT, class Cb > -std::istream& -operator>>(std::istream &is, - Compact_mesh_cell_base_3 &c) -{ - typename Compact_mesh_cell_base_3::Subdomain_index index; - if(is_ascii(is)) - is >> index; - else - read(is, index); - if(is) { - c.set_subdomain_index(index); - for(int i = 0; i < 4; ++i) - { - typename Compact_mesh_cell_base_3::Surface_patch_index i2; - if(is_ascii(is)) - is >> iformat(i2); - else - { - read(is, i2); - } - c.set_surface_patch_index(i, i2); + friend std::istream& operator>>(std::istream &is, Compact_mesh_cell_3 &c) + { + Subdomain_index index; + if(is_ascii(is)) + is >> index; + else + read(is, index); + if(is) { + c.set_subdomain_index(index); + for(int i = 0; i < 4; ++i) + { + Surface_patch_index i2; + if(is_ascii(is)) + is >> iformat(i2); + else + { + read(is, i2); + } + c.set_surface_patch_index(i, i2); + } } + return is; } - return is; -} -template < class GT, class MT, class Cb > -std::ostream& -operator<<(std::ostream &os, - const Compact_mesh_cell_base_3 &c) -{ - if(is_ascii(os)) - os << c.subdomain_index(); - else - write(os, c.subdomain_index()); - for(int i = 0; i < 4; ++i) + friend + std::ostream& operator<<(std::ostream &os, const Compact_mesh_cell_3 &c) { if(is_ascii(os)) - os << ' ' << oformat(c.surface_patch_index(i)); + os << c.subdomain_index(); else - write(os, c.surface_patch_index(i)); + write(os, c.subdomain_index()); + for(int i = 0; i < 4; ++i) + { + if(is_ascii(os)) + os << ' ' << oformat(c.surface_patch_index(i)); + else + write(os, c.surface_patch_index(i)); + } + return os; } - return os; -} +}; // end class Compact_mesh_cell_3 + +template< class GT, + class MD, + class TDS = void > +class Compact_mesh_cell_base_3; // Specialization for void. template @@ -768,7 +723,35 @@ public: typedef Triangulation_data_structure::Vertex_handle Vertex_handle; typedef Triangulation_data_structure::Cell_handle Cell_handle; template - struct Rebind_TDS { typedef Compact_mesh_cell_base_3 Other; }; + struct Rebind_TDS { + typedef Compact_mesh_cell_3 Other; + }; +}; + +template +class Compact_mesh_cell_generator_3 +{ +public: + typedef internal::Dummy_tds_3 Triangulation_data_structure; + typedef Triangulation_data_structure::Vertex_handle Vertex_handle; + typedef Triangulation_data_structure::Cell_handle Cell_handle; + template + struct Rebind_TDS { + typedef Compact_mesh_cell_3 Other; + }; }; } // end namespace CGAL diff --git a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h index 2c162e7cc61..49217739942 100644 --- a/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h +++ b/Mesh_3/include/CGAL/Mesh_3/C3T3_helpers.h @@ -3648,10 +3648,17 @@ incident_slivers(const Vertex_handle& v, std::vector incident_cells_; tr_.incident_cells(v, std::back_inserter(incident_cells_)); +#ifdef CGAL_CXX17 + std::remove_copy_if(incident_cells_.begin(), + incident_cells_.end(), + out, + std::not_fn(Is_sliver(c3t3_, criterion, sliver_bound))); +#else std::remove_copy_if(incident_cells_.begin(), incident_cells_.end(), out, std::not1(Is_sliver(c3t3_,criterion,sliver_bound))); +#endif return out; } diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h index a43b7bb1d24..60d0276330d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_global_optimizer.h @@ -426,7 +426,7 @@ private: } if ( m_mgo.is_time_limit_reached() ) - tbb::task::self().cancel_group_execution(); + m_mgo.cancel_group_execution(); } }; @@ -539,12 +539,16 @@ private: // restricted delaunay if ( m_mgo.is_time_limit_reached() ) { - tbb::task::self().cancel_group_execution(); + m_mgo.cancel_group_execution(); break; } } } }; + + void cancel_group_execution() { + tbb_task_group_context.cancel_group_execution(); + } #endif // CGAL_LINKED_WITH_TBB // ----------------------------------- @@ -567,6 +571,9 @@ private: #ifdef CGAL_MESH_3_OPTIMIZER_VERBOSE mutable FT sum_moves_; #endif +#ifdef CGAL_LINKED_WITH_TBB + tbb::task_group_context tbb_task_group_context; +#endif }; @@ -935,6 +942,7 @@ update_mesh(const Moves_vector& moves, Self, C3T3_helpers, Tr, Moves_vector, Moving_vertices_set, Outdated_cell_set>( *this, helper_, moves, moving_vertices, outdated_cells) + , tbb_task_group_context ); } // Sequential diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h index fb54c96a4ae..0d81d7a8455 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_3.h @@ -25,6 +25,15 @@ #include +#if CGAL_MESH_3_USE_INTEL_ITT +# include +# define CGAL_MESH_3_TASK_BEGIN(task_handle) __itt_task_begin(mesh_3_domain, __itt_null, __itt_null, task_handle); +# define CGAL_MESH_3_TASK_END(task_handle) __itt_task_end(mesh_3_domain); +#else +# define CGAL_MESH_3_TASK_BEGIN(task_handle) +# define CGAL_MESH_3_TASK_END(task_handle) +#endif + #include #include @@ -406,6 +415,13 @@ refine_mesh(std::string dump_after_refine_surface_prefix) CGAL::Real_timer timer; timer.start(); double elapsed_time = 0.; +#if CGAL_MESH_3_USE_INTEL_ITT + auto mesh_3_domain = __itt_domain_create("org.cgal.Mesh_3.refine_mesh"); + auto initialize_task_handle = __itt_string_handle_create("Mesher_3::initialize"); + auto refine_surface_mesh_task_handle = __itt_string_handle_create("Mesher_3 refine surface mesh"); + auto scan_cells_task_handle = __itt_string_handle_create("Mesher_3 scan triangulation for bad cells"); + auto refine_volume_mesh_task_handle = __itt_string_handle_create("Mesher_3 refine volume mesh"); +#endif // CGAL_MESH_3_USE_INTEL_ITT // First surface mesh could modify c3t3 without notifying cells_mesher // So we have to ensure that no old cell will be left in c3t3 @@ -419,12 +435,15 @@ refine_mesh(std::string dump_after_refine_surface_prefix) #ifndef CGAL_MESH_3_VERBOSE // Scan surface and refine it + CGAL_MESH_3_TASK_BEGIN(initialize_task_handle); initialize(); + CGAL_MESH_3_TASK_END(initialize_task_handle); #ifdef CGAL_MESH_3_PROFILING std::cerr << "Refining facets..." << std::endl; WallClockTimer t; #endif + CGAL_MESH_3_TASK_BEGIN(refine_surface_mesh_task_handle); facets_mesher_.refine(facets_visitor_); facets_mesher_.scan_edges(); refinement_stage = REFINE_FACETS_AND_EDGES; @@ -432,6 +451,7 @@ refine_mesh(std::string dump_after_refine_surface_prefix) facets_mesher_.scan_vertices(); refinement_stage = REFINE_FACETS_AND_EDGES_AND_VERTICES; facets_mesher_.refine(facets_visitor_); + CGAL_MESH_3_TASK_END(refine_surface_mesh_task_handle); #ifdef CGAL_MESH_3_PROFILING double facet_ref_time = t.elapsed(); std::cerr << "==== Facet refinement: " << facet_ref_time << " seconds ====" @@ -464,13 +484,17 @@ refine_mesh(std::string dump_after_refine_surface_prefix) if(!forced_stop()) { // Then scan volume and refine it + CGAL_MESH_3_TASK_BEGIN(scan_cells_task_handle); cells_mesher_.scan_triangulation(); + CGAL_MESH_3_TASK_END(scan_cells_task_handle); refinement_stage = REFINE_ALL; #ifdef CGAL_MESH_3_PROFILING std::cerr << "Refining cells..." << std::endl; t.reset(); #endif + CGAL_MESH_3_TASK_BEGIN(refine_volume_mesh_task_handle); cells_mesher_.refine(cells_visitor_); + CGAL_MESH_3_TASK_END(refine_volume_mesh_task_handle); #ifdef CGAL_MESH_3_PROFILING double cell_ref_time = t.elapsed(); std::cerr << "==== Cell refinement: " << cell_ref_time << " seconds ====" @@ -493,7 +517,9 @@ refine_mesh(std::string dump_after_refine_surface_prefix) } // end test of `maximal_number_of_vertices` #else // ifdef CGAL_MESH_3_VERBOSE std::cerr << "Start surface scan..."; + CGAL_MESH_3_TASK_BEGIN(initialize_task_handle); initialize(); + CGAL_MESH_3_TASK_END(initialize_task_handle); std::cerr << "end scan. [Bad facets:" << facets_mesher_.size() << "]"; std::cerr << std::endl << std::endl; elapsed_time += timer.time(); @@ -509,6 +535,7 @@ refine_mesh(std::string dump_after_refine_surface_prefix) std::cerr << "(" << r_tr.number_of_vertices() << "," << nbsteps << "," << cells_mesher_.debug_info() << ")"; + CGAL_MESH_3_TASK_BEGIN(refine_surface_mesh_task_handle); while ( ! facets_mesher_.is_algorithm_done() && ! forced_stop() ) { @@ -535,6 +562,7 @@ refine_mesh(std::string dump_after_refine_surface_prefix) } ++nbsteps; } + CGAL_MESH_3_TASK_END(refine_surface_mesh_task_handle); std::cerr << std::endl; std::cerr << "Total refining surface time: " << timer.time() << "s" << std::endl; std::cerr << std::endl; @@ -548,7 +576,9 @@ refine_mesh(std::string dump_after_refine_surface_prefix) facets_visitor_.activate(); dump_c3t3(r_c3t3_, dump_after_refine_surface_prefix); std::cerr << "Start volume scan..."; + CGAL_MESH_3_TASK_BEGIN(scan_cells_task_handle); cells_mesher_.scan_triangulation(); + CGAL_MESH_3_TASK_END(scan_cells_task_handle); refinement_stage = REFINE_ALL; std::cerr << "end scan. [Bad tets:" << cells_mesher_.size() << "]"; std::cerr << std::endl << std::endl; @@ -562,6 +592,7 @@ refine_mesh(std::string dump_after_refine_surface_prefix) std::cerr << "(" << r_tr.number_of_vertices() << "," << nbsteps << "," << cells_mesher_.debug_info() << ")"; + CGAL_MESH_3_TASK_BEGIN(refine_volume_mesh_task_handle); while ( ! cells_mesher_.is_algorithm_done() && ! forced_stop() ) { @@ -574,6 +605,7 @@ refine_mesh(std::string dump_after_refine_surface_prefix) % (nbsteps / timer.time()); ++nbsteps; } + CGAL_MESH_3_TASK_END(refine_volume_mesh_task_handle); std::cerr << std::endl; std::cerr << "Total refining volume time: " << timer.time() << "s" << std::endl; @@ -815,8 +847,6 @@ status() const { #ifdef CGAL_LINKED_WITH_TBB if(boost::is_convertible::value) { - const WorksharingDataStructureType* ws_ds = - this->get_worksharing_data_structure(); return Mesher_status( # if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE approximate_number_of_vertices(Concurrency_tag()), @@ -825,7 +855,7 @@ status() const approximate_number_of_vertices(CGAL::Sequential_tag()), #endif 0, - ws_ds->approximate_number_of_enqueued_element()); + 0); } else #endif // with TBB diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h index 3b59efebbd9..b0b7c00229c 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesher_level.h @@ -34,7 +34,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -# include +# include #endif #include @@ -748,7 +748,7 @@ public: Concurrent_mesher_config::get().refinement_batch_size) , m_lock_ds(0) , m_worksharing_ds(0) - , m_empty_root_task(0) + , m_task_group(0) #ifndef CGAL_NO_ATOMIC , m_stop_ptr(0) #endif @@ -875,13 +875,13 @@ public: void enqueue_task( const Container_element &ce, const Quality &quality, Mesh_visitor visitor) { - CGAL_assertion(m_empty_root_task != 0); + CGAL_assertion(m_task_group != 0); m_worksharing_ds->enqueue_work( Enqueue_element( *this, ce, quality, visitor), quality, - *m_empty_root_task + *m_task_group // NOTE: if you uncomment this line (Load_based_worksharing_ds), the element may // be a zombie at this point => thus, it may be "infinite" and cause an assertion error // in debug mode when computing the circumcenter @@ -905,8 +905,7 @@ public: previous_level.add_to_TLS_lists(true); add_to_TLS_lists(true); - m_empty_root_task = new( tbb::task::allocate_root() ) tbb::empty_task; - m_empty_root_task->set_ref_count(1); + m_task_group = new tbb::task_group; while (!no_longer_element_to_refine()) { @@ -915,7 +914,7 @@ public: enqueue_task(qe.second, qe.first, visitor); } - m_empty_root_task->wait_for_all(); + m_task_group->wait(); #if defined(CGAL_MESH_3_VERBOSE) || defined(CGAL_MESH_3_PROFILING) std::cerr << " Flushing"; @@ -923,16 +922,15 @@ public: bool keep_flushing = true; while (keep_flushing) { - m_empty_root_task->set_ref_count(1); - keep_flushing = m_worksharing_ds->flush_work_buffers(*m_empty_root_task); - m_empty_root_task->wait_for_all(); + keep_flushing = m_worksharing_ds->flush_work_buffers(*m_task_group); + m_task_group->wait(); #if defined(CGAL_MESH_3_VERBOSE) || defined(CGAL_MESH_3_PROFILING) std::cerr << "."; #endif } - tbb::task::destroy(*m_empty_root_task); - m_empty_root_task = 0; + delete m_task_group; + m_task_group = 0; splice_local_lists(); //previous_level.splice_local_lists(); // useless @@ -1160,8 +1158,8 @@ public: if(m_stop_ptr != 0 && m_stop_ptr->load(CGAL::cpp11::memory_order_acquire) == true) { - CGAL_assertion(m_empty_root_task != 0); - m_empty_root_task->cancel_group_execution(); + CGAL_assertion(m_task_group != 0); + m_task_group->cancel(); return true; } #endif // not defined CGAL_NO_ATOMIC @@ -1177,7 +1175,7 @@ protected: Lock_data_structure *m_lock_ds; WorksharingDataStructureType *m_worksharing_ds; - tbb::task *m_empty_root_task; + tbb::task_group *m_task_group; #ifndef CGAL_NO_ATOMIC CGAL::cpp11::atomic* m_stop_ptr; #endif diff --git a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h index b7b90c2e4ed..25783f027d2 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Refine_facets_3.h @@ -477,6 +477,12 @@ protected: /// Insert facet into refinement queue void insert_bad_facet(Facet facet, const Quality& quality) { +#if CGAL_MESH_3_VERY_VERBOSE + std::stringstream s; + s << "insert_bad_facet(" << debug_info_element_impl(facet) << ", ...) by thread " + << std::this_thread::get_id() << '\n'; + std::cerr << s.str(); +#endif // Insert the facet and its mirror this->add_bad_element( this->from_facet_to_refinement_queue_element(facet, mirror_facet(facet)), diff --git a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h index ac6e886e4a3..6cea47bc0b0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h +++ b/Mesh_3/include/CGAL/Mesh_3/Sliver_perturber.h @@ -53,7 +53,7 @@ #endif #ifdef CGAL_LINKED_WITH_TBB -# include +# include #endif #include @@ -335,10 +335,10 @@ protected: Lock_data_structure * get_lock_data_structure() const { return 0; } void unlock_all_elements() const {} - void create_root_task() const {} + void create_task_group() const {} bool flush_work_buffers() const { return true; } void wait_for_all() const {} - void destroy_root_task() const {} + void destroy_trask_group() const {} template void enqueue_work(Func, const PVertex &) const {} @@ -373,36 +373,34 @@ protected: m_lock_ds.unlock_all_points_locked_by_this_thread(); } - void create_root_task() const + void create_task_group() const { - m_empty_root_task = new( tbb::task::allocate_root() ) tbb::empty_task; - m_empty_root_task->set_ref_count(1); + m_task_group = new tbb::task_group; } bool flush_work_buffers() const { - m_empty_root_task->set_ref_count(1); - bool keep_flushing = m_worksharing_ds.flush_work_buffers(*m_empty_root_task); + bool keep_flushing = m_worksharing_ds.flush_work_buffers(*m_task_group); wait_for_all(); return keep_flushing; } void wait_for_all() const { - m_empty_root_task->wait_for_all(); + m_task_group->wait(); } - void destroy_root_task() const + void destroy_trask_group() const { - tbb::task::destroy(*m_empty_root_task); - m_empty_root_task = 0; + delete m_task_group; + m_task_group = 0; } template void enqueue_work(Func f, const PVertex &pv) const { - CGAL_assertion(m_empty_root_task != 0); - m_worksharing_ds.enqueue_work(f, pv, *m_empty_root_task); + CGAL_assertion(m_task_group != 0); + m_worksharing_ds.enqueue_work(f, pv, *m_task_group); } void increment_erase_counter(const Vertex_handle &vh) const @@ -410,12 +408,16 @@ protected: vh->increment_erase_counter(); } + void cancel() const { + return m_task_group->cancel(); + } + public: protected: mutable Lock_data_structure m_lock_ds; mutable Mesh_3::Auto_worksharing_ds m_worksharing_ds; - mutable tbb::task *m_empty_root_task; + mutable tbb::task_group *m_task_group; }; #endif // CGAL_LINKED_WITH_TBB @@ -704,7 +706,7 @@ private: } while (!could_lock_zone); if ( m_sliver_perturber.is_time_limit_reached() ) - tbb::task::self().cancel_group_execution(); + m_sliver_perturber.cancel(); } }; #endif @@ -933,7 +935,7 @@ perturb(const FT& sliver_bound, PQueue& pqueue, Visitor& visitor) const // Parallel if (boost::is_convertible::value) { - this->create_root_task(); + this->create_task_group(); while (pqueue.size() > 0) { @@ -957,7 +959,7 @@ perturb(const FT& sliver_bound, PQueue& pqueue, Visitor& visitor) const # endif } - this->destroy_root_task(); + this->destroy_trask_group(); } // Sequential else diff --git a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h index d97c90cf79d..ecc9607774f 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h +++ b/Mesh_3/include/CGAL/Mesh_3/Slivers_exuder.h @@ -55,7 +55,7 @@ #endif #ifdef CGAL_LINKED_WITH_TBB -# include +# include #endif @@ -122,10 +122,10 @@ protected: Lock_data_structure * get_lock_data_structure() const { return 0; } void unlock_all_elements() const {} - void create_root_task() const {} + void create_task_group() const {} bool flush_work_buffers() const { return true; } void wait_for_all() const {} - void destroy_root_task() const {} + void destroy_trask_group() const {} template void enqueue_work(Func, FT) const {} @@ -225,36 +225,34 @@ protected: m_lock_ds.unlock_all_points_locked_by_this_thread(); } - void create_root_task() const + void create_task_group() const { - m_empty_root_task = new( tbb::task::allocate_root() ) tbb::empty_task; - m_empty_root_task->set_ref_count(1); + m_task_group = new tbb::task_group; } bool flush_work_buffers() const { - m_empty_root_task->set_ref_count(1); - bool keep_flushing = m_worksharing_ds.flush_work_buffers(*m_empty_root_task); + bool keep_flushing = m_worksharing_ds.flush_work_buffers(*m_task_group); wait_for_all(); return keep_flushing; } void wait_for_all() const { - m_empty_root_task->wait_for_all(); + m_task_group->wait(); } - void destroy_root_task() const + void destroy_trask_group() const { - tbb::task::destroy(*m_empty_root_task); - m_empty_root_task = 0; + delete m_task_group; + m_task_group = 0; } template void enqueue_work(Func f, FT value) const { - CGAL_assertion(m_empty_root_task != 0); - m_worksharing_ds.enqueue_work(f, value, *m_empty_root_task); + CGAL_assertion(m_task_group != 0); + m_worksharing_ds.enqueue_work(f, value, *m_task_group); } public: @@ -311,9 +309,14 @@ protected: Erase_from_queue(cells_queue_)); } + void cancel() { + CGAL_assertion(m_task_group != nullptr); + m_task_group->cancel(); + } + mutable Lock_data_structure m_lock_ds; mutable Mesh_3::Auto_worksharing_ds m_worksharing_ds; - mutable tbb::task *m_empty_root_task; + mutable tbb::task_group *m_task_group; private: Tet_priority_queue cells_queue_; @@ -781,7 +784,7 @@ private: } if ( m_sliver_exuder.is_time_limit_reached() ) - tbb::task::self().cancel_group_execution(); + m_sliver_exuder.cancel(); } }; #endif @@ -920,7 +923,7 @@ pump_vertices(FT sliver_criterion_limit, // Parallel if (boost::is_convertible::value) { - this->create_root_task(); + this->create_task_group(); while (!this->cells_queue_empty()) { @@ -947,7 +950,7 @@ pump_vertices(FT sliver_criterion_limit, # endif } - this->destroy_root_task(); + this->destroy_trask_group(); } // Sequential else diff --git a/Mesh_3/include/CGAL/Mesh_3/Worksharing_data_structures.h b/Mesh_3/include/CGAL/Mesh_3/Worksharing_data_structures.h index 32b5816c83c..827ded14bdc 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Worksharing_data_structures.h +++ b/Mesh_3/include/CGAL/Mesh_3/Worksharing_data_structures.h @@ -23,7 +23,7 @@ #include #include -#include +#include #include #include #include @@ -267,7 +267,7 @@ public: virtual ~WorkItem() { } // Derived class defines the actual work. - virtual void run() = 0; + virtual void operator()() const = 0; virtual bool less_than(const WorkItem &) const = 0; }; @@ -294,16 +294,17 @@ public: : m_func(func), m_quality(quality) {} - virtual ~MeshRefinementWorkItem() + ~MeshRefinementWorkItem() override {} - void run() + void operator()() const override { m_func(); - tbb::scalable_allocator >().deallocate(this, 1); + tbb::scalable_allocator().deallocate( + const_cast(this), 1); } - bool less_than (const WorkItem &other) const + bool less_than (const WorkItem &other) const override { /*try { @@ -341,14 +342,17 @@ public: : m_func(func) {} - void run() + ~SimpleFunctorWorkItem() override = default; + + void operator()() const override { m_func(); - tbb::scalable_allocator >().deallocate(this, 1); + tbb::scalable_allocator().deallocate( + const_cast(this), 1); } // Irrelevant here - bool less_than (const WorkItem &other) const + bool less_than (const WorkItem &other) const override { // Just compare addresses return this < &other; @@ -378,13 +382,13 @@ public: m_batch.push_back(p_item); } - void run() + void operator()() const { std::sort(m_batch.begin(), m_batch.end(), CompareTwoWorkItems()); BatchIterator it = m_batch.begin(); BatchIterator it_end = m_batch.end(); for ( ; it != it_end ; ++it) - (*it)->run(); + (*it)->operator()(); } size_t size() const @@ -398,7 +402,7 @@ public: } protected: - Batch m_batch; + mutable Batch m_batch; }; @@ -410,7 +414,6 @@ protected: * =================== */ class WorkItemTask - : public tbb::task { public: WorkItemTask(WorkItem *pwi) @@ -419,7 +422,7 @@ public: } private: - /*override*/inline tbb::task* execute(); + inline void operator()() const; WorkItem *m_pwi; }; @@ -432,56 +435,27 @@ private: */ class Simple_worksharing_ds { -public: - // Constructors - Simple_worksharing_ds() - { - } - - /// Destructor - virtual ~Simple_worksharing_ds() - { - } - template - void enqueue_work(Func f, tbb::task &parent_task) const + void enqueue_work(Func f, tbb::task_group &task_group) const { - WorkItem *p_item = - tbb::scalable_allocator >().allocate(1); - new (p_item) SimpleFunctorWorkItem(f); - enqueue_task(create_task(p_item, parent_task)); - } - -protected: - - WorkItemTask *create_task(WorkItem *pwi, tbb::task &parent_task) const - { - return new(tbb::task::allocate_additional_child_of(parent_task)) WorkItemTask(pwi); - } - - void enqueue_task(WorkItemTask *t) const - { - tbb::task::spawn(*t); + task_group.run(f); } }; - - /* * ================== * class TokenTask * ================== */ class TokenTask - : public tbb::task { public: TokenTask(Load_based_worksharing_ds *p_wsds) : m_worksharing_ds(p_wsds) {} -private: - /*override*/inline tbb::task* execute(); + inline void operator()() const; +private: Load_based_worksharing_ds *m_worksharing_ds; }; @@ -526,7 +500,7 @@ public: } template - void enqueue_work(Func f, const Quality &quality, tbb::task &parent_task, const P3 &point) + void enqueue_work(Func f, const Quality &quality, tbb::task_group &task_group, const P3 &point) { WorkItem *p_item = new MeshRefinementWorkItem(f, quality); int index = m_stats.compute_index(point); @@ -534,13 +508,13 @@ public: wb.add_work_item(p_item); if (wb.size() >= NUM_WORK_ITEMS_PER_BATCH) { - add_batch_and_enqueue_task(wb, index, parent_task); + add_batch_and_enqueue_task(wb, index, task_group); wb.clear(); } } // Returns true if some items were flushed - bool flush_work_buffers(tbb::task &parent_task) + bool flush_work_buffers(tbb::task_group &task_group) { int num_flushed_items = 0; @@ -560,7 +534,7 @@ public: } for (int i = 0 ; i < num_flushed_items ; ++i) - enqueue_task(parent_task); + enqueue_task(task_group); return (num_flushed_items > 0); } @@ -593,7 +567,7 @@ public: std::cerr << "Running a batch of " << wb.size() << " elements on cell #" << index << std::endl; #endif - wb.run(); + wb(); add_occupation(index, -1); } @@ -610,19 +584,19 @@ protected: m_stats.add_batch(index, 1); } - void enqueue_task(tbb::task &parent_task) + void enqueue_task(tbb::task_group &task_group) { - parent_task.increment_ref_count(); // Warning: when using "enqueue", the system will use up to two threads // even if you told task_scheduler_init to use only one // (see http://software.intel.com/en-us/forums/showthread.php?t=101669) - tbb::task::spawn(*new(parent_task.allocate_child()) TokenTask(this)); + task_group.run(TokenTask(this)); } - void add_batch_and_enqueue_task(const WorkBuffer &wb, int index, tbb::task &parent_task) + void add_batch_and_enqueue_task(const WorkBuffer &wb, int index, + tbb::task_group &task_group) { add_batch(wb, index); - enqueue_task(parent_task); + enqueue_task(task_group); } void add_occupation(int cell_index, int to_add, int occupation_radius = 1) @@ -689,18 +663,16 @@ protected: * =================== */ class WorkBatchTask - : public tbb::task { public: WorkBatchTask(const WorkBatch &wb) : m_wb(wb) { - //set_affinity(tbb::task::self().affinity()); } -private: - /*override*/inline tbb::task* execute(); + inline void operator()() const; +private: WorkBatch m_wb; }; @@ -718,7 +690,6 @@ public: Concurrent_mesher_config::get().num_work_items_per_batch) { set_bbox(bbox); - m_cache_number_of_tasks = 0; } /// Destructor @@ -732,7 +703,7 @@ public: } template - void enqueue_work(Func f, tbb::task &parent_task) + void enqueue_work(Func f, tbb::task_group &task_group) { //WorkItem *p_item = new SimpleFunctorWorkItem(f); WorkItem *p_item = @@ -742,14 +713,13 @@ public: workbuffer.add_work_item(p_item); if (workbuffer.size() >= NUM_WORK_ITEMS_PER_BATCH) { - add_batch_and_enqueue_task(workbuffer, parent_task); + add_batch_and_enqueue_task(workbuffer, task_group); workbuffer.clear(); } - m_cache_number_of_tasks = parent_task.ref_count(); } template - void enqueue_work(Func f, const Quality &quality, tbb::task &parent_task) + void enqueue_work(Func f, const Quality &quality, tbb::task_group &task_group) { WorkItem *p_item = tbb::scalable_allocator >() @@ -759,14 +729,13 @@ public: workbuffer.add_work_item(p_item); if (workbuffer.size() >= NUM_WORK_ITEMS_PER_BATCH) { - add_batch_and_enqueue_task(workbuffer, parent_task); + add_batch_and_enqueue_task(workbuffer, task_group); workbuffer.clear(); } - m_cache_number_of_tasks = parent_task.ref_count(); } // Returns true if some items were flushed - bool flush_work_buffers(tbb::task &parent_task) + bool flush_work_buffers(tbb::task_group &task_group) { int num_flushed_items = 0; @@ -778,7 +747,7 @@ public: { if (it_buffer->size() > 0) { - tasks.push_back(create_task(*it_buffer, parent_task)); + tasks.push_back(create_task(*it_buffer)); it_buffer->clear(); ++num_flushed_items; } @@ -787,15 +756,14 @@ public: for (std::vector::const_iterator it = tasks.begin() ; it != tasks.end() ; ++it) { - enqueue_task(*it, parent_task); + enqueue_task(*it, task_group); } - m_cache_number_of_tasks = parent_task.ref_count(); return (num_flushed_items > 0); } - int approximate_number_of_enqueued_element() const { - return int(m_cache_number_of_tasks) * int(NUM_WORK_ITEMS_PER_BATCH); + [[deprecated]] int approximate_number_of_enqueued_element() const { + return 0; } protected: @@ -804,47 +772,44 @@ protected: typedef WorkBatch WorkBuffer; typedef tbb::enumerable_thread_specific TLS_WorkBuffer; - WorkBatchTask *create_task(const WorkBuffer &wb, tbb::task &parent_task) const + WorkBatchTask *create_task(const WorkBuffer &wb) const { - return new(tbb::task::allocate_additional_child_of(parent_task)) WorkBatchTask(wb); + auto ptr = tbb::scalable_allocator().allocate(1); + return new(ptr) WorkBatchTask(wb); } void enqueue_task(WorkBatchTask *task, - tbb::task &) const + tbb::task_group &task_group) const { - tbb::task::spawn(*task); + task_group.run(*task); } void add_batch_and_enqueue_task(const WorkBuffer &wb, - tbb::task &parent_task) const + tbb::task_group &task_group) const { - enqueue_task(create_task(wb, parent_task), parent_task); + enqueue_task(create_task(wb), task_group); } const size_t NUM_WORK_ITEMS_PER_BATCH; - std::atomic m_cache_number_of_tasks; TLS_WorkBuffer m_tls_work_buffers; }; -inline tbb::task* TokenTask::execute() +inline void TokenTask::operator()() const { m_worksharing_ds->run_next_work_item(); - return nullptr; } -inline tbb::task* WorkItemTask::execute() +inline void WorkItemTask::operator()() const { - m_pwi->run(); - return nullptr; + m_pwi->operator()(); } -inline tbb::task* WorkBatchTask::execute() +inline void WorkBatchTask::operator()() const { - m_wb.run(); - return nullptr; + m_wb.operator()(); } } } //namespace CGAL::Mesh_3 diff --git a/Mesh_3/include/CGAL/Mesh_3/io_signature.h b/Mesh_3/include/CGAL/Mesh_3/io_signature.h index d871b8ffe7d..2c0f02ab3b0 100644 --- a/Mesh_3/include/CGAL/Mesh_3/io_signature.h +++ b/Mesh_3/include/CGAL/Mesh_3/io_signature.h @@ -219,12 +219,10 @@ struct Get_io_signature > }; #ifdef CGAL_TRIANGULATION_3_H -template +template struct -Get_io_signature > > +Get_io_signature > { - typedef Triangulation_data_structure_3 Tds; - std::string operator()() { return std::string("Triangulation_3(") + Get_io_signature()() + diff --git a/Mesh_3/include/CGAL/Mesh_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_triangulation_3.h index 8d5373b1bd7..7bc643f4444 100644 --- a/Mesh_3/include/CGAL/Mesh_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_triangulation_3.h @@ -120,65 +120,40 @@ public: // template -struct Mesh_triangulation_3; - -// Sequential version (default) -template struct Mesh_triangulation_3 { private: - typedef typename Default::Lazy_get >::type K; + using K = typename Default::Lazy_get >::type; - typedef typename details::Mesh_geom_traits_generator::type Geom_traits; + using Geom_traits = typename details::Mesh_geom_traits_generator::type; - typedef typename Default::Get< + using Indices_tuple = Mesh_3::internal::Indices_tuple_t; + using Vertex_base = typename Default::Get< Vertex_base_, - Mesh_vertex_base_3 >::type Vertex_base; - typedef typename Default::Get< + Mesh_vertex_generator_3 >::type; + using Cell_base = typename Default::Get< Cell_base_, - Compact_mesh_cell_base_3 >::type Cell_base; - - typedef Triangulation_data_structure_3 Tds; - typedef Mesh_3_regular_triangulation_3_wrapper Triangulation; + Compact_mesh_cell_generator_3 >::type; + using Concurrency_tag = + typename Default::Get::type; + struct Tds : public Triangulation_data_structure_3 {}; + using Triangulation = + Mesh_3_regular_triangulation_3_wrapper; + ; public: - typedef Triangulation type; - typedef type Type; + using type = Triangulation; + using Type = type; }; // end struct Mesh_triangulation_3 - -#ifdef CGAL_LINKED_WITH_TBB -// Parallel version (specialization) -// -template -struct Mesh_triangulation_3 -{ -private: - typedef typename Default::Get::Kernel>::type K; - - typedef typename details::Mesh_geom_traits_generator::type Geom_traits; - - typedef typename Default::Get< - Vertex_base_, - Mesh_vertex_base_3 >::type Vertex_base; - typedef typename Default::Get< - Cell_base_, - Compact_mesh_cell_base_3 >::type Cell_base; - - typedef Triangulation_data_structure_3< - Vertex_base, Cell_base, Parallel_tag> Tds; - typedef Mesh_3_regular_triangulation_3_wrapper Triangulation; - -public: - typedef Triangulation type; - typedef type Type; -}; // end struct Mesh_triangulation_3 -#endif // CGAL_LINKED_WITH_TBB - } // end namespace CGAL #include diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index aeb3411a1e1..ecb1f9464c5 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -24,7 +24,7 @@ #include -#include +#include #include #include #include @@ -92,9 +92,10 @@ protected: // Adds information to Vb about the localization of the vertex in regards // to the 3D input complex. template > -class Mesh_vertex_base_3 + class Indices_tuple, + class Index_, + class Vb> +class Mesh_vertex_3 : public Vb, public Mesh_vertex_base_3_base< typename Vb::Triangulation_data_structure::Concurrency_tag> @@ -103,19 +104,12 @@ public: typedef Vb Cmvb3_base; typedef typename Vb::Vertex_handle Vertex_handle; - // To get correct vertex type in TDS - template < class TDS3 > - struct Rebind_TDS { - typedef typename Vb::template Rebind_TDS::Other Vb3; - typedef Mesh_vertex_base_3 Other; - }; - // Types - typedef typename MD::Index Index; - typedef typename GT::FT FT; + typedef Index_ Index; + typedef typename GT::FT FT; // Constructor - Mesh_vertex_base_3() + Mesh_vertex_3() : Vb() , number_of_incident_facets_(0) , number_of_components_(0) @@ -248,56 +242,77 @@ private: Vertex_handle previous_intrusive_; #endif std::size_t time_stamp_; +public: -}; // end class Mesh_vertex_base_3 + friend std::istream& operator>>(std::istream &is, Mesh_vertex_3& v) + { + is >> static_cast(v); + int dimension; + if(is_ascii(is)) { + is >> dimension; + + } else { + CGAL::read(is, dimension); + } + v.set_dimension(dimension); + CGAL_assertion(v.in_dimension() >= -1); + CGAL_assertion(v.in_dimension() < 4); + Index index = + Mesh_3::internal::Read_write_index()(is, v.in_dimension()); + v.set_index(index); + return is; + } + + friend std::ostream& operator<<(std::ostream &os, const Mesh_vertex_3& v) + { + os << static_cast(v); + if(is_ascii(os)) { + os << " " << v.in_dimension() + << " "; + } else { + CGAL::write(os, v.in_dimension()); + } + Mesh_3::internal::Read_write_index()(os, + v.in_dimension(), + v.index()); + return os; + } +}; // end class Mesh_vertex_3 template -inline -std::istream& -operator>>(std::istream &is, Mesh_vertex_base_3& v) -{ - typedef Mesh_vertex_base_3 Vertex; - typedef typename Vertex::Cmvb3_base Cmvb3_base; - is >> static_cast(v); - int dimension; - if(is_ascii(is)) { - is >> dimension; + class Vb = Regular_triangulation_vertex_base_3 > +struct Mesh_vertex_base_3 { + using Triangulation_data_structure = internal::Dummy_tds_3; + using Vertex_handle = typename Triangulation_data_structure::Vertex_handle; + using Cell_handle = typename Triangulation_data_structure::Cell_handle; - } else { - CGAL::read(is, dimension); - } - v.set_dimension(dimension); - CGAL_assertion(v.in_dimension() >= -1); - CGAL_assertion(v.in_dimension() < 4); - typename Vertex::Index index = - Mesh_3::internal::Read_mesh_domain_index()(v.in_dimension(), is); - v.set_index(index); - return is; -} + template < class TDS3 > + struct Rebind_TDS { + using Vb3 = typename Vb::template Rebind_TDS::Other; + using Other = Mesh_vertex_3 , + typename MD::Index, Vb3>; + }; +}; template -inline -std::ostream& -operator<<(std::ostream &os, const Mesh_vertex_base_3& v) -{ - typedef Mesh_vertex_base_3 Vertex; - typedef typename Vertex::Cmvb3_base Cmvb3_base; - os << static_cast(v); - if(is_ascii(os)) { - os << " " << v.in_dimension() - << " "; - } else { - CGAL::write(os, v.in_dimension()); - } - Mesh_3::internal::Write_mesh_domain_index()(os, - v.in_dimension(), - v.index()); - return os; -} + class Indices_tuple, + class Index, + class Vb = Regular_triangulation_vertex_base_3 > +struct Mesh_vertex_generator_3 { + using Triangulation_data_structure = internal::Dummy_tds_3; + using Vertex_handle = typename Triangulation_data_structure::Vertex_handle; + using Cell_handle = typename Triangulation_data_structure::Cell_handle; + + template < class TDS3 > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb3; + typedef Mesh_vertex_3 Other; + }; +}; } // end namespace CGAL diff --git a/Mesh_3/include/CGAL/Meshes/Filtered_multimap_container.h b/Mesh_3/include/CGAL/Meshes/Filtered_multimap_container.h index 4aa6f002599..94d5d1a9cb9 100644 --- a/Mesh_3/include/CGAL/Meshes/Filtered_multimap_container.h +++ b/Mesh_3/include/CGAL/Meshes/Filtered_multimap_container.h @@ -120,10 +120,16 @@ namespace CGAL { template void splice_local_lists_impl(Container &container) { +#ifdef CGAL_MESH_3_VERY_VERBOSE + std::cerr << "Filtered_multimap_container::splice_local_lists_impl()\n"; +#endif for(typename LocalList::iterator it_list = m_local_lists.begin() ; it_list != m_local_lists.end() ; ++it_list ) { +#ifdef CGAL_MESH_3_VERY_VERBOSE + std::cerr << " - " << it_list->size() << " elements\n"; +#endif container.insert(it_list->begin(), it_list->end()); it_list->clear(); } diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h b/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h index 62bde6e2135..fdb84a6c82b 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h @@ -23,10 +23,14 @@ #include #include -#include +#include +#include +#include #include #include +#include + namespace CGAL { namespace Mesh_3 { namespace internal { @@ -49,6 +53,26 @@ struct Index_generator typedef Index type; }; +template ::value> +struct Indices_tuple_generator +{ + using type = std::tuple; +}; + +template +struct Indices_tuple_generator +{ + using type = std::tuple; +}; + +template +using Indices_tuple_t = typename Indices_tuple_generator::type; + // Nasty meta-programming to get a boost::variant of four types that // may not be all different. template struct seq1 { @@ -245,6 +269,65 @@ struct Write_mesh_domain_index { }; // end template partial specialization // Write_mesh_domain_index +template +struct Read_write_index { + void operator()(std::ostream& os, int, Index index) const { + if(is_ascii(os)) os << oformat(index); + else CGAL::write(os, index); + } + Index operator()(std::istream& is, int) const { + Index index; + if(is_ascii(is)) is >> iformat(index); + else CGAL::read(is, index); + return index; + } +}; + +struct Variant_write_visitor { + std::ostream& os; + template + void operator()(T v) const { + if(is_ascii(os)) os << CGAL::oformat(v); + else CGAL::write(os, v); + } +}; + +template +struct Variant_read_visitor { + std::istream& is; + Index& variant; + template + void operator()(T) const { + T v; + if(is_ascii(is)) is >> CGAL::iformat(v); + else CGAL::read(is, v); + variant = v; + } +}; + +template +struct Read_write_index> { + using Index = boost::variant; + using index_seq = std::make_index_sequence::value>; + + template + Index get_index(int dimension, std::index_sequence) const{ + static const Index variants[] = { std::tuple_element_t{}... }; + return variants[dimension < 0 ? 0 : 3-dimension]; + } + + void operator()(std::ostream& os, int, Index index) const { + Variant_write_visitor visitor{os}; + apply_visitor(visitor, index); + } + Index operator()(std::istream& is, int dimension) const { + Index index = get_index(dimension, index_seq{}); + Variant_read_visitor visitor{is, index}; + apply_visitor(visitor, index); + return index; + } +}; + } // end namespace internal } // end namespace Mesh_3 } // end namespace CGAL diff --git a/Mesh_3/test/Mesh_3/CMakeLists.txt b/Mesh_3/test/Mesh_3/CMakeLists.txt index d731e12d4e4..90275373611 100644 --- a/Mesh_3/test/Mesh_3/CMakeLists.txt +++ b/Mesh_3/test/Mesh_3/CMakeLists.txt @@ -18,6 +18,8 @@ if ( CGAL_FOUND ) find_package( TBB QUIET ) include(CGAL_TBB_support) + find_package( ITT QUIET ) + # Use Eigen find_package(Eigen3 3.1.0 REQUIRED) #(3.1.0 or greater) include(CGAL_Eigen_support) @@ -117,7 +119,19 @@ if ( CGAL_FOUND ) endif() endforeach() endif() + if(TARGET ITT::ITT) + target_link_libraries(test_meshing_polyhedron_with_features PRIVATE ITT::ITT) + target_compile_definitions(test_meshing_polyhedron_with_features PRIVATE CGAL_MESH_3_USE_INTEL_ITT) + target_link_libraries(test_meshing_verbose PRIVATE ITT::ITT) + target_compile_definitions(test_meshing_verbose PRIVATE CGAL_MESH_3_USE_INTEL_ITT) + endif() + if(BUILD_TESTING) + set_tests_properties( + execution___of__test_meshing_polyhedron_with_features + execution___of__test_meshing_verbose + PROPERTIES RESOURCE_LOCK Mesh_3_Tests_IO) + endif() else() message(STATUS "This program requires the CGAL library, and will not be compiled.") diff --git a/Nef_2/include/CGAL/Nef_2/debug.h b/Nef_2/include/CGAL/Nef_2/debug.h index ff850cdf052..ce77dc610c6 100644 --- a/Nef_2/include/CGAL/Nef_2/debug.h +++ b/Nef_2/include/CGAL/Nef_2/debug.h @@ -59,8 +59,7 @@ #ifndef NDEBUG #define CGAL_NEF_TRACEN(t) if((debugthread%CGAL_NEF_DEBUG)==0) \ - std::cerr<< " "< struct Kernel_d_interface : public Base_ { typedef typename Get_functor::type Side_of_oriented_sphere_d; typedef typename Get_functor::type Power_side_of_power_sphere_d; typedef typename Get_functor::type Power_side_of_bounded_power_sphere_d; - typedef typename Get_functor::type Power_center_d; - typedef typename Get_functor::type Power_distance_d; + typedef typename Get_functor::type Construct_power_sphere_d; + typedef typename Get_functor::type Compute_power_product_d; typedef typename Get_functor::type Contained_in_affine_hull_d; typedef typename Get_functor::type Construct_flat_orientation_d; typedef typename Get_functor::type In_flat_orientation_d; @@ -222,8 +222,8 @@ template struct Kernel_d_interface : public Base_ { Side_of_oriented_sphere_d side_of_oriented_sphere_d_object()const{ return Side_of_oriented_sphere_d(*this); } Power_side_of_power_sphere_d power_side_of_power_sphere_d_object()const{ return Power_side_of_power_sphere_d(*this); } Power_side_of_bounded_power_sphere_d power_side_of_bounded_power_sphere_d_object()const{ return Power_side_of_bounded_power_sphere_d(*this); } - Power_center_d power_center_d_object()const{ return Power_center_d(*this); } - Power_distance_d power_distance_d_object()const{ return Power_distance_d(*this); } + Construct_power_sphere_d construct_power_sphere_d_object()const{ return Construct_power_sphere_d(*this); } + Compute_power_product_d compute_power_product_d_object()const{ return Compute_power_product_d(*this); } Side_of_bounded_sphere_d side_of_bounded_sphere_d_object()const{ return Side_of_bounded_sphere_d(*this); } Contained_in_affine_hull_d contained_in_affine_hull_d_object()const{ return Contained_in_affine_hull_d(*this); } Contained_in_linear_hull_d contained_in_linear_hull_d_object()const{ return Contained_in_linear_hull_d(*this); } diff --git a/NewKernel_d/test/NewKernel_d/Epick_d.cpp b/NewKernel_d/test/NewKernel_d/Epick_d.cpp index 3a3b150432f..9a1ae6be859 100644 --- a/NewKernel_d/test/NewKernel_d/Epick_d.cpp +++ b/NewKernel_d/test/NewKernel_d/Epick_d.cpp @@ -141,8 +141,8 @@ void test2(){ typedef typename K1::Construct_max_vertex_d CMV; typedef typename K1::Compute_squared_radius_d SR; typedef typename K1::Translated_point_d TP; - typedef typename K1::Power_center_d PC; - typedef typename K1::Power_distance_d PoD; + typedef typename K1::Construct_power_sphere_d PC; + typedef typename K1::Compute_power_product_d PoD; typedef typename K1::Construct_weighted_point_d CWP; typedef typename K1::Power_side_of_bounded_power_sphere_d PSBPS; typedef typename K1::Compute_squared_radius_smallest_orthogonal_sphere_d CSRSOS; @@ -210,12 +210,12 @@ void test2(){ CMV cMv Kinit(construct_max_vertex_d_object); SR sr Kinit(compute_squared_radius_d_object); TP tp Kinit(translated_point_d_object); - PC pc Kinit(power_center_d_object); + PC pc Kinit(construct_power_sphere_d_object); CWP cwp Kinit(construct_weighted_point_d_object); //PDW pdw Kinit(point_drop_weight_d_object); PDW const& pdw = cp; PW pw Kinit(compute_weight_d_object); - PoD pod Kinit(power_distance_d_object); + PoD pod Kinit(compute_power_product_d_object); PSBPS psbps Kinit(power_side_of_bounded_power_sphere_d_object); CSRSOS csrsos Kinit(compute_squared_radius_smallest_orthogonal_sphere_d_object); @@ -718,14 +718,14 @@ void test4(){ typedef typename Ker::Weighted_point_d WP; typedef typename Ker::Construct_circumcenter_d CCc; typedef typename Ker::Equal_d E; - typedef typename Ker::Power_center_d PC; - typedef typename Ker::Power_distance_d PoD; + typedef typename Ker::Construct_power_sphere_d PC; + typedef typename Ker::Compute_power_product_d PoD; typedef typename Ker::Affine_rank_d AR; Ker k(4); CCc ccc Kinit(construct_circumcenter_d_object); E ed Kinit(equal_d_object); - PC pc Kinit(power_center_d_object); - PoD pod Kinit(power_distance_d_object); + PC pc Kinit(construct_power_sphere_d_object); + PoD pod Kinit(compute_power_product_d_object); AR ar Kinit(affine_rank_d_object); auto mkpt=[](auto...x){double l[]{(double)x...};return P(std::begin(l), std::end(l));}; P tab1[]={mkpt(15,20,40,80),mkpt(10,23,36,80),mkpt(10,20,40,85),mkpt(10,15,40,80),mkpt(13,20,40,76)}; diff --git a/Number_types/include/CGAL/FPU.h b/Number_types/include/CGAL/FPU.h index 1d290381603..6d5f02a3075 100644 --- a/Number_types/include/CGAL/FPU.h +++ b/Number_types/include/CGAL/FPU.h @@ -75,8 +75,8 @@ extern "C" { // Pure and safe SSE2 mode (g++ -mfpmath=sse && (-msse2 || -march=pentium4)) // can be detected by : // TODO : see what Intel and VC++ have to say about this. -#if defined __FLT_EVAL_METHOD__ && defined __SSE2_MATH__ && \ - (__FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1) +#if defined _M_X64 || ( defined __FLT_EVAL_METHOD__ && defined __SSE2_MATH__ && \ + (__FLT_EVAL_METHOD__ == 0 || __FLT_EVAL_METHOD__ == 1) ) # define CGAL_SAFE_SSE2 # include #endif @@ -90,7 +90,7 @@ extern "C" { #if !defined CGAL_IA_NO_X86_OVER_UNDER_FLOW_PROTECT && \ (((defined __i386__ || defined __x86_64__) && !defined CGAL_SAFE_SSE2) \ || defined __ia64__ \ - || defined _M_IX86 || defined _M_X64 || defined _M_IA64 \ + || defined _M_IX86 || defined _M_IA64 \ || (defined FLT_EVAL_METHOD && FLT_EVAL_METHOD != 0 && FLT_EVAL_METHOD != 1)) # define CGAL_FPU_HAS_EXCESS_PRECISION #endif diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt b/Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt similarity index 100% rename from Optimal_bounding_box/benchmarks/Optimal_bounding_box/CMakeLists.txt rename to Optimal_bounding_box/benchmark/Optimal_bounding_box/CMakeLists.txt diff --git a/Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp b/Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp similarity index 100% rename from Optimal_bounding_box/benchmarks/Optimal_bounding_box/bench_obb.cpp rename to Optimal_bounding_box/benchmark/Optimal_bounding_box/bench_obb.cpp diff --git a/Periodic_2_triangulation_2/include/CGAL/internal/Static_filters/Periodic_2_orientation_2.h b/Periodic_2_triangulation_2/include/CGAL/internal/Static_filters/Periodic_2_orientation_2.h index f406962e3f7..f2084e3a83c 100644 --- a/Periodic_2_triangulation_2/include/CGAL/internal/Static_filters/Periodic_2_orientation_2.h +++ b/Periodic_2_triangulation_2/include/CGAL/internal/Static_filters/Periodic_2_orientation_2.h @@ -103,21 +103,7 @@ public: : Base(o2b), _dom(dom) { } -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - result_type - operator()(const Vector_2& u, const Vector_2& v) const - { - return Base::operator()(u, v); - } - - result_type - operator()(const Circle_2& c) const - { - return Base::operator()(c); - } -#endif /// Normal static orientation test, copied from Orientation_2 result_type operator()(const Point_2 &p, const Point_2 &q, const Point_2 &r) const diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_hierarchy_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_hierarchy_3.h index d8601463dab..5a46a8839b3 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_hierarchy_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_hierarchy_3.h @@ -523,7 +523,7 @@ random_level() && hierarchy[level_mult_cover]->number_of_sheets() == make_array(1,1,1) ) ++level_mult_cover; - boost::geometric_distribution<> proba(1.0/ratio); + boost::geometric_distribution<> proba(1.0/static_cast(ratio)); boost::variate_generator > die(random, proba); return (std::min)(die()-1, level_mult_cover); diff --git a/Periodic_3_triangulation_3/include/CGAL/internal/Static_filters/Periodic_3_orientation_3.h b/Periodic_3_triangulation_3/include/CGAL/internal/Static_filters/Periodic_3_orientation_3.h index 805c7b0f279..046cca7d418 100644 --- a/Periodic_3_triangulation_3/include/CGAL/internal/Static_filters/Periodic_3_orientation_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/internal/Static_filters/Periodic_3_orientation_3.h @@ -53,21 +53,7 @@ public: : Base(o3b), _dom(dom) { } -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else - result_type - operator()(const Vector_3& u, const Vector_3& v, const Vector_3& w) const - { - return Base::operator()(u,v,w); - } - - result_type - operator()(const Sphere_3& s) const - { - return Base::operator()(s); - } -#endif result_type operator()(const Point_3 &p, const Point_3 &q, diff --git a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h index 332552b0ac8..8304f78bf98 100644 --- a/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h +++ b/Periodic_4_hyperbolic_triangulation_2/include/CGAL/Periodic_4_hyperbolic_Delaunay_triangulation_traits_2.h @@ -50,23 +50,7 @@ class Hyperbolic_traits_with_translations_2_adaptor public: typedef typename Predicate::result_type result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Predicate::operator(); -#else - result_type operator()(const Point& p0, const Point& p1) const - { - return Predicate()(p0, p1); - } - result_type operator()(const Point& p0, const Point& p1, const Point& p2) const - { - return Predicate()(p0,p1,p2); - } - - result_type operator()(const Point& p0, const Point& p1, const Point& p2, const Point& p3) const - { - return Predicate()(p0,p1,p2,p3); - } -#endif Hyperbolic_traits_with_translations_2_adaptor(const Predicate_ pred = Predicate_()) : Predicate_(pred) {} @@ -127,14 +111,7 @@ private: public: typedef Point result_type; -#ifndef CGAL_CFG_MATCHING_BUG_6 using Construct_point_base::operator(); -#else - Point operator()(const NT& x, const NT& y) const - { - return Construct_point_base()(x,y); - } -#endif Periodic_4_construct_hyperbolic_point_2() { } diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index 5166b8dde69..a7c584e5466 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -256,7 +256,11 @@ remove_outliers( { std::nth_element (f2r, sorted_points.begin() + first_index_to_remove, - sorted_points.end()); + sorted_points.end(), + [](const std::pair& v1, const std::pair& v2) + { + return v1.first #include #include +#include // This package #include @@ -40,9 +41,11 @@ typedef Kernel::Point_3 Point; // ---------------------------------------------------------------------------- // Removes outliers -void test_avg_knn_sq_distance(std::deque& points, // input point set +template +void test_avg_knn_sq_distance(PointContainer& points, // input point set unsigned int nb_neighbors_remove_outliers, // K-nearest neighbors - double removed_percentage) // percentage of points to remove + double removed_percentage, + PointMap point_map) // percentage of points to remove { CGAL::Timer task_timer; task_timer.start(); std::cerr << "Removes outliers wrt average squared distance to k nearest neighbors (remove " @@ -52,11 +55,12 @@ void test_avg_knn_sq_distance(std::deque& points, // input point set // Removes outliers using erase-remove idiom points.erase(CGAL::remove_outliers (points, nb_neighbors_remove_outliers, - CGAL::parameters::threshold_percent(removed_percentage)), + CGAL::parameters::threshold_percent(removed_percentage). + point_map(point_map)), points.end()); // Optional: after erase(), use Scott Meyer's "swap trick" to trim excess capacity - std::deque(points).swap(points); + PointContainer(points).swap(points); std::size_t memory = CGAL::Memory_sizer().virtual_size(); @@ -125,8 +129,16 @@ int main(int argc, char * argv[]) // Test //*************************************** - test_avg_knn_sq_distance(points, nb_neighbors_remove_outliers, removed_percentage); + test_avg_knn_sq_distance(points, nb_neighbors_remove_outliers, removed_percentage, + CGAL::Identity_property_map()); + struct A{}; + std::vector< std::pair > points_bis; + points_bis.reserve(points.size()); + for (const Point p : points) + points_bis.push_back( std::make_pair(p, A()) ); + test_avg_knn_sq_distance(points_bis, nb_neighbors_remove_outliers, removed_percentage, + CGAL::First_of_pair_property_map>()); } // for each input file std::cerr << std::endl; diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPTriangulateFaceVisitor.h b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPTriangulateFaceVisitor.h new file mode 100644 index 00000000000..1ab5a7b94e8 --- /dev/null +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Concepts/PMPTriangulateFaceVisitor.h @@ -0,0 +1,34 @@ +/// \ingroup PkgPolygonMeshProcessingConcepts +/// \cgalConcept +/// +/// The concept `PMPTriangulateFaceVisitor` defines the requirements for the visitor +/// used in \link PMP_meshing_grp triangulation-related functions \endlink to track +/// the creation of new faces. +/// +/// \cgalRefines `CopyConstructible` +/// \cgalHasModel `CGAL::Polygon_mesh_processing::Triangulate_faces::Default_visitor`. + + +class PMPTriangulateFaceVisitor { +public: +/// Face decriptor type +typedef unspecified_type face_descriptor; + +/// @name Functions used by triangulate_face() and triangulate_faces() +/// @{ + /// called before the triangulation of `f_split`. Note that `f_split` + /// will be one of the faces of the triangulation. Each subsequent call to + /// `after_subface_created()` will correspond to + /// the creation of a new face of the triangulation of `f_split`. + void before_subface_creations(face_descriptor f_split); + + /// called when the triangulation of a face in `tm` is finished. + void after_subface_creations(); + + /// called after creating a new triangle face `f_new` to triangulate the face passed to `before_subface_creations()`. + /// Note that the call is placed just after a call to `add_face()` so the halfedge pointer is not set yet. + void after_subface_created(face_descriptor f_new); + + /// @} + +}; diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt index 20e39b29034..86f0ca346a9 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/Polygon_mesh_processing.txt @@ -202,6 +202,11 @@ as shown in the following example. \cgalExample{Polygon_mesh_processing/triangulate_faces_example.cpp} +An additional parameter, named `visitor` can be used to track the how faces +are triangulated into subfaces. The following examples shows how to use it. + +\cgalExample{Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp} + \subsubsection RemeshingExample_1 Isotropic Remeshing of a Region on a Polygon Mesh diff --git a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt index 66c4609d25c..9fa1de58990 100644 --- a/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt +++ b/Polygon_mesh_processing/doc/Polygon_mesh_processing/examples.txt @@ -29,4 +29,5 @@ \example Polygon_mesh_processing/shape_smoothing_example.cpp \example Polygon_mesh_processing/locate_example.cpp \example Polygon_mesh_processing/orientation_pipeline_example.cpp +\example Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp */ diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt index 8f748d69246..ec8bb41756b 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/CMakeLists.txt @@ -67,6 +67,7 @@ create_single_source_cgal_program( "compute_normals_example_Polyhedron.cpp" CXX create_single_source_cgal_program( "compute_normals_example.cpp" CXX_FEATURES cxx_range_for cxx_auto_type ) create_single_source_cgal_program( "point_inside_example.cpp") create_single_source_cgal_program( "triangulate_faces_example.cpp") +create_single_source_cgal_program( "triangulate_faces_split_visitor_example.cpp") create_single_source_cgal_program( "connected_components_example.cpp") create_single_source_cgal_program( "face_filtered_graph_example.cpp") create_single_source_cgal_program( "orient_polygon_soup_example.cpp") diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp index de555e8e25a..ebd86cda4ac 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/corefinement_consecutive_bool_op.cpp @@ -79,10 +79,10 @@ int main(int argc, char* argv[]) } Exact_point_map mesh1_exact_points = - mesh1.add_property_map("e:exact_point").first; + mesh1.add_property_map("v:exact_point").first; Exact_point_map mesh2_exact_points = - mesh2.add_property_map("e:exact_point").first; + mesh2.add_property_map("v:exact_point").first; Exact_vertex_point_map mesh1_vpm(mesh1_exact_points, mesh1); Exact_vertex_point_map mesh2_vpm(mesh2_exact_points, mesh2); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp new file mode 100644 index 00000000000..4036a4c504a --- /dev/null +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/triangulate_faces_split_visitor_example.cpp @@ -0,0 +1,105 @@ +#include +#include + +#include +#include + +#include +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel Kernel; +typedef Kernel::Point_3 Point; +typedef CGAL::Surface_mesh Surface_mesh; +typedef boost::graph_traits::face_descriptor face_descriptor; + + + +class Insert_iterator +{ + typedef boost::unordered_map Container; + Container& container; +public: + + Insert_iterator(Container &c) + : container(c) {} + + Insert_iterator& + operator=(const std::pair& p) + { + container[p.second] = p.first; + return *this; + } + + Insert_iterator& + operator*() { return *this; } + + Insert_iterator + operator++(int) { return *this; } + +}; + + +struct Visitor +{ + typedef boost::unordered_map Container; + + Container& container; + face_descriptor qfd; + + Visitor(Container& container) + : container(container) + {} + + void before_subface_creations(face_descriptor fd) + { + std::cout << "split : " << fd << " into:" << std::endl; + Container::iterator it = container.find(fd); + qfd = it->second; + container.erase(it); + } + + void after_subface_created(face_descriptor fd) + { + std::cout << " " << fd; + container[fd]=qfd; + } + + void after_subface_creations() + { + std::cout << std::endl; + } +}; + + +int main(int argc, char* argv[]) +{ + const char* filename = (argc > 1) ? argv[1] : "data/P.off"; + std::ifstream input(filename); + + Surface_mesh mesh; + if (!input || !(input >> mesh) || mesh.is_empty()) + { + std::cerr << "Not a valid off file." << std::endl; + return 1; + } + + boost::unordered_map t2q; + + Surface_mesh copy; + + copy_face_graph(mesh, copy, CGAL::Emptyset_iterator(), CGAL::Emptyset_iterator(),Insert_iterator(t2q)); + + Visitor v(t2q); + CGAL::Polygon_mesh_processing::triangulate_faces(copy, + CGAL::Polygon_mesh_processing::parameters::visitor(v)); + + + for(boost::unordered_map::iterator it = t2q.begin(); it != t2q.end(); ++it){ + std::cout << it->first << " " << it->second << std::endl; + } + + return 0; +} diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h index ae94faba8e2..95b7bd922c5 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/clip.h @@ -33,7 +33,14 @@ #include +#include +#include +#include +#include +#include #include +#include +#include namespace CGAL{ namespace Polygon_mesh_processing { @@ -420,10 +427,9 @@ generic_clip_impl( NamedParameters1>::type Vpm; typedef typename GetVertexPointMap::type Vpm2; - CGAL_USE_TYPE(Vpm2); - CGAL_assertion_code( - static const bool same_vpm = (boost::is_same::value); ) - CGAL_static_assertion(same_vpm); + + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); Vpm vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), get_property_map(boost::vertex_point, tm1)); @@ -469,25 +475,25 @@ generic_clip_impl( // User visitor typedef typename internal_np::Lookup_named_param_def < - internal_np::graph_visitor_t, + internal_np::visitor_t, NamedParameters1, Corefinement::Default_visitor//default > ::type User_visitor; - User_visitor uv(choose_parameter(get_parameter(np1, internal_np::graph_visitor))); + User_visitor uv(choose_parameter(get_parameter(np1, internal_np::visitor))); // surface intersection algorithm call typedef Corefinement::Generic_clip_output_builder Ob; typedef Corefinement::Surface_intersection_visitor_for_corefinement< - TriangleMesh, Vpm, Ob, Ecm_in, User_visitor> Algo_visitor; + TriangleMesh, Vpm, Vpm2, Ob, Ecm_in, User_visitor> Algo_visitor; Ecm_in ecm_in(tm1,tm2,ecm1,ecm2); Ob ob(tm1, tm2, vpm1, vpm2, algo_ecm1, fid_map1, use_compact_clipper); - Corefinement::Intersection_of_triangle_meshes + Corefinement::Intersection_of_triangle_meshes functor(tm1, tm2, vpm1, vpm2, Algo_visitor(uv,ob,ecm_in,&tm2)); functor(CGAL::Emptyset_iterator(), false, true); } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h index 22116a51ef8..670a4c183c9 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/connected_components.h @@ -438,7 +438,7 @@ std::size_t keep_largest_connected_components(PolygonMesh& pmesh, Output_iterator out = choose_parameter(get_parameter(np, internal_np::output_iterator)); // vector_property_map - boost::vector_property_map face_cc(fimap); + boost::vector_property_map face_cc(static_cast(num_faces(pmesh)), fimap); std::size_t num = connected_components(pmesh, face_cc, np); // Even if we do not want to keep anything we need to first @@ -594,7 +594,7 @@ std::size_t keep_large_connected_components(PolygonMesh& pmesh, Output_iterator out = choose_parameter(get_parameter(np, internal_np::output_iterator)); // vector_property_map - boost::vector_property_map face_cc(fim); + boost::vector_property_map face_cc(static_cast(num_faces(pmesh)), fim); std::size_t num = connected_components(pmesh, face_cc, np); std::vector component_size(num, 0); @@ -655,14 +655,12 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh { using parameters::choose_parameter; using parameters::get_parameter; + using parameters::is_default_parameter; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef typename boost::graph_traits::face_iterator face_iterator; typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::vertex_iterator vertex_iterator; typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; typedef typename boost::graph_traits::edge_descriptor edge_descriptor; - typedef typename boost::graph_traits::edge_iterator edge_iterator; typedef typename GetInitializedVertexIndexMap::type VertexIndexMap; VertexIndexMap vim = get_initialized_vertex_index_map(pmesh, np); @@ -671,10 +669,10 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh for(std::size_t i : components_to_keep) cc_to_keep.insert(i); - boost::vector_property_map keep_vertex(vim); - for(vertex_descriptor v : vertices(pmesh)){ + boost::vector_property_map keep_vertex(static_cast(num_vertices(pmesh)), vim); + for(vertex_descriptor v : vertices(pmesh)) keep_vertex[v] = false; - } + for(face_descriptor f : faces(pmesh)){ if (cc_to_keep.find(get(fcm,f)) != cc_to_keep.end()) put(fcm, f, keep ? 1 : 0); @@ -691,11 +689,9 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh } } - edge_iterator eb, ee; - for (boost::tie(eb, ee) = edges(pmesh); eb != ee;) + std::vector edges_to_remove; + for (edge_descriptor e : edges(pmesh)) { - edge_descriptor e = *eb; - ++eb; vertex_descriptor v = source(e, pmesh); vertex_descriptor w = target(e, pmesh); halfedge_descriptor h = halfedge(e, pmesh); @@ -703,7 +699,7 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh if (!keep_vertex[v] && !keep_vertex[w]){ // don't care about connectivity // As vertices are not kept the faces and vertices will be removed later - remove_edge(e, pmesh); + edges_to_remove.push_back(e); } else if (keep_vertex[v] && keep_vertex[w]){ face_descriptor fh = face(h, pmesh), ofh = face(oh, pmesh); @@ -736,7 +732,7 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh // shortcut the next pointers as e will be removed set_next(prev(h, pmesh), next(oh, pmesh), pmesh); set_next(prev(oh, pmesh), next(h, pmesh), pmesh); - remove_edge(e, pmesh); + edges_to_remove.push_back(e); } } else if (keep_vertex[v]){ @@ -744,7 +740,7 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh set_halfedge(v, prev(h, pmesh), pmesh); } set_next(prev(h, pmesh), next(oh, pmesh), pmesh); - remove_edge(e, pmesh); + edges_to_remove.push_back(e); } else { CGAL_assertion(keep_vertex[w]); @@ -752,26 +748,40 @@ void keep_or_remove_connected_components(PolygonMesh& pmesh set_halfedge(w, prev(oh, pmesh), pmesh); } set_next(prev(oh, pmesh), next(h, pmesh), pmesh); - remove_edge(e, pmesh); + edges_to_remove.push_back(e); } } + for (edge_descriptor e : edges_to_remove) + remove_edge(e, pmesh); - face_iterator fb, fe; // We now can remove all vertices and faces not marked as kept - for (boost::tie(fb, fe) = faces(pmesh); fb != fe;){ - face_descriptor f = *fb; - ++fb; - if (get(fcm,f) != 1){ - remove_face(f, pmesh); - } - } - vertex_iterator b, e; - for (boost::tie(b, e) = vertices(pmesh); b != e;){ - vertex_descriptor v = *b; - ++b; - if (!keep_vertex[v]){ + std::vector faces_to_remove; + for (face_descriptor f : faces(pmesh)) + if (get(fcm,f) != 1) + faces_to_remove.push_back(f); + for (face_descriptor f : faces_to_remove) + remove_face(f, pmesh); + + std::vector vertices_to_remove; + for(vertex_descriptor v: vertices(pmesh)) + if (!keep_vertex[v]) + vertices_to_remove.push_back(v); + if ( is_default_parameter(get_parameter(np, internal_np::vertex_is_constrained)) ) + for (vertex_descriptor v : vertices_to_remove) remove_vertex(v, pmesh); - } + else + { + typedef typename internal_np::Lookup_named_param_def // default (not used) + >::type Vertex_map; + Vertex_map is_cst = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), + Static_boolean_property_map()); + for (vertex_descriptor v : vertices_to_remove) + if (!get(is_cst, v)) + remove_vertex(v, pmesh); + else + set_halfedge(v, boost::graph_traits::null_halfedge(), pmesh); } } @@ -924,7 +934,7 @@ void remove_connected_components(PolygonMesh& pmesh typedef typename CGAL::GetInitializedFaceIndexMap::type FaceIndexMap; FaceIndexMap fim = CGAL::get_initialized_face_index_map(pmesh, np); - boost::vector_property_map face_cc(fim); + boost::vector_property_map face_cc(static_cast(num_faces(pmesh)), fim); connected_components(pmesh, face_cc, np); std::vector cc_to_remove; @@ -991,7 +1001,7 @@ void keep_connected_components(PolygonMesh& pmesh typedef typename CGAL::GetInitializedFaceIndexMap::type FaceIndexMap; FaceIndexMap fim = CGAL::get_initialized_face_index_map(pmesh, np); - boost::vector_property_map face_cc(fim); + boost::vector_property_map face_cc(static_cast(num_faces(pmesh)), fim); connected_components(pmesh, face_cc, np); std::vector cc_to_keep; @@ -1043,13 +1053,6 @@ void keep_connected_components(PolygonMesh& pmesh namespace internal { -template -struct No_mark -{ - friend bool get(No_mark, typename boost::graph_traits::edge_descriptor) { return false; } - friend void put(No_mark, typename boost::graph_traits::edge_descriptor, bool) { } -}; - template < class PolygonMesh, class PolygonMeshRange, class FIMap, class VIMap, class HIMap, class Ecm, class NamedParameters > @@ -1168,17 +1171,19 @@ void split_connected_components(const PolygonMesh& pmesh, PolygonMeshRange& cc_meshes, const NamedParameters& np) { + typedef Static_boolean_property_map< + typename boost::graph_traits::edge_descriptor, false> Default_ecm; typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, - internal::No_mark//default + Default_ecm//default > ::type Ecm; using parameters::choose_parameter; using parameters::get_parameter; Ecm ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - internal::No_mark()); + Default_ecm()); internal::split_connected_components_impl(CGAL::get_initialized_face_index_map(pmesh, np), CGAL::get_initialized_halfedge_index_map(pmesh, np), diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h index 2b1acf46173..e34c951e4ea 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h @@ -201,22 +201,19 @@ corefine_and_compute_boolean_operations( // Vertex point maps //for input meshes - typedef typename GetVertexPointMap::type Vpm; - typedef typename GetVertexPointMap::type Vpm2; - CGAL_USE_TYPE(Vpm2); - CGAL_assertion_code( - static const bool same_vpm = (boost::is_same::value); ) - CGAL_static_assertion(same_vpm); + typedef typename GetVertexPointMap::type VPM1; + typedef typename GetVertexPointMap::type VPM2; - Vpm vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), - get_property_map(boost::vertex_point, tm1)); + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); - Vpm vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), - get_property_map(boost::vertex_point, tm2)); + VPM1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), + get_property_map(boost::vertex_point, tm1)); - typedef typename boost::property_traits::value_type Point_3; + VPM2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), + get_property_map(boost::vertex_point, tm2)); + + typedef typename boost::property_traits::value_type Point_3; // for output meshes: here we have to use a trick so that if for a specific output // that is not requested, the default vpm does not have the same value type as the @@ -227,24 +224,24 @@ corefine_and_compute_boolean_operations( Corefinement::TweakedGetVertexPointMap, Corefinement::TweakedGetVertexPointMap, Corefinement::TweakedGetVertexPointMap - > Vpm_out_tuple_helper; + > VPM_out_tuple_helper; typedef std::tuple< - boost::optional< typename std::tuple_element<0, Vpm_out_tuple_helper>::type::type >, - boost::optional< typename std::tuple_element<1, Vpm_out_tuple_helper>::type::type >, - boost::optional< typename std::tuple_element<2, Vpm_out_tuple_helper>::type::type >, - boost::optional< typename std::tuple_element<3, Vpm_out_tuple_helper>::type::type > - > Vpm_out_tuple; + boost::optional< typename std::tuple_element<0, VPM_out_tuple_helper>::type::type >, + boost::optional< typename std::tuple_element<1, VPM_out_tuple_helper>::type::type >, + boost::optional< typename std::tuple_element<2, VPM_out_tuple_helper>::type::type >, + boost::optional< typename std::tuple_element<3, VPM_out_tuple_helper>::type::type > + > VPM_out_tuple; - Vpm_out_tuple vpm_out_tuple( + VPM_out_tuple vpm_out_tuple( Corefinement::get_vpm(std::get<0>(nps_out), output[0], - typename std::tuple_element<0, Vpm_out_tuple_helper>::type::Use_default_tag()), + typename std::tuple_element<0, VPM_out_tuple_helper>::type::Use_default_tag()), Corefinement::get_vpm(std::get<1>(nps_out), output[1], - typename std::tuple_element<1, Vpm_out_tuple_helper>::type::Use_default_tag()), + typename std::tuple_element<1, VPM_out_tuple_helper>::type::Use_default_tag()), Corefinement::get_vpm(std::get<2>(nps_out), output[2], - typename std::tuple_element<2, Vpm_out_tuple_helper>::type::Use_default_tag()), + typename std::tuple_element<2, VPM_out_tuple_helper>::type::Use_default_tag()), Corefinement::get_vpm(std::get<3>(nps_out), output[3], - typename std::tuple_element<3, Vpm_out_tuple_helper>::type::Use_default_tag()) + typename std::tuple_element<3, VPM_out_tuple_helper>::type::Use_default_tag()) ); if (&tm1==&tm2) @@ -367,16 +364,17 @@ corefine_and_compute_boolean_operations( // User visitor typedef typename internal_np::Lookup_named_param_def < - internal_np::graph_visitor_t, + internal_np::visitor_t, NamedParameters1, Corefinement::Default_visitor//default > ::type User_visitor; - User_visitor uv(choose_parameter(get_parameter(np1, internal_np::graph_visitor))); + User_visitor uv(choose_parameter(get_parameter(np1, internal_np::visitor))); // surface intersection algorithm call typedef Corefinement::Face_graph_output_builder Ob; typedef Corefinement::Surface_intersection_visitor_for_corefinement< - TriangleMesh, Vpm, Ob, Ecm_in, User_visitor> Algo_visitor; + TriangleMesh, VPM1, VPM2, Ob, Ecm_in, User_visitor> Algo_visitor; + Ecm_in ecm_in(tm1,tm2,ecm1,ecm2); Edge_mark_map_tuple ecms_out(ecm_out_0, ecm_out_1, ecm_out_2, ecm_out_3); Ob ob(tm1, tm2, vpm1, vpm2, fid_map1, fid_map2, ecm_in, vpm_out_tuple, ecms_out, uv, output); @@ -402,7 +401,7 @@ corefine_and_compute_boolean_operations( ob.setup_for_clipping_a_surface(use_compact_clipper); } - Corefinement::Intersection_of_triangle_meshes + Corefinement::Intersection_of_triangle_meshes functor(tm1, tm2, vpm1, vpm2, Algo_visitor(uv,ob,ecm_in)); functor(CGAL::Emptyset_iterator(), throw_on_self_intersection, true); @@ -735,20 +734,17 @@ corefine( TriangleMesh& tm1, choose_parameter(get_parameter(np1, internal_np::throw_on_self_intersection), false); // Vertex point maps - typedef typename GetVertexPointMap::type Vpm; - typedef typename GetVertexPointMap::type Vpm2; - CGAL_USE_TYPE(Vpm2); - CGAL_assertion_code( - static const bool same_vpm = (boost::is_same::value);) - CGAL_static_assertion(same_vpm); + typedef typename GetVertexPointMap::type VPM1; + typedef typename GetVertexPointMap::type VPM2; - Vpm vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), - get_property_map(boost::vertex_point, tm1)); + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); - Vpm vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), - get_property_map(boost::vertex_point, tm2)); + VPM1 vpm1 = choose_parameter(get_parameter(np1, internal_np::vertex_point), + get_property_map(boost::vertex_point, tm1)); + + VPM2 vpm2 = choose_parameter(get_parameter(np2, internal_np::vertex_point), + get_property_map(boost::vertex_point, tm2)); // Edge is-constrained maps typedef typename internal_np::Lookup_named_param_def < @@ -777,19 +773,20 @@ corefine( TriangleMesh& tm1, // User visitor typedef typename internal_np::Lookup_named_param_def < - internal_np::graph_visitor_t, + internal_np::visitor_t, NamedParameters1, Corefinement::Default_visitor//default > ::type User_visitor; - User_visitor uv(choose_parameter(get_parameter(np1, internal_np::graph_visitor))); + User_visitor uv(choose_parameter(get_parameter(np1, internal_np::visitor))); // surface intersection algorithm call typedef Corefinement::No_extra_output_from_corefinement Ob; typedef Corefinement::Surface_intersection_visitor_for_corefinement< - TriangleMesh, Vpm, Ob, Ecm, User_visitor> Algo_visitor; + TriangleMesh, VPM1, VPM2, Ob, Ecm, User_visitor> Algo_visitor; + Ob ob; Ecm ecm(tm1,tm2,ecm1,ecm2); - Corefinement::Intersection_of_triangle_meshes + Corefinement::Intersection_of_triangle_meshes functor(tm1, tm2, vpm1, vpm2, Algo_visitor(uv,ob,ecm,const_mesh_ptr)); functor(CGAL::Emptyset_iterator(), throw_on_self_intersection, true); } @@ -852,9 +849,9 @@ autorefine( TriangleMesh& tm, using parameters::get_parameter; // Vertex point maps - typedef typename GetVertexPointMap::type Vpm; + typedef typename GetVertexPointMap::type VPM; - Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_property_map(boost::vertex_point, tm)); // Edge is-constrained maps @@ -867,20 +864,20 @@ autorefine( TriangleMesh& tm, // User visitor typedef typename internal_np::Lookup_named_param_def < - internal_np::graph_visitor_t, + internal_np::visitor_t, NamedParameters, Corefinement::Default_visitor//default > ::type User_visitor; - User_visitor uv(choose_parameter(get_parameter(np, internal_np::graph_visitor))); + User_visitor uv(choose_parameter(get_parameter(np, internal_np::visitor))); // surface intersection algorithm call typedef Corefinement::No_extra_output_from_corefinement Ob; typedef Corefinement::Surface_intersection_visitor_for_corefinement< - TriangleMesh, Vpm, Ob, Ecm, User_visitor,true> Algo_visitor; + TriangleMesh, VPM, VPM, Ob, Ecm, User_visitor,true> Algo_visitor; Ob ob; - Corefinement::Intersection_of_triangle_meshes + Corefinement::Intersection_of_triangle_meshes functor(tm, vpm, Algo_visitor(uv,ob,ecm) ); functor(CGAL::Emptyset_iterator(), true); @@ -945,8 +942,8 @@ autorefine_and_remove_self_intersections( TriangleMesh& tm, using parameters::get_parameter; // Vertex point maps - typedef typename GetVertexPointMap::type Vpm; - Vpm vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + typedef typename GetVertexPointMap::type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), get_property_map(boost::vertex_point, tm)); // Face index map @@ -964,24 +961,24 @@ autorefine_and_remove_self_intersections( TriangleMesh& tm, // User visitor typedef typename internal_np::Lookup_named_param_def < - internal_np::graph_visitor_t, + internal_np::visitor_t, NamedParameters, Corefinement::Default_visitor//default > ::type User_visitor; - User_visitor uv(choose_parameter(get_parameter(np, internal_np::graph_visitor))); + User_visitor uv(choose_parameter(get_parameter(np, internal_np::visitor))); // surface intersection algorithm call typedef Corefinement::Output_builder_for_autorefinement Ob; typedef Corefinement::Surface_intersection_visitor_for_corefinement< - TriangleMesh, Vpm, Ob, Ecm, User_visitor,true> Algo_visitor; + TriangleMesh, VPM, VPM, Ob, Ecm, User_visitor,true> Algo_visitor; Ob ob(tm, vpm, fid_map, ecm); - Corefinement::Intersection_of_triangle_meshes + Corefinement::Intersection_of_triangle_meshes functor(tm, vpm, Algo_visitor(uv,ob,ecm) ); functor(CGAL::Emptyset_iterator(), true); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h index c3929c5c3cc..6f57675de59 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Face_graph_output_builder.h @@ -58,7 +58,8 @@ namespace PMP=Polygon_mesh_processing; namespace params=PMP::parameters; template ::value_type - >::Kernel >::type Kernel; + typename boost::property_traits::value_type + >::Kernel >::type Kernel; + typedef typename Default::Get > >::type EdgeMarkMapBind; @@ -111,8 +113,8 @@ class Face_graph_output_builder //Data members TriangleMesh &tm1, &tm2; // property maps of input meshes - const VertexPointMap vpm1; - const VertexPointMap vpm2; + const VertexPointMap1& vpm1; + const VertexPointMap2& vpm2; FaceIdMap1 fids1; FaceIdMap2 fids2; EdgeMarkMapBind& marks_on_input_edges; @@ -346,8 +348,8 @@ public: Face_graph_output_builder(TriangleMesh& tm1, TriangleMesh& tm2, - const VertexPointMap vpm1, - const VertexPointMap vpm2, + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2, FaceIdMap1 fids1, FaceIdMap2 fids2, EdgeMarkMapBind& marks_on_input_edges, @@ -1098,10 +1100,6 @@ public: if (!is_tm2_closed) patch_status_not_set_tm1.reset(); - typedef Side_of_triangle_mesh Inside_poly_test; - #ifdef CGAL_COREFINEMENT_POLYHEDRA_DEBUG #warning stop using next_marked_halfedge_around_target_vertex and create lists of halfedges instead? #endif @@ -1111,7 +1109,7 @@ public: CGAL::Bounded_side in_tm2 = is_tm2_inside_out ? ON_UNBOUNDED_SIDE : ON_BOUNDED_SIDE; - Inside_poly_test inside_tm2(tm2, vpm2); + Side_of_triangle_mesh inside_tm2(tm2, vpm2); for(face_descriptor f : faces(tm1)) { @@ -1173,7 +1171,7 @@ public: CGAL::Bounded_side in_tm1 = is_tm1_inside_out ? ON_UNBOUNDED_SIDE : ON_BOUNDED_SIDE; - Inside_poly_test inside_tm1(tm1, vpm1); + Side_of_triangle_mesh inside_tm1(tm1, vpm1); for(face_descriptor f : faces(tm2)) { const std::size_t f_id = get(fids2, f); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h index bcc8e75469d..d84788ff868 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Generic_clip_output_builder.h @@ -38,7 +38,8 @@ namespace PMP=Polygon_mesh_processing; namespace params=PMP::parameters; template @@ -48,7 +49,7 @@ class Generic_clip_output_builder typedef typename Default::Get< Kernel_, typename Kernel_traits< - typename boost::property_traits::value_type + typename boost::property_traits::value_type >::Kernel >::type Kernel; // graph_traits typedefs @@ -76,8 +77,8 @@ class Generic_clip_output_builder //Data members TriangleMesh &tm1, &tm2; // property maps of input meshes - const VertexPointMap vpm1; - const VertexPointMap vpm2; + const VertexPointMap1 vpm1; + const VertexPointMap2 vpm2; Ecm1 ecm1; FaceIdMap1 fids1; bool use_compact_clipper; @@ -105,8 +106,8 @@ public: Generic_clip_output_builder(TriangleMesh& tm1, TriangleMesh& tm2, - const VertexPointMap vpm1, - const VertexPointMap vpm2, + const VertexPointMap1 vpm1, + const VertexPointMap2 vpm2, const Ecm1& ecm1, FaceIdMap1 fids1, bool use_compact_clipper) @@ -167,7 +168,7 @@ public: typedef Side_of_triangle_mesh Inside_poly_test; + VertexPointMap2> Inside_poly_test; CGAL::Bounded_side in_tm2 = is_tm2_inside_out ? ON_UNBOUNDED_SIDE : ON_BOUNDED_SIDE; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Visitor.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Visitor.h index 62a021acfbd..ca0d31915bb 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Visitor.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/Visitor.h @@ -102,7 +102,8 @@ struct No_extra_output_from_corefinement // A visitor for Intersection_of_triangle_meshes that can be used to corefine // two meshes template< class TriangleMesh, - class VertexPointMap, + class VertexPointMap1, + class VertexPointMap2, class OutputBuilder_ = Default, class EdgeMarkMapBind_ = Default, class UserVisitor_ = Default, @@ -141,8 +142,9 @@ private: typedef boost::unordered_map Vertex_to_node_id; typedef std::map Mesh_to_vertex_to_node_id; // typedef for the CDT - typedef typename Intersection_nodes::Exact_kernel EK; + typedef Intersection_nodes INodes; + typedef typename INodes::Exact_kernel EK; typedef Triangulation_2_projection_traits_3 CDT_traits; typedef Triangulation_vertex_base_with_info_2 Vb; typedef Constrained_triangulation_face_base_2 Fb; @@ -365,7 +367,8 @@ public: } } - if (tm1_ptr==const_mesh_ptr) return; + if (tm1_ptr==const_mesh_ptr) + return; CGAL_assertion(!is_target_coplanar || !is_source_coplanar); //coplanar edge are not forwarded @@ -406,16 +409,16 @@ public: //sort node ids so that we can split the hedge //consecutively - template + template void sort_vertices_along_hedge(std::vector& node_ids, halfedge_descriptor hedge, const TriangleMesh& tm, - const VertexPointMap& vpm, + const VPM& vpm, const Node_vector& nodes) { std::sort(node_ids.begin(), node_ids.end(), - Less_along_a_halfedge + Less_along_a_halfedge (hedge, tm, vpm, nodes) ); } @@ -490,6 +493,8 @@ public: }; + typedef boost::unordered_map Face_boundaries; + //update the id of input mesh vertex that are also a node void update_face_indices( std::array& f_vertices, @@ -592,22 +597,366 @@ public: return vh; } - void finalize(Intersection_nodes& nodes, - const TriangleMesh& tm1, - const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2) + template + void split_halfedges(OnEdgeMapIterator it, + const VPM& vpm, + INodes& nodes, + std::map& mesh_to_face_boundaries) + { + TriangleMesh& tm=*it->first; + CGAL_assertion(&tm!=const_mesh_ptr); + + On_edge_map& on_edge_map=it->second; + On_face_map& on_face_map=on_face[&tm]; + Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm]; + + for(typename On_edge_map::iterator it2=on_edge_map.begin(); + it2!=on_edge_map.end(); + ++it2) + { + //the edge to be split + halfedge_descriptor hedge=halfedge(it2->first,tm); + //indices of the nodes to be inserted + Node_ids& node_ids=it2->second; + CGAL_assertion( std::set(node_ids.begin(), node_ids.end()) + .size()==node_ids.size() ); + //sort nodes along the egde to allow consecutive splits + sort_vertices_along_hedge(node_ids,hedge,tm,vpm,nodes); + + //save original face and nodes for face of hedge (1) + if ( !is_border(hedge,tm) ){ + face_descriptor f=face(hedge,tm); + typename Face_boundaries::iterator it_face = face_boundaries.find(f); + if (it_face==face_boundaries.end()) + it_face=face_boundaries.insert(std::make_pair(f,Face_boundary(hedge,tm))).first; + it_face->second.copy_node_ids(hedge,node_ids.begin(),node_ids.end()); + } + + //save original face and nodes for face of hedge->opposite (2) + typename Face_boundaries::iterator opposite_original_info=face_boundaries.end(); + halfedge_descriptor hedge_opp = opposite(hedge,tm); + if ( !is_border(hedge_opp,tm) ){ + face_descriptor f=face(hedge_opp,tm); + opposite_original_info=face_boundaries.find(f); + if (opposite_original_info==face_boundaries.end()) + opposite_original_info=face_boundaries.insert(std::make_pair(f,Face_boundary(hedge_opp,tm))).first; + opposite_original_info->second.copy_node_ids(hedge_opp,node_ids.rbegin(),node_ids.rend()); + } + + typename Mesh_to_map_node::iterator it_map=mesh_to_node_id_to_vertex.find(&tm); + CGAL_assertion(it_map!=mesh_to_node_id_to_vertex.end()); + //a map to identify the vertex in the polyhedron corresponding to an intersection point + Node_id_to_vertex& node_id_to_vertex=it_map->second; + + CGAL_assertion_code(vertex_descriptor original_vertex=source(hedge,tm);) + + //We need an edge incident to the source vertex of hedge. This is the first opposite edge created. + bool first=true; + halfedge_descriptor hedge_incident_to_src=Graph_traits::null_halfedge(); + bool hedge_is_marked = call_get(marks_on_edges,tm,edge(hedge,tm)); + //do split the edges + CGAL_assertion_code(vertex_descriptor expected_src=source(hedge,tm)); + for(std::size_t node_id : node_ids) + { + halfedge_descriptor hnew = Euler::split_edge(hedge, tm); + CGAL_assertion(expected_src==source(hnew,tm)); + vertex_descriptor vnew=target(hnew,tm); +// user_visitor.new_vertex_added(node_id, vnew, tm); // NODE_VISITOR_TAG + nodes.call_put(vpm, vnew, node_id, tm); + // register the new vertex in the output builder + output_builder.set_vertex_id(vnew, node_id, tm); + node_id_to_vertex[node_id]=vnew; + if (first){ + first=false; + hedge_incident_to_src=next(opposite(hedge,tm),tm); + } + + //update marker tags. If the edge was marked, then the resulting edges in the split must be marked + if ( hedge_is_marked ) + call_put(marks_on_edges,tm,edge(hnew,tm),true); + + CGAL_assertion_code(expected_src=vnew); + } + + CGAL_assertion(target(hedge_incident_to_src,tm)==original_vertex); + CGAL_assertion(face(hedge_incident_to_src,tm)==face(hedge_opp,tm)); + + //save original face and nodes for face of hedge->opposite (2) + if ( !is_border(hedge_opp,tm) ){ + CGAL_assertion(opposite_original_info!=face_boundaries.end()); + opposite_original_info->second.update_original_halfedge( + hedge_opp,hedge_incident_to_src,tm); + } + + //insert the two incident faces in on_face map so that they will be triangulated. + if (!is_border(hedge,tm)) on_face_map[face(hedge,tm)]; + if (!is_border(hedge_opp,tm)) on_face_map[face(hedge_opp,tm)]; + } + } + + template + void triangulate_intersected_faces(OnFaceMapIterator it, + const VPM& vpm, + INodes& nodes, + std::map& mesh_to_face_boundaries) + { + TriangleMesh& tm=*it->first; + CGAL_assertion(&tm!=const_mesh_ptr); + + On_face_map& on_face_map=it->second; + Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm]; + Node_id_to_vertex& node_id_to_vertex=mesh_to_node_id_to_vertex[&tm]; + Vertex_to_node_id& vertex_to_node_id=mesh_to_vertex_to_node_id[&tm]; + + const Node_id nb_nodes = nodes.size(); + + for (typename On_face_map::iterator it=on_face_map.begin(); + it!=on_face_map.end();++it) + { + face_descriptor f = it->first; //the face to be triangulated + Node_ids& node_ids = it->second; // ids of nodes in the interior of f + typename Face_boundaries::iterator it_fb=face_boundaries.find(f); + + std::map id_to_CDT_vh; + + //associate an edge of the triangulation to a halfedge in a given polyhedron + std::map,halfedge_descriptor> edge_to_hedge; + + // the vertices of f + std::array f_vertices; + // the node_id of an input vertex or a fake id (>=nb_nodes) + std::array f_indices = {{nb_nodes,nb_nodes+1,nb_nodes+2}}; + if (it_fb!=face_boundaries.end()){ //the boundary of the triangle face was refined + f_vertices[0]=it_fb->second.vertices[0]; + f_vertices[1]=it_fb->second.vertices[1]; + f_vertices[2]=it_fb->second.vertices[2]; + update_face_indices(f_vertices,f_indices,vertex_to_node_id); + if (doing_autorefinement) + it_fb->second.update_node_id_to_vertex_map(node_id_to_vertex, tm); + } + else{ + CGAL_assertion( is_triangle(halfedge(f,tm),tm) ); + halfedge_descriptor h0=halfedge(f,tm), h1=next(h0,tm), h2=next(h1,tm); + f_vertices[0]=target(h0,tm); //nb_nodes + f_vertices[1]=target(h1,tm); //nb_nodes+1 + f_vertices[2]=target(h2,tm); //nb_nodes+2 + + update_face_indices(f_vertices,f_indices,vertex_to_node_id); + edge_to_hedge[std::make_pair( f_indices[2],f_indices[0] )] = h0; + edge_to_hedge[std::make_pair( f_indices[0],f_indices[1] )] = h1; + edge_to_hedge[std::make_pair( f_indices[1],f_indices[2] )] = h2; + } + + typename EK::Point_3 p = nodes.to_exact(get(vpm,f_vertices[0])), + q = nodes.to_exact(get(vpm,f_vertices[1])), + r = nodes.to_exact(get(vpm,f_vertices[2])); +///TODO use a positive normal and remove all work around to guarantee that triangulation of coplanar patches are compatible + CDT_traits traits(typename EK::Construct_normal_3()(p,q,r)); + CDT cdt(traits); + + // insert triangle points + std::array triangle_vertices; + //we can do this to_exact because these are supposed to be input points. + triangle_vertices[0]=cdt.insert_outside_affine_hull(p); + triangle_vertices[1]=cdt.insert_outside_affine_hull(q); + triangle_vertices[2]=cdt.tds().insert_dim_up(cdt.infinite_vertex(), false); + triangle_vertices[2]->set_point(r); + + + triangle_vertices[0]->info()=f_indices[0]; + triangle_vertices[1]->info()=f_indices[1]; + triangle_vertices[2]->info()=f_indices[2]; + + node_id_to_vertex[nb_nodes ]=f_vertices[0]; + node_id_to_vertex[nb_nodes+1]=f_vertices[1]; + node_id_to_vertex[nb_nodes+2]=f_vertices[2]; + + //if one of the triangle input vertex is also a node + for (int ik=0;ik<3;++ik){ + if ( f_indices[ik]vertex(oi) ) ); + } + + // In this loop, for each original edge of the triangle, we insert + // the constrained edges and we recover the halfedge_descriptor + // corresponding to these constrained (they are already in tm) + Face_boundary& f_boundary=it_fb->second; + for (int i=0;i<3;++i){ + //handle case of halfedge starting at triangle_vertices[i] + // and ending at triangle_vertices[(i+1)%3] + + const Node_ids& ids_on_edge=f_boundary.node_ids_array[i]; + CDT_Vertex_handle previous=triangle_vertices[i]; + Node_id prev_index=f_indices[i];// node-id of the mesh vertex + halfedge_descriptor hedge = next(f_boundary.halfedges[(i+2)%3],tm); + CGAL_assertion( source(hedge,tm)==f_boundary.vertices[i] ); + if (!ids_on_edge.empty()){ //is there at least one node on this edge? + // fh must be an infinite face + // The points must be ordered from fh->vertex(cw(infinite_vertex)) to fh->vertex(ccw(infinite_vertex)) + for(Node_id id : ids_on_edge) + { + CDT_Vertex_handle vh=insert_point_on_ch_edge(cdt,infinite_faces[i],nodes.exact_node(id)); + vh->info()=id; + id_to_CDT_vh.insert(std::make_pair(id,vh)); + edge_to_hedge[std::make_pair(prev_index,id)]=hedge; + previous=vh; + hedge=next(hedge,tm); + prev_index=id; + } + } + else{ + CGAL_assertion_code(halfedge_descriptor hd=f_boundary.halfedges[i]); + CGAL_assertion( target(hd,tm) == f_boundary.vertices[(i+1)%3] ); + CGAL_assertion( source(hd,tm) == f_boundary.vertices[ i ] ); + } + CGAL_assertion(hedge==f_boundary.halfedges[i]); + edge_to_hedge[std::make_pair(prev_index,f_indices[(i+1)%3])] = + it_fb->second.halfedges[i]; + } + } + + //insert point inside face + for(Node_id node_id : node_ids) + { + CDT_Vertex_handle vh=cdt.insert(nodes.exact_node(node_id)); + vh->info()=node_id; + id_to_CDT_vh.insert(std::make_pair(node_id,vh)); + } + + std::vector > constrained_edges; + + // insert constraints that are interior to the triangle (in the case + // no edges are collinear in the meshes) + insert_constrained_edges(node_ids,cdt,id_to_CDT_vh,constrained_edges); + + // insert constraints between points that are on the boundary + // (not a contrained on the triangle boundary) + if (it_fb!=face_boundaries.end()) //is f not a triangle ? + { + for (int i=0;i<3;++i) + { + Node_ids& ids=it_fb->second.node_ids_array[i]; + insert_constrained_edges(ids,cdt,id_to_CDT_vh,constrained_edges,1); + } + } + + //insert coplanar edges for endpoints of triangles + for (int i=0;i<3;++i){ + Node_id nindex=triangle_vertices[i]->info(); + if ( nindex < nb_nodes ) + insert_constrained_edges_coplanar_case(nindex,cdt,id_to_CDT_vh); + } + + //XSL_TAG_CPL_VERT + //collect edges incident to a point that is the intersection of two + // coplanar faces. This ensure that triangulations are compatible. + if (it_fb!=face_boundaries.end()) //is f not a triangle ? + { + for (typename CDT::Finite_vertices_iterator + vit=cdt.finite_vertices_begin(), + vit_end=cdt.finite_vertices_end();vit_end!=vit;++vit) + { + //skip original vertices (that are not nodes) and non-coplanar face + // issued vertices (this is working because intersection points + // between coplanar facets are the first inserted) + if (vit->info() >= nb_nodes || + vit->info() >= number_coplanar_vertices) continue; + // \todo no need to insert constrained edges (they also are constrained + // in the other mesh)!! + typename std::map< Node_id,std::set >::iterator res = + coplanar_constraints.insert( + std::make_pair(vit->info(),std::set())).first; + //turn around the vertex and get incident edge + typename CDT::Edge_circulator start=cdt.incident_edges(vit); + typename CDT::Edge_circulator curr=start; + do{ + if (cdt.is_infinite(*curr) ) continue; + typename CDT::Edge mirror=cdt.mirror_edge(*curr); + if ( cdt.is_infinite( curr->first->vertex(curr->second) ) || + cdt.is_infinite( mirror.first->vertex(mirror.second) ) ) + continue; // skip edges that are on the boundary of the triangle + // (these are already constrained) + //insert edges in the set of constraints + CDT_Vertex_handle vh=vit; + int nindex = curr->first->vertex((curr->second+1)%3)==vh + ? (curr->second+2)%3 + : (curr->second+1)%3; + CDT_Vertex_handle vn=curr->first->vertex(nindex); + if ( vit->info() > vn->info() || vn->info()>=nb_nodes) + continue; //take only one out of the two edges + skip input + CGAL_assertion(vn->info()second.insert( vn->info() ); + }while(start!=++curr); + } + } + + // import the triangle in `cdt` in the face `f` of `tm` + triangulate_a_face(f, tm, nodes, node_ids, node_id_to_vertex, + edge_to_hedge, cdt, vpm, output_builder, user_visitor); + + // TODO Here we do the update only for internal edges. + // Update for border halfedges could be done during the split + + //3) mark halfedges that are common to two polyhedral surfaces + //recover halfedges inserted that are on the intersection + typedef std::pair Node_id_pair; + for(const Node_id_pair& node_id_pair : constrained_edges) + { + typename std::map + ::iterator it_poly_hedge=edge_to_hedge.find(node_id_pair); + //we cannot have an assertion here in case an edge or part of an edge is a constraints. + //Indeed, the graph_of_constraints report an edge 0,1 and 1,0 for example while only one of the two + //is defined as one of them defines an adjacent face + //CGAL_assertion(it_poly_hedge!=edge_to_hedge.end()); + if( it_poly_hedge!=edge_to_hedge.end() ){ + call_put(marks_on_edges,tm,edge(it_poly_hedge->second,tm),true); + output_builder.set_edge_per_polyline(tm,node_id_pair,it_poly_hedge->second); + } + else{ + //WARNING: in few case this is needed if the marked edge is on the border + //to optimize it might be better to only use sorted pair. TAG_SLXX1 + Node_id_pair opposite_pair(node_id_pair.second,node_id_pair.first); + it_poly_hedge=edge_to_hedge.find(opposite_pair); + CGAL_assertion( it_poly_hedge!=edge_to_hedge.end() ); + + call_put(marks_on_edges,tm,edge(it_poly_hedge->second,tm),true); + output_builder.set_edge_per_polyline(tm,opposite_pair,it_poly_hedge->second); + } + } + } + } + + void finalize(INodes& nodes, + const TriangleMesh& tm1, + const TriangleMesh& tm2, + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2) { nodes.all_nodes_created(); TriangleMesh* tm1_ptr = const_cast(&tm1); TriangleMesh* tm2_ptr = const_cast(&tm2); - std::map vpms; - vpms[tm1_ptr] = vpm1; - vpms[tm2_ptr] = vpm2; - vertex_descriptor null_vertex = Graph_traits::null_vertex(); const Node_id nb_nodes = nodes.size(); // we reserve nb_nodes+3 because we use the last three entries for the @@ -617,7 +966,6 @@ public: //store for each triangle face which boundary is intersected by the other surface, //original vertices (and halfedges in the refined mesh pointing on these vertices) - typedef boost::unordered_map Face_boundaries; std::map mesh_to_face_boundaries; //0) For each triangle mesh, collect original vertices that belongs to the intersection. @@ -632,6 +980,7 @@ public: { TriangleMesh& tm=*it->first; CGAL_assertion(&tm!=const_mesh_ptr); + // Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm]; Node_to_target_of_hedge_map& nodes_to_hedge=it->second; @@ -700,95 +1049,10 @@ public: for (typename std::map::iterator it=on_edge.begin(); it!=on_edge.end(); ++it) { - TriangleMesh& tm=*it->first; - CGAL_assertion(&tm!=const_mesh_ptr); - const VertexPointMap& vpm=vpms[&tm]; - On_edge_map& on_edge_map=it->second; - On_face_map& on_face_map=on_face[&tm]; - Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm]; - - for(typename On_edge_map::iterator it2=on_edge_map.begin(); - it2!=on_edge_map.end(); - ++it2) - { - //the edge to be split - halfedge_descriptor hedge=halfedge(it2->first,tm); - //indices of the nodes to be inserted - Node_ids& node_ids=it2->second; - CGAL_assertion( std::set(node_ids.begin(), node_ids.end()) - .size()==node_ids.size() ); - //sort nodes along the egde to allow consecutive splits - sort_vertices_along_hedge(node_ids,hedge,tm,vpm,nodes); - - //save original face and nodes for face of hedge (1) - if ( !is_border(hedge,tm) ){ - face_descriptor f=face(hedge,tm); - typename Face_boundaries::iterator it_face = face_boundaries.find(f); - if (it_face==face_boundaries.end()) - it_face=face_boundaries.insert(std::make_pair(f,Face_boundary(hedge,tm))).first; - it_face->second.copy_node_ids(hedge,node_ids.begin(),node_ids.end()); - } - - //save original face and nodes for face of hedge->opposite (2) - typename Face_boundaries::iterator opposite_original_info=face_boundaries.end(); - halfedge_descriptor hedge_opp = opposite(hedge,tm); - if ( !is_border(hedge_opp,tm) ){ - face_descriptor f=face(hedge_opp,tm); - opposite_original_info=face_boundaries.find(f); - if (opposite_original_info==face_boundaries.end()) - opposite_original_info=face_boundaries.insert(std::make_pair(f,Face_boundary(hedge_opp,tm))).first; - opposite_original_info->second.copy_node_ids(hedge_opp,node_ids.rbegin(),node_ids.rend()); - } - - typename Mesh_to_map_node::iterator it_map=mesh_to_node_id_to_vertex.find(&tm); - CGAL_assertion(it_map!=mesh_to_node_id_to_vertex.end()); - //a map to identify the vertex in the polyhedron corresponding to an intersection point - Node_id_to_vertex& node_id_to_vertex=it_map->second; - - CGAL_assertion_code(vertex_descriptor original_vertex=source(hedge,tm);) - - //We need an edge incident to the source vertex of hedge. This is the first opposite edge created. - bool first=true; - halfedge_descriptor hedge_incident_to_src=Graph_traits::null_halfedge(); - bool hedge_is_marked = call_get(marks_on_edges,tm,edge(hedge,tm)); - //do split the edges - CGAL_assertion_code(vertex_descriptor expected_src=source(hedge,tm)); - for(std::size_t node_id : node_ids) - { - halfedge_descriptor hnew = Euler::split_edge(hedge, tm); - CGAL_assertion(expected_src==source(hnew,tm)); - vertex_descriptor vnew=target(hnew,tm); -// user_visitor.new_vertex_added(node_id, vnew, tm); // NODE_VISITOR_TAG - nodes.call_put(vpm, vnew, node_id, tm); - // register the new vertex in the output builder - output_builder.set_vertex_id(vnew, node_id, tm); - node_id_to_vertex[node_id]=vnew; - if (first){ - first=false; - hedge_incident_to_src=next(opposite(hedge,tm),tm); - } - - //update marker tags. If the edge was marked, then the resulting edges in the split must be marked - if ( hedge_is_marked ) - call_put(marks_on_edges,tm,edge(hnew,tm),true); - - CGAL_assertion_code(expected_src=vnew); - } - - CGAL_assertion(target(hedge_incident_to_src,tm)==original_vertex); - CGAL_assertion(face(hedge_incident_to_src,tm)==face(hedge_opp,tm)); - - //save original face and nodes for face of hedge->opposite (2) - if ( !is_border(hedge_opp,tm) ){ - CGAL_assertion(opposite_original_info!=face_boundaries.end()); - opposite_original_info->second.update_original_halfedge( - hedge_opp,hedge_incident_to_src,tm); - } - - //insert the two incident faces in on_face map so that they will be triangulated. - if (!is_border(hedge,tm)) on_face_map[face(hedge,tm)]; - if (!is_border(hedge_opp,tm)) on_face_map[face(hedge_opp,tm)]; - } + if(it->first == tm1_ptr) + split_halfedges(it, vpm1, nodes, mesh_to_face_boundaries); + else + split_halfedges(it, vpm2, nodes, mesh_to_face_boundaries); } //2)triangulation of the triangle faces containing intersection point in their interior @@ -796,248 +1060,10 @@ public: for (typename std::map::iterator it=on_face.begin(); it!=on_face.end(); ++it) { - TriangleMesh& tm=*it->first; - CGAL_assertion(&tm!=const_mesh_ptr); - const VertexPointMap& vpm=vpms[&tm]; - On_face_map& on_face_map=it->second; - Face_boundaries& face_boundaries=mesh_to_face_boundaries[&tm]; - Node_id_to_vertex& node_id_to_vertex=mesh_to_node_id_to_vertex[&tm]; - Vertex_to_node_id& vertex_to_node_id=mesh_to_vertex_to_node_id[&tm]; - - for (typename On_face_map::iterator it=on_face_map.begin(); - it!=on_face_map.end();++it) - { - face_descriptor f = it->first; //the face to be triangulated - Node_ids& node_ids = it->second; // ids of nodes in the interior of f - typename Face_boundaries::iterator it_fb=face_boundaries.find(f); - - std::map id_to_CDT_vh; - - //associate an edge of the triangulation to a halfedge in a given polyhedron - std::map,halfedge_descriptor> edge_to_hedge; - - // the vertices of f - std::array f_vertices; - // the node_id of an input vertex or a fake id (>=nb_nodes) - std::array f_indices = {{nb_nodes,nb_nodes+1,nb_nodes+2}}; - if (it_fb!=face_boundaries.end()){ //the boundary of the triangle face was refined - f_vertices[0]=it_fb->second.vertices[0]; - f_vertices[1]=it_fb->second.vertices[1]; - f_vertices[2]=it_fb->second.vertices[2]; - update_face_indices(f_vertices,f_indices,vertex_to_node_id); - if (doing_autorefinement) - it_fb->second.update_node_id_to_vertex_map(node_id_to_vertex, tm); - } - else{ - CGAL_assertion( is_triangle(halfedge(f,tm),tm) ); - halfedge_descriptor h0=halfedge(f,tm), h1=next(h0,tm), h2=next(h1,tm); - f_vertices[0]=target(h0,tm); //nb_nodes - f_vertices[1]=target(h1,tm); //nb_nodes+1 - f_vertices[2]=target(h2,tm); //nb_nodes+2 - - update_face_indices(f_vertices,f_indices,vertex_to_node_id); - edge_to_hedge[std::make_pair( f_indices[2],f_indices[0] )] = h0; - edge_to_hedge[std::make_pair( f_indices[0],f_indices[1] )] = h1; - edge_to_hedge[std::make_pair( f_indices[1],f_indices[2] )] = h2; - } - - typename EK::Point_3 p = nodes.to_exact(get(vpm,f_vertices[0])), - q = nodes.to_exact(get(vpm,f_vertices[1])), - r = nodes.to_exact(get(vpm,f_vertices[2])); -///TODO use a positive normal and remove all work around to guarantee that triangulation of coplanar patches are compatible - CDT_traits traits(typename EK::Construct_normal_3()(p,q,r)); - CDT cdt(traits); - - // insert triangle points - std::array triangle_vertices; - //we can do this to_exact because these are supposed to be input points. - triangle_vertices[0]=cdt.insert_outside_affine_hull(p); - triangle_vertices[1]=cdt.insert_outside_affine_hull(q); - triangle_vertices[2]=cdt.tds().insert_dim_up(cdt.infinite_vertex(), false); - triangle_vertices[2]->set_point(r); - - - triangle_vertices[0]->info()=f_indices[0]; - triangle_vertices[1]->info()=f_indices[1]; - triangle_vertices[2]->info()=f_indices[2]; - - node_id_to_vertex[nb_nodes ]=f_vertices[0]; - node_id_to_vertex[nb_nodes+1]=f_vertices[1]; - node_id_to_vertex[nb_nodes+2]=f_vertices[2]; - - //if one of the triangle input vertex is also a node - for (int ik=0;ik<3;++ik){ - if ( f_indices[ik]vertex(oi) ) ); - } - - // In this loop, for each original edge of the triangle, we insert - // the constrained edges and we recover the halfedge_descriptor - // corresponding to these constrained (they are already in tm) - Face_boundary& f_boundary=it_fb->second; - for (int i=0;i<3;++i){ - //handle case of halfedge starting at triangle_vertices[i] - // and ending at triangle_vertices[(i+1)%3] - - const Node_ids& ids_on_edge=f_boundary.node_ids_array[i]; - CDT_Vertex_handle previous=triangle_vertices[i]; - Node_id prev_index=f_indices[i];// node-id of the mesh vertex - halfedge_descriptor hedge = next(f_boundary.halfedges[(i+2)%3],tm); - CGAL_assertion( source(hedge,tm)==f_boundary.vertices[i] ); - if (!ids_on_edge.empty()){ //is there at least one node on this edge? - // fh must be an infinite face - // The points must be ordered from fh->vertex(cw(infinite_vertex)) to fh->vertex(ccw(infinite_vertex)) - for(Node_id id : ids_on_edge) - { - CDT_Vertex_handle vh=insert_point_on_ch_edge(cdt,infinite_faces[i],nodes.exact_node(id)); - vh->info()=id; - id_to_CDT_vh.insert(std::make_pair(id,vh)); - edge_to_hedge[std::make_pair(prev_index,id)]=hedge; - previous=vh; - hedge=next(hedge,tm); - prev_index=id; - } - } - else{ - CGAL_assertion_code(halfedge_descriptor hd=f_boundary.halfedges[i]); - CGAL_assertion( target(hd,tm) == f_boundary.vertices[(i+1)%3] ); - CGAL_assertion( source(hd,tm) == f_boundary.vertices[ i ] ); - } - CGAL_assertion(hedge==f_boundary.halfedges[i]); - edge_to_hedge[std::make_pair(prev_index,f_indices[(i+1)%3])] = - it_fb->second.halfedges[i]; - } - } - - //insert point inside face - for(Node_id node_id : node_ids) - { - CDT_Vertex_handle vh=cdt.insert(nodes.exact_node(node_id)); - vh->info()=node_id; - id_to_CDT_vh.insert(std::make_pair(node_id,vh)); - } - - std::vector > constrained_edges; - - // insert constraints that are interior to the triangle (in the case - // no edges are collinear in the meshes) - insert_constrained_edges(node_ids,cdt,id_to_CDT_vh,constrained_edges); - - // insert constraints between points that are on the boundary - // (not a contrained on the triangle boundary) - if (it_fb!=face_boundaries.end()) //is f not a triangle ? - { - for (int i=0;i<3;++i) - { - Node_ids& ids=it_fb->second.node_ids_array[i]; - insert_constrained_edges(ids,cdt,id_to_CDT_vh,constrained_edges,1); - } - } - - //insert coplanar edges for endpoints of triangles - for (int i=0;i<3;++i){ - Node_id nindex=triangle_vertices[i]->info(); - if ( nindex < nb_nodes ) - insert_constrained_edges_coplanar_case(nindex,cdt,id_to_CDT_vh); - } - - //XSL_TAG_CPL_VERT - //collect edges incident to a point that is the intersection of two - // coplanar faces. This ensure that triangulations are compatible. - if (it_fb!=face_boundaries.end()) //is f not a triangle ? - { - for (typename CDT::Finite_vertices_iterator - vit=cdt.finite_vertices_begin(), - vit_end=cdt.finite_vertices_end();vit_end!=vit;++vit) - { - //skip original vertices (that are not nodes) and non-coplanar face - // issued vertices (this is working because intersection points - // between coplanar facets are the first inserted) - if (vit->info() >= nb_nodes || - vit->info() >= number_coplanar_vertices) continue; - // \todo no need to insert constrained edges (they also are constrained - // in the other mesh)!! - typename std::map< Node_id,std::set >::iterator res = - coplanar_constraints.insert( - std::make_pair(vit->info(),std::set())).first; - //turn around the vertex and get incident edge - typename CDT::Edge_circulator start=cdt.incident_edges(vit); - typename CDT::Edge_circulator curr=start; - do{ - if (cdt.is_infinite(*curr) ) continue; - typename CDT::Edge mirror=cdt.mirror_edge(*curr); - if ( cdt.is_infinite( curr->first->vertex(curr->second) ) || - cdt.is_infinite( mirror.first->vertex(mirror.second) ) ) - continue; // skip edges that are on the boundary of the triangle - // (these are already constrained) - //insert edges in the set of constraints - CDT_Vertex_handle vh=vit; - int nindex = curr->first->vertex((curr->second+1)%3)==vh - ? (curr->second+2)%3 - : (curr->second+1)%3; - CDT_Vertex_handle vn=curr->first->vertex(nindex); - if ( vit->info() > vn->info() || vn->info()>=nb_nodes) - continue; //take only one out of the two edges + skip input - CGAL_assertion(vn->info()second.insert( vn->info() ); - }while(start!=++curr); - } - } - - // import the triangle in `cdt` in the face `f` of `tm` - triangulate_a_face(f, tm, nodes, node_ids, node_id_to_vertex, - edge_to_hedge, cdt, vpm, output_builder, user_visitor); - - // TODO Here we do the update only for internal edges. - // Update for border halfedges could be done during the split - - //3) mark halfedges that are common to two polyhedral surfaces - //recover halfedges inserted that are on the intersection - typedef std::pair Node_id_pair; - for(const Node_id_pair& node_id_pair : constrained_edges) - { - typename std::map - ::iterator it_poly_hedge=edge_to_hedge.find(node_id_pair); - //we cannot have an assertion here in case an edge or part of an edge is a constraints. - //Indeed, the graph_of_constraints report an edge 0,1 and 1,0 for example while only one of the two - //is defined as one of them defines an adjacent face - //CGAL_assertion(it_poly_hedge!=edge_to_hedge.end()); - if( it_poly_hedge!=edge_to_hedge.end() ){ - call_put(marks_on_edges,tm,edge(it_poly_hedge->second,tm),true); - output_builder.set_edge_per_polyline(tm,node_id_pair,it_poly_hedge->second); - } - else{ - //WARNING: in few case this is needed if the marked edge is on the border - //to optimize it might be better to only use sorted pair. TAG_SLXX1 - Node_id_pair opposite_pair(node_id_pair.second,node_id_pair.first); - it_poly_hedge=edge_to_hedge.find(opposite_pair); - CGAL_assertion( it_poly_hedge!=edge_to_hedge.end() ); - - call_put(marks_on_edges,tm,edge(it_poly_hedge->second,tm),true); - output_builder.set_edge_per_polyline(tm,opposite_pair,it_poly_hedge->second); - } - } - } + if(it->first == tm1_ptr) + triangulate_intersected_faces(it, vpm1, nodes, mesh_to_face_boundaries); + else + triangulate_intersected_faces(it, vpm2, nodes, mesh_to_face_boundaries); } nodes.finalize(); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h index cd6dd59b944..8614627c59b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/face_graph_utils.h @@ -583,7 +583,8 @@ next_marked_halfedge_around_target_vertex( template void import_polyline( @@ -598,8 +599,8 @@ void import_polyline( VertexMap& pm1_to_output_vertices, const IntersectionEdgeMap& intersection_edges1, const IntersectionEdgeMap& intersection_edges2, - const VertexPointMap& vpm1, - const VertexPointMap& /*vpm2*/, + const VertexPointMap1& vpm1, + const VertexPointMap2& /*vpm2*/, const VertexPointMapOut& vpm_out, std::vector ::edge_descriptor>& output_shared_edges) @@ -1004,7 +1005,8 @@ void append_patches_to_triangle_mesh( template < class TriangleMesh, class IntersectionEdgeMap, - class VertexPointMap, + class VertexPointMap1, + class VertexPointMap2, class VertexPointMapOut, class EdgeMarkMap1, class EdgeMarkMap2, @@ -1024,8 +1026,8 @@ void fill_new_triangle_mesh( const IntersectionPolylines& polylines, const IntersectionEdgeMap& intersection_edges1, const IntersectionEdgeMap& intersection_edges2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2, + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2, const VertexPointMapOut& vpm_out, const EdgeMarkMap1& edge_mark_map1, const EdgeMarkMap2& edge_mark_map2, @@ -1261,7 +1263,8 @@ template +template std::tuple::halfedge_descriptor, bool,bool> @@ -87,23 +87,26 @@ intersection_type( typename boost::graph_traits::face_descriptor f_2, const TriangleMesh& tm1, const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2) + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2) { typedef boost::graph_traits GT; typedef typename GT::halfedge_descriptor halfedge_descriptor; typedef std::tuple result_type; - typedef typename boost::property_traits::reference Point_ref; - typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::property_traits::reference Point_ref1; + typedef typename boost::property_traits::reference Point_ref2; + typedef typename boost::property_traits::value_type Point_3; typedef typename Kernel_traits::Kernel Kernel; + CGAL_static_assertion((std::is_same::value_type>::value)); + halfedge_descriptor h_2=halfedge(f_2,tm2); - Point_ref a = get(vpm2, target(h_2,tm2) ); - Point_ref b = get(vpm2, target(next(h_2,tm2),tm2) ); - Point_ref c = get(vpm2, source(h_2,tm2) ); - Point_ref p = get(vpm1, source(h_1,tm1) ); - Point_ref q = get(vpm1, target(h_1,tm1) ); + Point_ref2 a = get(vpm2, target(h_2,tm2) ); + Point_ref2 b = get(vpm2, target(next(h_2,tm2),tm2) ); + Point_ref2 c = get(vpm2, source(h_2,tm2) ); + Point_ref1 p = get(vpm1, source(h_1,tm1) ); + Point_ref1 q = get(vpm1, target(h_1,tm1) ); const Orientation abcp = orientation(a,b,c,p); const Orientation abcq = orientation(a,b,c,q); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h index d5389e9f482..d7db498ae8c 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_callbacks.h @@ -67,15 +67,15 @@ public: }; template class Collect_face_bbox_per_edge_bbox_with_coplanar_handling { protected: const TriangleMesh& tm_faces; const TriangleMesh& tm_edges; - const VertexPointMap& vpmap_tmf; - const VertexPointMap& vpmap_tme; + const VertexPointMapF& vpmap_tmf; + const VertexPointMapE& vpmap_tme; EdgeToFaces& edge_to_faces; CoplanarFaceSet& coplanar_faces; @@ -83,7 +83,7 @@ protected: typedef typename Graph_traits::face_descriptor face_descriptor; typedef typename Graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename boost::property_traits::reference Point; + typedef typename boost::property_traits::reference Point; typedef CGAL::Box_intersection_d::ID_FROM_BOX_ADDRESS Box_policy; typedef CGAL::Box_intersection_d::Box_with_info_d Box; @@ -92,8 +92,8 @@ public: Collect_face_bbox_per_edge_bbox_with_coplanar_handling( const TriangleMesh& tm_faces, const TriangleMesh& tm_edges, - const VertexPointMap& vpmap_tmf, - const VertexPointMap& vpmap_tme, + const VertexPointMapF& vpmap_tmf, + const VertexPointMapE& vpmap_tme, EdgeToFaces& edge_to_faces, CoplanarFaceSet& coplanar_faces) : tm_faces(tm_faces) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h index 72c94c605d7..ab840fe75ec 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_impl.h @@ -83,10 +83,10 @@ struct Default_surface_intersection_visitor{ void start_new_polyline(std::size_t,std::size_t){} void add_node_to_polyline(std::size_t){} void input_have_coplanar_faces(){} - template + template void finalize(T&, const TriangleMesh&, const TriangleMesh&, - const VertexPointMap&, const VertexPointMap&) + const VPM1, const VPM2) {} void new_node_added_triple_face(std::size_t /* node_id */, face_descriptor /* f1 */, @@ -144,7 +144,7 @@ struct Node_id_set { }; template< class TriangleMesh, - class VertexPointMap, + class VertexPointMap1, class VertexPointMap2, class Node_visitor=Default_surface_intersection_visitor > class Intersection_of_triangle_meshes @@ -175,7 +175,7 @@ class Intersection_of_triangle_meshes // may contain several segments. typedef std::map< Face_pair_and_int, Node_id_set > Faces_to_nodes_map; typedef Intersection_nodes Node_vector; // data members @@ -188,11 +188,13 @@ class Intersection_of_triangle_meshes Faces_to_nodes_map f_to_node; //Associate a pair of triangles to their intersection points std::vector extra_terminal_nodes; //used only for autorefinement CGAL_assertion_code(bool doing_autorefinement;) + // member functions + template void filter_intersections(const TriangleMesh& tm_f, const TriangleMesh& tm_e, - const VertexPointMap& vpm_f, - const VertexPointMap& vpm_e, + const VPMF& vpm_f, + const VPME& vpm_e, bool throw_on_self_intersection) { std::vector face_boxes, edge_boxes; @@ -237,7 +239,7 @@ class Intersection_of_triangle_meshes Callback callback(tm_f, tm_e, edge_to_faces); #else typedef Collect_face_bbox_per_edge_bbox_with_coplanar_handling< - TriangleMesh, VertexPointMap, Edge_to_faces, Coplanar_face_set> + TriangleMesh, VPMF, VPME, Edge_to_faces, Coplanar_face_set> Callback; Callback callback(tm_f, tm_e, vpm_f, vpm_e, edge_to_faces, coplanar_faces); #endif @@ -258,8 +260,9 @@ class Intersection_of_triangle_meshes } // for autorefinement + template void filter_intersections(const TriangleMesh& tm, - const VertexPointMap& vpm) + const VPM& vpm) { std::vector face_boxes, edge_boxes; std::vector face_boxes_ptr, edge_boxes_ptr; @@ -296,7 +299,7 @@ class Intersection_of_triangle_meshes Edge_to_faces& edge_to_faces = stm_edge_to_ltm_faces; typedef Collect_face_bbox_per_edge_bbox_with_coplanar_handling_one_mesh< - TriangleMesh, VertexPointMap, Edge_to_faces, Coplanar_face_set> + TriangleMesh, VPM, Edge_to_faces, Coplanar_face_set> Callback; Callback callback(tm, vpm, edge_to_faces, coplanar_faces); @@ -527,12 +530,12 @@ class Intersection_of_triangle_meshes } } - void compute_intersection_of_coplanar_faces( - Node_id& current_node, - const TriangleMesh& tm1, - const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2) + template + void compute_intersection_of_coplanar_faces(Node_id& current_node, + const TriangleMesh& tm1, + const TriangleMesh& tm2, + const VPM1& vpm1, + const VPM2& vpm2) { CGAL_assertion( &tm1 < &tm2 || &tm1==&tm2 ); @@ -637,12 +640,13 @@ class Intersection_of_triangle_meshes //add a new node in the final graph. //it is the intersection of the triangle with the segment + template void add_new_node(halfedge_descriptor h_1, face_descriptor f_2, const TriangleMesh& tm1, const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2, + const VPM1& vpm1, + const VPM2& vpm2, std::tuple inter_res) @@ -657,11 +661,12 @@ class Intersection_of_triangle_meshes } } + template void compute_intersection_points(Edge_to_faces& tm1_edge_to_tm2_faces, const TriangleMesh& tm1, const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2, + const VPM1& vpm1, + const VPM2& vpm2, Node_id& current_node) { typedef std::tuple Inter_type; @@ -821,8 +826,9 @@ class Intersection_of_triangle_meshes } }; + template void detect_intersections_in_the_graph(const TriangleMesh& tm, - const VertexPointMap& vpm, + const VPM& vpm, Node_id& current_node) { boost::unordered_map void construct_polylines(Output_iterator out){ - typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::property_traits::value_type Point_3; std::size_t nb_nodes=nodes.size(); std::vector graph(nb_nodes); //counts the number of time each node has been seen @@ -1262,8 +1268,8 @@ class Intersection_of_triangle_meshes public: Intersection_of_triangle_meshes(const TriangleMesh& tm1, const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2, + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2, const Node_visitor& v=Node_visitor()) : nodes(tm1, tm2, vpm1, vpm2) , visitor(v) @@ -1275,7 +1281,7 @@ public: // for autorefinement Intersection_of_triangle_meshes(const TriangleMesh& tm, - const VertexPointMap& vpm, + const VertexPointMap1& vpm, const Node_visitor& v=Node_visitor()) : nodes(tm, tm, vpm, vpm) , visitor(v) @@ -1293,8 +1299,8 @@ public: const TriangleMesh& tm1=nodes.tm1; const TriangleMesh& tm2=nodes.tm2; - const VertexPointMap& vpm1=nodes.vpm1; - const VertexPointMap& vpm2=nodes.vpm2; + const VertexPointMap1& vpm1=nodes.vpm1; + const VertexPointMap2& vpm2=nodes.vpm2; filter_intersections(tm1, tm2, vpm1, vpm2, throw_on_self_intersection); filter_intersections(tm2, tm1, vpm2, vpm1, throw_on_self_intersection); @@ -1308,6 +1314,7 @@ public: compute_intersection_of_coplanar_faces(current_node, tm1, tm2, vpm1, vpm2); else compute_intersection_of_coplanar_faces(current_node, tm2, tm1, vpm2, vpm1); + visitor.set_number_of_intersection_points_from_coplanar_faces(current_node+1); if (!coplanar_faces.empty()) visitor.input_have_coplanar_faces(); @@ -1324,6 +1331,7 @@ public: compute_intersection_points(tm1_edge_to_tm2_faces, tm1, tm2, vpm1, vpm2, current_node); compute_intersection_points(tm2_edge_to_tm1_faces, tm2, tm1, vpm2, vpm1, current_node); + if (!build_polylines){ visitor.finalize(nodes,tm1,tm2,vpm1,vpm2); return output; @@ -1361,7 +1369,7 @@ public: CGAL_assertion(doing_autorefinement); const TriangleMesh& tm=nodes.tm1; - const VertexPointMap& vpm=nodes.vpm1; + const VertexPointMap1& vpm=nodes.vpm1; filter_intersections(tm, vpm); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_nodes.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_nodes.h index 9d43f9cc043..99ff0a7815f 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_nodes.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_nodes.h @@ -28,23 +28,26 @@ namespace Corefinement { // polylines. Different specializations are available depending whether // predicates on constructions are needed. template ::value_type + typename boost::property_traits::value_type >::Kernel::FT >::value > class Intersection_nodes; //Store only the double version of the intersection points. template -class Intersection_nodes + class VertexPointMap1, class VertexPointMap2> +class Intersection_nodes { //typedefs - typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::property_traits::value_type Point_3; + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); + typedef typename Kernel_traits::Kernel Input_kernel; typedef std::vector Nodes_vector; typedef CGAL::Exact_predicates_exact_constructions_kernel Exact_kernel; @@ -67,12 +70,13 @@ class Intersection_nodes public: const TriangleMesh &tm1, &tm2; - VertexPointMap vpm1, vpm2; + const VertexPointMap1& vpm1; + const VertexPointMap2& vpm2; Intersection_nodes(const TriangleMesh& tm1_, const TriangleMesh& tm2_, - const VertexPointMap& vpm1_, - const VertexPointMap& vpm2_) + const VertexPointMap1& vpm1_, + const VertexPointMap2& vpm2_) : tm1(tm1_) , tm2(tm2_) , vpm1(vpm1_) @@ -97,12 +101,13 @@ public: //add a new node in the final graph. //it is the intersection of the triangle with the segment + template // VertexPointMap1 or VertexPointMap2 void add_new_node(halfedge_descriptor h_a, face_descriptor f_b, const TriangleMesh& tm_a, const TriangleMesh& tm_b, - const VertexPointMap vpm_a, - const VertexPointMap& vpm_b) + const VPM_A& vpm_a, + const VPM_B& vpm_b) { halfedge_descriptor h_b = halfedge(f_b, tm_b); add_new_node( @@ -114,12 +119,8 @@ public: to_exact( get(vpm_a, target(h_a,tm_a)) ) ) ); } - void add_new_node(halfedge_descriptor edge_1, face_descriptor face_2) - { - add_new_node(edge_1, face_2, tm1, tm2, vpm1, vpm2); - } - - void call_put(const VertexPointMap& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh&) + template // VertexPointMap1 or VertexPointMap2 + void call_put(const VPM& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh&) { put(vpm, vd, nodes[i]); } @@ -132,14 +133,18 @@ public: // second specializations: store an exact copy of the points so // that we can answer exactly predicates -template -class Intersection_nodes +template +class Intersection_nodes { //typedefs public: typedef CGAL::Exact_predicates_exact_constructions_kernel Exact_kernel; + private: - typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::property_traits::value_type Point_3; + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); + typedef typename Kernel_traits::Kernel Input_kernel; typedef Cartesian_converter Double_to_exact; @@ -160,14 +165,16 @@ private: Exact_kernel::Intersect_3 exact_intersection; std::vector tm1_vertices, tm2_vertices; const bool doing_autorefinement; + public: const TriangleMesh &tm1, &tm2; - VertexPointMap vpm1, vpm2; + const VertexPointMap1& vpm1; + const VertexPointMap2& vpm2; Intersection_nodes(const TriangleMesh& tm1_, const TriangleMesh& tm2_, - const VertexPointMap& vpm1_, - const VertexPointMap& vpm2_) + const VertexPointMap1& vpm1_, + const VertexPointMap2& vpm2_) : doing_autorefinement(&tm1_ == &tm2_) , tm1(tm1_) , tm2(tm2_) @@ -211,12 +218,13 @@ public: //add a new node in the final graph. //it is the intersection of the triangle with the segment + template // VertexPointMap1 or VertexPointMap2 void add_new_node(halfedge_descriptor h_a, face_descriptor f_b, const TriangleMesh& tm_a, const TriangleMesh& tm_b, - const VertexPointMap vpm_a, - const VertexPointMap& vpm_b) + const VPM_A vpm_a, + const VPM_B vpm_b) { halfedge_descriptor h_b = halfedge(f_b, tm_b); add_new_node( @@ -229,11 +237,12 @@ public: } // use to resolve intersection of 3 faces in autorefinement only + template void add_new_node(halfedge_descriptor h1, halfedge_descriptor h2, halfedge_descriptor h3, const TriangleMesh& tm, - const VertexPointMap& vpm) + const VPM& vpm) { // TODO Far from optimal! typedef Exact_kernel::Plane_3 Plane_3; @@ -257,11 +266,6 @@ public: add_new_node(*pt); } - void add_new_node(halfedge_descriptor edge_1, face_descriptor face_2) - { - add_new_node(edge_1, face_2, tm1, tm2, vpm1, vpm2); - } - //the point is an input void add_new_node(const Point_3& p){ enodes.push_back(to_exact(p)); @@ -273,7 +277,8 @@ public: tm2_vertices.resize(enodes.size(), GT::null_vertex()); } - void call_put(const VertexPointMap& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh& tm) + template // VertexPointMap1 or VertexPointMap2 + void call_put(const VPM& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh& tm) { put(vpm, vd, exact_to_double(enodes[i])); if (&tm1==&tm) @@ -306,11 +311,16 @@ public: //Third specialization: The kernel already has exact constructions. -template -class Intersection_nodes +template +class Intersection_nodes { //typedefs - typedef typename boost::property_traits::value_type Point_3; + typedef typename boost::property_traits::value_type Point_3; + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); + typedef typename Kernel_traits::Kernel Input_kernel; typedef std::vector Nodes_vector; @@ -326,12 +336,13 @@ public: typedef Input_kernel Exact_kernel; const TriangleMesh &tm1, &tm2; - VertexPointMap vpm1, vpm2; + const VertexPointMap1& vpm1; + const VertexPointMap2& vpm2; Intersection_nodes(const TriangleMesh& tm1_, const TriangleMesh& tm2_, - const VertexPointMap& vpm1_, - const VertexPointMap& vpm2_) + const VertexPointMap1& vpm1_, + const VertexPointMap2& vpm2_) : tm1(tm1_) , tm2(tm2_) , vpm1(vpm1_) @@ -346,11 +357,12 @@ public: size_t size() const {return nodes.size();} const Point_3& exact_node(std::size_t i) const {return nodes[i];} + template void add_new_node(halfedge_descriptor h1, halfedge_descriptor h2, halfedge_descriptor h3, const TriangleMesh& tm, - const VertexPointMap& vpm) + const VPM& vpm) { // TODO Far from optimal! typedef typename Exact_kernel::Plane_3 Plane_3; @@ -376,12 +388,13 @@ public: //add a new node in the final graph. //it is the intersection of the triangle with the segment + template // VertexPointMap1 or VertexPointMap2 void add_new_node(halfedge_descriptor h_a, face_descriptor f_b, const TriangleMesh& tm_a, const TriangleMesh& tm_b, - const VertexPointMap vpm_a, - const VertexPointMap& vpm_b) + const VPM_A& vpm_a, + const VPM_B& vpm_b) { halfedge_descriptor h_b=halfedge(f_b,tm_b); @@ -394,12 +407,6 @@ public: get(vpm_a, target(h_a,tm_a)) ) ); } - void add_new_node(halfedge_descriptor edge_1, face_descriptor face_2) - { - add_new_node(edge_1, face_2, tm1, tm2, vpm1, vpm2); - } - - void add_new_node(const Point_3& p) { nodes.push_back(p); @@ -407,7 +414,8 @@ public: const Point_3& to_exact(const Point_3& p) const { return p; } - void call_put(const VertexPointMap& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh&) + template // VertexPointMap1 or VertexPointMap2 + void call_put(const VPM& vpm, vertex_descriptor vd, std::size_t i, TriangleMesh&) { put(vpm, vd, nodes[i]); } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_of_coplanar_triangles_3.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_of_coplanar_triangles_3.h index d4645badd45..3c4efee0abb 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_of_coplanar_triangles_3.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/intersection_of_coplanar_triangles_3.h @@ -27,10 +27,15 @@ namespace CGAL{ namespace Polygon_mesh_processing { namespace Corefinement{ -template -struct Intersect_coplanar_faces_3{ +template +struct Intersect_coplanar_faces_3 +{ // typedefs - typedef typename boost::property_traits::value_type Point; + typedef typename boost::property_traits::value_type Point; + + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); + typedef typename CGAL::Kernel_traits::Kernel Input_kernel; typedef CGAL::Exact_predicates_exact_constructions_kernel Exact_kernel; @@ -40,12 +45,14 @@ struct Intersect_coplanar_faces_3{ typedef Coplanar_intersection Inter_pt_info; // data members const TriangleMesh &tm1, &tm2; - const VertexPointMap &vpm1, &vpm2; + const VertexPointMap1& vpm1; + const VertexPointMap2& vpm2; + // constructor Intersect_coplanar_faces_3(const TriangleMesh& tm1_, const TriangleMesh& tm2_, - const VertexPointMap& vpm1_, - const VertexPointMap& vpm2_) + const VertexPointMap1& vpm1_, + const VertexPointMap2& vpm2_) : tm1(tm1_), tm2(tm2_), vpm1(vpm1_), vpm2(vpm2_) {} @@ -282,14 +289,14 @@ struct Intersect_coplanar_faces_3{ } }; -template +template void intersection_coplanar_faces( typename boost::graph_traits::face_descriptor f1, typename boost::graph_traits::face_descriptor f2, const TriangleMesh& tm1, const TriangleMesh& tm2, - const VertexPointMap& vpm1, - const VertexPointMap& vpm2, + const VertexPointMap1& vpm1, + const VertexPointMap2& vpm2, std::list< Coplanar_intersection >& inter_pts) { typedef boost::graph_traits GT; @@ -297,7 +304,7 @@ void intersection_coplanar_faces( halfedge_descriptor h1=halfedge(f1,tm1), h2=halfedge(f2,tm2); - Intersect_coplanar_faces_3 + Intersect_coplanar_faces_3 intersect_cpln(tm1, tm2, vpm1, vpm2); // We will add in `inter_pts` the initial triangle of h1 diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/predicates.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/predicates.h index a296e8de90a..4b25b21e472 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/predicates.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/internal/Corefinement/predicates.h @@ -122,15 +122,15 @@ bool are_triangles_coplanar_same_side( } -template +template bool are_triangles_coplanar_same_side(Node_id o_prime_index, Node_id o_index, Node_id p_index, Node_id q_index, vertex_descriptor p, vertex_descriptor q, - const Vpm& vpm_p, - const Vpm& vpm_q, + const VPMP& vpm_p, + const VPMQ& vpm_q, const Node_vector& nodes) { const Node_id NID((std::numeric_limits::max)()); @@ -142,7 +142,7 @@ bool are_triangles_coplanar_same_side(Node_id o_prime_index, ); } -template +template bool sorted_around_edge( Node_id o_prime_index, Node_id o_index, Node_id p1_index, @@ -151,8 +151,8 @@ bool sorted_around_edge( Node_id o_prime_index, vertex_descriptor p1, vertex_descriptor p2, vertex_descriptor q, - const Vpm& vpm_p, - const Vpm& vpm_q, + const VPMP& vpm_p, + const VPMQ& vpm_q, const Node_vector& nodes) { const Node_id NID((std::numeric_limits::max)()); 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 e64e707bbd8..ead3281779e 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 @@ -324,6 +324,10 @@ namespace internal { halfedge_status_pmap_ = get(CGAL::dynamic_halfedge_property_t(), pmesh); CGAL_assertion(CGAL::is_triangle_mesh(mesh_)); + CGAL_assertion_code(input_mesh_is_valid_ = CGAL::is_valid_polygon_mesh(pmesh)); + CGAL_warning_msg(input_mesh_is_valid_, + "The input mesh is not a valid polygon mesh. " + "It could lead PMP::isotropic_remeshing() to fail."); } ~Incremental_remesher() @@ -1033,7 +1037,7 @@ namespace internal { put(vpmap_, vp.first, initial_pos);//cancel move } - CGAL_assertion(is_valid_polygon_mesh(mesh_)); + CGAL_assertion(!input_mesh_is_valid_ || is_valid_polygon_mesh(mesh_)); CGAL_assertion(is_triangle_mesh(mesh_)); }//end for loop (nit == nb_iterations) @@ -1067,7 +1071,7 @@ namespace internal { Point proj = trees[patch_id_to_index_map[get_patch_id(face(halfedge(v, mesh_), mesh_))]]->closest_point(get(vpmap_, v)); put(vpmap_, v, proj); } - CGAL_assertion(is_valid_polygon_mesh(mesh_)); + CGAL_assertion(!input_mesh_is_valid_ || is_valid_polygon_mesh(mesh_)); CGAL_assertion(is_triangle_mesh(mesh_)); #ifdef CGAL_PMP_REMESHING_DEBUG debug_self_intersections(); @@ -1524,7 +1528,7 @@ private: // update status using constrained edge map if (!boost::is_same >::value) + Static_boolean_property_map >::value) { for(edge_descriptor e : edges(mesh_)) { @@ -1961,6 +1965,7 @@ private: EdgeIsConstrainedMap ecmap_; VertexIsConstrainedMap vcmap_; FaceIndexMap fimap_; + CGAL_assertion_code(bool input_mesh_is_valid_;) };//end class Incremental_remesher }//end namespace internal diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h index 3516580d7e0..fd5a838f16b 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/intersection.h @@ -1758,21 +1758,18 @@ surface_intersection(const TriangleMesh& tm1, const bool throw_on_self_intersection = parameters::choose_parameter(parameters::get_parameter(np1, internal_np::throw_on_self_intersection), false); - typedef typename GetVertexPointMap::const_type Vpm; - typedef typename GetVertexPointMap::const_type Vpm2; - CGAL_USE_TYPE(Vpm2); - CGAL_assertion_code( - static const bool same_vpm = (boost::is_same::value);) - CGAL_static_assertion(same_vpm); + typedef typename GetVertexPointMap::const_type VPM1; + typedef typename GetVertexPointMap::const_type VPM2; - Vpm vpm1 = parameters::choose_parameter(parameters::get_parameter(np1, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, tm1)); - Vpm vpm2 = parameters::choose_parameter(parameters::get_parameter(np2, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, tm2)); + CGAL_static_assertion((std::is_same::value_type, + typename boost::property_traits::value_type>::value)); - Corefinement::Intersection_of_triangle_meshes + VPM1 vpm1 = parameters::choose_parameter(parameters::get_parameter(np1, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, tm1)); + VPM2 vpm2 = parameters::choose_parameter(parameters::get_parameter(np2, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, tm2)); + + Corefinement::Intersection_of_triangle_meshes functor(tm1, tm2, vpm1, vpm2); return functor(polyline_output, throw_on_self_intersection, true); } @@ -1814,17 +1811,14 @@ surface_self_intersection(const TriangleMesh& tm, const NamedParameters& np) { // Vertex point maps - typedef typename GetVertexPointMap::const_type Vpm; + typedef typename GetVertexPointMap::const_type VPM; - Vpm vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), - get_const_property_map(CGAL::vertex_point, tm)); + VPM vpm = parameters::choose_parameter(parameters::get_parameter(np, internal_np::vertex_point), + get_const_property_map(CGAL::vertex_point, tm)); // surface intersection algorithm call - typedef Corefinement::Default_surface_intersection_visitor Visitor; - Corefinement::Intersection_of_triangle_meshes - functor(tm, vpm); + typedef Corefinement::Default_surface_intersection_visitor Visitor; + Corefinement::Intersection_of_triangle_meshes functor(tm, vpm); polyline_output=functor(polyline_output, true); return polyline_output; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/manifoldness.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/manifoldness.h index d818c4c4915..5d3b20d2355 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/manifoldness.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/manifoldness.h @@ -174,10 +174,10 @@ std::size_t make_umbrella_manifold(typename boost::graph_traits::ha typedef typename internal_np::Lookup_named_param_def // default (no constraint pmap) + Static_boolean_property_map // default (no constraint pmap) >::type VerticesMap; VerticesMap cmap = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); std::size_t nb_new_vertices = 0; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h index 6318c23a212..e85a3f6acfc 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h @@ -1281,7 +1281,7 @@ bool does_bound_a_volume(const TriangleMesh& tm, const NamedParameters& np) CGAL_precondition(is_closed(tm)); CGAL_precondition(is_triangle_mesh(tm)); - Static_property_map vidmap(0); // dummy map not used + Constant_property_map vidmap(0); // dummy map not used std::size_t res = volume_connected_components(tm, vidmap, np.do_orientation_tests(true) .i_used_as_a_predicate(true)); @@ -1370,7 +1370,7 @@ void orient_to_bound_a_volume(TriangleMesh& tm, std::vector face_cc(num_faces(tm), std::size_t(-1)); std::vector nesting_levels; std::vector is_cc_outward_oriented; - Static_property_map vidmap(0); // dummy map not used + Constant_property_map vidmap(0); // dummy map not used volume_connected_components(tm, vidmap, parameters::vertex_point_map(vpm) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h index b44e0f1d99a..fcaa0c5bd51 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/polygon_soup_to_polygon_mesh.h @@ -292,6 +292,17 @@ void polygon_soup_to_polygon_mesh(const PointRange& points, /// \cond SKIP_IN_MANUAL +template +void polygon_soup_to_polygon_mesh(const PointRange& points, + const PolygonRange& polygons, + PolygonMesh& out, + const NamedParameters_PS& np_ps) +{ + return polygon_soup_to_polygon_mesh(points, polygons, out, np_ps, parameters::all_default()); +} + template void polygon_soup_to_polygon_mesh(const PointRange& points, const PolygonRange& polygons, diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h index 33b8ba7f908..556998e2f9a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/random_perturbation.h @@ -182,10 +182,10 @@ void random_perturbation(VertexRange vertices typedef typename internal_np::Lookup_named_param_def < internal_np::vertex_is_constrained_t, NamedParameters, - Constant_property_map // default + Static_boolean_property_map // default > ::type VCMap; VCMap vcmap = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); unsigned int seed = choose_parameter(get_parameter(np, internal_np::random_seed), -1); bool do_project = choose_parameter(get_parameter(np, internal_np::do_project), true); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h index 78fd29ed683..04acb56d43a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/remesh.h @@ -214,18 +214,18 @@ void isotropic_remeshing(const FaceRange& faces typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, - Constant_property_map // default (no constraint pmap) + Static_boolean_property_map // default (no constraint pmap) > ::type ECMap; ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); typedef typename internal_np::Lookup_named_param_def < internal_np::vertex_is_constrained_t, NamedParameters, - Constant_property_map // default (no constraint pmap) + Static_boolean_property_map // default (no constraint pmap) > ::type VCMap; VCMap vcmap = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); bool protect = choose_parameter(get_parameter(np, internal_np::protect_constraints), false); typedef typename internal_np::Lookup_named_param_def < @@ -405,18 +405,18 @@ void split_long_edges(const EdgeRange& edges typedef typename internal_np::Lookup_named_param_def < internal_np::edge_is_constrained_t, NamedParameters, - Constant_property_map // default (no constraint pmap) + Static_boolean_property_map // default (no constraint pmap) > ::type ECMap; ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); typename internal::Incremental_remesher, // no constraint pmap + Static_boolean_property_map, // no constraint pmap internal::Connected_components_pmap, FIMap > remesher(pmesh, vpmap, gt, false/*protect constraints*/, ecmap, - Constant_property_map(false), + Static_boolean_property_map(), internal::Connected_components_pmap(faces(pmesh), pmesh, ecmap, fimap, false), fimap, false/*need aabb_tree*/); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h index 931858e4170..46b3dbe9ae8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair.h @@ -225,7 +225,7 @@ std::size_t remove_connected_components_of_negligible_size(TriangleMesh& tmesh, return 0; // Compute the connected components only once - boost::vector_property_map face_cc(fim); + boost::vector_property_map face_cc(static_cast(num_faces(tmesh)), fim); std::size_t num = connected_components(tmesh, face_cc, np); #ifdef CGAL_PMP_DEBUG_SMALL_CC_REMOVAL @@ -256,7 +256,7 @@ std::size_t remove_connected_components_of_negligible_size(TriangleMesh& tmesh, // Volumes make no sense for CCs that are not closed std::vector cc_closeness(num, true); - std::vector component_volumes(num); + std::vector component_volumes(num, FT(0)); if(use_volumes) { 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 99fa07969c9..c8c2ca3cd5d 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 @@ -183,13 +183,15 @@ bool is_collapse_geometrically_valid(typename boost::graph_traits: */ template -boost::optional get_collapse_volume(typename boost::graph_traits::halfedge_descriptor h, - const TriangleMesh& tmesh, - const VPM& vpm, - const Traits& gt) +boost::optional +get_collapse_volume(typename boost::graph_traits::halfedge_descriptor h, + const TriangleMesh& tmesh, + const VPM& vpm, + const Traits& gt) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::FT FT; typedef typename boost::property_traits::reference Point_ref; typedef typename Traits::Vector_3 Vector_3; @@ -204,8 +206,8 @@ boost::optional get_collapse_volume(typename boost::graph_traits::edge_descr const Traits& gt) { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::FT FT; halfedge_descriptor h = halfedge(e, tmesh), ho = opposite(h, tmesh); CGAL_assertion(!get(vcm, source(h, tmesh)) || !get(vcm, target(h, tmesh))); - boost::optional dv1 = get_collapse_volume(h, tmesh, vpm, gt); - boost::optional dv2 = get_collapse_volume(ho, tmesh, vpm, gt); + boost::optional dv1 = get_collapse_volume(h, tmesh, vpm, gt); + boost::optional dv2 = get_collapse_volume(ho, tmesh, vpm, gt); // the resulting point of the collapse of a halfedge is the target of the halfedge before collapse if(get(vcm, source(h, tmesh))) @@ -288,6 +291,7 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, { typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename Traits::FT FT; typedef typename boost::property_traits::reference Point_ref; typedef typename Traits::Vector_3 Vector_3; @@ -318,16 +322,16 @@ bool should_flip(typename boost::graph_traits::edge_descriptor e, const Vector_3 v23 = gt.construct_vector_3_object()(p2, p3); const Vector_3 v30 = gt.construct_vector_3_object()(p3, p0); - const double p1p3 = gt.compute_scalar_product_3_object()( - gt.construct_cross_product_vector_3_object()(v12, v23), - gt.construct_cross_product_vector_3_object()(v30, v01)); + const FT p1p3 = gt.compute_scalar_product_3_object()( + gt.construct_cross_product_vector_3_object()(v12, v23), + gt.construct_cross_product_vector_3_object()(v30, v01)); const Vector_3 v21 = gt.construct_opposite_vector_3_object()(v12); const Vector_3 v03 = gt.construct_opposite_vector_3_object()(v30); - const double p0p2 = gt.compute_scalar_product_3_object()( - gt.construct_cross_product_vector_3_object()(v01, v21), - gt.construct_cross_product_vector_3_object()(v23, v03)); + const FT p0p2 = gt.compute_scalar_product_3_object()( + gt.construct_cross_product_vector_3_object()(v01, v21), + gt.construct_cross_product_vector_3_object()(v23, v03)); return p0p2 <= p1p3; } @@ -353,17 +357,17 @@ bool remove_almost_degenerate_faces(const FaceRange& face_range, typedef typename boost::graph_traits::edge_descriptor edge_descriptor; typedef typename boost::graph_traits::face_descriptor face_descriptor; - typedef Constant_property_map Default_VCM; + typedef Static_boolean_property_map Default_VCM; typedef typename internal_np::Lookup_named_param_def::type VCM; - VCM vcm_np = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), Default_VCM(false)); + VCM vcm_np = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), Default_VCM()); - typedef Constant_property_map Default_ECM; + typedef Static_boolean_property_map Default_ECM; typedef typename internal_np::Lookup_named_param_def::type ECM; - ECM ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), Default_ECM(false)); + ECM ecm = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), Default_ECM()); typedef typename GetVertexPointMap::const_type VPM; VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), @@ -1689,37 +1693,23 @@ bool remove_degenerate_faces(const FaceRange& face_range, // Ignore faces with null edges if(!all_removed) { - std::map are_degenerate_edges; - - for(face_descriptor fd : degenerate_face_set) + typename std::set::iterator it = degenerate_face_set.begin(); + while(it != degenerate_face_set.end()) { - for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, tmesh), tmesh)) + bool has_degenerate_edge = false; + for(halfedge_descriptor hd : halfedges_around_face(halfedge(*it, tmesh), tmesh)) { - edge_descriptor ed = edge(hd, tmesh); - std::pair::iterator, bool> is_insert_successful = - are_degenerate_edges.insert(std::make_pair(ed, false)); - - bool is_degenerate = false; - if(is_insert_successful.second) + const edge_descriptor ed = edge(hd, tmesh); + if(is_degenerate_edge(ed, tmesh, np)) { - // did not previously exist in the map, so actually have to check if it is degenerate - if(traits.equal_3_object()(get(vpmap, target(ed, tmesh)), get(vpmap, source(ed, tmesh)))) - is_degenerate = true; - } - - is_insert_successful.first->second = is_degenerate; - - if(is_degenerate) - { - halfedge_descriptor h = halfedge(ed, tmesh); - if(!is_border(h, tmesh)) - degenerate_face_set.erase(face(h, tmesh)); - - h = opposite(h, tmesh); - if(!is_border(h, tmesh)) - degenerate_face_set.erase(face(h, tmesh)); + has_degenerate_edge = true; + it = degenerate_face_set.erase(it); + break; } } + + if(!has_degenerate_edge) + ++it; } } diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h index f91c077789f..be8a32276be 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/repair_self_intersections.h @@ -15,8 +15,7 @@ #include -#include -#include +#include #include #include #include diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h index 94d86cc5572..ebfb661d346 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/shape_predicates.h @@ -403,7 +403,7 @@ is_needle_triangle_face(typename boost::graph_traits::face_descrip if(min_sq_length == 0) return min_h; - const FT sq_threshold = threshold * threshold; + const FT sq_threshold = square(FT(threshold)); if(max_sq_length / min_sq_length >= sq_threshold) { CGAL_assertion(min_h != boost::graph_traits::null_halfedge()); @@ -482,7 +482,7 @@ is_cap_triangle_face(typename boost::graph_traits::face_descriptor typedef typename Traits::FT FT; typedef typename Traits::Vector_3 Vector_3; - const FT sq_threshold = threshold * threshold; + const FT sq_threshold = square(FT(threshold)); const halfedge_descriptor h0 = halfedge(f, tm); std::array sq_lengths; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h index de49b0ad6e6..c054e7feda8 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_mesh.h @@ -158,7 +158,7 @@ void smooth_mesh(const FaceRange& faces, typedef typename internal_np::Lookup_named_param_def // default + Static_boolean_property_map // default > ::type ECMap; typedef internal::Area_smoother Area_optimizer; @@ -218,7 +218,7 @@ void smooth_mesh(const FaceRange& faces, } ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); // a constrained edge has constrained extremities for(face_descriptor f : faces) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_shape.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_shape.h index 6693d4dace2..b1b663eb731 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_shape.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/smooth_shape.h @@ -115,7 +115,7 @@ void smooth_shape(const FaceRange& faces, typedef typename internal_np::Lookup_named_param_def< internal_np::vertex_is_constrained_t, NamedParameters, - Constant_property_map >::type VCMap; + Static_boolean_property_map >::type VCMap; using parameters::choose_parameter; using parameters::get_parameter; @@ -124,7 +124,7 @@ void smooth_shape(const FaceRange& faces, VertexPointMap vpmap = choose_parameter(get_parameter(np, internal_np::vertex_point), get_property_map(CGAL::vertex_point, tmesh)); VCMap vcmap = choose_parameter(get_parameter(np, internal_np::vertex_is_constrained), - Constant_property_map(false)); + Static_boolean_property_map()); const unsigned int nb_iterations = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); #if defined(CGAL_EIGEN3_ENABLED) diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h index 8f16d4d7bdb..6b5035e45fa 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/stitch_borders.h @@ -352,7 +352,7 @@ void run_stitch_borders(PolygonMesh& pmesh, CGAL_USE(vpm); std::vector vertices_to_delete; - for(const halfedges_pair hk : to_stitch) + for(const halfedges_pair& hk : to_stitch) { halfedge_descriptor h1 = hk.first; halfedge_descriptor h2 = hk.second; @@ -412,7 +412,7 @@ void run_stitch_borders(PolygonMesh& pmesh, /// In order to avoid having to maintain a set with halfedges to stitch /// we do on purpose next-prev linking that might not be useful but that /// is harmless and still less expensive than doing queries in a set - for(const halfedges_pair hk : to_stitch) + for(const halfedges_pair& hk : to_stitch) { halfedge_descriptor h1 = hk.first; halfedge_descriptor h2 = hk.second; @@ -430,7 +430,7 @@ void run_stitch_borders(PolygonMesh& pmesh, /// update HDS connectivity, removing the second halfedge /// of each the pair and its opposite - for(const halfedges_pair hk : to_stitch) + for(const halfedges_pair& hk : to_stitch) { halfedge_descriptor h1 = hk.first; halfedge_descriptor h2 = hk.second; @@ -491,7 +491,7 @@ std::size_t stitch_borders_impl(PolygonMesh& pmesh, typedef boost::unordered_map Uf_handles; Uf_handles uf_handles; - for(const halfedges_pair hk : to_stitch) + for(const halfedges_pair& hk : to_stitch) { halfedge_descriptor h1 = hk.first; halfedge_descriptor h2 = hk.second; @@ -575,7 +575,7 @@ std::size_t stitch_borders_impl(PolygonMesh& pmesh, { std::vector to_stitch_filtered; to_stitch_filtered.reserve( to_stitch.size()); - for(const halfedges_pair hk : to_stitch) + for(const halfedges_pair& hk : to_stitch) { // We test both halfedges because the previous test // might involve only one of the two halfedges @@ -591,7 +591,7 @@ std::size_t stitch_borders_impl(PolygonMesh& pmesh, // redo union find as some "master" vertex might be unstitchable uf_vertices.clear(); uf_handles.clear(); - for(const halfedges_pair hk : to_stitch_filtered) + for(const halfedges_pair& hk : to_stitch_filtered) { halfedge_descriptor h1 = hk.first; halfedge_descriptor h2 = hk.second; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/triangulate_faces.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/triangulate_faces.h index 9abbfeadf1c..a4c38c7b040 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/triangulate_faces.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/triangulate_faces.h @@ -45,11 +45,32 @@ namespace CGAL { namespace Polygon_mesh_processing { +namespace Triangulate_faces +{ +/** \ingroup PMP_meshing_grp +* %Default new face visitor model of `PMPTriangulateFaceVisitor`. +* All its functions have an empty body. This class can be used as a +* base class if only some of the functions of the concept require to be +* overriden. +*/ +template +struct Default_visitor { + typedef boost::graph_traits GT; + typedef typename GT::face_descriptor face_descriptor; + + void before_subface_creations(face_descriptor /*f_old*/) {} + void after_subface_creations() {} + void after_subface_created(face_descriptor /*f_new*/) {} +}; + +} //end namespace Triangulate_faces + namespace internal { template + , typename Kernel + , typename Visitor> class Triangulate_modifier { typedef Kernel Traits; @@ -80,7 +101,7 @@ public: return fh->info().is_external; } - bool triangulate_face(face_descriptor f, PM& pmesh, bool use_cdt) + bool triangulate_face(face_descriptor f, PM& pmesh, bool use_cdt, Visitor visitor) { typedef typename Traits::FT FT; @@ -116,14 +137,15 @@ public: */ FT p1p3 = CGAL::cross_product(p2-p1,p3-p2) * CGAL::cross_product(p0-p3,p1-p0); FT p0p2 = CGAL::cross_product(p1-p0,p1-p2) * CGAL::cross_product(p3-p2,p3-p0); - if(p0p2>p1p3) - { - CGAL::Euler::split_face(v0, v2, pmesh); - } - else - { - CGAL::Euler::split_face(v1, v3, pmesh); - } + visitor.before_subface_creations(f); + halfedge_descriptor res = (p0p2>p1p3) + ? CGAL::Euler::split_face(v0, v2, pmesh) + : CGAL::Euler::split_face(v1, v3, pmesh); + + visitor.after_subface_created(face(res,pmesh)); + visitor.after_subface_created(face(opposite(res,pmesh),pmesh)); + + visitor.after_subface_creations(); } else { @@ -143,18 +165,18 @@ public: Itag> CDT; P_traits cdt_traits(normal); CDT cdt(cdt_traits); - return triangulate_face_with_CDT(f, pmesh, cdt); + return triangulate_face_with_CDT(f, pmesh, cdt, visitor); } #else CGAL_USE(use_cdt); #endif - return triangulate_face_with_hole_filling(f, pmesh); + return triangulate_face_with_hole_filling(f, pmesh, visitor); } return true; } template - bool triangulate_face_with_CDT(face_descriptor f, PM& pmesh, CDT& cdt) + bool triangulate_face_with_CDT(face_descriptor f, PM& pmesh, CDT& cdt, Visitor visitor) { std::size_t original_size = CGAL::halfedges_around_face(halfedge(f, pmesh), pmesh).size(); @@ -212,6 +234,7 @@ public: // then modify the polyhedron + visitor.before_subface_creations(f); // make_hole. (see comment in function body) this->make_hole(halfedge(f, pmesh), pmesh); @@ -268,12 +291,14 @@ public: set_next(h2, h0, pmesh); Euler::fill_hole(h0, pmesh); + visitor.after_subface_created(face(h0, pmesh)); } } + visitor.after_subface_creations(); return true; } - bool triangulate_face_with_hole_filling(face_descriptor f, PM& pmesh) + bool triangulate_face_with_hole_filling(face_descriptor f, PM& pmesh, Visitor visitor) { namespace PMP = CGAL::Polygon_mesh_processing; @@ -307,6 +332,7 @@ public: ++i; } + visitor.before_subface_creations(f); bool first = true; std::vector hedges; hedges.reserve(4); @@ -316,6 +342,7 @@ public: first=false; else f=add_face(pmesh); + visitor.after_subface_created(f); std::array indices = make_array( triangle.first, @@ -346,11 +373,12 @@ public: set_halfedge(f, hedges[0], pmesh); hedges.clear(); } + visitor.after_subface_creations(); return true; } template - bool operator()(FaceRange face_range, PM& pmesh, bool use_cdt) + bool operator()(FaceRange face_range, PM& pmesh, bool use_cdt, Visitor visitor) { bool result = true; // One need to store facet handles into a vector, because the list of @@ -368,7 +396,7 @@ public: // Iterates on the vector of face descriptors for(face_descriptor f : facets) { - if(!this->triangulate_face(f, pmesh, use_cdt)) + if(!this->triangulate_face(f, pmesh, use_cdt, visitor)) result = false; } return result; @@ -422,6 +450,14 @@ public: * \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} * \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.} * \cgalParamNEnd +* +* \cgalParamNBegin{visitor} +* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces} +* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`} +* \cgalParamDefault{`Triangulate_faces::Default_visitor`} +* \cgalParamExtra{Note that the visitor will be copied, so +* it must not have any data member that does not have a reference-like type.} +* \cgalParamNEnd * \cgalNamedParamsEnd * * @return `true` if the face has been triangulated. @@ -446,8 +482,17 @@ bool triangulate_face(typename boost::graph_traits::face_descriptor //Option bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true); - internal::Triangulate_modifier modifier(vpmap, traits); - return modifier.triangulate_face(f, pmesh, use_cdt); + typedef typename internal_np::Lookup_named_param_def< + internal_np::visitor_t, + NamedParameters, + Triangulate_faces::Default_visitor//default + >::type Visitor; + Visitor visitor = choose_parameter( + get_parameter(np, internal_np::visitor), + Triangulate_faces::Default_visitor()); + + internal::Triangulate_modifier modifier(vpmap, traits); + return modifier.triangulate_face(f, pmesh, use_cdt, visitor); } template @@ -487,6 +532,14 @@ bool triangulate_face(typename boost::graph_traits::face_descriptor * \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} * \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.} * \cgalParamNEnd +* +* \cgalParamNBegin{visitor} +* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces} +* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`} +* \cgalParamDefault{`Triangulate_faces::Default_visitor`} +* \cgalParamExtra{Note that the visitor will be copied, so +* it must not have any data member that does not have a reference-like type.} +* `\cgalParamNEnd * \cgalNamedParamsEnd * * @return `true` if all the faces have been triangulated. @@ -513,8 +566,17 @@ bool triangulate_faces(FaceRange face_range, //Option bool use_cdt = choose_parameter(get_parameter(np, internal_np::use_delaunay_triangulation), true); - internal::Triangulate_modifier modifier(vpmap, traits); - return modifier(face_range, pmesh, use_cdt); + typedef typename internal_np::Lookup_named_param_def< + internal_np::visitor_t, + NamedParameters, + Triangulate_faces::Default_visitor//default + >::type Visitor; + Visitor visitor = choose_parameter( + get_parameter(np, internal_np::visitor), + Triangulate_faces::Default_visitor()); + + internal::Triangulate_modifier modifier(vpmap, traits); + return modifier(face_range, pmesh, use_cdt, visitor); } template @@ -548,6 +610,14 @@ bool triangulate_faces(FaceRange face_range, PolygonMesh& pmesh) * \cgalParamDefault{a \cgal Kernel deduced from the point type, using `CGAL::Kernel_traits`} * \cgalParamExtra{The geometric traits class must be compatible with the vertex point type.} * \cgalParamNEnd +* +* \cgalParamNBegin{visitor} +* \cgalParamDescription{a visitor that enables to track how faces are triangulated into subfaces} +* \cgalParamType{a class model of `PMPTriangulateFaceVisitor`} +* \cgalParamDefault{`Triangulate_faces::Default_visitor`} +* \cgalParamExtra{Note that the visitor will be copied, so +* it must not have any data member that does not have a reference-like type.} +* \cgalParamNEnd * \cgalNamedParamsEnd * * @return `true` if all the faces have been triangulated. diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt index 6c0c88bd4b7..4b475645a03 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/CMakeLists.txt @@ -120,13 +120,13 @@ if(OpenMesh_FOUND) endif() find_package(Ceres QUIET) -if(TARGET ceres) +if(TARGET ceres AND TARGET CGAL::Eigen_support) target_compile_definitions( test_mesh_smoothing PRIVATE CGAL_PMP_USE_CERES_SOLVER ) - target_link_libraries( test_mesh_smoothing PRIVATE ceres ) + target_link_libraries( test_mesh_smoothing PUBLIC CGAL::Eigen_support PRIVATE ceres ) # target_compile_definitions( test_pmp_repair_self_intersections PRIVATE CGAL_PMP_USE_CERES_SOLVER ) # target_link_libraries( test_pmp_repair_self_intersections PRIVATE ceres ) -endif(TARGET ceres) +endif(TARGET ceres AND TARGET CGAL::Eigen_support) if(BUILD_TESTING) set_tests_properties( diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_polyhedron.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_polyhedron.cpp index 9b5a81b4855..45ad5168a05 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_polyhedron.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/connected_component_polyhedron.cpp @@ -38,7 +38,7 @@ void mesh_with_id(const char* argv1, const bool save_output) boost::vector_property_map::type> - fccmap(get(CGAL::face_index,sm)); + fccmap(static_cast(num_faces(sm)), get(CGAL::face_index,sm)); std::size_t num = PMP::connected_components(sm, fccmap); if (strcmp(argv1, "data/blobby_3cc.off") == 0) @@ -92,7 +92,7 @@ void mesh_no_id(const char* argv1, const bool save_output) boost::vector_property_map::type> - fccmap(fim); + fccmap(static_cast(num_faces(sm)), fim); std::size_t num = PMP::connected_components(sm, fccmap); @@ -133,7 +133,7 @@ void test_border_cases() boost::vector_property_map::type> - fccmap(get(boost::face_index,sm)); + fccmap(static_cast(num_faces(sm)), get(boost::face_index,sm)); PMP::connected_components(sm, fccmap); std::size_t nb_faces=num_faces(sm); diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp index ac372682ca6..6aff2516947 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_pmp_repair_degeneracies.cpp @@ -1,6 +1,7 @@ #define CGAL_PMP_DEBUG_SMALL_CC_REMOVAL #include +#include #include #include @@ -21,6 +22,7 @@ namespace PMP = CGAL::Polygon_mesh_processing; namespace CP = CGAL::parameters; typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; +typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; template void detect_degeneracies(const EdgeRange& edge_range, @@ -340,17 +342,21 @@ void test() typedef CGAL::Surface_mesh Surface_mesh; typedef CGAL::Polyhedron_3 Polyhedron_with_ID; - std::cout << "EPICK SM TESTS" << std::endl; + std::cout << "SM TESTS" << std::endl; test(); - std::cout << "EPICK POLYHEDRON TESTS" << std::endl; + std::cout << "POLYHEDRON TESTS" << std::endl; test(); } int main(int /*argc*/, char** /*argv*/) { + std::cout << "EPICK TESTS" << std::endl; test(); + std::cout << "EPECK TESTS" << std::endl; + test(); + std::cout << "Done" << std::endl; return EXIT_SUCCESS; diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index 77d8ceb74d2..504852e366e 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -371,6 +371,7 @@ MainWindow::MainWindow(const QStringList &keywords, bool verbose, QWidget* paren // Setup the submenu of the View menu that can toggle the dockwidgets Q_FOREACH(QDockWidget* widget, findChildren()) { + widget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable); ui->menuDockWindows->addAction(widget->toggleViewAction()); } ui->menuDockWindows->removeAction(ui->dummyAction); @@ -1285,7 +1286,7 @@ QList MainWindow::loadItem(QFileInfo fileinfo, QCursor tmp_cursor(Qt::WaitCursor); CGAL::Three::Three::CursorScopeGuard guard(tmp_cursor); QList result = loader->load(fileinfo, ok, add_to_scene); - if(result.empty() || !ok) + if(!ok) { QApplication::restoreOverrideCursor(); QMessageBox::warning(this, tr("Error"), @@ -1579,6 +1580,8 @@ void MainWindow::showSceneContextMenu(const QPoint& p) { has_stats = true; } QMenu menu; + menu.addAction(actionAddToGroup); + menu.insertSeparator(0); Q_FOREACH(QString name, menu_actions.keys()) { if(name == QString("alpha slider") @@ -2579,6 +2582,10 @@ void MainWindow::makeNewGroup() { Scene_group_item * group = new Scene_group_item(); scene->addItem(group); + for(Scene::Item_id id : scene->selectionIndices()) + { + scene->changeGroup(scene->item(id), group); + } } void MainWindow::on_upButton_pressed() @@ -2956,6 +2963,7 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() std::vector colors; std::vector rendering_modes; QStringList not_saved; + Polyhedron_demo_io_plugin_interface* camera_plugin = nullptr; for(int i = 0; i < scene->numberOfEntries(); ++i) { Scene_item* item = scene->item(i); @@ -2963,6 +2971,8 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() QString ext; for(Polyhedron_demo_io_plugin_interface* iop : io_plugins) { + if(iop->name() == "camera_positions_plugin") + camera_plugin = iop; if(iop->isDefaultLoader(item)) { QString sf = iop->saveNameFilters().split(";;").first(); @@ -2992,6 +3002,23 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() colors.push_back(item->color()); rendering_modes.push_back(item->renderingMode()); } + bool has_camera_positions = false; + if(camera_plugin) + { + QString fullpath = make_fullpath("camera_tmp.camera.txt"); + QList dummy; + if(camera_plugin->save(QFileInfo(fullpath), dummy)) + { + QByteArray item = file_to_string(fullpath.toStdString().c_str()); + os << "var camera_positions= [\'"; + os<setTotalPass(nb); }); + + action = subviewer->findChild("actionScaleScene"); + action->setCheckable(true); + action->setChecked(false); + connect(action, &QAction::triggered, + viewer, &Viewer::scaleScene); + action= subviewer->findChild("actionBackFrontShading"); connect(action, SIGNAL(toggled(bool)), viewer, SLOT(setBackFrontShading(bool))); @@ -3450,6 +3490,10 @@ SubViewer::SubViewer(QWidget *parent, MainWindow* mw, Viewer* mainviewer) actionBackFrontShading->setChecked(false); viewMenu->addAction(actionBackFrontShading); + QAction* actionScaleScene = new QAction("&Scale the Scene...",this); + actionScaleScene->setObjectName("actionScaleScene"); + viewMenu->addAction(actionScaleScene); + if(mainviewer) setAttribute(Qt::WA_DeleteOnClose); setWindowIcon(QIcon(":/cgal/icons/resources/menu.png")); diff --git a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp index 3b5862b0c9b..c47593831be 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/AABB_tree/Cut_plugin.cpp @@ -34,6 +34,8 @@ #include #include #include +#include +#include #ifdef CGAL_LINKED_WITH_TBB #include @@ -230,242 +232,6 @@ typedef QMap Facet_sm_trees; typedef QMap Edge_sm_trees; -class Q_DECL_EXPORT Scene_aabb_item : public CGAL::Three::Scene_item_rendering_helper -{ - Q_OBJECT -public: - Scene_aabb_item(const Facet_sm_tree& tree) - { - const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset(); - positions_lines.clear(); - - CGAL::AABB_drawing_traits > traits; - traits.v_edges = &positions_lines; - for(int i=0; i<3; ++i) - traits.offset[i] = offset[i]; - - tree.traversal(0, traits); - const CGAL::Bbox_3 bbox = tree.bbox(); - setBbox(Bbox(bbox.xmin(), - bbox.ymin(), - bbox.zmin(), - bbox.xmax(), - bbox.ymax(), - bbox.zmax())); - qDebug()<name()<<" at creation: "<(v); - initGL(viewer); - } - invalidateOpenGLBuffers(); - } - - ~Scene_aabb_item() - { - } - - bool isFinite() const { return false; } - bool isEmpty() const { return is_tree_empty; } - //computed in constructor - void compute_bbox() const {} - - Scene_aabb_item* clone() const { - return 0; - } - - QString toolTip() const { - return - tr("

    %1 (mode: %2, color: %3)
    " - "AABB_tree

    " - "

    Number of nodes: %4

    ") - .arg(this->name()) - .arg(this->renderingModeName()) - .arg(this->color().name()) - .arg(tree_size); - } - - - // Indicate if rendering mode is supported - bool supportsRenderingMode(RenderingMode m) const { - return (m == Wireframe); - } - - // Wireframe OpenGL drawing in a display list - void invalidateOpenGLBuffers() - { - setBuffersFilled(false); - getEdgeContainer(0)->reset_vbos(ALL); - } -private: - std::size_t tree_size; - bool is_tree_empty; - mutable std::vector positions_lines; - mutable std::size_t nb_lines; -public: - void initializeBuffers(CGAL::Three::Viewer_interface *viewer)const - { - Ec* ec = getEdgeContainer(0); - ec->allocate(Ec::Vertices, - positions_lines.data(), - static_cast(positions_lines.size()*sizeof(float))); - ec->initializeBuffers(viewer); - ec->setFlatDataSize(nb_lines); - //positions_lines.clear(); - //positions_lines.shrink_to_fit(); - setBuffersFilled(true); - } - void drawEdges(CGAL::Three::Viewer_interface* viewer) const - { - if ( getBuffersFilled() && - ! getBuffersInit(viewer)) - { - initializeBuffers(viewer); - setBuffersInit(viewer, true); - } - if(!getBuffersFilled()) - { - initializeBuffers(viewer); - } - Ec* ec = getEdgeContainer(0); - ec->setColor(this->color()); - ec->draw(viewer, true); - } -}; // end class Scene_aabb_item - -class Q_DECL_EXPORT Scene_edges_item : public CGAL::Three::Scene_item_rendering_helper -{ - Q_OBJECT -public: - Scene_edges_item() - { - positions_lines.resize(0); - setEdgeContainer(0, new Ec(Vi::PROGRAM_NO_SELECTION, false)); - } - ~Scene_edges_item() - { - } - bool isFinite() const { return true; } - bool isEmpty() const { return edges.empty(); } - void compute_bbox() const { - if(isEmpty()) - { - setBbox(Bbox()); - return; - } - CGAL::Bbox_3 bbox = edges.begin()->bbox(); - for(size_t i = 1, end = edges.size(); i < end; ++i) { - bbox = bbox + edges[i].bbox(); - } - setBbox(Bbox(bbox.xmin(), - bbox.ymin(), - bbox.zmin(), - bbox.xmax(), - bbox.ymax(), - bbox.zmax())); - } - void invalidateOpenGLBuffers() - { - setBuffersFilled(false); - getEdgeContainer(0)->reset_vbos(ALL); - compute_bbox(); - } - - Scene_edges_item* clone() const { - Scene_edges_item* item = new Scene_edges_item(); - item->edges = edges; - return item; - } - - QString toolTip() const { - return - tr("

    %1 (mode: %2, color: %3)
    " - "Edges

    " - "

    Number of edges: %4

    ") - .arg(this->name()) - .arg(this->renderingModeName()) - .arg(this->color().name()) - .arg(edges.size()); - } - - // Indicate if rendering mode is supported - bool supportsRenderingMode(RenderingMode m) const { - return (m == Wireframe); - } - - - - bool save(std::ostream& os) const - { - os.precision(17); - for(size_t i = 0, end = edges.size(); i < end; ++i){ - os << "2 " << edges[i].source() << " " << edges[i].target() << "\n"; - } - return true; - } - -public: - std::vector edges; -private: - mutable std::vector positions_lines; - mutable std::size_t nb_lines; - void initializeBuffers(CGAL::Three::Viewer_interface *viewer)const - { - Ec* ec = getEdgeContainer(0); - ec->initializeBuffers(viewer); - ec->setFlatDataSize(nb_lines); - positions_lines.clear(); - positions_lines.shrink_to_fit(); - } - void computeElements() const - { - const CGAL::qglviewer::Vec v_offset = Three::mainViewer()->offset(); - Simple_kernel::Vector_3 offset(v_offset.x, v_offset.y, v_offset.z); - QApplication::setOverrideCursor(Qt::WaitCursor); - positions_lines.clear(); - - for(size_t i = 0, end = edges.size(); - i < end; ++i) - { - const Simple_kernel::Point_3& a = edges[i].source()+offset; - const Simple_kernel::Point_3& b = edges[i].target()+offset; - positions_lines.push_back(a.x()); positions_lines.push_back(a.y()); positions_lines.push_back(a.z()); - positions_lines.push_back(b.x()); positions_lines.push_back(b.y()); positions_lines.push_back(b.z()); - } - getEdgeContainer(0)->allocate( - Ec::Vertices, - positions_lines.data(), - static_cast(positions_lines.size()*sizeof(float))); - nb_lines = positions_lines.size(); - setBuffersFilled(true); - QApplication::restoreOverrideCursor(); - } - void drawEdges(CGAL::Three::Viewer_interface* viewer) const - { - if(!isInit(viewer)) - initGL(viewer); - if ( getBuffersFilled() && - ! getBuffersInit(viewer)) - { - initializeBuffers(viewer); - setBuffersInit(viewer, true); - } - if(!getBuffersFilled()) - { - computeElements(); - initializeBuffers(viewer); - } - Ec* ec = getEdgeContainer(0); - ec->setColor(this->color()); - ec->draw(viewer, true); - } -}; // end class Scene_edges_item - class Q_DECL_EXPORT Scene_aabb_plane_item : public Scene_plane_item { Q_OBJECT @@ -781,6 +547,384 @@ private: } }; + +class Q_DECL_EXPORT Scene_aabb_item : public CGAL::Three::Scene_item_rendering_helper +{ + Q_OBJECT +public: + Scene_aabb_item(const Facet_sm_tree& tree) + { + filter_plane = false; + tree_size = tree.size(); + is_tree_empty = tree.empty(); + traversal(tree.size(), *tree.root_node(), 0); + lvlSlider = new QSlider(Qt::Horizontal); + lvlSlider->setMinimum(-1); + lvlSlider->setMaximum(static_cast(boxes.size())-1); + lvlSlider->setValue(-1); + lvlSlider->setPageStep(1); + const CGAL::Bbox_3 bbox = tree.bbox(); + setBbox(Bbox(bbox.xmin(), + bbox.ymin(), + bbox.zmin(), + bbox.xmax(), + bbox.ymax(), + bbox.zmax())); + qDebug()<name()<<" at creation: "<(v); + initGL(viewer); + } + invalidateOpenGLBuffers(); + } + + ~Scene_aabb_item() + { + } + + QMenu* contextMenu() + { + const char* prop_name = "Menu modified by Scene_aabb_item."; + + QMenu* menu = Scene_item::contextMenu(); + bool menuChanged = menu->property(prop_name).toBool(); + if (!menuChanged) { + + QAction* filterAction = new QAction(tr("Only Intersected Boxes")); + filterAction->setCheckable(true); + filterAction->setChecked(false); + connect(filterAction, &QAction::toggled, this, [this](bool b){ + if(b) + { + filter_plane = true; + invalidateOpenGLBuffers(); + redraw(); + } + else + { + filter_plane = false; + invalidateOpenGLBuffers(); + redraw(); + } + }); + menu->addAction(filterAction); + + QMenu *container = new QMenu(tr("Tree level")); + QWidgetAction *sliderAction = new QWidgetAction(0); + connect(lvlSlider, &QSlider::valueChanged, this, + [this](){ + invalidateOpenGLBuffers(); + redraw(); + }); + sliderAction->setDefaultWidget(lvlSlider); + + container->addAction(sliderAction); + menu->addMenu(container); + + + menu->setProperty(prop_name, true); + } + return menu; + } + + + bool isFinite() const { return false; } + bool isEmpty() const { return is_tree_empty; } + //computed in constructor + void compute_bbox() const {} + + Scene_aabb_item* clone() const { + return 0; + } + + QString toolTip() const { + return + tr("

    %1 (mode: %2, color: %3)
    " + "AABB_tree

    " + "

    Number of nodes: %4

    " + "

    Instructions:
    Check Only Intersected Boxes in the item's menu to filter out the boxes of the tree that are not intersected by the plane.
    " + "Use the cursor Tree level to only print the boxes of the Nth level. The most left-hand level is the full Tree.

    ") + .arg(this->name()) + .arg(this->renderingModeName()) + .arg(this->color().name()) + .arg(tree_size); + } + + + // Indicate if rendering mode is supported + bool supportsRenderingMode(RenderingMode m) const { + return (m == Wireframe); + } + + void invalidateOpenGLBuffers() + { + setBuffersFilled(false); + for(CGAL::QGLViewer* v: CGAL::QGLViewer::QGLViewerPool()) + { + CGAL::Three::Viewer_interface* viewer = static_cast(v); + if(viewer == NULL) + continue; + setBuffersInit(viewer, false); + } + getEdgeContainer(0)->reset_vbos(ALL); + } + + void update_tree(Scene_aabb_plane_item* plane_item)const + { + positions_lines.clear(); + const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset(); + CGAL::AABB_drawing_traits > traits; + for(int i=0; i<3; ++i) + traits.offset[i] = offset[i]; + traits.v_edges = &positions_lines; + if(lvlSlider->value() != -1) + { + for(const auto& bb : boxes[lvlSlider->value()]) + { + if(!plane_item || (!filter_plane) || CGAL::do_intersect(plane_item->plane(offset), bb)) + traits.gl_draw(bb); + } + } + else + { + for(std::size_t i=0; iplane(offset), bb)) + traits.gl_draw(bb); + } + } + } + nb_lines = positions_lines.size(); + Ec* ec = getEdgeContainer(0); + ec->allocate(Ec::Vertices, + positions_lines.data(), + static_cast(positions_lines.size()*sizeof(float))); + setBuffersFilled(true); + } + +private: + std::size_t tree_size; + bool is_tree_empty; + bool filter_plane; + mutable std::vector positions_lines; + mutable std::size_t nb_lines; + std::vector > boxes; + QSlider* lvlSlider; + + void + traversal(const std::size_t nb_primitives, + const CGAL::AABB_node& node, + int lvl) + { + //traversed lvl by lvl, so one push_back should be enough. + if(static_cast(boxes.size()) <= lvl ) + boxes.push_back(std::vector()); + CGAL_assertion(static_cast(boxes.size()) > lvl); + boxes[lvl].push_back(node.bbox()); + + // Recursive traversal + switch(nb_primitives) + { + case 2: + break; + case 3: + traversal(2, node.right_child(), lvl +1); + break; + default: + traversal(nb_primitives/2, node.left_child(),lvl +1); + traversal(nb_primitives-nb_primitives/2, node.right_child(), lvl +1); + } + } + + Scene_aabb_plane_item* get_plane_item()const + { + Scene_aabb_plane_item* plane_item = nullptr; + if(filter_plane) + for(int i=0; i< CGAL::Three::Three::scene()->numberOfEntries(); ++i) + { + plane_item = qobject_cast(CGAL::Three::Three::scene()->item(i)); + if(plane_item) + { + return plane_item; + } + } + return nullptr; + } + + +public: + void initializeBuffers(CGAL::Three::Viewer_interface *viewer)const + { + Ec* ec = getEdgeContainer(0); + ec->initializeBuffers(viewer); + ec->setFlatDataSize(nb_lines); + positions_lines.clear(); + positions_lines.shrink_to_fit(); + } + + void drawEdges(CGAL::Three::Viewer_interface* viewer) const + { + if(!isInit(viewer)){ + setBuffersFilled(false); + setBuffersInit(viewer, false); + initGL(viewer); + } + if ( getBuffersFilled() && + ! getBuffersInit(viewer)) + { + initializeBuffers(viewer); + setBuffersInit(viewer, true); + } + if(!getBuffersFilled()) + { + update_tree(get_plane_item()); + initializeBuffers(viewer); + } + Ec* ec = getEdgeContainer(0); + ec->setColor(this->color()); + ec->draw(viewer, true); + } + + void computeElements() const + { + update_tree(get_plane_item()); + } + +}; // end class Scene_aabb_item + +class Q_DECL_EXPORT Scene_edges_item : public CGAL::Three::Scene_item_rendering_helper +{ + Q_OBJECT +public: + Scene_edges_item() + { + positions_lines.resize(0); + setEdgeContainer(0, new Ec(Vi::PROGRAM_NO_SELECTION, false)); + } + ~Scene_edges_item() + { + } + bool isFinite() const { return true; } + bool isEmpty() const { return edges.empty(); } + void compute_bbox() const { + if(isEmpty()) + { + setBbox(Bbox()); + return; + } + CGAL::Bbox_3 bbox = edges.begin()->bbox(); + for(size_t i = 1, end = edges.size(); i < end; ++i) { + bbox = bbox + edges[i].bbox(); + } + setBbox(Bbox(bbox.xmin(), + bbox.ymin(), + bbox.zmin(), + bbox.xmax(), + bbox.ymax(), + bbox.zmax())); + } + void invalidateOpenGLBuffers() + { + setBuffersFilled(false); + getEdgeContainer(0)->reset_vbos(ALL); + compute_bbox(); + } + + Scene_edges_item* clone() const { + Scene_edges_item* item = new Scene_edges_item(); + item->edges = edges; + return item; + } + + QString toolTip() const { + return + tr("

    %1 (mode: %2, color: %3)
    " + "Edges

    " + "

    Number of edges: %4

    ") + .arg(this->name()) + .arg(this->renderingModeName()) + .arg(this->color().name()) + .arg(edges.size()); + } + + // Indicate if rendering mode is supported + bool supportsRenderingMode(RenderingMode m) const { + return (m == Wireframe); + } + + + + bool save(std::ostream& os) const + { + os.precision(17); + for(size_t i = 0, end = edges.size(); i < end; ++i){ + os << "2 " << edges[i].source() << " " << edges[i].target() << "\n"; + } + return true; + } + +public: + std::vector edges; +private: + mutable std::vector positions_lines; + mutable std::size_t nb_lines; + void initializeBuffers(CGAL::Three::Viewer_interface *viewer)const + { + Ec* ec = getEdgeContainer(0); + ec->initializeBuffers(viewer); + ec->setFlatDataSize(nb_lines); + positions_lines.clear(); + positions_lines.shrink_to_fit(); + } + void computeElements() const + { + const CGAL::qglviewer::Vec v_offset = Three::mainViewer()->offset(); + Simple_kernel::Vector_3 offset(v_offset.x, v_offset.y, v_offset.z); + QApplication::setOverrideCursor(Qt::WaitCursor); + positions_lines.clear(); + + for(size_t i = 0, end = edges.size(); + i < end; ++i) + { + const Simple_kernel::Point_3& a = edges[i].source()+offset; + const Simple_kernel::Point_3& b = edges[i].target()+offset; + positions_lines.push_back(a.x()); positions_lines.push_back(a.y()); positions_lines.push_back(a.z()); + positions_lines.push_back(b.x()); positions_lines.push_back(b.y()); positions_lines.push_back(b.z()); + } + getEdgeContainer(0)->allocate( + Ec::Vertices, + positions_lines.data(), + static_cast(positions_lines.size()*sizeof(float))); + nb_lines = positions_lines.size(); + setBuffersFilled(true); + QApplication::restoreOverrideCursor(); + } + void drawEdges(CGAL::Three::Viewer_interface* viewer) const + { + if(!isInit(viewer)) + initGL(viewer); + if ( getBuffersFilled() && + ! getBuffersInit(viewer)) + { + initializeBuffers(viewer); + setBuffersInit(viewer, true); + } + if(!getBuffersFilled()) + { + computeElements(); + initializeBuffers(viewer); + } + Ec* ec = getEdgeContainer(0); + ec->setColor(this->color()); + ec->draw(viewer, true); + } +}; // end class Scene_edges_item + using namespace CGAL::Three; class Polyhedron_demo_cut_plugin : public QObject, @@ -1280,6 +1424,17 @@ void Polyhedron_demo_cut_plugin::cut() { if(!plane_item) return; + + for(int id =0; id < CGAL::Three::Three::scene()->numberOfEntries(); ++id) + { + Scene_item* item = CGAL::Three::Three::scene()->item(id); + Scene_aabb_item* aabb_item = qobject_cast(item); + if(!aabb_item){ + continue; + } + aabb_item->invalidateOpenGLBuffers(); + } + switch(plane_item->cutPlaneType()) { case Scene_aabb_plane_item::CUT_SEGMENTS: diff --git a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/CMakeLists.txt index d3321fa9ea6..808b159c0ab 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/CMakeLists.txt @@ -3,7 +3,8 @@ include( polyhedron_demo_macros ) polyhedron_demo_plugin(camera_positions_plugin Camera_positions_plugin Camera_positions_list - ${cameraUI_FILES}) + ${cameraUI_FILES} + KEYWORDS Viewer) target_link_libraries( camera_positions_plugin PUBLIC demo_framework) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.cpp b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.cpp index 707a5b7fff3..c015e8f495c 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.cpp @@ -89,13 +89,9 @@ void Camera_positions_list::activatedRow(QModelIndex index) Three::activeViewer()->moveCameraToCoordinates(s); } -void Camera_positions_list::on_saveButton_pressed() -{ - QString filename = - QFileDialog::getSaveFileName(this, - tr("Save camera coordinates to file"), - QString(), - tr("(*.camera.txt)")); +bool Camera_positions_list::save(QString filename) { + if(m_model->rowCount() <1) + return false; QFile file(filename); file.open(QIODevice::WriteOnly); QTextStream out(&file); @@ -108,6 +104,17 @@ void Camera_positions_list::on_saveButton_pressed() << "\n"; } file.close(); + return true; +} + +void Camera_positions_list::on_saveButton_pressed() +{ + QString filename = + QFileDialog::getSaveFileName(this, + tr("Save camera coordinates to file"), + QString(), + tr("(*.camera.txt)")); + save(filename); } void Camera_positions_list::on_openButton_pressed() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.h b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.h index 575fd68b603..f9d43a2a88d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.h +++ b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_list.h @@ -15,6 +15,7 @@ public: public Q_SLOTS: void load(QString filename); + bool save(QString filename); protected Q_SLOTS: void on_plusButton_pressed(); void on_minusButton_pressed(); @@ -41,3 +42,4 @@ private: }; #endif + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_plugin.cpp index e252689a452..53104cf7256 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Camera_position/Camera_positions_plugin.cpp @@ -31,8 +31,11 @@ public: return QList(); } - bool canSave(const Scene_item*) override { return false; } - bool save(QFileInfo,QList& ) override {return false; } + bool canSave(const Scene_item*) override { return true; } + bool save(QFileInfo fileinfo,QList& ) override + { + return cpl->save(fileinfo.filePath()); + } private: Camera_positions_list* cpl; }; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt index 0f03d24021e..06ce345920d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/CMakeLists.txt @@ -1,6 +1,6 @@ include( polyhedron_demo_macros ) if(TARGET CGAL::Eigen_support) qt5_wrap_ui( display_propertyUI_FILES Display_property.ui ) - polyhedron_demo_plugin(display_property_plugin Display_property_plugin ${display_propertyUI_FILES}) + polyhedron_demo_plugin(display_property_plugin Display_property_plugin ${display_propertyUI_FILES} KEYWORDS Viewer) target_link_libraries(display_property_plugin PUBLIC scene_surface_mesh_item scene_points_with_normal_item scene_color_ramp CGAL::Eigen_support) endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui index 95538bdfcff..7a5a19621f4 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property.ui @@ -7,7 +7,7 @@ 0 0 292 - 492 + 508 @@ -16,16 +16,52 @@ - + - - - RAMP DISPLAYING + + + Qt::ScrollBarAlwaysOff + + true + + + + + 0 + 0 + 127 + 430 + + + + + + + RAMP DISPLAYING + + + + + + + + + + + + + + + + + + + @@ -33,6 +69,67 @@ + + + + 0 + + + + Ramp + + + + + + Ramp Colors + + + + + + Color Min... + + + + + + + Color Max... + + + + + + + + + + + Map + + + + + + Initial Color... + + + + + + + + + + + Select Source Points + + + true + + + @@ -56,53 +153,6 @@ - - - - Ramp Colors - - - - - - Color Min... - - - - - - - Color Max... - - - - - - - - - - - - - - - - - Select Source Points - - - true - - - - - - - - - - @@ -157,6 +207,9 @@ + + QComboBox::AdjustToContents + Smallest Angle Per Face diff --git a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp index 27f909449a6..df7f0d9c330 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Display/Display_property_plugin.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include #include @@ -20,6 +21,7 @@ #include "Messages_interface.h" #include "Scene_surface_mesh_item.h" #include "Color_ramp.h" +#include "Color_map.h" #include #include "ui_Display_property.h" #include "id_printing.h" @@ -28,11 +30,14 @@ #include #include #include +#include +#include #define ARBITRARY_DBL_MIN 1.0E-30 #define ARBITRARY_DBL_MAX 1.0E+30 + //Item for heat values typedef CGAL::Three::Triangle_container Tri; typedef CGAL::Three::Viewer_interface VI; @@ -332,10 +337,14 @@ class DisplayPropertyPlugin : public: - bool applicable(QAction*) const Q_DECL_OVERRIDE + bool applicable(QAction* action) const Q_DECL_OVERRIDE { CGAL::Three::Scene_item* item = scene->item(scene->mainSelectionIndex()); - return qobject_cast(item); + if(action == _actions.back()) + return qobject_cast(item); + else + return qobject_cast(item) + || qobject_cast(item); } QList actions() const Q_DECL_OVERRIDE @@ -357,7 +366,7 @@ public: this->mw = mw; this->current_item = NULL; - QAction *actionDisplayAngles= new QAction(QString("Display Properties"), mw); + QAction *actionDisplayProperties= new QAction(QString("Display Properties"), mw); QAction *actionHeatMethod= new QAction(QString("Heat Method"), mw); actionHeatMethod->setProperty("submenuName", "Color"); @@ -367,10 +376,10 @@ public: gM = 1.0; bm = 0.0; bM = 0.0; - actionDisplayAngles->setProperty("submenuName", "Color"); + actionDisplayProperties->setProperty("submenuName", "Color"); - if(actionDisplayAngles) { - connect(actionDisplayAngles, SIGNAL(triggered()), + if(actionDisplayProperties) { + connect(actionDisplayProperties, SIGNAL(triggered()), this, SLOT(openDialog())); if(actionHeatMethod) { @@ -380,7 +389,7 @@ public: this->dock_widget->show(); }); } - _actions << actionDisplayAngles; + _actions << actionDisplayProperties; _actions << actionHeatMethod; } @@ -396,6 +405,12 @@ public: dock_widget->maxColorButton->setPalette(palette); dock_widget->maxColorButton->setStyle(QStyleFactory::create("Fusion")); dock_widget->maxColorButton->update(); + + palette = QPalette(Qt::green); + dock_widget->initColorButton->setPalette(palette); + dock_widget->initColorButton->setStyle(QStyleFactory::create("Fusion")); + dock_widget->initColorButton->update(); + connect(dock_widget->colorizeButton, SIGNAL(clicked(bool)), this, SLOT(colorize())); @@ -438,6 +453,23 @@ public: replaceRamp(); }); + connect(dock_widget->initColorButton, &QPushButton::pressed, + this, [this]() + { + QColor initColor = QColorDialog::getColor(); + if (!initColor.isValid()) + { + return; + } + + QPalette palette(initColor); + rI = initColor.redF(); + gI = initColor.greenF(); + bI = initColor.blueF(); + dock_widget->initColorButton->setPalette(palette); + dock_widget->initColorButton->update(); + }); + connect(dock_widget->sourcePointsButton, SIGNAL(toggled(bool)), this, SLOT(on_sourcePointsButton_toggled(bool))); connect(dock_widget->deleteButton, &QPushButton::clicked, @@ -446,100 +478,207 @@ public: dock_widget->zoomToMaxButton->setEnabled(false); dock_widget->zoomToMinButton->setEnabled(false); Scene* scene_obj =static_cast(scene); - connect(scene_obj, &Scene::itemIndexSelected, - this, &DisplayPropertyPlugin::enableButtons); + connect(scene_obj, SIGNAL(itemIndexSelected(int)), + this,SLOT(enableButtons(int))); + connect(scene_obj, SIGNAL(itemIndexSelected(int)), + this,SLOT(detectScalarProperties(int))); + on_propertyBox_currentIndexChanged(0); + + } +private: + + void detectSMScalarProperties(SMesh* smesh) + { + std::vector vprop = smesh->properties(); + std::vector fprop = smesh->properties(); + for(auto s : vprop) + if(is_property_scalar(s, smesh)) + { + dock_widget->propertyBox->addItem(s.c_str()); + } + for(auto s : fprop) + if(is_property_scalar(s, smesh)) + { + dock_widget->propertyBox->addItem(s.c_str()); + } + } + + void detectPSScalarProperties(Point_set* ps) + { + for(auto s : ps->properties()) + if(is_property_scalar(s, ps)) + { + dock_widget->propertyBox->addItem(s.c_str()); + } } private Q_SLOTS: + void detectScalarProperties(int i) + { + for(int j = dock_widget->propertyBox->count(); j>=0; --j) + dock_widget->propertyBox->removeItem(j); + + Scene_surface_mesh_item* sm_item = + qobject_cast(scene->item(i)); + Scene_points_with_normal_item* p_item = + qobject_cast(scene->item(i)); + + if(sm_item) + { + dock_widget->propertyBox->addItem("Smallest Angle Per Face"); + dock_widget->propertyBox->addItem("Scaled Jacobian"); + dock_widget->propertyBox->addItem("Heat Intensity"); + dock_widget->propertyBox->addItem("Heat Intensity (Intrinsic Delaunay)"); + detectSMScalarProperties(sm_item->face_graph()); + + } + else if(p_item) + { + detectPSScalarProperties(p_item->point_set()); + } + int width = dock_widget->propertyBox->minimumSizeHint().width(); + dock_widget->propertyBox->view()->setMinimumWidth(width); + } + void openDialog() { if(dock_widget->isVisible()) { dock_widget->hide(); } else{ - replaceRamp(); dock_widget->show(); dock_widget->raise(); } } + void colorizePS(Scene_points_with_normal_item* ps_item) + { + ps_item->point_set()->add_colors(); + if(!treat_point_property(dock_widget->propertyBox->currentText().toStdString(), ps_item->point_set())) + { + QApplication::restoreOverrideCursor(); + return; + } + ps_item->setPointsMode(); + ps_item->invalidateOpenGLBuffers(); + ps_item->itemChanged(); + } void colorize() { + Scene_points_with_normal_item* p_item = + qobject_cast(scene->item(scene->mainSelectionIndex())); + if(p_item) + { + colorizePS(p_item); + return; + } Scene_heat_item* h_item = nullptr; - Scene_surface_mesh_item* item = + Scene_surface_mesh_item* sm_item = qobject_cast(scene->item(scene->mainSelectionIndex())); - if(!item) + if(!sm_item) { h_item = qobject_cast(scene->item(scene->mainSelectionIndex())); if(!h_item) return; - item = h_item->getParent(); + sm_item = h_item->getParent(); } QApplication::setOverrideCursor(Qt::WaitCursor); - - replaceRamp(); - item->face_graph()->collect_garbage(); + sm_item->face_graph()->collect_garbage(); switch(dock_widget->propertyBox->currentIndex()){ case 0: - displayAngles(item); + displayAngles(sm_item); break; case 1: - displayScaledJacobian(item); + displayScaledJacobian(sm_item); break; case 2: - if(!displayHeatIntensity(item)) + dock_widget->colorChoiceWidget->setCurrentIndex(0); + if(!displayHeatIntensity(sm_item)){ + QApplication::restoreOverrideCursor(); return; - item->setRenderingMode(Gouraud); + } + sm_item->setRenderingMode(Gouraud); break; - default: // Heat Method (Intrinsic Delaunay) - if(!displayHeatIntensity(item, true)) + case 3:// Heat Method (Intrinsic Delaunay) + dock_widget->colorChoiceWidget->setCurrentIndex(0); + if(!displayHeatIntensity(sm_item, true)) return; - item->setRenderingMode(Gouraud); + sm_item->setRenderingMode(Gouraud); + break; + default: + if(dock_widget->propertyBox->currentText().contains("v:")) + { + if(!treat_sm_property(dock_widget->propertyBox->currentText().toStdString(), sm_item->face_graph())) + { + QApplication::restoreOverrideCursor(); + return; + } + sm_item->setRenderingMode(Gouraud); + } + else if(dock_widget->propertyBox->currentText().contains("f:")) + { + if(!treat_sm_property(dock_widget->propertyBox->currentText().toStdString(), sm_item->face_graph())) + { + QApplication::restoreOverrideCursor(); + return; + } + sm_item->setRenderingMode(Flat); + } break; } - connect(item, &Scene_surface_mesh_item::itemChanged, - this, [item](){ + connect(sm_item, &Scene_surface_mesh_item::itemChanged, + this, [sm_item](){ bool does_exist; SMesh::Property_map pmap; - boost::tie(pmap, does_exist) = - item->face_graph()->property_map("f:jacobian"); + std::tie(pmap, does_exist) = + sm_item->face_graph()->property_map("f:jacobian"); if(does_exist) - item->face_graph()->remove_property_map(pmap); - boost::tie(pmap, does_exist) = - item->face_graph()->property_map("f:angle"); + sm_item->face_graph()->remove_property_map(pmap); + std::tie(pmap, does_exist) = + sm_item->face_graph()->property_map("f:angle"); if(does_exist) - item->face_graph()->remove_property_map(pmap); + sm_item->face_graph()->remove_property_map(pmap); }); QApplication::restoreOverrideCursor(); - item->invalidateOpenGLBuffers(); - item->redraw(); + sm_item->invalidateOpenGLBuffers(); + sm_item->redraw(); if(dock_widget->propertyBox->currentIndex() != 2){ dock_widget->zoomToMinButton->setEnabled(true); dock_widget->zoomToMaxButton->setEnabled(true);} } - void enableButtons() + void enableButtons(int i) { - Scene_surface_mesh_item* item = - qobject_cast(scene->item(scene->mainSelectionIndex())); - if(! item ) + Scene_surface_mesh_item* sm_item = + qobject_cast(scene->item(i)); + + Scene_points_with_normal_item* ps_item = + qobject_cast(scene->item(i)); + + if(! sm_item && ! ps_item) { dock_widget->zoomToMinButton->setEnabled(false); dock_widget->zoomToMaxButton->setEnabled(false); } - - switch(dock_widget->propertyBox->currentIndex()) + else if(ps_item) { - case 0: - dock_widget->zoomToMinButton->setEnabled(angles_max.count(item)>0 ); - dock_widget->zoomToMaxButton->setEnabled(angles_max.count(item)>0 ); - break; - case 1: - dock_widget->zoomToMinButton->setEnabled(jacobian_max.count(item)>0); - dock_widget->zoomToMaxButton->setEnabled(jacobian_max.count(item)>0); - break; - default: - break; + dock_widget->zoomToMinButton->setEnabled(false); + dock_widget->zoomToMaxButton->setEnabled(false); + } + else if(sm_item){ + switch(dock_widget->propertyBox->currentIndex()) + { + case 0: + dock_widget->zoomToMinButton->setEnabled(angles_max.count(sm_item)>0 ); + dock_widget->zoomToMaxButton->setEnabled(angles_max.count(sm_item)>0 ); + break; + case 1: + dock_widget->zoomToMinButton->setEnabled(jacobian_max.count(sm_item)>0); + dock_widget->zoomToMaxButton->setEnabled(jacobian_max.count(sm_item)>0); + break; + default: + break; + } } } @@ -552,13 +691,13 @@ private Q_SLOTS: SMesh& smesh = *item->face_graph(); SMesh::Property_map jacobians; bool found; - boost::tie(jacobians, found) = smesh.property_map("f:jacobian"); + std::tie(jacobians, found) = smesh.property_map("f:jacobian"); if(found) { smesh.remove_property_map(jacobians); } SMesh::Property_map angles; - boost::tie(angles, found) = smesh.property_map("f:angle"); + std::tie(angles, found) = smesh.property_map("f:angle"); if(found) { smesh.remove_property_map(angles); @@ -572,7 +711,7 @@ private Q_SLOTS: //compute and store the jacobian per face bool non_init; SMesh::Property_map fjacobian; - boost::tie(fjacobian, non_init) = smesh.add_property_map("f:jacobian", 0); + std::tie(fjacobian, non_init) = smesh.add_property_map("f:jacobian", 0); if(non_init) { double res_min = ARBITRARY_DBL_MAX, @@ -601,29 +740,7 @@ private Q_SLOTS: connect(item, &Scene_surface_mesh_item::itemChanged, this, &DisplayPropertyPlugin::resetProperty); } - //scale a color ramp between min and max - double max = maxBox; - double min = minBox; - //fill f:color pmap - SMesh::Property_map fcolors = - smesh.add_property_map("f:color", CGAL::Color()).first; - for(boost::graph_traits::face_iterator fit = faces(smesh).begin(); - fit != faces(smesh).end(); - ++fit) - { - if(min == max) - --min; - double f = (fjacobian[*fit]-min)/(max-min); - if(fmax) - f = max; - CGAL::Color color( - 255*color_ramp.r(f), - 255*color_ramp.g(f), - 255*color_ramp.b(f)); - fcolors[*fit] = color; - } + treat_sm_property("f:jacobian", item->face_graph()); } bool resetScaledJacobian(Scene_surface_mesh_item* item) @@ -638,6 +755,7 @@ private Q_SLOTS: return true; } + void displayAngles(Scene_surface_mesh_item* item) { SMesh& smesh = *item->face_graph(); @@ -646,7 +764,7 @@ private Q_SLOTS: //compute and store smallest angle per face bool non_init; SMesh::Property_map fangle; - boost::tie(fangle, non_init) = smesh.add_property_map("f:angle", 0); + std::tie(fangle, non_init) = smesh.add_property_map("f:angle", 0); if(non_init) { double res_min = ARBITRARY_DBL_MAX, @@ -738,31 +856,7 @@ private Q_SLOTS: connect(item, &Scene_surface_mesh_item::itemChanged, this, &DisplayPropertyPlugin::resetProperty); } - //scale a color ramp between min and max - - float max = maxBox; - float min = minBox; - - //fill f:color pmap - SMesh::Property_map fcolors = - smesh.add_property_map("f:color", CGAL::Color()).first; - for(boost::graph_traits::face_iterator fit = faces(smesh).begin(); - fit != faces(smesh).end(); - ++fit) - { - if(min == max) - --min; - float f = (fangle[*fit]-min)/(max-min); - if(f<0) - f = 0; - if(f>1) - f = 1; - CGAL::Color color( - 255*color_ramp.r(f), - 255*color_ramp.g(f), - 255*color_ramp.b(f)); - fcolors[*fit] = color; - } + treat_sm_property("f:angle", item->face_graph()); } bool resetAngles(Scene_surface_mesh_item* item) @@ -810,6 +904,8 @@ private Q_SLOTS: connect(item, &Scene_surface_mesh_item::aboutToBeDestroyed, [this,item](){ auto it = mesh_heat_method_map.find(item); + if(it == mesh_heat_method_map.end()) + return; delete it->second; mesh_heat_method_map.erase(it); } @@ -868,7 +964,7 @@ private Q_SLOTS: color_ramp = Color_ramp(rm, rM, gm, gM, bm, bM); dock_widget->minBox->setValue(min); dock_widget->maxBox->setValue(max); - + displayLegend(); //} SMesh::Property_map vcolors = mesh.add_property_map("v:color", CGAL::Color()).first; @@ -922,62 +1018,66 @@ private Q_SLOTS: void replaceRamp() { - color_ramp = Color_ramp(rm, rM, gm, gM, bm, bM); - displayLegend(); - minBox = dock_widget->minBox->value(); - maxBox = dock_widget->maxBox->value(); + if(dock_widget->colorChoiceWidget->currentIndex() == 0) + { + color_ramp = Color_ramp(rm, rM, gm, gM, bm, bM); + displayLegend(); + minBox = dock_widget->minBox->value(); + maxBox = dock_widget->maxBox->value(); + } } void on_propertyBox_currentIndexChanged(int) { - switch(dock_widget->propertyBox->currentIndex()) - { - case 0: - { - dock_widget->groupBox-> setEnabled(true); - dock_widget->groupBox_3->setEnabled(true); + dock_widget->sourcePointsButton->setEnabled(false); + Scene_surface_mesh_item* item = + qobject_cast(scene->item(scene->mainSelectionIndex())); + if(! item ) + dock_widget->maxBox->setValue(180); + else{ + switch(dock_widget->propertyBox->currentIndex()) + { + case 0: + { + dock_widget->groupBox-> setEnabled(true); + dock_widget->groupBox_3->setEnabled(true); - dock_widget->sourcePointsButton->setEnabled(false); + dock_widget->minBox->setMinimum(0); + dock_widget->minBox->setMaximum(360); + dock_widget->minBox->setValue(0); + dock_widget->maxBox->setMinimum(0); + dock_widget->maxBox->setMaximum(360); + if(is_triangle_mesh(*item->face_graph())) + dock_widget->maxBox->setValue(60); + else if(is_quad_mesh(*item->face_graph())) + dock_widget->maxBox->setValue(90); + replaceRamp(); + break; + } + case 1: + dock_widget->groupBox-> setEnabled(true); + dock_widget->groupBox_3->setEnabled(true); - dock_widget->minBox->setMinimum(0); - dock_widget->minBox->setMaximum(360); - dock_widget->minBox->setValue(0); + dock_widget->minBox->setMinimum(-1000); + dock_widget->minBox->setMaximum(1000); + dock_widget->minBox->setValue(0); - dock_widget->maxBox->setMinimum(0); - dock_widget->maxBox->setMaximum(360); - Scene_surface_mesh_item* item = - qobject_cast(scene->item(scene->mainSelectionIndex())); - if(! item ) - dock_widget->maxBox->setValue(180); - else if(is_triangle_mesh(*item->face_graph())) - dock_widget->maxBox->setValue(60); - else if(is_quad_mesh(*item->face_graph())) - dock_widget->maxBox->setValue(90); - break; + dock_widget->maxBox->setMinimum(-1000); + dock_widget->maxBox->setMaximum(1000); + dock_widget->maxBox->setValue(2); + break; + case 2: + case 3: + dock_widget->sourcePointsButton->setEnabled(true); + default: + dock_widget->maxBox->setMinimum(-99999999); + dock_widget->maxBox->setMaximum(99999999); + dock_widget->minBox->setMinimum(-99999999); + dock_widget->minBox->setMaximum(99999999); + dock_widget->groupBox-> setEnabled(false); + dock_widget->groupBox_3->setEnabled(false); + } } - case 1: - dock_widget->groupBox-> setEnabled(true); - dock_widget->groupBox_3->setEnabled(true); - dock_widget->sourcePointsButton->setEnabled(false); - - dock_widget->minBox->setMinimum(-1000); - dock_widget->minBox->setMaximum(1000); - dock_widget->minBox->setValue(0); - - dock_widget->maxBox->setMinimum(-1000); - dock_widget->maxBox->setMaximum(1000); - dock_widget->maxBox->setValue(2); - break; - default: - dock_widget->maxBox->setMinimum(0); - dock_widget->maxBox->setMaximum(99999999); - dock_widget->groupBox-> setEnabled(false); - dock_widget->groupBox_3->setEnabled(false); - dock_widget->sourcePointsButton->setEnabled(true); - - } - replaceRamp(); - enableButtons(); } void closure()Q_DECL_OVERRIDE @@ -987,6 +1087,7 @@ private Q_SLOTS: void on_zoomToMinButton_pressed() { + Scene_surface_mesh_item* item = qobject_cast(scene->item(scene->mainSelectionIndex())); if(!item) @@ -1053,6 +1154,8 @@ private Q_SLOTS: void delete_group() { + if(scene->selectionIndices().empty()) + return; Scene_item* item = scene->item(scene->selectionIndices().first()); Scene_group_item* group = qobject_cast(item); if(!group || !group->property("heat_group").toBool()) @@ -1060,6 +1163,18 @@ private Q_SLOTS: for(auto child_id : group->getChildren()) { if(Scene_surface_mesh_item* child = qobject_cast(scene->item(child_id))){ + auto it = mesh_heat_method_map.find(child); + if(it != mesh_heat_method_map.end()) + mesh_heat_method_map.erase(it); + + auto it2 = mesh_heat_item_map.find(child); + if(it2 != mesh_heat_item_map.end()) + mesh_heat_item_map.erase(it2); + + auto it3 = mesh_heat_method_idt_map.find(child); + if(it3 != mesh_heat_method_idt_map.end()) + mesh_heat_method_idt_map.erase(it3); + group->unlockChild(child); group->removeChild(child); scene->addChild(child); @@ -1069,6 +1184,7 @@ private Q_SLOTS: } } scene->erase(scene->item_id(group)); + source_points = nullptr; } @@ -1181,11 +1297,74 @@ private Q_SLOTS: source_points->itemChanged(); } private: + template + bool displayPSProperty(Point_set* ps, PM pm); + template + bool displaySMProperty(SMesh& smesh, PM pm, vertex_descriptor); + template + bool displaySMProperty(SMesh& smesh, PM pm, face_descriptor); + template + bool treat_sm_property(std::string name, SMesh* sm); + //cannot be treated as a sm_property because the property_map<>() function takes only 1 template arg. + bool treat_point_property(std::string name, Point_set* sm); + template + bool is_property_scalar(std::string name, const SMesh* sm); + //same problem of number of templates + bool is_property_scalar(std::string name, const Point_set* ps); + template + void displayMapLegend(const std::vector& values) + { + // Create a legend_ and display it + const std::size_t size = (std::min)(color_map.size(), (std::size_t)256); + const int text_height = 20; + const int height = text_height*static_cast(size) + text_height; + const int width = 140; + const int cell_width = width/3; + const int top_margin = 15; + const int left_margin = 5; + const int drawing_height = height - text_height + top_margin; + + legend_ = QPixmap(width, height ); + legend_.fill(QColor(200, 200, 200)); + + QPainter painter(&legend_); + painter.setPen(Qt::black); + painter.setBrush(QColor(200, 200, 200)); + + int j = 0; + int tick_height = text_height; + for (std::size_t i = 0; i< size; ++i, j+=tick_height) + { + QColor color(color_map[i].red(), + color_map[i].green(), + color_map[i].blue()); + painter.fillRect(left_margin, + drawing_height - top_margin - j, + cell_width, + tick_height, + color); + QRect text_rect(left_margin + cell_width+10, drawing_height - top_margin - j, + 50, text_height); + painter.drawText(text_rect, Qt::AlignCenter, tr("%1").arg(values[i], 0, 'f', 3, QLatin1Char(' '))); + } + if(color_map.size() > size){ + QRect text_rect(left_margin + cell_width+10, 0, + 50, text_height); + painter.drawText(text_rect, Qt::AlignCenter, tr("[...]")); + } + // draw right vertical line + painter.setPen(Qt::blue); + + painter.drawLine(QPoint(left_margin + cell_width+10, drawing_height - top_margin +tick_height), + QPoint(left_margin + cell_width+10, + drawing_height - top_margin - static_cast(size)*tick_height+tick_height)); + dock_widget->legendLabel->setPixmap(legend_); + } void displayLegend() { - // Create an legend_ and display it + // Create a legend_ and display it const int height = 256; - const int width = 90; + const int width = 140; const int cell_width = width/3; const int top_margin = 5; const int left_margin = 5; @@ -1199,14 +1378,13 @@ private: painter.setPen(Qt::black); painter.setBrush(QColor(200, 200, 200)); - // Build legend_ data double min_value(dock_widget->minBox->value()), max_value(dock_widget->maxBox->value()); + // Build legend_ data std::vector graduations(100); for(int i=0; i<100; ++i) graduations[i] = i/100.0; - // draw int i=0; for (std::vector::iterator it = graduations.begin(), end = graduations.end(); it != end; ++it, i+=2) @@ -1220,37 +1398,39 @@ private: 2, color); } - // draw right vertical line painter.setPen(Qt::blue); - painter.drawLine(QPoint(left_margin + cell_width+10, drawing_height - top_margin), + painter.drawLine(QPoint(left_margin + cell_width+10, drawing_height - top_margin + 2), QPoint(left_margin + cell_width+10, - drawing_height - top_margin - static_cast(graduations.size())*2)); - - + drawing_height - top_margin - static_cast(graduations.size())*2 + 2)); // draw min value and max value painter.setPen(Qt::blue); QRect min_text_rect(left_margin + cell_width+10,drawing_height - top_margin, - 50, text_height); + 100, text_height); painter.drawText(min_text_rect, Qt::AlignCenter, tr("%1").arg(min_value, 0, 'f', 1)); QRect max_text_rect(left_margin + cell_width+10, drawing_height - top_margin - 200, - 50, text_height); + 100, text_height); painter.drawText(max_text_rect, Qt::AlignCenter, tr("%1").arg(max_value, 0, 'f', 1)); dock_widget->legendLabel->setPixmap(legend_); } + double scaled_jacobian(const face_descriptor& f , const SMesh &mesh); QList _actions; Color_ramp color_ramp; + std::vector color_map; DockWidget* dock_widget; double rm; double rM; + double rI; double gm; double gM; + double gI; double bm; double bM; + double bI; boost::unordered_map > jacobian_min; boost::unordered_map > jacobian_max; @@ -1270,6 +1450,243 @@ private: boost::unordered_map mesh_heat_method_map; boost::unordered_map mesh_heat_method_idt_map; + + template friend class PropertyDisplayer; + + //CRTP used to display properties of surface meshes(vertex and face) and point set. + template + struct PropertyDisplayer + { + typedef typename PM::value_type Value_type; + PropertyDisplayer(DataSet& ds, PM pm, DisplayPropertyPlugin* parent) + :dataset(ds), property_map(pm), parent(parent) + {} + + virtual void fill_values(){} + virtual void set_colors_map(std::unordered_map &value_index_map){} + virtual void set_colors_ramp(){} + bool operator()() + { + parent->minBox = ARBITRARY_DBL_MAX; + parent->maxBox = -ARBITRARY_DBL_MAX; + static_cast(this)->fill_values(); + std::sort(values.begin(), values.end()); + auto end = std::unique(values.begin(), values.end()); + + + parent->minBox = *values.begin(); + parent->maxBox = *(end-1); + parent->dock_widget->minBox->setValue(parent->minBox); + parent->dock_widget->maxBox->setValue(parent->maxBox); + + //fill color pmap + if(parent->dock_widget->colorChoiceWidget->currentIndex() == 1) + { + std::unordered_map value_index_map; + //fill map + std::size_t counter = 0; + for(auto it = values.begin(); it != end; ++it) + { + value_index_map[*it] = counter++; + } + parent->color_map.clear(); + compute_color_map(QColor(parent->rI, parent->gI, parent->bI),std::distance(values.begin(), end), + std::back_inserter(parent->color_map)); + static_cast(this)->set_colors_map(value_index_map); + parent->displayMapLegend(values); + } + else + { + //scale a color ramp between min and max + parent->replaceRamp(); + static_cast(this)->set_colors_ramp(); + } + return true; + } + + + DataSet& dataset; + PM property_map; + std::vector values; + DisplayPropertyPlugin* parent; + }; + + template + struct PSDisplayer + : public PropertyDisplayer > + { + typedef typename PM::value_type Value_type; + typedef PropertyDisplayer > Base; + PSDisplayer(Point_set& ds, PM pm, DisplayPropertyPlugin* parent) + :Base(ds, pm, parent) + {} + void fill_values() + { + for(auto p : this->dataset) + { + this->values.push_back(this->property_map[p]); + } + } + + void set_colors_map(std::unordered_map &value_index_map) + { + for(Point_set::iterator pit = this->dataset.begin(); + pit != this->dataset.end(); + ++pit) + { + CGAL::Color color( + this->parent->color_map[value_index_map[this->property_map[*pit]]].red(), + this->parent->color_map[value_index_map[this->property_map[*pit]]].green(), + this->parent->color_map[value_index_map[this->property_map[*pit]]].blue()); + this->dataset.set_color(*pit, color.red(), color.green(), color.blue()); + } + } + + void set_colors_ramp() + { + float max = this->parent->maxBox; + float min = this->parent->minBox; + for(Point_set::iterator pit = this->dataset.begin(); + pit != this->dataset.end(); + ++pit) + { + if(min == max) + --min; + float f = (static_cast(this->property_map[*pit])-min)/(max-min); + if(f<0) + f = 0; + if(f>1) + f = 1; + CGAL::Color color( + 255*this->parent->color_ramp.r(f), + 255*this->parent->color_ramp.g(f), + 255*this->parent->color_ramp.b(f)); + this->dataset.set_color(*pit, color.red(), color.green(), color.blue()); + } + } + + }; + + + template + struct SMVertexDisplayer + : public PropertyDisplayer > + { + typedef typename PM::value_type Value_type; + typedef PropertyDisplayer > Base; + SMVertexDisplayer(SMesh& ds, PM pm, DisplayPropertyPlugin* parent) + :Base(ds, pm, parent) + {} + + void fill_values() + { + for(auto v : vertices(this->dataset)) + { + this->values.push_back(this->property_map[v]); + } + } + + void set_colors_map(std::unordered_map &value_index_map) + { + SMesh::Property_map vcolors = + this->dataset.template add_property_map("v:color", CGAL::Color()).first; + for(boost::graph_traits::vertex_iterator vit = vertices(this->dataset).begin(); + vit != vertices(this->dataset).end(); + ++vit) + { + CGAL::Color color( + this->parent->color_map[value_index_map[this->property_map[*vit]]].red(), + this->parent->color_map[value_index_map[this->property_map[*vit]]].green(), + this->parent->color_map[value_index_map[this->property_map[*vit]]].blue()); + vcolors[*vit] = color; + } + } + + void set_colors_ramp() + { + SMesh::Property_map vcolors = + this->dataset.template add_property_map("v:color", CGAL::Color()).first; + float max = this->parent->maxBox; + float min = this->parent->minBox; + for(boost::graph_traits::vertex_iterator vit = vertices(this->dataset).begin(); + vit != vertices(this->dataset).end(); + ++vit) + { + if(min == max) + --min; + float f = (static_cast(this->property_map[*vit])-min)/(max-min); + if(f<0) + f = 0; + if(f>1) + f = 1; + CGAL::Color color( + 255*this->parent->color_ramp.r(f), + 255*this->parent->color_ramp.g(f), + 255*this->parent->color_ramp.b(f)); + vcolors[*vit] = color; + } + } + }; + + template + struct SMFaceDisplayer + : public PropertyDisplayer > + { + typedef PropertyDisplayer > Base; + typedef typename PM::value_type Value_type; + SMFaceDisplayer(SMesh& ds, PM pm, DisplayPropertyPlugin* parent) + :Base(ds, pm, parent) + {} + void fill_values() + { + for(auto f : faces(this->dataset)) + { + this->values.push_back(this->property_map[f]); + } + } + + void set_colors_map(std::unordered_map &value_index_map) + { + SMesh::Property_map fcolors = + this->dataset.template add_property_map("f:color", CGAL::Color()).first; + for(boost::graph_traits::face_iterator fit = faces(this->dataset).begin(); + fit != faces(this->dataset).end(); + ++fit) + { + CGAL::Color color( + this->parent->color_map[value_index_map[this->property_map[*fit]]].red(), + this->parent->color_map[value_index_map[this->property_map[*fit]]].green(), + this->parent->color_map[value_index_map[this->property_map[*fit]]].blue()); + fcolors[*fit] = color; + } + } + + void set_colors_ramp() + { + SMesh::Property_map fcolors = + this->dataset.template add_property_map("f:color", CGAL::Color()).first; + float max = this->parent->maxBox; + float min = this->parent->minBox; + for(boost::graph_traits::face_iterator fit = faces(this->dataset).begin(); + fit != faces(this->dataset).end(); + ++fit) + { + if(min == max) + --min; + float f = (static_cast(this->property_map[*fit])-min)/(max-min); + if(f<0) + f = 0; + if(f>1) + f = 1; + CGAL::Color color( + 255*this->parent->color_ramp.r(f), + 255*this->parent->color_ramp.g(f), + 255*this->parent->color_ramp.b(f)); + fcolors[*fit] = color; + } + } + }; + }; /// Code based on the verdict module of vtk @@ -1328,5 +1745,338 @@ private: } + bool DisplayPropertyPlugin::is_property_scalar(std::string name, const Point_set* ps) + { + if(name == "red" + || name == "green" + || name == "blue") + { + return false; + } + + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + if(ps->template property_map(name).second) + { + return true; + } + return false; + } + + template + bool DisplayPropertyPlugin::is_property_scalar(std::string name, const SMesh* sm) + { + + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + if(sm->template property_map(name).second) + { + return true; + } + return false; + } + + bool DisplayPropertyPlugin::treat_point_property(std::string name, Point_set* ps) + { + typedef typename Point_set::template Property_map Int8_map; + typedef typename Point_set::template Property_map Uint8_map; + typedef typename Point_set::template Property_map Int16_map; + typedef typename Point_set::template Property_map Uint16_map; + typedef typename Point_set::template Property_map Int32_map; + typedef typename Point_set::template Property_map Uint32_map; + typedef typename Point_set::template Property_map Int64_map; + typedef typename Point_set::template Property_map Uint64_map; + typedef typename Point_set::template Property_map Float_map; + typedef typename Point_set::template Property_map Double_map; + + bool okay = false; + { + Int8_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Uint8_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Int16_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Uint16_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Int32_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Uint32_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Int64_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Uint64_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Float_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + + { + Double_map pmap; + std::tie(pmap, okay) = ps->property_map(name); + if(okay) + { + return displayPSProperty(ps, pmap); + } + } + return false; + } + + template + bool DisplayPropertyPlugin::treat_sm_property(std::string name, SMesh* sm) + { + typedef typename SMesh::template Property_map Int8_map; + typedef typename SMesh::template Property_map Uint8_map; + typedef typename SMesh::template Property_map Int16_map; + typedef typename SMesh::template Property_map Uint16_map; + typedef typename SMesh::template Property_map Int32_map; + typedef typename SMesh::template Property_map Uint32_map; + typedef typename SMesh::template Property_map Int64_map; + typedef typename SMesh::template Property_map Uint64_map; + typedef typename SMesh::template Property_map Float_map; + typedef typename SMesh::template Property_map Double_map; + + bool okay = false; + { + Int8_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Uint8_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Int16_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Uint16_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Int32_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Uint32_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Int64_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Uint64_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Float_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + + { + Double_map pmap; + std::tie(pmap, okay) = sm->property_map(name); + if(okay) + { + return displaySMProperty(*sm, pmap, TAG()); + } + } + return false; + } + + template + bool DisplayPropertyPlugin::displayPSProperty(Point_set* ps, PM pm) + { + PSDisplayer display_property(*ps, pm, this); + return display_property(); + } + + template + bool DisplayPropertyPlugin::displaySMProperty(SMesh& smesh, PM pm, vertex_descriptor) + { + SMVertexDisplayer display_property(smesh, pm, this); + return display_property(); + } + + template + bool DisplayPropertyPlugin::displaySMProperty(SMesh& smesh, PM pm, face_descriptor) + { + SMFaceDisplayer display_property(smesh, pm, this); + return display_property(); + } #include "Display_property_plugin.moc" + diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt index b3a02fe105a..cccd05d4b08 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/CMakeLists.txt @@ -1,35 +1,35 @@ include( polyhedron_demo_macros ) -polyhedron_demo_plugin(gocad_plugin GOCAD_io_plugin KEYWORDS IO) +polyhedron_demo_plugin(gocad_plugin GOCAD_io_plugin KEYWORDS Viewer) target_link_libraries(gocad_plugin PUBLIC scene_surface_mesh_item) qt5_wrap_ui( funcUI_FILES Function_dialog.ui ) -polyhedron_demo_plugin(io_implicit_function_plugin Implicit_function_io_plugin ${funcUI_FILES} KEYWORDS IO Mesh_3) +polyhedron_demo_plugin(io_implicit_function_plugin Implicit_function_io_plugin ${funcUI_FILES} KEYWORDS Viewer Mesh_3) target_link_libraries(io_implicit_function_plugin PUBLIC scene_implicit_function_item) -polyhedron_demo_plugin(nef_io_plugin Nef_io_plugin KEYWORDS IO) +polyhedron_demo_plugin(nef_io_plugin Nef_io_plugin KEYWORDS Viewer) target_link_libraries(nef_io_plugin PUBLIC scene_nef_polyhedron_item) -polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS IO Mesh_3 PointSetProcessing Classification PMP) +polyhedron_demo_plugin(off_plugin OFF_io_plugin KEYWORDS Viewer Mesh_3 PointSetProcessing Classification PMP) target_link_libraries(off_plugin PUBLIC scene_polygon_soup_item scene_points_with_normal_item scene_surface_mesh_item) -polyhedron_demo_plugin(off_to_nef_plugin OFF_to_nef_io_plugin KEYWORDS IO) +polyhedron_demo_plugin(off_to_nef_plugin OFF_to_nef_io_plugin KEYWORDS Viewer) target_link_libraries(off_to_nef_plugin PUBLIC scene_nef_polyhedron_item) -polyhedron_demo_plugin(polylines_io_plugin Polylines_io_plugin KEYWORDS IO Mesh_3) +polyhedron_demo_plugin(polylines_io_plugin Polylines_io_plugin KEYWORDS Viewer Mesh_3) target_link_libraries(polylines_io_plugin PUBLIC scene_polylines_item) -polyhedron_demo_plugin(wkt_plugin WKT_io_plugin KEYWORDS IO PointSetProcessing Mesh_3) +polyhedron_demo_plugin(wkt_plugin WKT_io_plugin KEYWORDS Viewer PointSetProcessing Mesh_3) target_link_libraries(wkt_plugin PUBLIC scene_polylines_item) -polyhedron_demo_plugin(stl_plugin STL_io_plugin KEYWORDS IO PMP) +polyhedron_demo_plugin(stl_plugin STL_io_plugin KEYWORDS Viewer PMP) target_link_libraries(stl_plugin PUBLIC scene_surface_mesh_item scene_polygon_soup_item) -polyhedron_demo_plugin(surf_io_plugin Surf_io_plugin KEYWORDS IO PMP) +polyhedron_demo_plugin(surf_io_plugin Surf_io_plugin KEYWORDS Viewer PMP) target_link_libraries(surf_io_plugin PUBLIC scene_surface_mesh_item) -polyhedron_demo_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS IO) +polyhedron_demo_plugin(lcc_io_plugin lcc_io_plugin KEYWORDS Viewer) target_link_libraries(lcc_io_plugin PUBLIC scene_lcc_item) @@ -44,7 +44,7 @@ if (VTK_FOUND) set(VTK_LIBRARIES VTK::CommonCore VTK::IOCore VTK::IOLegacy VTK::IOXML VTK::FiltersCore VTK::FiltersSources) endif() if(VTK_LIBRARIES) - polyhedron_demo_plugin(vtk_plugin VTK_io_plugin KEYWORDS IO Mesh_3) + polyhedron_demo_plugin(vtk_plugin VTK_io_plugin KEYWORDS Viewer Mesh_3) target_link_libraries(vtk_plugin PUBLIC scene_surface_mesh_item scene_polylines_item scene_c3t3_item scene_points_with_normal_item ${VTK_LIBRARIES}) target_compile_definitions(vtk_plugin PRIVATE -DCGAL_USE_VTK) @@ -57,7 +57,7 @@ if (VTK_FOUND) else() message(STATUS "NOTICE : the vtk IO plugin needs VTK 6.0 or greater and will not be compiled.") endif() -polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS IO PointSetProcessing Classification) +polyhedron_demo_plugin(xyz_plugin XYZ_io_plugin KEYWORDS Viewer PointSetProcessing Classification) target_link_libraries(xyz_plugin PUBLIC scene_points_with_normal_item) list(FIND CMAKE_CXX_COMPILE_FEATURES cxx_rvalue_references has_cxx_rvalues) @@ -68,12 +68,12 @@ if(has_cxx_rvalues LESS 0 OR has_cxx_variadic LESS 0) else() set(needed_cxx_features cxx_rvalue_references cxx_variadic_templates) - polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS IO PointSetProcessing Classification PMP) + polyhedron_demo_plugin(ply_plugin PLY_io_plugin KEYWORDS Viewer PointSetProcessing Classification PMP) target_link_libraries(ply_plugin PUBLIC scene_points_with_normal_item scene_polygon_soup_item scene_surface_mesh_item scene_textured_item) target_compile_features(ply_plugin PRIVATE ${needed_cxx_features}) if (TARGET CGAL::LASLIB_support) - polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS IO PointSetProcessing Classification) + polyhedron_demo_plugin(las_plugin LAS_io_plugin KEYWORDS Viewer PointSetProcessing Classification) target_link_libraries(las_plugin PUBLIC scene_points_with_normal_item CGAL::LASLIB_support) target_compile_features(las_plugin PRIVATE ${needed_cxx_features}) else() @@ -90,7 +90,7 @@ find_library(3MF_LIBRARIES NAMES 3MF DOC "Path to the lib3MF library") if(3MF_LIBRARIES AND 3MF_INCLUDE_DIR AND EXISTS "${3MF_INCLUDE_DIR}/Model/COM/NMR_DLLInterfaces.h") include_directories(${3MF_INCLUDE_DIR}) - polyhedron_demo_plugin(3mf_io_plugin 3mf_io_plugin KEYWORDS IO PMP) + polyhedron_demo_plugin(3mf_io_plugin 3mf_io_plugin KEYWORDS Viewer PMP) target_link_libraries(3mf_io_plugin PRIVATE scene_surface_mesh_item scene_points_with_normal_item scene_polylines_item ${3MF_LIBRARIES}) target_compile_definitions(3mf_io_plugin PRIVATE -DCGAL_LINKED_WITH_3MF) else() diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp index 9388fa0f5f2..d105002b071 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/PLY_io_plugin.cpp @@ -5,6 +5,7 @@ #include #include +#include #include #include @@ -99,12 +100,16 @@ load(QFileInfo fileinfo, bool& ok, bool add_to_scene) { if (input_is_mesh) // Open mesh or polygon soup { // First try mesh - SMesh *surface_mesh = new SMesh(); std::string comments; - - if (CGAL::read_PLY(in, *surface_mesh, comments)) + Scene_surface_mesh_item* sm_item = new Scene_surface_mesh_item(); + if (CGAL::read_PLY(in, *sm_item->face_graph(), comments)) { - Scene_surface_mesh_item* sm_item = new Scene_surface_mesh_item(surface_mesh); + if(sm_item->face_graph()->property_map("f:patch_id").second) + { + sm_item->setItemIsMulticolor(true); + sm_item->computeItemColorVectorAutomatically(true); + } + sm_item->invalidateOpenGLBuffers(); sm_item->setName(fileinfo.completeBaseName()); sm_item->comments() = comments; QApplication::restoreOverrideCursor(); @@ -113,6 +118,10 @@ load(QFileInfo fileinfo, bool& ok, bool add_to_scene) { CGAL::Three::Three::scene()->addItem(sm_item); return QList()<has_normals()) item->setRenderingMode(CGAL::Three::Three::defaultPointSetRenderingMode()); item->setName(fileinfo.completeBaseName()); + QApplication::restoreOverrideCursor(); ok = true; + if(add_to_scene) CGAL::Three::Three::scene()->addItem(item); return QList()<((c->weighted_circumcenter().x() - bbox.xmin()) + float relPos = static_cast((c->weighted_circumcenter(gt).x() - bbox.xmin()) / (bbox.xmax() - bbox.xmin())); float TRANSPARENCY_ALPHA_VALUE = 1.f - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt index 03ada7360f3..7de294de730 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt @@ -35,7 +35,7 @@ endif() find_package(Boost QUIET OPTIONAL_COMPONENTS filesystem system) if(Boost_FILESYSTEM_FOUND) qt5_wrap_ui( imgUI_FILES Image_res_dialog.ui raw_image.ui) - polyhedron_demo_plugin(io_image_plugin Io_image_plugin Volume_plane_intersection.cpp Raw_image_dialog.cpp ${imgUI_FILES} ${VOLUME_MOC_OUTFILES} KEYWORDS IO Mesh_3) + polyhedron_demo_plugin(io_image_plugin Io_image_plugin Volume_plane_intersection.cpp Raw_image_dialog.cpp ${imgUI_FILES} ${VOLUME_MOC_OUTFILES} KEYWORDS Viewer Mesh_3) target_link_libraries(io_image_plugin PUBLIC scene_image_item ${VTK_LIBRARIES} CGAL::CGAL_ImageIO) if(VTK_LIBRARIES) target_compile_definitions(io_image_plugin PRIVATE CGAL_USE_VTK) @@ -63,7 +63,7 @@ target_link_libraries(mesh_3_optimization_plugin PUBLIC scene_c3t3_item scene_su message(STATUS "The Mesh_3_optimization_plugin requires Eigen, which was not found, and will use a deprecated class to replace it. Warnings are to be expected.") endif()#eigen -polyhedron_demo_plugin(c3t3_io_plugin C3t3_io_plugin KEYWORDS IO Mesh_3) +polyhedron_demo_plugin(c3t3_io_plugin C3t3_io_plugin KEYWORDS Viewer Mesh_3) target_link_libraries(c3t3_io_plugin PUBLIC scene_c3t3_item) qt5_wrap_ui( ribUI_FILES Rib_dialog.ui) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_mesh_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_mesh_plugin.cpp new file mode 100644 index 00000000000..a9045771804 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_mesh_plugin.cpp @@ -0,0 +1,326 @@ +#include "Messages_interface.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "Scene_surface_mesh_item.h" +#include +#include +#include +#include + +#include "ui_Animate_widget.h" +#include + +using namespace CGAL::Three; +typedef Viewer_interface Vi; + + +class DockWidget : + public QDockWidget, + public Ui::AnimateWidget +{ +public: + DockWidget(QString name, QWidget *parent) + :QDockWidget(name,parent) + { + setupUi(this); + } +}; + + + +class Q_DECL_EXPORT Animate_mesh_plugin : + public QObject, + public CGAL::Three::Polyhedron_demo_plugin_helper +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") +public : + void init(QMainWindow* mw, + CGAL::Three::Scene_interface* scene_interface, + Messages_interface* mi) override { + //get the references + this->scene = scene_interface; + this->messages = mi; + this->mw = mw; + actionAnimate = new QAction("Animate Surface Mesh", mw); + actionAnimate->setProperty("subMenuName","Operations on Polyhedra"); + + dock_widget = new DockWidget("Mesh Animation", mw); + dock_widget->setVisible(false); // do not show at the beginning + addDockWidget(dock_widget); + connect(actionAnimate, &QAction::triggered, + this, &Animate_mesh_plugin::init_animation); + + connect(dock_widget->startButton, &QPushButton::clicked, + this, &Animate_mesh_plugin::start_animation); + + connect(dock_widget->resetButton, &QPushButton::clicked, + this, &Animate_mesh_plugin::reset_animation); + + connect(dock_widget->nextButton, &QPushButton::clicked, + this, &Animate_mesh_plugin::next_frame); + connect(dock_widget->prevButton, &QPushButton::clicked, + this, &Animate_mesh_plugin::prev_frame); + connect(dock_widget->stopButton, &QPushButton::clicked, + this, [this](){ + timer.stop(); + }); + connect(&timer, SIGNAL (timeout()), this, SLOT (next_frame())); + frame = -1; + connect(dock_widget->helpButton, &QPushButton::clicked,this, [this](){ + QMessageBox::information(dock_widget, QString("Animation"), + QString("The TRJS format contains informations for a succession of modifications on a Surface Mesh. " + "Such a modification is called a frame, and every frame is composed with a ligne for the " + "number of points modified, and one ligne per modified point and its index.\n\n" + "Example:\n\n" + "n \n" + "id1 x1 y1 z1 \n" + "... \n" + "idn xn yn zn \n" + "m \n" + "id1 x1 y1 z1 \n" + "... \n" + "idm xm ym zm")); + }); + + } + + bool applicable(QAction*) const override + { + Scene_item* item = scene->item(scene->mainSelectionIndex()); + if(!item) + return false; + return qobject_cast(item); + } + + QList actions() const override{ + return QList() << actionAnimate; + } + +public Q_SLOTS: + + void read_frame() + { + typedef boost::property_map::type VPmap; + const CGAL::qglviewer::Vec offset = Three::mainViewer()->offset(); + + std::ifstream is(filepath.toUtf8()); + is.seekg(position); + if(!is.good()) + { + timer.stop(); + return; + } + int nb_verts; + is >> nb_verts; + if(!is.good()) + { + timer.stop(); + return; + } + + if(nb_verts != 0) + { + EPICK::FT x,y,z; + for(int i = 0; i< nb_verts; ++i) + { + int id; + is >> id; + if(!is.good()) + { + timer.stop(); + return; + } + is >> x; + if(!is.good()) + { + timer.stop(); + return; + } + is >> y; + if(!is.good()) + { + timer.stop(); + return; + } + is >> z; + if(!is.good()) + { + timer.stop(); + return; + } + if(id <= static_cast(sm_item->face_graph()->number_of_vertices())) + { + SMesh::Vertex_index vh(id); + VPmap vpm = get(CGAL::vertex_point, *sm_item->face_graph()); + put(vpm, vh, Point_3(x-offset.x, + y-offset.y, + z-offset.z)); + sm_item->updateVertex(vh); + } + } + } + + sm_item->redraw(); + if(!is.good()) + { + timer.stop(); + return; + } + } + + void next_frame() + { + if(frame == static_cast(frame_pos.size()-1)) + { + timer.stop(); + return; + } + position = frame_pos[++frame]; + dock_widget->frameSlider->setValue(frame); + dock_widget->frameLabel->setText(QString("%1/%2").arg(frame).arg(frame_pos.size()-1)); + read_frame(); + } + + void prev_frame() + { + if(frame <= 0) + return; + position = frame_pos[--frame]; + dock_widget->frameSlider->setValue(frame); + dock_widget->frameLabel->setText(QString("%1/%2").arg(frame).arg(frame_pos.size()-1)); + read_frame(); + } + + void start_animation() + { + timer.start(dock_widget->frame_time->value()); + } + + void reset_animation() + { + timer.stop(); + frame=-1; + dock_widget->frameSlider->setValue(frame); + dock_widget->frameLabel->setText(QString("%1/%2").arg(frame).arg(frame_pos.size()-1)); + for(std::size_t id = 0; idface_graph()->points()[SMesh::Vertex_index( + static_cast::size_type>(id))]//not size_t on windows. + =initial_points[id]; + } + sm_item->invalidateOpenGLBuffers(); + sm_item->redraw(); + } + + void init_animation() + { + clean_up(); + Scene_item* item = scene->item(scene->mainSelectionIndex()); + if(!item) + return; + sm_item = qobject_cast(item); + connect(sm_item, &Scene_surface_mesh_item::aboutToBeDestroyed, this, + [this](){ + clean_up(); + }); + initial_points.reserve(sm_item->face_graph()->number_of_vertices()); + for(const auto& p : sm_item->face_graph()->points()) + initial_points.push_back(p); + + //ask the file (*.trjs) + QFileDialog dialog(mw); + QStringList filters; + filters << "Trajectories file(*.trjs)"; + dialog.setNameFilters(filters); + dialog.setFileMode(QFileDialog::ExistingFiles); + if(dialog.exec() != QDialog::Accepted) { return; } + QFileInfo info(dialog.selectedFiles().first()); + filepath = info.filePath(); + position = 0; + dock_widget->resetButton->setEnabled(true); + dock_widget->startButton->setEnabled(true); + dock_widget->prevButton->setEnabled(true); + dock_widget->nextButton->setEnabled(true); + dock_widget->stopButton->setEnabled(true); + dock_widget->frameSlider->setEnabled(true); + dock_widget->setWindowTitle(QString("Animate %1").arg(sm_item->name())); + if(!info.exists()) + { + QMessageBox::warning(mw, "Error","File does not exist."); + return; + } + + if(!dock_widget->isVisible()) { dock_widget->show(); } + + //pre-process to count frames + QApplication::setOverrideCursor(Qt::WaitCursor); + std::ifstream is(filepath.toUtf8()); + frame_pos.clear(); + while(is.good()) + { + std::string line; + std::streampos pos = is.tellg(); + std::getline(is, line); + if(line.length() > 0 && line.find(" ") == std::string::npos) + frame_pos.push_back(pos); + } + is.close(); + dock_widget->frameSlider->setMaximum(static_cast(frame_pos.size())-1); + dock_widget->frameLabel->setText(QString("%1/%2").arg(frame).arg(frame_pos.size()-1)); + + connect(dock_widget->frameSlider, &QSlider::sliderMoved, [this](int i){ + frame = i; + position = frame_pos[frame]; + dock_widget->frameLabel->setText(QString("%1/%2").arg(frame).arg(frame_pos.size()-1)); + read_frame(); + }); + + QApplication::restoreOverrideCursor(); + } + + void closure() override + { + dock_widget->hide(); + } + + void clean_up() + { + sm_item=nullptr; + position=0; + frame_pos.clear(); + filepath=""; + frame = -1; + dock_widget->resetButton->setEnabled(false); + dock_widget->startButton->setEnabled(false); + dock_widget->prevButton->setEnabled(false); + dock_widget->nextButton->setEnabled(false); + dock_widget->stopButton->setEnabled(false); + dock_widget->frameSlider->setEnabled(false); + dock_widget->setWindowTitle(QString("Animate")); + initial_points.clear(); + initial_points.shrink_to_fit(); + } + +private: + QAction* actionAnimate; + Messages_interface* messages; + Scene_interface* scene; + DockWidget* dock_widget; + QString filepath; + std::streampos position; + Scene_surface_mesh_item* sm_item; + std::vector frame_pos; + QTimer timer; + int frame; + std::vector initial_points; +}; //end of plugin class +#include "Animate_mesh_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_widget.ui new file mode 100644 index 00000000000..3afb30392b0 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/Animate_widget.ui @@ -0,0 +1,230 @@ + + + AnimateWidget + + + + 0 + 0 + 371 + 183 + + + + Qt::DefaultContextMenu + + + Animate + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/help_button.png:/cgal/icons/resources/help_button.png + + + + + + + + + + + Frame time(ms): + + + + + + + ms + + + 1 + + + 9999 + + + 500 + + + + + + + + + + + Qt::Horizontal + + + QSlider::TicksAbove + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 0/N + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/play.jpeg:/cgal/icons/resources/play.jpeg + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/pause.jpeg:/cgal/icons/resources/pause.jpeg + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/left_arrow.png:/cgal/icons/resources/left_arrow.png + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/right_arrow.png:/cgal/icons/resources/right_arrow.png + + + + + + + + 0 + 0 + + + + + + + + :/cgal/icons/resources/reset.jpg:/cgal/icons/resources/reset.jpg + + + + + + + + + + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt index baa5f345435..550669a0c5a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Operations_on_polyhedra/CMakeLists.txt @@ -9,6 +9,10 @@ include( polyhedron_demo_macros ) polyhedron_demo_plugin(diff_between_meshes_plugin Diff_between_meshes_plugin) target_link_libraries(diff_between_meshes_plugin PUBLIC scene_surface_mesh_item) + qt5_wrap_ui( animateUI_FILES Animate_widget.ui ) + polyhedron_demo_plugin(animate_mesh_plugin Animate_mesh_plugin ${animateUI_FILES}) + target_link_libraries(animate_mesh_plugin PUBLIC scene_surface_mesh_item) + if( METIS_FOUND ) qt5_wrap_ui( partitionUI_FILES PartitionDialog.ui ) polyhedron_demo_plugin(partition_plugin Partition_graph_plugin ${partitionUI_FILES}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp index 75b996dda51..49cb1b2f15f 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp @@ -417,12 +417,9 @@ void Polyhedron_demo_affine_transform_plugin::grid() Scene_item::Bbox b = item->bbox(); - double x_t(CGAL::sqrt(CGAL::squared_distance(Kernel::Point_3((b.min)(0), (b.min)(1), (b.min)(2)), - Kernel::Point_3((b.max)(0), (b.min)(1), (b.min)(2))))), - y_t(CGAL::sqrt(CGAL::squared_distance(Kernel::Point_3((b.min)(0), (b.min)(1), (b.min)(2)), - Kernel::Point_3((b.min)(0), (b.max)(1), (b.min)(2))))), - z_t(CGAL::sqrt(CGAL::squared_distance(Kernel::Point_3((b.min)(0), (b.min)(1), (b.min)(2)), - Kernel::Point_3((b.min)(0), (b.min)(1), (b.max)(2))))); + double x_t(1.001*((b.max)(0)- (b.min)(0))), + y_t(1.001*((b.max)(1)- (b.min)(1))), + z_t(1.001*((b.max)(2)- (b.min)(2))); GridDialog dialog(mw); dialog.x_space_doubleSpinBox->setValue(x_t); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 672e4fb0f7a..d6025740c6a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -5,19 +5,37 @@ #include #include #include + #include #include + +#include +#include + +#include +#include + #include #include #include +#include + #include "Scene_surface_mesh_item.h" #include "Scene_points_with_normal_item.h" #include "Scene_polylines_item.h" -#include -#include -#include + #include "ui_Basic_generator_widget.h" +struct Face : public std::array +{ + Face(int i, int j, int k) + { + (*this)[0] = i; + (*this)[1] = j; + (*this)[2] = k; + } +}; + class GeneratorWidget : public QDockWidget, public Ui::BasicGenerator @@ -703,53 +721,85 @@ void Basic_generator_plugin::generateLines() } Q_FOREACH(QString s, list) { - if(!s.isEmpty()) + if(!s.isEmpty()) + { + double res = s.toDouble(&ok); + if(!ok) { - double res = s.toDouble(&ok); - if(!ok) - { - QMessageBox *msgBox = new QMessageBox; - msgBox->setWindowTitle("Error"); - msgBox->setText("ERROR : Coordinates are invalid."); - msgBox->exec(); - break; - } - else - { - coord[counter] = res; - counter++; - } + QMessageBox *msgBox = new QMessageBox; + msgBox->setWindowTitle("Error"); + msgBox->setText("ERROR : Coordinates are invalid."); + msgBox->exec(); + break; } - if(!dock_widget->polygon_checkBox->isChecked() && counter == 3) + else { - Scene_polylines_item::Point_3 p(coord[0], coord[1], coord[2]); - polyline.push_back(p); - counter =0; - } - else if(dock_widget->polygon_checkBox->isChecked() && counter == 2) - { - Scene_polylines_item::Point_3 p(coord[0], coord[1], 0); - polyline.push_back(p); - counter = 0; + coord[counter] = res; + counter++; } + } + if(!dock_widget->polygon_checkBox->isChecked() && counter == 3) + { + Scene_polylines_item::Point_3 p(coord[0], coord[1], coord[2]); + polyline.push_back(p); + counter =0; + } + else if(dock_widget->polygon_checkBox->isChecked() && counter == 2) + { + Scene_polylines_item::Point_3 p(coord[0], coord[1], 0); + polyline.push_back(p); + counter = 0; + } } if(dock_widget->polygon_checkBox->isChecked()) { polyline.push_back(polyline.front()); //polygon_2 are not closed. } - if(ok) + if(ok) + { + dock_widget->line_textEdit->clear(); + if(dock_widget->fill_checkBox->isChecked()) { - dock_widget->line_textEdit->clear(); - Scene_polylines_item* item = new Scene_polylines_item(); - item->polylines = polylines; - item->invalidateOpenGLBuffers(); - item->setName(dock_widget->name_lineEdit->text()); - item->setColor(Qt::black); - item->setProperty("polylines metadata", polylines_metadata); - item->invalidateOpenGLBuffers(); - Scene_interface::Item_id id = scene->addItem(item); - scene->setSelectedItem(id); + CGAL::Three::Three::CursorScopeGuard guard(Qt::WaitCursor); + QApplication::processEvents(); + if(polyline.front() != polyline.back()) { + polyline.push_back(polyline.front()); + } + if(polyline.size() < 4) { // no triangle, skip it (needs at least 3 + 1 repeat) + QMessageBox::warning(mw, "Warning", "Needs at least 3 points to triangulate. Aborting."); + return; + } + std::vector patch; + CGAL::Polygon_mesh_processing::triangulate_hole_polyline(polyline, + std::back_inserter(patch), + CGAL::Polygon_mesh_processing::parameters::use_delaunay_triangulation(true)); + + if(patch.empty()) { + QMessageBox::warning(mw, "Warning", "Triangulation failed."); + return; + } + SMesh* poly = new SMesh; + CGAL::Polygon_mesh_processing::polygon_soup_to_polygon_mesh(polyline, + patch, + *poly); + + Scene_surface_mesh_item* poly_item = new Scene_surface_mesh_item(poly); + poly_item->setName(dock_widget->name_lineEdit->text()); + poly_item->setRenderingMode(FlatPlusEdges); + scene->setSelectedItem(scene->addItem(poly_item)); } + else + { + Scene_polylines_item* item = new Scene_polylines_item(); + item->polylines = polylines; + item->invalidateOpenGLBuffers(); + item->setName(dock_widget->name_lineEdit->text()); + item->setColor(Qt::black); + item->setProperty("polylines metadata", polylines_metadata); + Scene_interface::Item_id id = scene->addItem(item); + scene->setSelectedItem(id); + } + } } struct Point_generator diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui index 865622d53a5..5d276e0149d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_widget.ui @@ -18,7 +18,7 @@ - 2 + 0 @@ -31,7 +31,7 @@ - :/cgal/Polyhedron_3/resources/prism.png + :/cgal/Polyhedron_3/resources/prism.png false @@ -223,7 +223,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/icosphere.png + :/cgal/Polyhedron_3/resources/icosphere.png @@ -540,7 +540,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/hexahedron.png + :/cgal/Polyhedron_3/resources/hexahedron.png false @@ -750,7 +750,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/tetrahedron.png + :/cgal/Polyhedron_3/resources/tetrahedron.png @@ -881,7 +881,7 @@ QGroupBox::title { - :/cgal/Polyhedron_3/resources/grid.png + :/cgal/Polyhedron_3/resources/grid.png @@ -1050,7 +1050,7 @@ QGroupBox::title { <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt;"><br /></p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html>
    false @@ -1068,11 +1068,22 @@ p, li { white-space: pre-wrap; } - - - From Polygon_2 - - + + + + + From Polygon_2 + + + + + + + Triangulate + + + + @@ -1087,7 +1098,7 @@ p, li { white-space: pre-wrap; } <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'Sans Serif'; font-size:9pt; font-weight:400; font-style:normal;"> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Sans Serif'; font-size:10pt;"><br /></p></body></html> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-size:10pt;"><br /></p></body></html> false @@ -1172,6 +1183,9 @@ p, li { white-space: pre-wrap; }
    CGAL_double_edit.h
    - + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt index 56d43cccef3..a7d9eac607b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/CMakeLists.txt @@ -77,7 +77,7 @@ polyhedron_demo_plugin(polyhedron_stitching_plugin Polyhedron_stitching_plugin K target_link_libraries(polyhedron_stitching_plugin PUBLIC scene_surface_mesh_item scene_polylines_item) qt5_wrap_ui( selectionUI_FILES Selection_widget.ui) -polyhedron_demo_plugin(selection_plugin Selection_plugin ${selectionUI_FILES} KEYWORDS PMP IO Classification Mesh_3) +polyhedron_demo_plugin(selection_plugin Selection_plugin ${selectionUI_FILES} KEYWORDS PMP Viewer Classification Mesh_3) target_link_libraries(selection_plugin PUBLIC scene_selection_item scene_points_with_normal_item scene_polylines_item) #to keep it simple to compile @@ -95,7 +95,7 @@ target_link_libraries(surface_intersection_plugin PUBLIC scene_surface_mesh_item qt5_wrap_ui( repairUI_FILES RemoveNeedlesDialog.ui) polyhedron_demo_plugin(repair_polyhedron_plugin Repair_polyhedron_plugin ${repairUI_FILES} KEYWORDS PMP) -target_link_libraries(repair_polyhedron_plugin PUBLIC scene_surface_mesh_item) +target_link_libraries(repair_polyhedron_plugin PUBLIC scene_points_with_normal_item scene_surface_mesh_item) qt5_wrap_ui( isotropicRemeshingUI_FILES Isotropic_remeshing_dialog.ui) polyhedron_demo_plugin(isotropic_remeshing_plugin Isotropic_remeshing_plugin ${isotropicRemeshingUI_FILES} KEYWORDS PMP) @@ -111,7 +111,7 @@ if(TARGET CGAL::TBB_support) target_link_libraries(distance_plugin PUBLIC CGAL::TBB_support) endif() -polyhedron_demo_plugin(detect_sharp_edges_plugin Detect_sharp_edges_plugin KEYWORDS IO Mesh_3 PMP) +polyhedron_demo_plugin(detect_sharp_edges_plugin Detect_sharp_edges_plugin KEYWORDS Viewer Mesh_3 PMP) target_link_libraries(detect_sharp_edges_plugin PUBLIC scene_surface_mesh_item) qt5_wrap_ui( randomPerturbationUI_FILES Random_perturbation_dialog.ui) diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp index 757c72b6cc1..120f4ef4f99 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Engrave_text_plugin.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #include @@ -455,17 +456,28 @@ public Q_SLOTS: qobject_cast (scene->item(scene->mainSelectionIndex())); if(!sel_item) + { + QMessageBox::information(mw, "Error", "No selection found."); return; + } if(sel_item->selected_facets.empty()) { + QMessageBox::information(mw, "Error", "No selected facets."); cleanup(); return; } if(!CGAL::is_closed(*sel_item->polyhedron())) { + QMessageBox::information(mw, "Error", "The surface mesh must be closed."); cleanup(); return; } + + connect(sel_item, &Scene_polyhedron_selection_item::aboutToBeDestroyed, this, + [this](){ + sel_item = nullptr; + }); + if(visu_item) scene->erase(scene->item_id(visu_item)); visu_item = nullptr; @@ -573,7 +585,10 @@ public Q_SLOTS: Tree aabb_tree(faces(*sm).first, faces(*sm).second, *sm, uv_map_3); visu_item = new Scene_polylines_item; - + connect(visu_item, &Scene_polylines_item::aboutToBeDestroyed, this, + [this](){ + visu_item = nullptr; + }); // compute 3D coordinates transfo = @@ -757,6 +772,8 @@ public Q_SLOTS: } SMesh result; + if(!sel_item) + return; CGAL::copy_face_graph(*sel_item->polyhedron(), result); bool OK = PMP::corefine_and_compute_difference(result, text_mesh_complete, result); @@ -800,7 +817,8 @@ public Q_SLOTS: textMesh = new Scene_surface_mesh_item(text_mesh); connect(textMesh, &Scene_surface_mesh_item::aboutToBeDestroyed, this, [this](){ - textMesh = nullptr;}); + textMesh = nullptr; + }); textMesh->setName("Extruded Text"); scene->addItem(textMesh); } @@ -907,7 +925,8 @@ private: dock_widget->rot_slider->setValue(0); translation = EPICK::Vector_2(0,0); uv_map_3.reset(); - graphics_scene->clear(); + if(graphics_scene) + graphics_scene->clear(); if(sel_item) { scene->erase(scene->item_id(sel_item)); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp index c00c1fee0d3..78d6371ded0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Isotropic_remeshing_plugin.cpp @@ -378,7 +378,7 @@ public Q_SLOTS: *selection_item->polyhedron(), selection_item->constrained_edges_pmap(), get(CGAL::vertex_point, *selection_item->polyhedron()), - CGAL::Static_property_map(1), + CGAL::Constant_property_map(1), 4. / 3. * target_length)) { QApplication::restoreOverrideCursor(); @@ -578,7 +578,7 @@ public Q_SLOTS: pmesh, ecm, get(CGAL::vertex_point, pmesh), - CGAL::Static_property_map(1), + CGAL::Constant_property_map(1), 4. / 3. * target_length)) { QApplication::restoreOverrideCursor(); @@ -609,6 +609,12 @@ public Q_SLOTS: .number_of_relaxation_steps(nb_smooth) .edge_is_constrained_map(ecm) .relax_constraints(smooth_features)); + + //recollect sharp edges + for(edge_descriptor e : edges(pmesh)) + eif[e] = false; + for(edge_descriptor e : edges_to_protect) + eif[e] = true; } if (fpmap_valid) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp index 1c1e7f3bd70..e2c4d3b576d 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Join_and_split_polyhedra_plugin.cpp @@ -237,7 +237,7 @@ void Polyhedron_demo_join_and_split_polyhedra_plugin::on_actionColorConnectedCom = get(boost::face_index, pmesh); boost::vector_property_map::type> - fccmap(fim); + fccmap(static_cast(num_faces(pmesh)),fim); boost::property_map >::type pid = get(CGAL::face_patch_id_t(), pmesh); diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp index 59365eb0d0e..f16ad282266 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Repair_polyhedron_plugin.cpp @@ -1,6 +1,7 @@ #include #include "Scene_surface_mesh_item.h" +#include "Scene_points_with_normal_item.h" #include #include #include @@ -47,6 +48,7 @@ public: actionRemoveSelfIntersections = new QAction(tr("Remove Self-Intersections"), mw); actionStitchCloseBorderHalfedges = new QAction(tr("Stitch Close Border Halfedges"), mw); actionDuplicateNMVertices = new QAction(tr("Duplicate Non-Manifold Vertices"), mw); + actionExtractNMVertices = new QAction(tr("Extract Non-Manifold Vertices"), mw); actionMergeDuplicatedVerticesOnBoundaryCycles = new QAction(tr("Merge Duplicated Vertices on Boundary Cycles"), mw); actionAutorefine = new QAction(tr("Autorefine Mesh"), mw); actionAutorefineAndRMSelfIntersections = new QAction(tr("Autorefine and Remove Self-Intersections"), mw); @@ -57,6 +59,7 @@ public: actionRemoveSelfIntersections->setObjectName("actionRemoveSelfIntersections"); actionStitchCloseBorderHalfedges->setObjectName("actionStitchCloseBorderHalfedges"); actionDuplicateNMVertices->setObjectName("actionDuplicateNMVertices"); + actionExtractNMVertices->setObjectName("actionExtractNMVertices"); actionMergeDuplicatedVerticesOnBoundaryCycles->setObjectName("actionMergeDuplicatedVerticesOnBoundaryCycles"); actionAutorefine->setObjectName("actionAutorefine"); actionAutorefineAndRMSelfIntersections->setObjectName("actionAutorefineAndRMSelfIntersections"); @@ -67,6 +70,7 @@ public: actionRemoveSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); actionRemoveIsolatedVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); actionDuplicateNMVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); + actionExtractNMVertices->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); actionMergeDuplicatedVerticesOnBoundaryCycles->setProperty("subMenuName", "Polygon Mesh Processing/Repair"); actionAutorefine->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); actionAutorefineAndRMSelfIntersections->setProperty("subMenuName", "Polygon Mesh Processing/Repair/Experimental"); @@ -82,6 +86,7 @@ public: << actionRemoveSelfIntersections << actionStitchCloseBorderHalfedges << actionDuplicateNMVertices + << actionExtractNMVertices << actionMergeDuplicatedVerticesOnBoundaryCycles << actionAutorefine << actionAutorefineAndRMSelfIntersections @@ -104,6 +109,8 @@ public: template void on_actionDuplicateNMVertices_triggered(Scene_interface::Item_id index); template + void on_actionExtractNMVertices_triggered(Scene_interface::Item_id index); + template void on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered(Scene_interface::Item_id index); template void on_actionAutorefine_triggered(Scene_interface::Item_id index); @@ -116,6 +123,7 @@ public Q_SLOTS: void on_actionRemoveSelfIntersections_triggered(); void on_actionStitchCloseBorderHalfedges_triggered(); void on_actionDuplicateNMVertices_triggered(); + void on_actionExtractNMVertices_triggered(); void on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered(); void on_actionAutorefine_triggered(); void on_actionAutorefineAndRMSelfIntersections_triggered(); @@ -127,6 +135,7 @@ private: QAction* actionRemoveSelfIntersections; QAction* actionStitchCloseBorderHalfedges; QAction* actionDuplicateNMVertices; + QAction* actionExtractNMVertices; QAction* actionMergeDuplicatedVerticesOnBoundaryCycles; QAction* actionAutorefine; QAction* actionAutorefineAndRMSelfIntersections; @@ -147,6 +156,7 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionRemoveIsolatedVertices_t *poly_item->polyhedron()); CGAL::Three::Three::information(tr(" %1 isolated vertices have been removed.") .arg(nbv)); + poly_item->setNbIsolatedvertices(0); poly_item->invalidateOpenGLBuffers(); Q_EMIT poly_item->itemChanged(); } @@ -346,6 +356,32 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_trig } } +template +void Polyhedron_demo_repair_polyhedron_plugin::on_actionExtractNMVertices_triggered(Scene_interface::Item_id index) +{ + namespace PMP = CGAL::Polygon_mesh_processing; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + if (Item* poly_item = qobject_cast(scene->item(index))) + { + std::vector hds; + PMP::non_manifold_vertices(*poly_item->face_graph(), std::back_inserter(hds)); + if(hds.empty()) + { + CGAL::Three::Three::information(tr(" No NM vertex found.")); + return; + } + Scene_points_with_normal_item* pitem = new Scene_points_with_normal_item(); + pitem->setColor(Qt::red); + pitem->setName(QString("%1 nm vertices").arg(poly_item->name())); + for(const auto& h : hds) + { + pitem->point_set()->insert(poly_item->face_graph()->point(target(h, *poly_item->face_graph()))); + } + scene->addItem (pitem); + } +} + void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_triggered() { QApplication::setOverrideCursor(Qt::WaitCursor); @@ -354,6 +390,14 @@ void Polyhedron_demo_repair_polyhedron_plugin::on_actionDuplicateNMVertices_trig QApplication::restoreOverrideCursor(); } +void Polyhedron_demo_repair_polyhedron_plugin::on_actionExtractNMVertices_triggered() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + on_actionExtractNMVertices_triggered(index); + QApplication::restoreOverrideCursor(); +} + template void Polyhedron_demo_repair_polyhedron_plugin::on_actionMergeDuplicatedVerticesOnBoundaryCycles_triggered(Scene_interface::Item_id index) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h b/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h index 3ec4c1871b7..e83fbd4637a 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Scene_facegraph_item_k_ring_selection.h @@ -273,7 +273,7 @@ public Q_SLOTS: boost::vector_property_map::type> - fccmap; + fccmap(static_cast(num_faces(poly))); //get connected componant from the picked face std::set final_sel; diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp index 01e2d38a4da..28eb05147da 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Selection_plugin.cpp @@ -1,4 +1,4 @@ -#include + #include #include #include @@ -895,7 +895,6 @@ public Q_SLOTS: case 0: Q_EMIT set_operation_mode(-1); on_Selection_type_combo_box_changed(ui_widget.Selection_type_combo_box->currentIndex()); - selection_item->polyhedron_item()->switchToGouraudPlusEdge(false); break; //Edition mode case 1: @@ -933,10 +932,6 @@ public Q_SLOTS: if(selection_item) { selection_item->on_Ctrlz_pressed(); - if(mode == 11) - selection_item->polyhedron_item()->switchToGouraudPlusEdge(true); - else - selection_item->polyhedron_item()->switchToGouraudPlusEdge(false); } if(ui_widget.selectionOrEuler->currentIndex() == 0) { diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp index a4218856893..d71f08a2274 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.cpp @@ -201,7 +201,7 @@ private: const double max_distance_to_plane = dialog.epsilon(); const double max_accepted_angle = - (std::acos(dialog.normal_tolerance()) * 180.0) / CGAL_PI; + dialog.normal_tolerance(); const std::size_t min_region_size = dialog.min_points(); @@ -248,7 +248,19 @@ private: 64 + rnd.get_int(0, 192), 64 + rnd.get_int(0, 192))); } - + if(color_vector.empty()) + { + for(const auto& f : faces(fg)) + { + fg.property_map("f:patch_id").first[f] = + static_cast(0); + } + CGAL::Random rnd(static_cast(0)); + color_vector.push_back(QColor( + 64 + rnd.get_int(0, 192), + 64 + rnd.get_int(0, 192), + 64 + rnd.get_int(0, 192))); + } colored_item->invalidateOpenGLBuffers(); scene->addItem(colored_item); } @@ -273,7 +285,7 @@ private: const double max_distance_to_plane = dialog.epsilon(); const double max_accepted_angle = - (std::acos(dialog.normal_tolerance()) * 180.0) / CGAL_PI; + dialog.normal_tolerance(); const std::size_t min_region_size = dialog.min_points(); @@ -648,7 +660,7 @@ private: CGAL::Shape_detection::Plane_map(), CGAL::Shape_detection::Point_to_shape_index_map(*points, planes), true, true, true, true, - 180 * std::acos (op.normal_threshold) / CGAL_PI, op.epsilon); + op.normal_threshold, op.epsilon); std::cerr << "done" << std::endl; } @@ -927,8 +939,14 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetectShapesSM_t dialog.label_4->setEnabled(false); dialog.m_cluster_epsilon_field->setEnabled(false); dialog.groupBox_3->setEnabled(false); - + //todo: check default values + dialog.m_epsilon_field->setValue(0.01*sm_item->diagonalBbox()); + std::size_t nb_faces = mesh->number_of_faces(); + dialog.m_min_pts_field->setValue((std::max)(static_cast(0.01*nb_faces), 1)); if(!dialog.exec()) return; + + if(dialog.min_points() > static_cast(nb_faces)) + dialog.m_min_pts_field->setValue(static_cast(nb_faces)); QApplication::setOverrideCursor(Qt::WaitCursor); if (dialog.region_growing()) { detect_shapes_with_region_growing_sm(sm_item, dialog); @@ -969,6 +987,8 @@ void Polyhedron_demo_point_set_shape_detection_plugin::on_actionDetect_triggered Point_set_demo_point_set_shape_detection_dialog dialog; if(!dialog.exec()) return; + if(dialog.min_points() > static_cast(points->size())) + dialog.m_min_pts_field->setValue(static_cast(points->size())); QApplication::setOverrideCursor(Qt::WaitCursor); if (dialog.region_growing()) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui index 684acace812..98fc4f751c5 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_shape_detection_plugin.ui @@ -152,7 +152,7 @@ - Normal Tolerance: + Normal Tolerance (in degrees): @@ -165,7 +165,7 @@
    - 0.90 + 30 diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt index 45c1eccb50e..f849310c106 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/CMakeLists.txt @@ -20,10 +20,6 @@ qt5_wrap_ui( segmentationUI_FILES Mesh_segmentation_widget.ui) polyhedron_demo_plugin(mesh_segmentation_plugin Mesh_segmentation_plugin ${segmentationUI_FILES}) target_link_libraries(mesh_segmentation_plugin PUBLIC scene_surface_mesh_item) -qt5_wrap_ui( mesh_plane_detectionUI_FILES Mesh_plane_detection_dialog.ui) -polyhedron_demo_plugin(mesh_plane_detection_plugin Mesh_plane_detection_plugin ${mesh_plane_detectionUI_FILES}) -target_link_libraries(mesh_plane_detection_plugin PUBLIC scene_surface_mesh_item) - qt5_wrap_ui( mesh_simplificationUI_FILES Mesh_simplification_dialog.ui) polyhedron_demo_plugin(mesh_simplification_plugin Mesh_simplification_plugin ${mesh_simplificationUI_FILES}) target_link_libraries(mesh_simplification_plugin PUBLIC scene_surface_mesh_item scene_selection_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui deleted file mode 100644 index e855d47f55c..00000000000 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_dialog.ui +++ /dev/null @@ -1,125 +0,0 @@ - - - Mesh_plane_detection_dialog - - - - 0 - 0 - 349 - 117 - - - - Mesh Plane Detection - - - - - - - - Minimum area - - - - - - - Maximum deviation from normal - - - - - - - ° - - - 1 - - - 90 - - - 30 - - - - - - - 0.01 - - - - - - - - - Qt::Vertical - - - - 20 - 13 - - - - - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - - - DoubleEdit - QLineEdit -
    CGAL_double_edit.h
    -
    -
    - - - - buttonBox - accepted() - Mesh_plane_detection_dialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - buttonBox - rejected() - Mesh_plane_detection_dialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - -
    diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp deleted file mode 100644 index 4e29d3aa423..00000000000 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Mesh_plane_detection_plugin.cpp +++ /dev/null @@ -1,250 +0,0 @@ -#include -#include - -#include "Scene_surface_mesh_item.h" -#include "Scene.h" -#include "Color_map.h" - -#include -#include -#include -#include -#include -#include -#include -#include -//#include -#include -#include -#include -#include -#include -#include - -#include "ui_Mesh_plane_detection_dialog.h" - -namespace PMP = CGAL::Polygon_mesh_processing; - -using namespace CGAL::Three; -class Polyhedron_demo_mesh_plane_detection_plugin : - public QObject, - public Polyhedron_demo_plugin_helper -{ - Q_OBJECT - Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) - Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0") - - public: - - QList actions() const { - return QList() << actionPlaneDetection; - } - - bool applicable(QAction*) const { - return - qobject_cast(scene->item(scene->mainSelectionIndex())); - } - - void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { - this->scene = scene_interface; - this->mw = mainWindow; - actionPlaneDetection = new QAction("Mesh Plane Detection", mw); - actionPlaneDetection->setProperty("subMenuName", "Triangulated Surface Mesh Segmentation"); - actionPlaneDetection->setObjectName("actionPlaneDetection"); - - // adding slot for itemAboutToBeDestroyed signal, aim is removing item from item-functor map. - if( Scene* scene = dynamic_cast(scene_interface) ) { - connect(scene, SIGNAL(itemAboutToBeDestroyed(CGAL::Three::Scene_item*)), this, SLOT(itemAboutToBeDestroyed(CGAL::Three::Scene_item*))); - } - - autoConnectActions(); - } - virtual void closure() - { - } - - template - void colorize_segmentation(Scene_surface_mesh_item* item, SegmentPropertyMap& segment_ids, std::vector& color_vector); - - void check_and_set_ids(SMesh *sm); - -public Q_SLOTS: - void on_actionPlaneDetection_triggered(); - void itemAboutToBeDestroyed(CGAL::Three::Scene_item*); -private: - QAction* actionPlaneDetection; - - - template - void detect_planes_in_mesh (SMesh& mesh, const double area_min, - const double angle_max, - OutputIterator output) - { - typedef SMesh::size_type size_type; - - std::cerr << "Detecting planes with:" << std::endl - << " * Area min = " << area_min << std::endl - << " * Min cos angle = " << angle_max << std::endl; - std::vector label_region(mesh.number_of_faces(), 0); - int class_index = 0; - - - for (typename SMesh::Face_iterator f = mesh.faces_begin(); f != mesh.faces_end(); ++f) - { - if (label_region[*f] != 0) - continue; - class_index++; - label_region[*f] = class_index; - double area = PMP::face_area (*f, mesh, PMP::parameters::geom_traits(EPICK())); - - //characteristics of the seed - EPICK::Vector_3 normal_seed = PMP::compute_face_normal (*f, mesh, PMP::parameters::geom_traits(EPICK())); - EPICK::Point_3 pt_seed = mesh.point(target(halfedge(*f, mesh), mesh)); - EPICK::Plane_3 optimal_plane(pt_seed, normal_seed); - // Kernel::Plane_3 optimal_plane = f->plane(); - - //initialization containers - std::vector index_container (1,*f); - std::vector index_container_former_ring (1, *f); - std::list index_container_current_ring; - - //propagation - bool propagation = true; - do{ - - propagation = false; - - for (size_type k = 0; k < index_container_former_ring.size(); k++) - { - typename SMesh::Halfedge_around_face_circulator - circ( mesh.halfedge(SMesh::Face_index(index_container_former_ring[k])), mesh) - , start = circ; - - do - { - if (is_border(*circ, mesh)) - continue; - - typename SMesh::Face_index - neighbor = mesh.face(opposite(*circ, mesh)); - size_type neighbor_index = neighbor; - if (label_region[neighbor_index] == 0) - { - EPICK::Vector_3 normal - = PMP::compute_face_normal (neighbor, mesh, PMP::parameters::geom_traits(EPICK())); - - if (std::fabs(normal * optimal_plane.orthogonal_vector()) > angle_max) - { - label_region[neighbor_index] = class_index; - propagation = true; - index_container_current_ring.push_back(neighbor_index); - area += PMP::face_area (neighbor, mesh, PMP::parameters::geom_traits(EPICK())); - } - } - } - while (++ circ != start); - } - - //update containers - index_container_former_ring.clear(); - for (std::list::iterator it = index_container_current_ring.begin(); - it != index_container_current_ring.end(); ++it) - { - index_container_former_ring.push_back(*it); - index_container.push_back(*it); - } - index_container_current_ring.clear(); - - } while (propagation); - - //Test the number of inliers -> reject if inferior to Nmin - if (area < area_min) - { - class_index--; - label_region[*f] = 0; - for (size_type k = 0; k < index_container.size(); k++) - label_region[index_container[k]] = 0; - } - } - std::cerr << class_index << " planes detected" << std::endl; - - std::copy (label_region.begin(), label_region.end(), output); - } - -}; - -void Polyhedron_demo_mesh_plane_detection_plugin::itemAboutToBeDestroyed(CGAL::Three::Scene_item*) -{ -} - -void Polyhedron_demo_mesh_plane_detection_plugin::on_actionPlaneDetection_triggered() -{ - const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); - - Scene_surface_mesh_item* poly_item = - qobject_cast(scene->item(index)); - - if (poly_item) - { - SMesh& pmesh =*poly_item->polyhedron(); - - QDialog dialog(mw); - Ui::Mesh_plane_detection_dialog ui; - ui.setupUi(&dialog); - ui.minimumAreaDoubleSpinBox->setMinimum(0.00001); - // check user cancellation - if(dialog.exec() == QDialog::Rejected) - return; - - QElapsedTimer time; - time.start(); - std::cerr << "Detecting planes... "; - QApplication::setOverrideCursor(Qt::WaitCursor); - QApplication::processEvents(); - - //check_and_set_ids (&pmesh); - std::vector indices; - detect_planes_in_mesh (pmesh, - ui.minimumAreaDoubleSpinBox->value(), - std::fabs(std::cos (CGAL_PI * ui.maximumDeviationFromNormalSpinBox->value() / 180.)), - std::back_inserter (indices)); - - //poly_item->set_color_vector_read_only(true); - colorize_segmentation (poly_item, indices, poly_item->color_vector()); - - std::cerr << "ok (" << time.elapsed() << " ms, " - << pmesh.number_of_halfedges() / 2 << " edges)" << std::endl; - - poly_item->invalidateOpenGLBuffers(); - scene->itemChanged(index); - QApplication::restoreOverrideCursor(); - } - -} - -template -void Polyhedron_demo_mesh_plane_detection_plugin::colorize_segmentation( - Scene_surface_mesh_item* item, - SegmentPropertyMap& segment_ids, - std::vector& color_vector) -{ - item->setItemIsMulticolor(true); - item->computeItemColorVectorAutomatically(true); - SMesh* sm = item->face_graph(); - color_vector.clear(); - std::size_t max_segment = 0; - for(SMesh::Face_iterator facet_it = sm->faces_begin(); - facet_it != sm->faces_end(); ++facet_it) - { - std::size_t segment_id = segment_ids[static_cast(*facet_it)]; - sm->property_map("f:patch_id").first[*facet_it] = static_cast(segment_id); - max_segment = (std::max)(max_segment, segment_id); - } - color_vector.push_back(QColor(0, 0, 0)); - for(std::size_t i = 1; i <= max_segment; ++i) - color_vector.push_back (QColor (CGAL::get_default_random().get_int (41, 255), - CGAL::get_default_random().get_int (35, 238), - CGAL::get_default_random().get_int (35, 255))); -} - -#include "Mesh_plane_detection_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp index 45f6c3afa8a..ddcea01a397 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Surface_mesh/Offset_meshing_plugin.cpp @@ -518,9 +518,8 @@ void Polyhedron_demo_offset_meshing_plugin::offset_meshing() .arg(approx) .arg(offset_value)); new_item->setColor(Qt::magenta); - new_item->setRenderingMode(item->renderingMode()); + new_item->setWireframeMode(); CGAL::Three::Three::scene()->addItem(new_item); - item->setVisible(false); CGAL::Three::Three::scene()->itemChanged(index); QApplication::restoreOverrideCursor(); diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc index aef40f45e8f..9a10f5c14a8 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc +++ b/Polyhedron/demo/Polyhedron/Polyhedron_3.qrc @@ -33,6 +33,9 @@ resources/help_button.png resources/exit.png resources/menu.png + resources/play.jpeg + resources/pause.jpeg + resources/reset.jpg resources/about.html diff --git a/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.cpp b/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.cpp index 0418d405f72..51a425f57f0 100644 --- a/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.cpp +++ b/Polyhedron/demo/Polyhedron/Polyhedron_demo_plugin_helper.cpp @@ -9,7 +9,7 @@ void CGAL::Three::Polyhedron_demo_plugin_helper::addDockWidget(QDockWidget* dock { mw->addDockWidget(::Qt::LeftDockWidgetArea, dock_widget); dock_widget->setSizePolicy(QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred)); - + dock_widget->setFeatures(QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetFloatable); QList dockWidgets = mw->findChildren(); int counter = 0; Q_FOREACH(QDockWidget* dock, dockWidgets) { diff --git a/Polyhedron/demo/Polyhedron/Scene.cpp b/Polyhedron/demo/Polyhedron/Scene.cpp index 8ea8f34d521..6ddc13cc074 100644 --- a/Polyhedron/demo/Polyhedron/Scene.cpp +++ b/Polyhedron/demo/Polyhedron/Scene.cpp @@ -90,6 +90,8 @@ Scene::addItem(CGAL::Three::Scene_item* item) item->drawEdges(CGAL::Three::Three::mainViewer()); item->drawPoints(CGAL::Three::Three::mainViewer()); CGAL::Three::Three::mainViewer()->setDepthPeelingFbo(fbo); + if(group) + m_groups.append(id); return id; } @@ -110,6 +112,7 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi QList group_children; if(group) { + m_groups.removeAll(index); Q_FOREACH(Item_id id, group->getChildren()) { CGAL::Three::Scene_item* child = group->getChild(id); @@ -152,6 +155,7 @@ Scene::replaceItem(Scene::Item_id index, CGAL::Three::Scene_item* item, bool emi if(group) { addGroup(group); + m_groups.append(index); } itemChanged(index); Q_EMIT restoreCollapsedState(); @@ -173,6 +177,7 @@ Scene::erase(Scene::Item_id index) setSelectedItemsList(QList()<parentGroup() && item->parentGroup()->isChildLocked(item)) return -1; @@ -248,6 +253,7 @@ Scene::erase(QList indices) item->parentGroup()->removeChild(item); children.removeAll(removed_item); indexErased(removed_item); + m_groups.removeAll(removed_item); m_entries.removeAll(item); Q_EMIT itemAboutToBeDestroyed(item); @@ -1359,9 +1365,15 @@ QItemSelection Scene::createSelectionAll() //it is not possible to directly create a selection with items that have different parents, so //we do it iteratively. QItemSelection sel; - for(int i=0; i< m_entries.size(); ++i) - sel.select(index_map.keys(i).at(0), - index_map.keys(i).at(4)); + sel.select(this->createIndex(0, 0), + this->createIndex(m_entries.size(), LastColumn)); + for(const auto& gid : m_groups) + { + CGAL::Three::Scene_group_item* group = + qobject_cast(item(gid)); + sel.select(index_map.keys(group->getChildren().first()).at(0), + index_map.keys(group->getChildren().last()).at(4)); + } return sel; } @@ -1726,7 +1738,7 @@ void Scene::updatePrimitiveIds(CGAL::Three::Scene_item* it) } } } -bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) +bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler) { CGAL::Three::Scene_item *i = item(mainSelectionIndex()); if(!i) @@ -1734,7 +1746,7 @@ bool Scene::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_inte Scene_print_item_interface* spit= qobject_cast(i); if(spit && i->visible()) { - bool res = spit->testDisplayId(x,y,z, viewer); + bool res = spit->testDisplayId(x,y,z, viewer, scaler); return res; } else diff --git a/Polyhedron/demo/Polyhedron/Scene.h b/Polyhedron/demo/Polyhedron/Scene.h index 6240a255abf..1159739e3e7 100644 --- a/Polyhedron/demo/Polyhedron/Scene.h +++ b/Polyhedron/demo/Polyhedron/Scene.h @@ -64,6 +64,7 @@ public: int numberOfEntries() const Q_DECL_OVERRIDE; // returns the list of items. const QList& entries() const { return m_entries; } + Q_INVOKABLE CGAL::Three::Scene_item* item(int) const Q_DECL_OVERRIDE; int item_id(CGAL::Three::Scene_item*) const Q_DECL_OVERRIDE; @@ -94,7 +95,7 @@ public: void printAllIds() Q_DECL_OVERRIDE; //!Re-computes the primitiveIds for `item` void updatePrimitiveIds(Scene_item *item) Q_DECL_OVERRIDE; - bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) Q_DECL_OVERRIDE; + bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler) Q_DECL_OVERRIDE; Bbox bbox() const Q_DECL_OVERRIDE; void computeBbox(); double len_diagonal() const Q_DECL_OVERRIDE @@ -280,6 +281,7 @@ private: typedef QList Entries; //List containing all the scene_items. Entries m_entries; + QList m_groups; //used to optimize createSelectionAll() QList children; // Index of the currently selected item. int selected_item; diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp index 10b5b4e3fb8..69de06f2d58 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.cpp @@ -67,7 +67,6 @@ public: { undo_(); item->compute_normal_maps(); - item->polyhedron_item()->invalidateOpenGLBuffers(); item->invalidateOpenGLBuffers(); item->redraw(); } @@ -1838,7 +1837,6 @@ Scene_polyhedron_selection_item::Scene_polyhedron_selection_item(Scene_face_grap Scene_polyhedron_selection_item::~Scene_polyhedron_selection_item() { - poly_item->switchToGouraudPlusEdge(false); delete d; Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()){ CGAL::Three::Viewer_interface* viewer = dynamic_cast(v); @@ -2256,9 +2254,9 @@ void Scene_polyhedron_selection_item::printAllIds() { d->item->polyhedron_item()->printAllIds(); } -bool Scene_polyhedron_selection_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer)const +bool Scene_polyhedron_selection_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler)const { - return d->item->polyhedron_item()->testDisplayId(x, y, z, viewer); + return d->item->polyhedron_item()->testDisplayId(x, y, z, viewer, scaler); return false; } diff --git a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.h b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.h index dbfca601296..71cd28e6f85 100644 --- a/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_polyhedron_selection_item.h @@ -218,7 +218,7 @@ public: bool printEdgeIds() const; bool printFaceIds() const; void printAllIds(); - bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*)const; + bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*, const QVector3D&)const; bool shouldDisplayIds(CGAL::Three::Scene_item *current_item) const; QString defaultSaveName() const { diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp index 99d5cb0c9f5..ce14acf35e8 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.cpp @@ -49,9 +49,10 @@ #include #include #include "id_printing.h" +#include +#include #endif - typedef CGAL::Three::Triangle_container Tri; typedef CGAL::Three::Edge_container Ed; typedef CGAL::Three::Point_container Pt; @@ -92,6 +93,23 @@ public: typedef CGAL::AABB_traits AABB_traits; typedef CGAL::AABB_tree Input_facets_AABB_tree; + +struct KeyHash +{ + std::size_t operator()(const std::pair& k) const + { + return std::hash()(k.first) ^ (std::hash()(k.second) << 1); + } +}; + +struct KeyEqual { + bool operator()(const std::pair& lhs, + const std::pair& rhs) const + { + return lhs.first == rhs.first && lhs.second == rhs.second; + } +}; + struct Scene_surface_mesh_item_priv{ typedef EPICK::Point_3 Point; @@ -171,6 +189,7 @@ struct Scene_surface_mesh_item_priv{ << Points; item->setProperty("classname", QString("surface_mesh"));\ ids_need_update = false; + flat_vertex_map_ready = false; } ~Scene_surface_mesh_item_priv() @@ -247,6 +266,8 @@ struct Scene_surface_mesh_item_priv{ mutable std::vector smooth_vertices; mutable std::vector smooth_normals; mutable std::vector flat_vertices; + mutable std::vector > flat_vertices_map; + mutable std::vector cumul_id; mutable std::size_t flat_vertices_size; mutable std::vector flat_normals; mutable std::vector f_colors; @@ -268,6 +289,7 @@ struct Scene_surface_mesh_item_priv{ int genus; bool self_intersect; bool ids_need_update; + bool flat_vertex_map_ready; mutable QSlider* alphaSlider; QList supported_rendering_modes; }; @@ -504,9 +526,7 @@ void Scene_surface_mesh_item_priv::compute_elements(Scene_item_rendering_helper: initialize_colors(); } - //compute the Flat data - flat_vertices.clear(); flat_normals.clear(); f_colors.clear(); @@ -519,7 +539,8 @@ void Scene_surface_mesh_item_priv::compute_elements(Scene_item_rendering_helper: { if(name.testFlag(Scene_item_rendering_helper::GEOMETRY)) { - Point p = positions[source(hd, *smesh_)] + offset; + vertex_descriptor vd = source(hd, *smesh_); + Point p = positions[vd] + offset; CPF::add_point_in_buffer(p, flat_vertices); } if(name.testFlag(Scene_item_rendering_helper::NORMALS)) @@ -1283,6 +1304,7 @@ void Scene_surface_mesh_item::invalidate(Gl_data_names name) delete_aabb_tree(this); d->smesh_->collect_garbage(); d->invalidate_stats(); + d->flat_vertex_map_ready = false; } setBuffersFilled(false); Q_FOREACH(CGAL::QGLViewer* v, CGAL::QGLViewer::QGLViewerPool()) @@ -1624,7 +1646,7 @@ QString Scene_surface_mesh_item::computeStats(int type) { boost::vector_property_map::type> - fccmap(get(boost::face_index, *(d->smesh_))); + fccmap(static_cast(num_faces(*(d->smesh_))), get(boost::face_index, *(d->smesh_))); return QString::number(CGAL::Polygon_mesh_processing::connected_components(*(d->smesh_), fccmap)); } case NB_BORDER_EDGES: @@ -2125,7 +2147,7 @@ void Scene_surface_mesh_item::printAllIds() d->killIds(); } -bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer)const +bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler)const { const CGAL::qglviewer::Vec offset = static_cast(CGAL::QGLViewer::QGLViewerPool().first())->offset(); EPICK::Point_3 src(x - offset.x, @@ -2133,13 +2155,14 @@ bool Scene_surface_mesh_item::testDisplayId(double x, double y, double z, CGAL:: z - offset.z); CGAL::qglviewer::Camera* cam = viewer->camera(); - EPICK::Point_3 dest( cam->position().x - offset.x, - cam->position().y - offset.y, - cam->position().z - offset.z); + EPICK::Point_3 dest( cam->position().x/scaler.x() - offset.x, + cam->position().y/scaler.y() - offset.y, + cam->position().z/scaler.z() - offset.z); EPICK::Vector_3 v(src,dest); EPICK::Vector_3 dir(cam->viewDirection().x, cam->viewDirection().y, cam->viewDirection().z); + if(-CGAL::scalar_product(v, dir) < cam->zNear()) //if src is behind the near plane, don't display. return false; v = 0.01*v; @@ -2355,43 +2378,69 @@ void write_in_vbo(Vbo* vbo, cgal_gl_data* data, //only works on indexed data void Scene_surface_mesh_item::updateVertex(vertex_descriptor vh) { + if(!d->flat_vertex_map_ready) + fill_flat_vertex_map(); const CGAL::qglviewer::Vec offset = static_cast( CGAL::QGLViewer::QGLViewerPool().first())->offset(); + std::size_t id = vh; + cgal_gl_data new_point[3]; + Point_3 p = face_graph()->point(vh); + for(int i=0; i<3; ++i) + new_point[i]=p[i]+offset[i]; + + write_in_vbo(getTriangleContainer(0)->getVbo(Tri::Smooth_vertices), + new_point, + id); + + write_in_vbo( + getPointContainer(0)->getVbo(Pt::Vertices), + new_point,id); + + write_in_vbo( + getEdgeContainer(0)->getVbo(Ed::Vertices), + new_point,id); + + for(const auto & v_it : CGAL::vertices_around_target(vh, *face_graph())) { - std::size_t id = vh; - cgal_gl_data new_point[3]; - Point_3 p = face_graph()->point(vh); + EPICK::Vector_3 n = CGAL::Polygon_mesh_processing::compute_vertex_normal(v_it, *face_graph()); + cgal_gl_data new_n[3]; for(int i=0; i<3; ++i) - new_point[i]=p[i]+offset[i]; - - write_in_vbo(getTriangleContainer(0)->getVbo(Tri::Smooth_vertices), - new_point, - id); - + new_n[i]=n[i]; + id = v_it; write_in_vbo( - getPointContainer(0)->getVbo(Pt::Vertices), - new_point,id); - - write_in_vbo( - getEdgeContainer(0)->getVbo(Ed::Vertices), - new_point,id); - - for(auto v_it : CGAL::vertices_around_target(vh, *face_graph())) - { - EPICK::Vector_3 n = CGAL::Polygon_mesh_processing::compute_vertex_normal(v_it, *face_graph()); - for(int i=0; i<3; ++i) - new_point[i]=n[i]; - id = v_it; - write_in_vbo( - getTriangleContainer(0)->getVbo(Tri::Smooth_normals), - new_point,id); - } - d->ids_need_update = true; - redraw(); + getTriangleContainer(0)->getVbo(Tri::Smooth_normals), + new_n,id); } + //flat data now + for(const auto& id : d->flat_vertices_map[vh]) + { + write_in_vbo(getTriangleContainer(1)->getVbo(Tri::Flat_vertices), + new_point, + id); + } + + + for(const auto& f_it : CGAL::faces_around_target( halfedge(vh, *face_graph()), *face_graph())) + { + EPICK::Vector_3 n = CGAL::Polygon_mesh_processing::compute_face_normal(f_it, *face_graph()); + cgal_gl_data new_n[3]; + for(int i=0; i<3; ++i) + new_n[i]=n[i]; + + for(std::size_t id = d->cumul_id[f_it]; id < d->cumul_id[f_it+1]; ++id) + { + write_in_vbo( + getTriangleContainer(1)->getVbo(Tri::Flat_normals), + new_n, id); + } + + } + d->ids_need_update = true; + redraw(); } + void Scene_surface_mesh_item::updateIds(vertex_descriptor vh) { if(d->ids_need_update && @@ -2414,25 +2463,133 @@ void Scene_surface_mesh_item::updateIds(vertex_descriptor vh) } } -void Scene_surface_mesh_item::switchToGouraudPlusEdge(bool b) + +void Scene_surface_mesh_item::fill_flat_vertex_map() { - if (!b && !d->supported_rendering_modes.contains(Flat)) + typedef EPICK::Point_3 Point; + typedef CGAL::Surface_mesh SMesh; + typedef boost::graph_traits::face_descriptor face_descriptor; + typedef CGAL::Buffer_for_vao CPF; + + if(d->flat_vertex_map_ready) + return; + + SMesh::Property_map fnormals = + face_graph()->property_map("f:normal").first; + + d->flat_vertices_map.clear(); + d->flat_vertices_map.resize(face_graph()->number_of_vertices()); + d->cumul_id.clear(); + std::size_t counter = 0; + for(face_descriptor fd : faces(*face_graph())) { - d->supported_rendering_modes = QList() << FlatPlusEdges - << Wireframe - << Flat - << Gouraud - << Points; - setFlatPlusEdgesMode(); - invalidateOpenGLBuffers(); - redraw(); - } - else if(b) - { - d->supported_rendering_modes = QList() << GouraudPlusEdges - << Wireframe - << Gouraud - << Points; - setGouraudPlusEdgesMode(); + d->cumul_id.push_back(counter); + if(is_triangle(halfedge(fd,*face_graph()),*face_graph())) + { + for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, *face_graph()),*face_graph())) + { + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + } + } + else + { + std::vector facet_points; + for(halfedge_descriptor hd : halfedges_around_face(halfedge(fd, *face_graph()),*face_graph())) + { + facet_points.push_back(face_graph()->points()[target(hd, *face_graph())]); + } + bool is_convex = CPF::is_facet_convex(facet_points, fnormals[fd]); + if(is_convex && is_quad(halfedge(fd,*face_graph()),*face_graph()) ) + { + //1st half + halfedge_descriptor hd = halfedge(fd, *face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + + hd = next(halfedge(fd, *face_graph()),*face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + + hd = next(next(halfedge(fd, *face_graph()),*face_graph()), *face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + + //2nd half + hd = halfedge(fd, *face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + + hd = next(next(halfedge(fd, *face_graph()),*face_graph()), *face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + + hd = prev(halfedge(fd, *face_graph()), *face_graph()); + d->flat_vertices_map[source(hd, *face_graph())].push_back(counter++); + } + else if(is_convex) + { + SMesh::Halfedge_around_face_circulator he(halfedge(fd, *face_graph()), *face_graph()); + SMesh::Halfedge_around_face_circulator he_end = he; + while(next(*he, *face_graph()) != prev(*he_end, *face_graph())) + { + ++he; + vertex_descriptor v0(target(*he_end, *face_graph())), + v1(target(*he, *face_graph())), + v2(target(next(*he, *face_graph()), *face_graph())); + d->flat_vertices_map[v0].push_back(counter++); + d->flat_vertices_map[v1].push_back(counter++); + d->flat_vertices_map[v2].push_back(counter++); + } + } + else + { + //Computes the normal of the facet + EPICK::Vector_3 normal = fnormals[fd]; + if(normal == CGAL::NULL_VECTOR) + { + boost::graph_traits::halfedge_descriptor start = prev(halfedge(fd, *face_graph()), *face_graph()); + boost::graph_traits::halfedge_descriptor hd = halfedge(fd, *face_graph()); + boost::graph_traits::halfedge_descriptor next_=next(hd, *face_graph()); + do + { + const Point_3& pa = face_graph()->point(target(hd, *face_graph())); + const Point_3& pb = face_graph()->point(target(next_, *face_graph())); + const Point_3& pc = face_graph()->point(target(prev(hd, *face_graph()), *face_graph())); + if (!CGAL::collinear (pa, pb, pc)) + { + normal = CGAL::cross_product(pb-pa, pc -pa); + break; + } + next_ =next(next_, *face_graph()); + }while(next_ != start); + + if (normal == CGAL::NULL_VECTOR) // No normal could be computed, return + { + qDebug()<<"Warning : normal is not valid. Facet not displayed"; + return; + } + } + //check if normal contains NaN values + if (normal.x() != normal.x() || normal.y() != normal.y() || normal.z() != normal.z()) + { + qDebug()<<"Warning : normal is not valid. Facet not displayed"; + return; + } + + typedef FacetTriangulator::vertex_descriptor> FT; + const CGAL::qglviewer::Vec off = static_cast(CGAL::QGLViewer::QGLViewerPool().first())->offset(); + EPICK::Vector_3 offset(off.x,off.y,off.z); + FT triangulation(fd,normal,face_graph(), offset); + //iterates on the internal faces + for(FT::CDT::Finite_faces_iterator + ffit = triangulation.cdt->finite_faces_begin(), + end = triangulation.cdt->finite_faces_end(); + ffit != end; ++ffit) + { + if(ffit->info().is_external) + continue; + d->flat_vertices_map[triangulation.v2v[ffit->vertex(0)]].push_back(counter++); + d->flat_vertices_map[triangulation.v2v[ffit->vertex(1)]].push_back(counter++); + d->flat_vertices_map[triangulation.v2v[ffit->vertex(2)]].push_back(counter++); + } + } + } } + d->cumul_id.push_back(counter); + d->flat_vertex_map_ready = true; } diff --git a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h index b8b88be572f..fba5cb89635 100644 --- a/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h +++ b/Polyhedron/demo/Polyhedron/Scene_surface_mesh_item.h @@ -149,15 +149,15 @@ public: bool printFaceIds()const Q_DECL_OVERRIDE; void printAllIds() Q_DECL_OVERRIDE; bool shouldDisplayIds(CGAL::Three::Scene_item *current_item) const Q_DECL_OVERRIDE; - bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface*)const Q_DECL_OVERRIDE; + bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface*, const QVector3D &scaler)const Q_DECL_OVERRIDE; float alpha() const Q_DECL_OVERRIDE; void setAlpha(int alpha) Q_DECL_OVERRIDE; QSlider* alphaSlider(); void computeElements() const Q_DECL_OVERRIDE; void initializeBuffers(CGAL::Three::Viewer_interface*)const Q_DECL_OVERRIDE; void updateVertex(vertex_descriptor vh); + void fill_flat_vertex_map(); void updateIds(vertex_descriptor vh); - void switchToGouraudPlusEdge(bool b); //replace flatPlusEdge by gouraudPlusEdge and ban Flat. Q_SIGNALS: void item_is_about_to_be_changed(); void selection_done(); diff --git a/Polyhedron/demo/Polyhedron/TextRenderer.cpp b/Polyhedron/demo/Polyhedron/TextRenderer.cpp index 2e9ce45fefe..9a18b8d19ab 100644 --- a/Polyhedron/demo/Polyhedron/TextRenderer.cpp +++ b/Polyhedron/demo/Polyhedron/TextRenderer.cpp @@ -2,7 +2,7 @@ #include #include #include "Scene_polyhedron_selection_item.h" -void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer) +void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer, const QVector3D& scaler) { QPainter *painter = viewer->getPainter(); if (!painter->isActive()) @@ -23,10 +23,15 @@ void TextRenderer::draw(CGAL::Three::Viewer_interface *viewer) if(viewer->testDisplayId(src.x, src.y, src.z)) { if(item->is_3D()) - rect = QRect(int(camera->projectedCoordinatesOf(src).x-item->width()/2), - int(camera->projectedCoordinatesOf(src).y-item->height()/2), + { + src.x *= scaler.x(); + src.y *= scaler.y(); + src.z *= scaler.z(); + rect = QRect(int(camera->projectedCoordinatesOf(src).x -item->width()/2), + int(camera->projectedCoordinatesOf(src).y -item->height()/2), int(item->width()), int(item->height())); + } else rect = QRect(int(src.x-item->width()/2), int(src.y-item->height()/2), diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index 95ede4b08db..b215784e429 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include #ifdef CGAL_USE_WEBSOCKETS #include @@ -25,6 +26,7 @@ #include #include "ui_LightingDialog.h" +#include "CGAL_double_edit.h" #if defined(_WIN32) #include @@ -46,8 +48,10 @@ public: bool clipping; bool projection_is_ortho; bool cam_sharing; + bool scene_scaling; GLfloat gl_point_size; QVector4D clipbox[6]; + QVector3D scaler; QPainter *painter; // L i g h t i n g @@ -117,6 +121,7 @@ public: { return shader_programs; } + #ifdef CGAL_USE_WEBSOCKETS QWebSocket m_webSocket; #endif @@ -292,6 +297,8 @@ void Viewer::doBindings() d->textRenderer = new TextRenderer(); d->is_2d_selection_mode = false; d->is_connected = false; + d->scene_scaling = false; + d->scaler = QVector3D(1,1,1); connect( d->textRenderer, SIGNAL(sendMessage(QString,int)), this, SLOT(printMessage(QString,int)) ); @@ -407,7 +414,7 @@ Viewer::~Viewer() .arg(d->back_color.redF()) .arg(d->back_color.greenF()) .arg(d->back_color.blueF())); - + makeCurrent(); d->vao.destroy(); if(d->_recentFunctions) delete d->_recentFunctions; @@ -831,9 +838,23 @@ void Viewer::postSelection(const QPoint& pixel) point = camera()->pointUnderPixel(pixel, found) - offset(); } if(found) { - Q_EMIT selectedPoint(point.x, - point.y, - point.z); + QVector3D transformed_point(point.x, + point.y, + point.z); + if(d->scene_scaling) + { + transformed_point = QVector3D( + point.x+offset().x, + point.y+offset().y, + point.z+offset().z); + transformed_point = transformed_point/d->scaler; + transformed_point[0] -=offset().x ; + transformed_point[1] -=offset().y ; + transformed_point[2] -=offset().z ; + } + Q_EMIT selectedPoint(transformed_point.x(), + transformed_point.y(), + transformed_point.z()); CGAL::qglviewer::Vec dir; CGAL::qglviewer::Vec orig; if(d->projection_is_ortho) @@ -931,6 +952,10 @@ void Viewer::attribBuffers(int program_name) const { this->camera()->getModelViewProjectionMatrix(d_mat); for (int i=0; i<16; ++i) mvp_mat.data()[i] = GLfloat(d_mat[i]); + if(d->scene_scaling){ + mvp_mat.scale(d->scaler); + mv_mat.scale(d->scaler); + } QOpenGLShaderProgram* program = getShaderProgram(program_name); program->bind(); @@ -1130,7 +1155,7 @@ void Viewer::drawVisualHints() { d->textRenderer->addText(message_text); } - d->textRenderer->draw(this); + d->textRenderer->draw(this, d->scaler); if (d->_displayMessage) d->textRenderer->removeText(message_text); @@ -1458,7 +1483,7 @@ void Viewer::wheelEvent(QWheelEvent* e) bool Viewer::testDisplayId(double x, double y, double z) { - return d->scene->testDisplayId(x,y,z,this); + return d->scene->testDisplayId(x,y,z,this, d->scaler); } QPainter* Viewer::getPainter(){return d->painter;} @@ -1552,26 +1577,26 @@ void Viewer_impl::showDistance(QPoint pixel) rendering_program_dist.setAttributeBuffer("vertex",GL_FLOAT,0,3); buffer.release(); vao.release(); - distance_is_displayed = true; - double dist = std::sqrt((BPoint.x-APoint.x)*(BPoint.x-APoint.x) + (BPoint.y-APoint.y)*(BPoint.y-APoint.y) + (BPoint.z-APoint.z)*(BPoint.z-APoint.z)); + double dist = std::sqrt((BPoint.x-APoint.x)/scaler.x()*(BPoint.x-APoint.x)/scaler.x() + (BPoint.y-APoint.y)/scaler.y()*(BPoint.y-APoint.y)/scaler.y() + (BPoint.z-APoint.z)/scaler.z()*(BPoint.z-APoint.z)/scaler.z()); QFont font; font.setBold(true); TextItem *ACoord = new TextItem(float(APoint.x), float(APoint.y), float(APoint.z), QString("A(%1,%2,%3)") - .arg(APoint.x-viewer->offset().x, 0, 'g', 10) - .arg(APoint.y-viewer->offset().y, 0, 'g', 10) - .arg(APoint.z-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true); + .arg(APoint.x/scaler.x()-viewer->offset().x, 0, 'g', 10) + .arg(APoint.y/scaler.y()-viewer->offset().y, 0, 'g', 10) + .arg(APoint.z/scaler.z()-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true); distance_text.append(ACoord); TextItem *BCoord = new TextItem(float(BPoint.x), float(BPoint.y), float(BPoint.z), QString("B(%1,%2,%3)") - .arg(BPoint.x-viewer->offset().x, 0, 'g', 10) - .arg(BPoint.y-viewer->offset().y, 0, 'g', 10) - .arg(BPoint.z-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true); + .arg(BPoint.x/scaler.x()-viewer->offset().x, 0, 'g', 10) + .arg(BPoint.y/scaler.y()-viewer->offset().y, 0, 'g', 10) + .arg(BPoint.z/scaler.z()-viewer->offset().z, 0, 'g', 10), true, font, Qt::red, true); + distance_text.append(BCoord); CGAL::qglviewer::Vec centerPoint = 0.5*(BPoint+APoint); TextItem *centerCoord = new TextItem(float(centerPoint.x), @@ -1583,12 +1608,12 @@ void Viewer_impl::showDistance(QPoint pixel) Q_FOREACH(TextItem* ti, distance_text) textRenderer->addText(ti); Q_EMIT(viewer->sendMessage(QString("First point : A(%1,%2,%3), second point : B(%4,%5,%6), distance between them : %7") - .arg(APoint.x-viewer->offset().x) - .arg(APoint.y-viewer->offset().y) - .arg(APoint.z-viewer->offset().z) - .arg(BPoint.x-viewer->offset().x) - .arg(BPoint.y-viewer->offset().y) - .arg(BPoint.z-viewer->offset().z) + .arg(APoint.x/scaler.x()-viewer->offset().x) + .arg(APoint.y/scaler.y()-viewer->offset().y) + .arg(APoint.z/scaler.z()-viewer->offset().z) + .arg(BPoint.x/scaler.x()-viewer->offset().x) + .arg(BPoint.y/scaler.y()-viewer->offset().y) + .arg(BPoint.z/scaler.z()-viewer->offset().z) .arg(dist, 0, 'g', 10))); } @@ -1958,6 +1983,56 @@ bool Viewer::isClipping() const { return d->clipping; } + +void Viewer::scaleScene() +{ + CGAL::Bbox_3 bbox = CGAL::Three::Three::scene()->bbox(); + if(!d->scene_scaling) + { + QMultipleInputDialog dialog ("Scale Scene", CGAL::Three::Three::mainWindow()); + DoubleEdit* x_val = dialog.add ("Scale along X"); + DoubleEdit* y_val = dialog.add ("Scale along Y"); + DoubleEdit* z_val = dialog.add ("Scale along Z"); + x_val->setMinimum(0); + y_val->setMinimum(0); + z_val->setMinimum(0); + if(bbox != CGAL::Bbox_3(0,0,0,0,0,0)) + { + QPushButton* norm_button = dialog.add (""); + norm_button->setText("Normalize"); + norm_button->setToolTip("Automatically fill values to display the scene in a unit cube."); + + connect(norm_button, &QPushButton::clicked, this, + [x_val, y_val, z_val, &bbox](){ + x_val->setValue(1.0/(bbox.xmax()-bbox.xmin())); + y_val->setValue(1.0/(bbox.ymax()-bbox.ymin())); + z_val->setValue(1.0/(bbox.zmax()-bbox.zmin())); + }); + } + if (dialog.exec() != QDialog::Accepted) + { + parent()->findChild("actionScaleScene")->setChecked(false); + return; + } + d->scaler.setX(x_val->text()==""?1.0:x_val->value()); + d->scaler.setY(y_val->text()==""?1.0:y_val->value()); + d->scaler.setZ(z_val->text()==""?1.0:z_val->value()); + + if(d->scaler.x() == 0.0 || d->scaler.y() == 0.0 || d->scaler.z()== 0.0) + { + parent()->findChild("actionScaleScene")->setChecked(false); + return; + } + } + else + d->scaler = QVector3D(1,1,1); + + CGAL::qglviewer::Vec vmin(((float)bbox.xmin()+offset().x)*d->scaler.x(), ((float)bbox.ymin()+offset().y)*d->scaler.y(), ((float)bbox.zmin()+offset().z)*d->scaler.z()), + vmax(((float)bbox.xmax()+offset().x)*d->scaler.x(), ((float)bbox.ymax()+offset().y)*d->scaler.y(), ((float)bbox.zmax()+offset().z)*d->scaler.z()); + camera()->setPivotPoint((vmin+vmax)*0.5); + camera()->fitBoundingBox(vmin, vmax); + d->scene_scaling = !d->scene_scaling; +} #ifdef CGAL_USE_WEBSOCKETS void Viewer::setShareCam(bool b, QString session) { diff --git a/Polyhedron/demo/Polyhedron/Viewer.h b/Polyhedron/demo/Polyhedron/Viewer.h index 0d5bd3541df..7fceedbb0e7 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.h +++ b/Polyhedron/demo/Polyhedron/Viewer.h @@ -137,7 +137,7 @@ public Q_SLOTS: void onSocketConnected(); void onTextMessageSocketReceived(QString message); #endif - + void scaleScene(); protected: void paintEvent(QPaintEvent *)Q_DECL_OVERRIDE; void paintGL()Q_DECL_OVERRIDE; diff --git a/Polyhedron/demo/Polyhedron/include/id_printing.h b/Polyhedron/demo/Polyhedron/include/id_printing.h index 7c999641a82..b3ad4bb8648 100644 --- a/Polyhedron/demo/Polyhedron/include/id_printing.h +++ b/Polyhedron/demo/Polyhedron/include/id_printing.h @@ -569,7 +569,7 @@ int zoomToId(const Mesh& mesh, get(ppmap, vh).y() + offset.y, get(ppmap, vh).z() + offset.z); typename boost::graph_traits::halfedge_descriptor hf = halfedge(vh, mesh); - if(CGAL::is_border_edge(hf, mesh)) + if(CGAL::is_border(hf, mesh)) { hf = opposite(hf, mesh); } diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag index 4a2f5cd9798..26eb7b16578 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.frag @@ -1,13 +1,13 @@ varying highp vec4 color; -varying highp vec4 fP; -varying highp vec3 fN; -uniform highp vec4 light_pos; -uniform highp vec4 light_diff; -uniform highp vec4 light_spec; -uniform highp vec4 light_amb; +varying highp vec4 fP; +varying highp vec3 fN; +uniform highp vec4 light_pos; +uniform highp vec4 light_diff; +uniform highp vec4 light_spec; +uniform highp vec4 light_amb; uniform highp float spec_power ; -uniform int is_two_side; +uniform int is_two_side; uniform bool is_selected; uniform highp float near; uniform highp float far; @@ -32,29 +32,29 @@ void main(void) { gl_FragColor = vec4(d,d,d,1.0); else { - if(color.w<0) + if(color.w<0.) { highp vec4 my_color = vec4(color.xyz, 1.); - highp vec3 L = light_pos.xyz - fP.xyz; - highp vec3 V = -fP.xyz; - highp vec3 N; + highp vec3 L = light_pos.xyz - fP.xyz; + highp vec3 V = -fP.xyz; + highp vec3 N; if(fN == vec3(0.0,0.0,0.0)) { gl_FragColor = my_color; return; } - else - N = normalize(fN); - L = normalize(L); - V = normalize(V); - highp vec3 R = reflect(-L, N); + else + N = normalize(fN); + L = normalize(L); + V = normalize(V); + highp vec3 R = reflect(-L, N); highp vec4 diffuse; - if(is_two_side == 1) - diffuse = abs(dot(N,L)) * light_diff * my_color; - else - diffuse = max(dot(N,L), 0.0) * light_diff * my_color; - highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; + if(is_two_side == 1) + diffuse = abs(dot(N,L)) * light_diff * my_color; + else + diffuse = max(dot(N,L), 0.0) * light_diff * my_color; + highp vec4 specular = pow(max(dot(R,V), 0.0), spec_power) * light_spec; highp vec4 ret_color = vec4((my_color*light_amb).xyz + diffuse.xyz + specular.xyz,1); if(is_selected) gl_FragColor = vec4(ret_color.r+70.0/255.0, ret_color.g+70.0/255.0, ret_color.b+70.0/255.0, alpha); diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert index a1578e13062..d2c861cfd7a 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3.vert @@ -1,4 +1,4 @@ -//#version 100 +//#version 100 attribute highp vec4 vertex; attribute highp vec3 normals; attribute highp vec3 colors; @@ -7,33 +7,33 @@ uniform highp mat4 mvp_matrix; uniform highp mat4 mv_matrix; uniform highp vec4 cutplane; uniform highp float shrink_factor; -varying highp vec4 fP; -varying highp vec3 fN; -varying highp vec4 color; +varying highp vec4 fP; +varying highp vec3 fN; +varying highp vec4 color; uniform highp float point_size; void main(void) { gl_PointSize = point_size; color = vec4(colors, vertex.x * cutplane.x + vertex.y * cutplane.y + vertex.z * cutplane.z + cutplane.w); - fP = mv_matrix * vertex; + fP = mv_matrix * vertex; - mat3 mv_matrix_3; - mv_matrix_3[0] = mv_matrix[0].xyz; - mv_matrix_3[1] = mv_matrix[1].xyz; - mv_matrix_3[2] = mv_matrix[2].xyz; - fN = mv_matrix_3* normals; - - highp mat4 transOB = mat4(1, 0, 0, 0, // first column - 0, 1, 0, 0, // second column - 0, 0, 1, 0, // third column + mat3 mv_matrix_3; + mv_matrix_3[0] = mv_matrix[0].xyz; + mv_matrix_3[1] = mv_matrix[1].xyz; + mv_matrix_3[2] = mv_matrix[2].xyz; + fN = mv_matrix_3* normals; + + highp mat4 transOB = mat4(1., 0., 0., 0., // first column + 0., 1., 0., 0., // second column + 0., 0., 1., 0., // third column center.x, center.y, center.z, 1); // fourth column - highp mat4 transBO = mat4(1, 0, 0, 0, // first column - 0, 1, 0, 0, // second column - 0, 0, 1, 0, // third column + highp mat4 transBO = mat4(1., 0., 0., 0., // first column + 0., 1., 0., 0., // second column + 0., 0., 1., 0., // third column -center.x, -center.y, -center.z, 1); // fourth column - highp mat4 scaling = mat4(shrink_factor, 0, 0, 0, - 0, shrink_factor, 0, 0, - 0, 0, shrink_factor, 0, - 0, 0, 0, 1); + highp mat4 scaling = mat4(shrink_factor, 0., 0., 0., + 0., shrink_factor, 0., 0., + 0., 0., shrink_factor, 0., + 0., 0., 0., 1.); gl_Position = mvp_matrix *transOB * scaling * transBO * vertex; } diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag index 24fa8d08dc5..5bd8af81496 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_c3t3_edges.frag @@ -1,9 +1,9 @@ varying highp vec4 color; -void main(void) -{ - if(color.w<0) - gl_FragColor = vec4(0,0,0,1.0); +void main(void) +{ + if(color.w<0.) + gl_FragColor = vec4(0.,0.,0.,1.0); else discard; -} +} diff --git a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag index d7e0564ef4f..b05e589a187 100644 --- a/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag +++ b/Polyhedron/demo/Polyhedron/resources/compatibility_shaders/shader_with_light.frag @@ -23,9 +23,9 @@ uniform bool back_front_shading; uniform sampler2D sampler; uniform highp float alpha; -highp float depth(float z) +highp float depth(highp float z) { - return (2 * near) / (far + near - z * (far - near)); + return (2.0 * near) / (far + near - z * (far - near)); } void main(void) { @@ -53,7 +53,7 @@ void main(void) { highp vec4 my_color = highp vec4(color.xyz, 1.0); if(fN == vec3(0.0,0.0,0.0)) { - out_color = my_color; + gl_FragColor = my_color; return; } N = normalize(fN); @@ -61,16 +61,16 @@ void main(void) { V = normalize(V); highp vec3 R = reflect(-L, N); highp vec4 diffuse; - float dot_prod = dot(N,L); - + highp float dot_prod = dot(N,L); + if(back_front_shading) { - if (dot_prod > 0) + if (dot_prod > 0.0) my_color = front_color; else my_color = back_color; } - + if(is_two_side == 1) diffuse = abs(dot(N,L)) * light_diff * color; else diff --git a/Polyhedron/demo/Polyhedron/resources/pause.jpeg b/Polyhedron/demo/Polyhedron/resources/pause.jpeg new file mode 100644 index 00000000000..1da108b76f8 Binary files /dev/null and b/Polyhedron/demo/Polyhedron/resources/pause.jpeg differ diff --git a/Polyhedron/demo/Polyhedron/resources/play.jpeg b/Polyhedron/demo/Polyhedron/resources/play.jpeg new file mode 100644 index 00000000000..c039554ae98 Binary files /dev/null and b/Polyhedron/demo/Polyhedron/resources/play.jpeg differ diff --git a/Polyhedron/demo/Polyhedron/resources/reset.jpg b/Polyhedron/demo/Polyhedron/resources/reset.jpg new file mode 100644 index 00000000000..c83b429e0c8 Binary files /dev/null and b/Polyhedron/demo/Polyhedron/resources/reset.jpg differ diff --git a/Polyhedron/doc/Polyhedron/CGAL/Polyhedron_3.h b/Polyhedron/doc/Polyhedron/CGAL/Polyhedron_3.h index d31827bc706..65fd33ce8ae 100644 --- a/Polyhedron/doc/Polyhedron/CGAL/Polyhedron_3.h +++ b/Polyhedron/doc/Polyhedron/CGAL/Polyhedron_3.h @@ -862,16 +862,34 @@ public: */ typedef unspecified_type Vertex_handle; + /*! + range type for iterating over the vertices, with a nested + type `iterator` that has as value type `Vertex_handle` + */ + typedef Iterator_range Vertex_handles; + /*! handle to halfedge. */ typedef unspecified_type Halfedge_handle; + /*! + range type for iterating over the halfedges, with a nested + type `iterator` that has as value type `Halfedge_handle` + */ + typedef Iterator_range Halfedge_handles; + /*! handle to facet. */ typedef unspecified_type Facet_handle; + /*! + range type for iterating over the facets, with a nested + type `iterator` that has as value type `Facet_handle` + */ + typedef Iterator_range Facet_handles; + /*! iterator over all vertices. */ @@ -904,16 +922,31 @@ public: */ typedef unspecified_type Edge_iterator; + /*! + range type for iterating over the edges. + */ + typedef Iterator_range Edges; + /*! iterator over all points. */ typedef unspecified_type Point_iterator; + /*! + range type for iterating over the points of the vertices. + */ + typedef Iterator_range Points; + /*! iterator over all plane equations. */ typedef unspecified_type Plane_iterator; + /*! + range type for iterating over the planes of the facets. + */ + typedef Iterator_range Planes; + /// @} /// \name Types for Tagging Optional Features @@ -1096,6 +1129,12 @@ public: */ Vertex_iterator vertices_end(); + /*! + returns a range of handles over the vertices. + \note The value type of `Vertex_handles::iterator` is `Vertex_handle`. + */ + Vertex_handles vertex_handles(); + /*! iterator over all halfedges. @@ -1107,6 +1146,12 @@ public: */ Halfedge_iterator halfedges_end(); + /*! + returns a range of handles over the halfedges. + \note The value type of `Halfedge_handles::iterator` is `Halfedge_handle`. + */ + Halfedge_handles halfedge_handles(); + /*! iterator over all facets (excluding holes). @@ -1118,6 +1163,12 @@ public: */ Facet_iterator facets_end(); + /*! + returns a range of handles over the facets. + \note The value type of `Facet_handles::iterator` is `Facet_handle`. + */ + Facet_handles facet_handles(); + /*! iterator over all edges. */ @@ -1128,6 +1179,11 @@ public: */ Edge_iterator edges_end(); + /*! + returns a range of iterators over the edges. + */ + Edges edges(); + /*! iterator over all points. */ @@ -1138,6 +1194,11 @@ public: */ Point_iterator points_end(); + /*! + returns a range of iterators over the points. + */ + Points points(); + /*! iterator over all plane equations. */ @@ -1148,6 +1209,11 @@ public: */ Plane_iterator planes_end(); + /*! + returns a range of iterators over the planes. + */ + Planes planes(); + /*! returns the traits class. */ diff --git a/Polyhedron/include/CGAL/Polyhedron_3.h b/Polyhedron/include/CGAL/Polyhedron_3.h index 8c661dde5cd..8c2fce47dfe 100644 --- a/Polyhedron/include/CGAL/Polyhedron_3.h +++ b/Polyhedron/include/CGAL/Polyhedron_3.h @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -523,6 +524,9 @@ public: typedef typename HDS::Halfedge_iterator Halfedge_iterator; typedef typename HDS::Face_iterator Face_iterator; + typedef Iterator_range< Prevent_deref > Vertex_handles; + typedef Iterator_range< Prevent_deref > Halfedge_handles; + typedef typename HDS::Vertex_const_handle Vertex_const_handle; typedef typename HDS::Halfedge_const_handle Halfedge_const_handle; typedef typename HDS::Face_const_handle Face_const_handle; @@ -530,6 +534,9 @@ public: typedef typename HDS::Halfedge_const_iterator Halfedge_const_iterator; typedef typename HDS::Face_const_iterator Face_const_iterator; + typedef Iterator_range< Prevent_deref > Vertex_const_handles; + typedef Iterator_range< Prevent_deref > Halfedge_const_handles; + // Auxiliary iterators for convenience typedef Project_point Proj_point; typedef Iterator_project @@ -537,12 +544,18 @@ public: typedef Iterator_project Point_const_iterator; + typedef Iterator_range< Point_iterator > Points; + typedef Iterator_range< Point_const_iterator > Const_points; + typedef Project_plane Proj_plane; typedef Iterator_project Plane_iterator; typedef Iterator_project Plane_const_iterator; + typedef Iterator_range< Plane_iterator > Planes; + typedef Iterator_range< Plane_const_iterator > Const_planes; + typedef typename HDS::Edge_iterator Edge_iterator; typedef typename HDS::Edge_const_iterator Edge_const_iterator; /* @@ -552,6 +565,9 @@ public: Edge_const_iterator; */ + typedef Iterator_range< Edge_iterator > Edges; + typedef Iterator_range< Edge_const_iterator > Const_edges; + // All face related types get a related facet type name. typedef Face Facet; typedef Face_handle Facet_handle; @@ -559,6 +575,9 @@ public: typedef Face_const_handle Facet_const_handle; typedef Face_const_iterator Facet_const_iterator; + typedef Iterator_range< Prevent_deref > Facet_handles; + typedef Iterator_range< Prevent_deref > Facet_const_handles; + // Supported options by HDS. typedef typename VBase::Supports_vertex_halfedge Supports_vertex_halfedge; @@ -817,16 +836,28 @@ public: Vertex_iterator vertices_end() { return hds_.vertices_end();} + Vertex_handles vertex_handles() { + return make_prevent_deref_range(vertices_begin(), vertices_end()); + } + Halfedge_iterator halfedges_begin() { return hds_.halfedges_begin();} // iterator over all halfedges Halfedge_iterator halfedges_end() { return hds_.halfedges_end();} + Halfedge_handles halfedge_handles() { + return make_prevent_deref_range(halfedges_begin(), halfedges_end()); + } + Facet_iterator facets_begin() { return hds_.faces_begin();} // iterator over all facets Facet_iterator facets_end() { return hds_.faces_end();} + Facet_handles facet_handles() { + return make_prevent_deref_range(facets_begin(), facets_end()); + } + // The constant iterators and circulators. Vertex_const_iterator vertices_begin() const { @@ -836,28 +867,57 @@ public: return hds_.vertices_end(); } + Vertex_const_handles vertex_handles() const { + return make_prevent_deref_range(vertices_begin(), vertices_end()); + } + Halfedge_const_iterator halfedges_begin() const { return hds_.halfedges_begin(); } Halfedge_const_iterator halfedges_end() const { return hds_.halfedges_end(); } + + Halfedge_const_handles halfedge_handles() const { + return make_prevent_deref_range(halfedges_begin(), halfedges_end()); + } + Facet_const_iterator facets_begin() const { return hds_.faces_begin();} Facet_const_iterator facets_end() const { return hds_.faces_end();} + Facet_const_handles facet_handles() const { + return make_prevent_deref_range(facets_begin(), facets_end()); + } + // Auxiliary iterators for convinience Point_iterator points_begin() { return vertices_begin();} Point_iterator points_end() { return vertices_end();} + Points points() { + return Points(points_begin(), points_end()); + } + Point_const_iterator points_begin() const { return vertices_begin();} Point_const_iterator points_end() const { return vertices_end();} + Const_points points() const { + return Const_points(points_begin(), points_end()); + } + Plane_iterator planes_begin() { return facets_begin();} Plane_iterator planes_end() { return facets_end();} + Planes planes() { + return Planes(planes_begin(), planes_end()); + } + Plane_const_iterator planes_begin() const { return facets_begin();} Plane_const_iterator planes_end() const { return facets_end();} + Const_planes planes() const { + return Const_planes(planes_begin(), planes_end()); + } + Edge_iterator edges_begin() { return halfedges_begin();} // iterator over all edges. The iterator refers to halfedges, but // enumerates only one of the two corresponding opposite @@ -865,9 +925,17 @@ public: Edge_iterator edges_end() { return halfedges_end();} // end of the range over all edges. + Edges edges() { + return Edges(edges_begin(), edges_end()); + } + Edge_const_iterator edges_begin() const { return halfedges_begin();} Edge_const_iterator edges_end() const { return halfedges_end();} + Const_edges edges() const { + return Const_edges(edges_begin(), edges_end()); + } + Traits& traits() { return m_traits; } const Traits& traits() const { return m_traits; } diff --git a/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3_features.h b/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3_features.h index dc2069dd7f9..b74fd55f97c 100644 --- a/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3_features.h +++ b/Polyhedron/include/CGAL/boost/graph/properties_Polyhedron_3_features.h @@ -27,8 +27,8 @@ BOOST_MPL_HAS_XXX_TRAIT_DEF(Plane_3) template struct Get_static_property_map { typedef boost::graph_traits > Graph_traits; - typedef CGAL::Static_property_map > type; + typedef CGAL::Constant_property_map > type; }; } // end namespace internal diff --git a/Polyhedron/test/Polyhedron/test_polyhedron_range_based_loops.cpp b/Polyhedron/test/Polyhedron/test_polyhedron_range_based_loops.cpp new file mode 100644 index 00000000000..da08b8d781f --- /dev/null +++ b/Polyhedron/test/Polyhedron/test_polyhedron_range_based_loops.cpp @@ -0,0 +1,171 @@ +#include +#include +#include +#include + +using Kernel = CGAL::Simple_cartesian; +using Traits = CGAL::Polyhedron_traits_3; +using Polyhedron = CGAL::Polyhedron_3; +using Point_3 = typename Kernel::Point_3; + +void test_vertex_handles_and_points( + Polyhedron& polyhedron) { + + auto pit = polyhedron.points_begin(); + auto vit = polyhedron.vertices_begin(); + for (auto vh : polyhedron.vertex_handles()) { + assert(vh == vit); + assert(vh->point() == vit->point()); + assert(vh->point() == *pit); + ++vit; ++pit; + } + assert(pit == polyhedron.points_end()); + assert(vit == polyhedron.vertices_end()); + + pit = polyhedron.points_begin(); + vit = polyhedron.vertices_begin(); + for (auto& point : polyhedron.points()) { + assert(*pit == point); + assert(vit->point() == point); + ++vit; ++pit; + } + assert(pit == polyhedron.points_end()); + assert(vit == polyhedron.vertices_end()); +} + +void test_const_vertex_handles_and_points( + const Polyhedron& polyhedron) { + + auto pit = polyhedron.points_begin(); + auto vit = polyhedron.vertices_begin(); + for (const auto vh : polyhedron.vertex_handles()) { + assert(vh == vit); + assert(vh->point() == vit->point()); + assert(vh->point() == *pit); + ++vit; ++pit; + } + assert(pit == polyhedron.points_end()); + assert(vit == polyhedron.vertices_end()); + + pit = polyhedron.points_begin(); + vit = polyhedron.vertices_begin(); + for (const auto& point : polyhedron.points()) { + assert(*pit == point); + assert(vit->point() == point); + ++vit; ++pit; + } + assert(pit == polyhedron.points_end()); + assert(vit == polyhedron.vertices_end()); +} + +void test_facet_handles_and_planes( + Polyhedron& polyhedron) { + + auto pit = polyhedron.planes_begin(); + auto fit = polyhedron.facets_begin(); + for (auto fh : polyhedron.facet_handles()) { + assert(fh == fit); + assert(fh->plane() == fit->plane()); + assert(fh->plane() == *pit); + ++fit; ++pit; + } + assert(pit == polyhedron.planes_end()); + assert(fit == polyhedron.facets_end()); + + pit = polyhedron.planes_begin(); + fit = polyhedron.facets_begin(); + for (auto& plane : polyhedron.planes()) { + assert(*pit == plane); + assert(fit->plane() == plane); + ++fit; ++pit; + } + assert(pit == polyhedron.planes_end()); + assert(fit == polyhedron.facets_end()); +} + +void test_const_facet_handles_and_planes( + const Polyhedron& polyhedron) { + + auto pit = polyhedron.planes_begin(); + auto fit = polyhedron.facets_begin(); + for (const auto fh : polyhedron.facet_handles()) { + assert(fh == fit); + assert(fh->plane() == fit->plane()); + assert(fh->plane() == *pit); + ++fit; ++pit; + } + assert(pit == polyhedron.planes_end()); + assert(fit == polyhedron.facets_end()); + + pit = polyhedron.planes_begin(); + fit = polyhedron.facets_begin(); + for (const auto& plane : polyhedron.planes()) { + assert(*pit == plane); + assert(fit->plane() == plane); + ++fit; ++pit; + } + assert(pit == polyhedron.planes_end()); + assert(fit == polyhedron.facets_end()); +} + +void test_halfedge_handles_and_edges( + Polyhedron& polyhedron) { + + auto hit = polyhedron.halfedges_begin(); + for (auto hh : polyhedron.halfedge_handles()) { + assert(hh == hit); + assert(hh->facet() == hit->facet()); + assert(hh->vertex() == hit->vertex()); + ++hit; + } + assert(hit == polyhedron.halfedges_end()); + + auto eit = polyhedron.edges_begin(); + for (auto& edge : polyhedron.edges()) { + assert((*eit).facet() == edge.facet()); + assert((*eit).vertex() == edge.vertex()); + ++eit; + } + assert(eit == polyhedron.edges_end()); +} + +void test_const_halfedge_handles_and_edges( + const Polyhedron& polyhedron) { + + auto hit = polyhedron.halfedges_begin(); + for (const auto hh : polyhedron.halfedge_handles()) { + assert(hh == hit); + assert(hh->facet() == hit->facet()); + assert(hh->vertex() == hit->vertex()); + ++hit; + } + assert(hit == polyhedron.halfedges_end()); + + auto eit = polyhedron.edges_begin(); + for (const auto& edge : polyhedron.edges()) { + assert((*eit).facet() == edge.facet()); + assert((*eit).vertex() == edge.vertex()); + ++eit; + } + assert(eit == polyhedron.edges_end()); +} + +int main() { + + Polyhedron polyhedron; + const auto h = polyhedron.make_tetrahedron( + Point_3(1, 0, 0), Point_3(0, 1, 0), + Point_3(0, 0, 1), Point_3(0, 0, 0)); + assert(polyhedron.is_valid()); + assert(polyhedron.is_tetrahedron(h)); + + test_vertex_handles_and_points(polyhedron); + test_const_vertex_handles_and_points(polyhedron); + test_facet_handles_and_planes(polyhedron); + test_const_facet_handles_and_planes(polyhedron); + test_halfedge_handles_and_edges(polyhedron); + test_const_halfedge_handles_and_edges(polyhedron); + + std::cout << "test_polyhedron_range_based_loops: SUCCESS" << std::endl; + return EXIT_SUCCESS; +} diff --git a/Principal_component_analysis/include/CGAL/PCA_util_Eigen.h b/Principal_component_analysis/include/CGAL/PCA_util_Eigen.h index 66494ba125a..dfabb50a0b0 100644 --- a/Principal_component_analysis/include/CGAL/PCA_util_Eigen.h +++ b/Principal_component_analysis/include/CGAL/PCA_util_Eigen.h @@ -144,9 +144,9 @@ assemble_covariance_matrix_3(InputIterator first, FT x0 = t[0].x(); FT y0 = t[0].y(); FT z0 = t[0].z(); - FT delta[9] = {t[0].x(), t[1].x(), t[2].x(), - t[0].y(), t[1].y(), t[2].y(), - t[0].z(), t[1].z(), t[2].z()}; + FT delta[9] = {t[1].x()-x0, t[3].x()-x0, t[5].x()-x0, + t[1].y()-y0, t[3].y()-y0, t[5].y()-y0, + t[1].z()-z0, t[3].z()-z0, t[5].z()-z0}; Matrix transformation (delta); FT volume = t.volume(); @@ -548,9 +548,9 @@ assemble_covariance_matrix_3(InputIterator first, // assemble 2nd order moment about the origin. Matrix moment; - moment << 1.0, 0.5, 0.0, - 0.5, 1.0, 0.0, - 0.0, 0.0, 0.0; + moment << 1.0/3.0, 0.5/3.0, 0.0, + 0.5/3.0, 1.0/3.0, 0.0, + 0.0, 0.0, 0.0; for(InputIterator it = first; it != beyond; diff --git a/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_rectangles_2.h b/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_rectangles_2.h index 67d23e04d64..7aad5b86554 100644 --- a/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_rectangles_2.h +++ b/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_rectangles_2.h @@ -171,7 +171,8 @@ linear_least_squares_fitting_2(InputIterator first, segments.push_back(Segment_2(t[3],t[0])); } - return linear_least_squares_fitting_2(segments.begin(),segments.end(),line,c,K(),tag, + return linear_least_squares_fitting_2(segments.begin(),segments.end(),line,c, + (Segment_2*)nullptr, K(),tag, diagonalize_traits); } // end linear_least_squares_fitting_2 for rectangle set with 1D tag @@ -209,7 +210,8 @@ linear_least_squares_fitting_2(InputIterator first, points.push_back(Point_2(t[3])); } - return linear_least_squares_fitting_2(points.begin(),points.end(),line,c,K(),tag, + return linear_least_squares_fitting_2(points.begin(),points.end(),line,c, + (Point_2*)nullptr, K(),tag, diagonalize_traits); } // end linear_least_squares_fitting_2 for rectangle set with 0D tag diff --git a/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_segments_2.h b/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_segments_2.h index 8bf70443120..f290e741eef 100644 --- a/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_segments_2.h +++ b/Principal_component_analysis/include/CGAL/linear_least_squares_fitting_segments_2.h @@ -157,7 +157,7 @@ linear_least_squares_fitting_2(InputIterator first, points.push_back(s[0]); points.push_back(s[1]); } - return linear_least_squares_fitting_2(points.begin(),points.end(),line,c,k,(Point*)nullptr,tag, + return linear_least_squares_fitting_2(points.begin(),points.end(),line,c,(Point*)nullptr,k,tag, diagonalize_traits); } // end linear_least_squares_fitting_2 for segment set with 1D tag diff --git a/Principal_component_analysis/test/Principal_component_analysis/test_validity.cpp b/Principal_component_analysis/test/Principal_component_analysis/test_validity.cpp new file mode 100644 index 00000000000..26bddf76fe7 --- /dev/null +++ b/Principal_component_analysis/test/Principal_component_analysis/test_validity.cpp @@ -0,0 +1,378 @@ +/* + This test checks that the outputs of all variants of PCA are + correct. + + To do so: + - N Point_3 objects are generated on a random line + - N*N Point_3 objects are generated on a random plane + + For each variant of the PCA, we generate objects "centered" on the + reference points: + - Sphere_3 centered on each point with random radius + - Equilateral Triangle_3 centered on each point with random length + - Point_2 using first 2 coordinates of Point_3 + - etc. + + PCA is then computed for Line_2 in 2D or for Line_3 and Plane_3 in + 3D. Then, the mean distance between the original points (or 2D + variants if 2D case) and the estimated support is computed: if it + higher than 0.01% of the diameter of the point cloud, an assertion + is raised. + + This only tests an obvious case where the PCA is computed on a set + of exactly aligned objects, but it should help avoiding the + introduction of bugs. + */ + +#include +#include +#include +#include + +#include + +typedef CGAL::Simple_cartesian Kernel; +typedef Kernel::Point_3 Point_3; +typedef Kernel::Segment_3 Segment_3; +typedef Kernel::Vector_3 Vector_3; +typedef Kernel::Sphere_3 Sphere_3; +typedef Kernel::Triangle_3 Triangle_3; +typedef Kernel::Tetrahedron_3 Tetrahedron_3; +typedef Kernel::Iso_cuboid_3 Iso_cuboid_3; +typedef Kernel::Plane_3 Plane_3; +typedef Kernel::Line_3 Line_3; + +typedef Kernel::Point_2 Point_2; +typedef Kernel::Vector_2 Vector_2; +typedef Kernel::Circle_2 Circle_2; +typedef Kernel::Iso_rectangle_2 Iso_rectangle_2; +typedef Kernel::Segment_2 Segment_2; +typedef Kernel::Triangle_2 Triangle_2; +typedef Kernel::Line_2 Line_2; + +CGAL::Random rnd; + +/* + Functions used to generate objects "centered" on points (objects + whose centers of mass are on the points). + */ + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + target.reserve (source.size()); + std::copy (source.begin(), source.end(), std::back_inserter (target)); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back (Point_2 (source[i].x(), source[i].y())); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + Vector_3 diff (rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01)); + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back (Segment_3 (source[i] + diff, source[i] - diff)); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + Vector_2 diff (rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01)); + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + { + Point_2 p (source[i].x(), source[i].y()); + target.push_back (Segment_2 (p + diff, p - diff)); + } +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + double radius = rnd.get_double(0, 0.01); + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back (Sphere_3 (source[i], radius * radius)); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + double radius = rnd.get_double(0, 0.01); + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + { + Point_2 p (source[i].x(), source[i].y()); + target.push_back (Circle_2 (p, radius * radius)); + } +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + // General equilateral triangles + double length = rnd.get_double(0, 0.01); + double height = length * std::sqrt(3.) / 2.; + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back + (Triangle_3 (source[i] + Vector_3 (0, 0, 2. * height / 3.), + source[i] + Vector_3 (0, -length/2., -height/3.), + source[i] + Vector_3 (0, length/2., -height/3.))); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + // General equilateral triangles + double length = rnd.get_double(0, 0.01); + double height = length * std::sqrt(3.) / 2.; + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + { + Point_2 p (source[i].x(), source[i].y()); + target.push_back + (Triangle_2 (p + Vector_2 (0, 2. * height / 3.), + p + Vector_2 (-length/2., -height/3.), + p + Vector_2 (length/2., -height/3.))); + } +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + // General regular tetrahedra + double length = rnd.get_double(0, 0.01); + double height = length * std::sqrt(2. / 3.); + + double height_tri = length * std::sqrt(3.) / 2.; + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back + (Tetrahedron_3 (source[i] + Vector_3 (0, 0, 3. * height / 4.), + source[i] + Vector_3 (0, 2. * height_tri / 3., -height/4.), + source[i] + Vector_3 (-length/2., -height_tri / 3., -height/4.), + source[i] + Vector_3 (length/2., -height_tri / 3., -height/4.))); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + Vector_3 diff (rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01)); + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + target.push_back (Iso_cuboid_3 (source[i] + diff, source[i] - diff)); +} + +void generate_objects_centered_on_points (const std::vector& source, + std::vector& target) +{ + Vector_2 diff (rnd.get_double(0, 0.01), + rnd.get_double(0, 0.01)); + + target.reserve (source.size()); + for (std::size_t i = 0; i < source.size(); ++ i) + { + Point_2 p (source[i].x(), source[i].y()); + target.push_back (Iso_rectangle_2 (p + diff, p - diff)); + } +} + +/* + Compute distances between original points to Line_3/Plane_3/Line_2 + */ + +double distance (const Point_3& p, const Line_3& l) +{ return std::sqrt (CGAL::squared_distance (p, l)); } +double distance (const Point_3& p, const Plane_3& pl) +{ return std::sqrt (CGAL::squared_distance (p, pl)); } +double distance (const Point_3& p, const Line_2& l) +{ return std::sqrt (CGAL::squared_distance (Point_2 (p.x(), p.y()), l)); } + +/* + Test quality of fit and raise assertion if too low. + */ + +template +void assert_quality (const std::vector& points, const Fitted& fitted) +{ + double mean_dist = 0; + for (std::size_t i = 0; i < points.size(); ++ i) + { + double dist = distance (points[i], fitted); + mean_dist += dist; + } + mean_dist /= points.size(); + + std::cerr << "mean distance = " << mean_dist << std::endl; + + CGAL_assertion_code + (double limit = 1e-3 * std::sqrt (CGAL::squared_distance (points.front(), points.back()))); + CGAL_assertion (mean_dist < limit); +} + +/* + Reference test functions, both in 2D and 3D. + */ + +template +void test (const std::vector& objects, + const std::vector& points, + const CGAL::Dimension_tag<2>& /* ambient dimension */) +{ + std::cerr << " CGAL::Dimension_tag<" << dim << ">: "; + Fitted fitted; + CGAL::linear_least_squares_fitting_2 + (objects.begin(), objects.end(), fitted, CGAL::Dimension_tag()); + assert_quality (points, fitted); +} + +template +void test (const std::vector& objects, + const std::vector& points, + const CGAL::Dimension_tag<3>& /* ambient dimension */) +{ + std::cerr << " CGAL::Dimension_tag<" << dim << ">: "; + Fitted fitted; + CGAL::linear_least_squares_fitting_3 + (objects.begin(), objects.end(), fitted, CGAL::Dimension_tag()); + assert_quality (points, fitted); +} + +template +void test (const std::vector& points) +{ + std::vector objects; + generate_objects_centered_on_points (points, objects); + test + (objects, points, typename CGAL::Ambient_dimension::type()); +} + + + + +int main() +{ + std::cerr << "Validity test with seed " << rnd.get_seed() << std::endl; + + Point_3 origin (rnd.get_double(), rnd.get_double(), rnd.get_double()); + Vector_3 base1 (rnd.get_double(), rnd.get_double(), rnd.get_double()); + Vector_3 base2 (rnd.get_double(), rnd.get_double(), rnd.get_double()); + + std::cerr << "Origin = " << origin << std::endl + << "Base1 = " << base1 << std::endl + << "Base2 = " << base2 << std::endl; + + std::size_t nb_points_on_line = 100; + std::vector points_on_line; + points_on_line.reserve (nb_points_on_line); + for (std::size_t i = 0; i < nb_points_on_line; ++ i) + points_on_line.push_back (Point_3 (origin + double(i) * base1)); + + std::vector points_on_plane; + points_on_plane.reserve (nb_points_on_line * nb_points_on_line); + for (std::size_t i = 0; i < nb_points_on_line; ++ i) + for (std::size_t j = 0; j < nb_points_on_line; ++ j) + points_on_plane.push_back (Point_3 (origin + double(i) * base1 + double(j) * base2)); + + std::cerr << std::endl << "=== 2D ===" << std::endl << std::endl; + + std::cerr << "[Testing line fitting on Point_2 objects]" << std::endl; + test (points_on_line); + + std::cerr << "[Testing line fitting on Segment_2 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing line fitting on Circle_2 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing line fitting on Triangle_2 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing line fitting on Iso_rectangle_2 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + test (points_on_line); + + std::cerr << std::endl << "=== 3D ===" << std::endl << std::endl; + + std::cerr << "[Testing line fitting on Point_3 objects]" << std::endl; + test (points_on_line); + + std::cerr << "[Testing plane fitting on Point_3 objects]" << std::endl; + test (points_on_plane); + + std::cerr << "[Testing line fitting on Segment_3 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing plane fitting on Segment_3 objects]" << std::endl; + test (points_on_plane); + test (points_on_plane); + + std::cerr << "[Testing line fitting on Sphere_3 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing plane fitting on Sphere_3 objects]" << std::endl; + test (points_on_plane); + test (points_on_plane); + + std::cerr << "[Testing line fitting on Triangle_3 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing plane fitting on Triangle_3 objects]" << std::endl; + test (points_on_plane); + test (points_on_plane); + test (points_on_plane); + + std::cerr << "[Testing line fitting on Tetrahedron_3 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing plane fitting on Tetrahedron_3 objects]" << std::endl; + test (points_on_plane); + test (points_on_plane); + test (points_on_plane); + test (points_on_plane); + + std::cerr << "[Testing line fitting on Iso_cuboid_3 objects]" << std::endl; + test (points_on_line); + test (points_on_line); + test (points_on_line); + test (points_on_line); + + std::cerr << "[Testing plane fitting on Iso_cuboid_3 objects]" << std::endl; + test (points_on_plane); + test (points_on_plane); + test (points_on_plane); + test (points_on_plane); + + return EXIT_SUCCESS; +} diff --git a/Property_map/include/CGAL/property_map.h b/Property_map/include/CGAL/property_map.h index f5f50023601..30b5b72f2ed 100644 --- a/Property_map/include/CGAL/property_map.h +++ b/Property_map/include/CGAL/property_map.h @@ -37,33 +37,28 @@ namespace CGAL { /// \cond SKIP_DOXYGEN -/// This class is almost the same as boost::static_property_map -/// The difference is that it is writable, although put() does nothing -template -class Static_property_map +/// A boolean property map return a const value at compile time +template +class Static_boolean_property_map { public: - typedef K key_type; - typedef V value_type; - typedef const V& reference; + typedef Key key_type; + typedef bool value_type; + typedef bool reference; typedef boost::read_write_property_map_tag category; -private: - V v; - public: - Static_property_map(V pv) - :v(pv){} + inline friend value_type - get(const Static_property_map& pm, const key_type&) + get(Static_boolean_property_map, const key_type&) { - return pm.v; + return default_value; } inline friend void - put(Static_property_map&, const key_type&, const value_type&) + put(Static_boolean_property_map, const key_type&, const value_type&) {} }; diff --git a/Ridges_3/test/Ridges_3/PolyhedralSurf.h b/Ridges_3/test/Ridges_3/PolyhedralSurf.h index fb3a689ce6d..ad4297ba8d0 100644 --- a/Ridges_3/test/Ridges_3/PolyhedralSurf.h +++ b/Ridges_3/test/Ridges_3/PolyhedralSurf.h @@ -43,12 +43,13 @@ struct Wrappers_VFH:public CGAL::Polyhedron_items_3 { template < class Refs, class Traits > struct Face_wrapper { //typedef typename Traits::Vector_3 Vector_3; //all types needed by the facet... - typedef struct { - public: - typedef typename Traits::Vector_3 Vector_3; - } FGeomTraits; + struct FGeomTraits { + public: + typedef typename Traits::Vector_3 Vector_3; + }; + typedef FGeomTraits FGT; //custom type instantiated... - typedef My_facet < Refs, CGAL::Tag_true, FGeomTraits > Face; + typedef My_facet < Refs, CGAL::Tag_true, FGT > Face; }; }; diff --git a/STL_Extension/include/CGAL/Cache.h b/STL_Extension/include/CGAL/Cache.h index 30204959ebc..4db526e8624 100644 --- a/STL_Extension/include/CGAL/Cache.h +++ b/STL_Extension/include/CGAL/Cache.h @@ -1,5 +1,3 @@ -// ============================================================================= -// // Copyright (c) 2001-2007 Max-Planck-Institute Saarbruecken (Germany). // All rights reserved. // @@ -11,7 +9,6 @@ // // Author(s) : Michael Hemmer // -// ============================================================================= #ifndef CGAL_CACHE_H #define CGAL_CACHE_H 1 diff --git a/STL_Extension/include/CGAL/Uncertain.h b/STL_Extension/include/CGAL/Uncertain.h index 947e3dfcef7..21f46a9196a 100644 --- a/STL_Extension/include/CGAL/Uncertain.h +++ b/STL_Extension/include/CGAL/Uncertain.h @@ -612,18 +612,6 @@ Uncertain operator*(Uncertain a, T b) // enum_cast overload -#ifdef CGAL_CFG_MATCHING_BUG_5 - -template < typename T, typename U > -inline -Uncertain enum_cast_bug(Uncertain u, const T*) -{ - return Uncertain(static_cast(u.inf()), - static_cast(u.sup())); -} - -#else - template < typename T, typename U > inline Uncertain enum_cast(Uncertain u) @@ -631,8 +619,6 @@ Uncertain enum_cast(Uncertain u) return Uncertain(static_cast(u.inf()), static_cast(u.sup())); } -#endif - } //namespace CGAL #endif // CGAL_UNCERTAIN_H diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Alpha_shape_mesher.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Alpha_shape_mesher.h index f23db4bb890..19a20242b28 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Alpha_shape_mesher.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/Alpha_shape_mesher.h @@ -180,6 +180,11 @@ public: } + ~Alpha_shape_mesher () + { + clear_surface(); + } + /// \cond SKIP_IN_MANUAL template void operator() (InputIterator begin, InputIterator end, OutputIterator output) diff --git a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/internal/Auto_count.h b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/internal/Auto_count.h index ccc85cdd5e3..4a131d7279c 100644 --- a/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/internal/Auto_count.h +++ b/Scale_space_reconstruction_3/include/CGAL/Scale_space_reconstruction_3/internal/Auto_count.h @@ -1,4 +1,3 @@ -//A unary operator to that counts instances. //Copyright (C) 2013 INRIA - Sophia Antipolis // // This file is part of CGAL (www.cgal.org). diff --git a/Scripts/developer_scripts/autotest_cgal b/Scripts/developer_scripts/autotest_cgal index 558256bc1b5..70830eb86c9 100755 --- a/Scripts/developer_scripts/autotest_cgal +++ b/Scripts/developer_scripts/autotest_cgal @@ -391,7 +391,7 @@ setup_dirs() log "${ACTUAL_LOGFILE}" "Creating ${CGAL_DIR}/cmake/platforms" fi - CGAL_RELEASE_DIR="${CGAL_DIR}" + export CGAL_RELEASE_DIR="${CGAL_DIR}" CGAL_RELEASE_ID=`basename "${CGAL_RELEASE_DIR}"` @@ -653,7 +653,7 @@ EOF cat >> "$file" <> "${ACTUAL_LOGFILE}" +echo "Running `basename ${0}` "'$Revision$' >> "${ACTUAL_LOGFILE}" # Sanity checks if [ "${REFERENCE_PLATFORMS_DIR}" = "must_be_set_in_.autocgalrc" ]; then @@ -865,11 +865,11 @@ fi # Detects cygwin if uname | grep -q "CYGWIN"; then JOM="`which jom`" - if [ -e "$JOM" ]; then + if [ -e "$JOM" ]; then CMAKE_GENERATOR='-GNMake Makefiles JOM' MAKE_CMD='jom' log "${ACTUAL_LOGFILE}" "Cygwin detected, jom detected, using jom" - else + else CMAKE_GENERATOR='-GNMake Makefiles' MAKE_CMD='nmake' log "${ACTUAL_LOGFILE}" "Cygwin detected, using nmake" @@ -886,7 +886,7 @@ if [ -z "$IS_CYGWIN" ]; then lockfile -r 1 "$LOCK_FILE"; if [ ${?} != 0 ]; then PID=`cat "$LOCK_FILE"` - if kill -0 "$PID"; then + if kill -0 "$PID"; then log "${ACTUAL_LOGFILE}" "COULD NOT ACQUIRE LOCK! LOCKING PROCESS PID=$PID"; exit 1; else @@ -943,7 +943,7 @@ if [ "${BUILD_HOSTS}" = "localhost" ]; then TEXT="`value_of COMPILERS_localhost`" if [ -z "${DO_NOT_TEST}" ]; then if [ -z "${TEXT}" ]; then - printf "Skipping testing phase (use the -n option to remove this message).\n" + printf "Skipping testing phase (use the -n option to remove this message).\n" DO_NOT_TEST="y" fi fi diff --git a/Scripts/developer_scripts/merge_pr_with_label b/Scripts/developer_scripts/merge_pr_with_label index 2598ef8c0cc..6d61a3d6cb8 100755 --- a/Scripts/developer_scripts/merge_pr_with_label +++ b/Scripts/developer_scripts/merge_pr_with_label @@ -9,7 +9,7 @@ fi for pr in $(python3 ./Scripts/developer_scripts/list_pull_requests.py "$1" --unmerged); do if ! hub merge $pr; then - echo $p; + echo $pr; break fi done diff --git a/Scripts/developer_scripts/tag_pr_per_release.sh b/Scripts/developer_scripts/tag_pr_per_release.sh index ba1fab8f3b6..a8927dcfe17 100644 --- a/Scripts/developer_scripts/tag_pr_per_release.sh +++ b/Scripts/developer_scripts/tag_pr_per_release.sh @@ -24,7 +24,7 @@ set -e # Exit the script on first error, for safety PREVIOUS_MAJOR_RELEASE=$1 CURRENT_RELEASE=$2 -REMOTE=`git config branch.releases/CGAL-${PREVIOUS_MAJOR_RELEASE}-branch.remote` +REMOTE=`git config branch.releases/CGAL-${PREVIOUS_MAJOR_RELEASE}-branch.remote || git config branch.${PREVIOUS_MAJOR_RELEASE}.x-branch.remote` # $REMOTE should be the "cgal" remote, but a CGAL developer may have keep the # name "origin", or set to another one. diff --git a/Scripts/developer_scripts/test_license_check/ImageIO.h b/Scripts/developer_scripts/test_license_check/ImageIO.h index 50ad48b44ad..4e3a23c1651 100644 --- a/Scripts/developer_scripts/test_license_check/ImageIO.h +++ b/Scripts/developer_scripts/test_license_check/ImageIO.h @@ -13,7 +13,7 @@ // // These files are provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE // WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. -// $URL: svn+ssh://scm.gforge.inria.fr/svn/cgal/branches/releases/CGAL-4.1-branch/CGALimageIO/include/CGAL/ImageIO.h $ +// $URL: $ // $Id: ImageIO.h 67097 2012-01-13 13:36:56Z lrineau $ // // SPDX-License-Identifier: LGPL-3.0-or-later diff --git a/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h b/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h index 847292efe83..7ff6e46a3f6 100644 --- a/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h +++ b/Shape_detection/include/CGAL/Shape_detection/deprecated/Region_growing.h @@ -688,7 +688,10 @@ namespace Shape_detection { p->m_indices.clear(); std::copy (index_container.begin(), index_container.end(), std::back_inserter (p->m_indices)); - dynamic_cast(p)->update (optimal_plane); + + Plane_shape* ps = dynamic_cast(p); + CGAL_assume (ps != nullptr); + ps->update (optimal_plane); m_extracted_shapes->push_back (boost::shared_ptr(p)); } else diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/Euler_extensions.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/Euler_extensions.h index 513892ed99e..52851bdface 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/Euler_extensions.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/Euler_extensions.h @@ -1,5 +1,3 @@ -// ====================================================================== -// // Copyright (c) 2005-2017 GeometryFactory (France). All Rights Reserved. // // This file is part of CGAL (www.cgal.org) @@ -11,7 +9,6 @@ // // Author(s): Le-Jeng Shiue // -// ====================================================================== #ifndef CGAL_SUBDIVISION_METHOD_3_INTERNAL_EULER_EXTENSIONS_H #define CGAL_SUBDIVISION_METHOD_3_INTERNAL_EULER_EXTENSIONS_H diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/subdivision_hosts_impl_3.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/subdivision_hosts_impl_3.h index 91831bd3747..3f4b418f6e8 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/subdivision_hosts_impl_3.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/internal/subdivision_hosts_impl_3.h @@ -1,5 +1,3 @@ -// ====================================================================== -// // Copyright (c) 2005-2017 GeometryFactory (France). All Rights Reserved. // // This file is part of CGAL (www.cgal.org) @@ -11,7 +9,6 @@ // // Author(s): Le-Jeng Shiue // -// ====================================================================== #ifndef CGAL_SUBDIVISION_HOSTS_IMPL_3_H #define CGAL_SUBDIVISION_HOSTS_IMPL_3_H diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_hosts_3.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_hosts_3.h index 9c3e5a269bb..3cb74375919 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_hosts_3.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_hosts_3.h @@ -1,5 +1,3 @@ -// ====================================================================== -// // Copyright (c) 2017 GeometryFactory (France). All Rights Reserved. // // This file is part of CGAL (www.cgal.org) @@ -11,7 +9,6 @@ // // Author(s): Le-Jeng Shiue // -// ====================================================================== #ifndef CGAL_SUBDIVISION_HOSTS_3_H #define CGAL_SUBDIVISION_HOSTS_3_H diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h index 1b84e3f9f67..e9750084e8a 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_masks_3.h @@ -1,5 +1,3 @@ -// ====================================================================== -// // Copyright (c) 2005-2017 GeometryFactory (France). All Rights Reserved. // // This file is part of CGAL (www.cgal.org) @@ -11,7 +9,6 @@ // // Author(s): Le-Jeng Shiue // -// ====================================================================== #ifndef CGAL_SUBDIVISION_MASKS_3_H #define CGAL_SUBDIVISION_MASKS_3_H diff --git a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_methods_3.h b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_methods_3.h index 831599410d1..80b654de8d8 100644 --- a/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_methods_3.h +++ b/Subdivision_method_3/include/CGAL/Subdivision_method_3/subdivision_methods_3.h @@ -1,5 +1,3 @@ -// ====================================================================== -// // Copyright (c) 2005-2017 GeometryFactory (France). All Rights Reserved. // // This file is part of CGAL (www.cgal.org) @@ -11,7 +9,6 @@ // // Author(s): Le-Jeng Shiue // -// ====================================================================== #ifndef CGAL_SUBDIVISION_METHODS_3_H #define CGAL_SUBDIVISION_METHODS_3_H diff --git a/Subdivision_method_3/include/CGAL/subdivision_method_3.h b/Subdivision_method_3/include/CGAL/subdivision_method_3.h index 421a8d6a396..92232fa4d3c 100644 --- a/Subdivision_method_3/include/CGAL/subdivision_method_3.h +++ b/Subdivision_method_3/include/CGAL/subdivision_method_3.h @@ -1,4 +1,3 @@ -// ====================================================================== // // Copyright (c) 2017 GeometryFactory (France). All Rights Reserved. // @@ -11,7 +10,6 @@ // // Author(s): // -// ====================================================================== /** * \ingroup PkgSurfaceSubdivisionMethod3Ref diff --git a/Surface_mesh/include/CGAL/Surface_mesh/IO.h b/Surface_mesh/include/CGAL/Surface_mesh/IO.h index cd8fb59c76d..d891192f99c 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/IO.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/IO.h @@ -1,4 +1,3 @@ -//============================================================================= // Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen // Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University // Copyright (C) 2014 GeometryFactory diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h index 108744ccf64..6904a04ba33 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Properties.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Properties.h @@ -1,4 +1,3 @@ -//============================================================================= // Copyright (C) 2001-2005 by Computer Graphics Group, RWTH Aachen // Copyright (C) 2011 by Graphics & Geometry Group, Bielefeld University // Copyright (C) 2014 GeometryFactory diff --git a/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh_features.h b/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh_features.h index 8ba1a3c1bee..b3881cb789e 100644 --- a/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh_features.h +++ b/Surface_mesh/include/CGAL/boost/graph/properties_Surface_mesh_features.h @@ -36,7 +36,7 @@ struct property_map, CGAL::face_patch_id_t > typedef typename boost::graph_traits >::face_descriptor face_descriptor; - typedef CGAL::Static_property_map >::face_descriptor,std::pair > type; + typedef CGAL::Constant_property_map >::face_descriptor,std::pair > type; typedef type const_type; }; @@ -111,7 +111,7 @@ template CGAL_PROPERTY_SURFACE_MESH_RETURN_TYPE(CGAL::face_patch_id_t) inline get(CGAL::face_patch_id_t, const Surface_mesh

    &) { - typedef CGAL::Static_property_map >::face_descriptor,std::pair > Pmap; + typedef CGAL::Constant_property_map >::face_descriptor,std::pair > Pmap; return Pmap(std::make_pair(0,1)); } diff --git a/Surface_mesh_segmentation/examples/Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp b/Surface_mesh_segmentation/examples/Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp index dd5ab74df9d..189f068b136 100644 --- a/Surface_mesh_segmentation/examples/Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp +++ b/Surface_mesh_segmentation/examples/Surface_mesh_segmentation/extract_segmentation_into_mesh_example.cpp @@ -44,11 +44,10 @@ int main(int argc, char** argv ) typedef CGAL::Face_filtered_graph Filtered_graph; //print area of each segment and then put it in a Mesh and print it in an OFF file - Filtered_graph segment_mesh(mesh, 0, segment_property_map); + Filtered_graph segment_mesh(mesh); for(std::size_t id = 0; id < number_of_segments; ++id) { - if(id > 0) - segment_mesh.set_selected_faces(id, segment_property_map); + segment_mesh.set_selected_faces(id, segment_property_map); std::cout << "Segment "< diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/AABB_traits.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/AABB_traits.h index 991da9ecbb7..f6f7f3bffe9 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/AABB_traits.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/AABB_traits.h @@ -1,4 +1,3 @@ -#ifndef CGAL_INTERNAL_SURFACE_MESH_SEGMENTATION_AABB_TRAITS_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_INTERNAL_SURFACE_MESH_SEGMENTATION_AABB_TRAITS_H #define CGAL_INTERNAL_SURFACE_MESH_SEGMENTATION_AABB_TRAITS_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Disk_samplers.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Disk_samplers.h index 60719936baf..cd8917ed12b 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Disk_samplers.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Disk_samplers.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H #define CGAL_SURFACE_MESH_SEGMENTATION_DISK_SAMPLERS_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Expectation_maximization.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Expectation_maximization.h index bbc6542de01..0982f5eea0a 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Expectation_maximization.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Expectation_maximization.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_EXPECTATION_MAXIMIZATION_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_EXPECTATION_MAXIMIZATION_H #define CGAL_SURFACE_MESH_SEGMENTATION_EXPECTATION_MAXIMIZATION_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h index d94a257b866..6c6e231a604 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Filters.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -10,7 +9,7 @@ // // Author(s) : Ilker O. Yaz - +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H #define CGAL_SURFACE_MESH_SEGMENTATION_FILTERS_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/K_means_clustering.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/K_means_clustering.h index 0216c1ead8c..c35b6301648 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/K_means_clustering.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/K_means_clustering.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_K_MEANS_CLUSTERING_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_K_MEANS_CLUSTERING_H #define CGAL_SURFACE_MESH_SEGMENTATION_K_MEANS_CLUSTERING_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h index efc0e3774aa..f7b84968dd7 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/SDF_calculation.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_SDF_CALCULATION_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_SDF_CALCULATION_H #define CGAL_SURFACE_MESH_SEGMENTATION_SDF_CALCULATION_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h index 6adc33af483..3e1aeb637a4 100644 --- a/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h +++ b/Surface_mesh_segmentation/include/CGAL/internal/Surface_mesh_segmentation/Surface_mesh_segmentation.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -11,6 +10,7 @@ // Author(s) : Ilker O. Yaz +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_H #define CGAL_SURFACE_MESH_SEGMENTATION_H #include diff --git a/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h b/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h index 766f706d431..dd1a6914a75 100644 --- a/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h +++ b/Surface_mesh_segmentation/include/CGAL/mesh_segmentation.h @@ -1,4 +1,3 @@ -#ifndef CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H // Copyright (c) 2014 GeometryFactory Sarl (France). // All rights reserved. // @@ -10,7 +9,7 @@ // // Author(s) : Ilker O. Yaz - +#ifndef CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H #define CGAL_SURFACE_MESH_SEGMENTATION_MESH_SEGMENTATION_H #include diff --git a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h index 2bacc02174a..826cadc8581 100644 --- a/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h +++ b/Surface_mesh_simplification/include/CGAL/Surface_mesh_simplification/edge_collapse.h @@ -98,7 +98,7 @@ int edge_collapse(TM& tmesh, choose_parameter >(get_parameter(np, internal_np::edge_is_constrained)), choose_parameter >(get_parameter(np, internal_np::get_cost_policy)), choose_parameter >(get_parameter(np, internal_np::get_placement_policy)), - choose_parameter(get_parameter(np, internal_np::graph_visitor))); + choose_parameter(get_parameter(np, internal_np::visitor))); } template diff --git a/Surface_mesher/examples/Surface_mesher/mesh_an_implicit_function.cpp b/Surface_mesher/examples/Surface_mesher/mesh_an_implicit_function.cpp index d8cf41cd013..c62844c85d5 100644 --- a/Surface_mesher/examples/Surface_mesher/mesh_an_implicit_function.cpp +++ b/Surface_mesher/examples/Surface_mesher/mesh_an_implicit_function.cpp @@ -2,6 +2,10 @@ #include #include #include +#include +#include + +#include // default triangulation for Surface_mesher typedef CGAL::Surface_mesh_default_triangulation_3 Tr; @@ -18,6 +22,8 @@ typedef FT (*Function)(Point_3); typedef CGAL::Implicit_surface_3 Surface_3; +typedef CGAL::Surface_mesh Surface_mesh; + FT sphere_function (Point_3 p) { const FT x2=p.x()*p.x(), y2=p.y()*p.y(), z2=p.z()*p.z(); return x2+y2+z2-1; @@ -39,5 +45,10 @@ int main() { // meshing surface CGAL::make_surface_mesh(c2t3, surface, criteria, CGAL::Non_manifold_tag()); + Surface_mesh sm; + CGAL::facets_in_complex_2_to_triangle_mesh(c2t3, sm); + std::ofstream out("sphere.off"); + out << sm << std::endl; + std::cout << "Final number of points: " << tr.number_of_vertices() << "\n"; } diff --git a/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_medit.h b/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_medit.h index 97a170bac35..f84385c8555 100644 --- a/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_medit.h +++ b/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_medit.h @@ -19,6 +19,7 @@ #include #include +#include namespace CGAL { @@ -41,19 +42,34 @@ output_surface_facets_to_medit (std::ostream& os, const C2t3& c2t3) //os << std::setprecision(20); + std::unordered_map V; + + for(typename C2t3::Facet_iterator + fit = c2t3.facets_begin(), + end = c2t3.facets_end(); + fit != end; ++fit) + { + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 0))] = 0; + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 1))] = 0; + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 2))] = 0; + } + // Finite vertices coordinates. os << "Vertices\n" - << tr.number_of_vertices() << " \n"; + << V.size() << " \n"; + - std::map V; int inum = 0; for(Finite_vertices_iterator vit = tr.finite_vertices_begin(); vit != tr.finite_vertices_end(); ++vit) { - V[vit] = inum++; - Point p = static_cast(vit->point()); - os << p.x() << " " << p.y() << " " << p.z() << " 0 \n"; + auto it = V.find(vit); + if(it != V.end()){ + it->second = inum++; + Point p = static_cast(vit->point()); + os << p.x() << " " << p.y() << " " << p.z() << " 0 \n"; + } } diff --git a/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_vtk.h b/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_vtk.h index 289f5eca096..2a76461b98a 100644 --- a/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_vtk.h +++ b/Surface_mesher/include/CGAL/IO/Complex_2_in_triangulation_3_to_vtk.h @@ -17,7 +17,7 @@ #include -#include +#include #include #include @@ -38,24 +38,38 @@ vtkPolyData* output_c2t3_to_vtk_polydata(const C2T3& c2t3, vtkPoints* const vtk_points = vtkPoints::New(); vtkCellArray* const vtk_cells = vtkCellArray::New(); - vtk_points->Allocate(c2t3.triangulation().number_of_vertices()); - vtk_cells->Allocate(c2t3.number_of_facets()); - std::map V; + std::unordered_map V; vtkIdType inum = 0; + for(typename C2T3::Facet_iterator + fit = c2t3.facets_begin(), + end = c2t3.facets_end(); + fit != end; ++fit) + { + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 0))] = 0; + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 1))] = 0; + V[fit->first->vertex(tr.vertex_triple_index(fit->second, 2))] = 0; + } + + vtk_points->Allocate(V.size()); + vtk_cells->Allocate(c2t3.number_of_facets()); + for(typename Triangulation::Finite_vertices_iterator vit = tr.finite_vertices_begin(), end = tr.finite_vertices_end(); vit != end; ++vit) { - typedef typename Triangulation::Point Point; - const Point& p = vit->point(); - vtk_points->InsertNextPoint(CGAL::to_double(p.x()), - CGAL::to_double(p.y()), - CGAL::to_double(p.z())); - V[vit] = inum++; + auto it = V.find(vit); + if(it != V.end()){ + typedef typename Triangulation::Point Point; + const Point& p = vit->point(); + vtk_points->InsertNextPoint(CGAL::to_double(p.x()), + CGAL::to_double(p.y()), + CGAL::to_double(p.z())); + it->second = inum++; + } } for(typename C2T3::Facet_iterator fit = c2t3.facets_begin(), diff --git a/Surface_mesher/include/CGAL/IO/facets_in_complex_2_to_triangle_mesh.h b/Surface_mesher/include/CGAL/IO/facets_in_complex_2_to_triangle_mesh.h index 0e5eb61465e..db78a6bb947 100644 --- a/Surface_mesher/include/CGAL/IO/facets_in_complex_2_to_triangle_mesh.h +++ b/Surface_mesher/include/CGAL/IO/facets_in_complex_2_to_triangle_mesh.h @@ -1,7 +1,5 @@ // Copyright (c) 2007-09 INRIA Sophia-Antipolis (France). // Copyright (c) 2017 GeometryFactory (France). - - // All rights reserved. // // This file is part of CGAL (www.cgal.org). @@ -11,6 +9,7 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // Author(s) : Maxime Gimeno, Pierre Alliez + #ifndef CGAL_FACETS_IN_COMPLEX_2_TO_TRIANGLE_MESH_H #define CGAL_FACETS_IN_COMPLEX_2_TO_TRIANGLE_MESH_H @@ -19,7 +18,7 @@ #include #include -#include +#include #include namespace CGAL{ @@ -58,6 +57,9 @@ void facets_in_complex_2_to_triangle_mesh(const C2T3& c2t3, TriangleMesh& graph) VertexPointMap vpmap = get(boost::vertex_point, graph); const typename Tr::size_type number_of_facets = c2t3.number_of_facets(); { + //used to set indices of vertices + std::unordered_map V; + // Finite vertices coordinates. Finite_facets_iterator fit = tr.finite_facets_begin(); std::set oriented_set; @@ -65,7 +67,7 @@ void facets_in_complex_2_to_triangle_mesh(const C2T3& c2t3, TriangleMesh& graph) CGAL_assertion_code(typename Tr::size_type nb_facets = 0; ) - while (oriented_set.size() != number_of_facets) { + while (oriented_set.size() != number_of_facets) { while ( fit->first->is_facet_on_surface(fit->second) == false || oriented_set.find(*fit) != oriented_set.end() || @@ -105,12 +107,17 @@ void facets_in_complex_2_to_triangle_mesh(const C2T3& c2t3, TriangleMesh& graph) (top_facet->first->vertex(tr.vertex_triple_index(top_facet->second, 0))->point().z() + top_facet->first->vertex(tr.vertex_triple_index(top_facet->second, 1))->point().z() + top_facet->first->vertex(tr.vertex_triple_index(top_facet->second, 2))->point().z())/3.; - double z = - (fit->first->vertex(tr.vertex_triple_index(fit->second, 0))->point().z() - + fit->first->vertex(tr.vertex_triple_index(fit->second, 1))->point().z() - + fit->first->vertex(tr.vertex_triple_index(fit->second, 2))->point().z())/3.; - if (top_z < z) + Vertex_handle v0 = fit->first->vertex(tr.vertex_triple_index(fit->second, 0)); + Vertex_handle v1 = fit->first->vertex(tr.vertex_triple_index(fit->second, 1)); + Vertex_handle v2 = fit->first->vertex(tr.vertex_triple_index(fit->second, 2)); + double z = (v0->point().z() + v1->point().z() + v2->point().z())/3.; + if (top_z < z){ top_facet = fit; + } + // we just put them in the map and index them later + V[v0] = 0; + V[v1] = 0; + V[v2] = 0; } // - orient the facet with max z towards +Z axis Vertex_handle v0 = top_facet->first->vertex(tr.vertex_triple_index(top_facet->second, 0)); @@ -120,8 +127,6 @@ void facets_in_complex_2_to_triangle_mesh(const C2T3& c2t3, TriangleMesh& graph) const Vector Z(0, 0, 1); bool regular_orientation = (Z * normal >= 0); - //used to set indices of vertices - std::map V; int inum = 0; //add vertices std::vector::vertex_descriptor> vertices; @@ -129,17 +134,19 @@ void facets_in_complex_2_to_triangle_mesh(const C2T3& c2t3, TriangleMesh& graph) vit != tr.finite_vertices_end(); ++vit) { - - typename boost::graph_traits::vertex_descriptor v = add_vertex(graph); - vertices.push_back(v); - put(vpmap, - v, - Point_3( - vit->point().x(), - vit->point().y(), - vit->point().z()) - ); - V.insert(std::make_pair(vit, inum++)); + auto it = V.find(vit); + if(it != V.end()){ + typename boost::graph_traits::vertex_descriptor v = add_vertex(graph); + vertices.push_back(v); + put(vpmap, + v, + Point_3( + vit->point().x(), + vit->point().y(), + vit->point().z()) + ); + it->second = inum++; + } } //add faces for(typename std::set::const_iterator fit = diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_utils.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_utils.h index c59f9ff2cf4..d3c785ea8f2 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_utils.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_utils.h @@ -22,11 +22,11 @@ * Auxiliary functions for the usage of the various sweep-line visitors. */ -#include -#include -#include #include #include + +#include +#include #include namespace CGAL { @@ -49,40 +49,30 @@ void make_x_monotone(CurveInputIter begin, CurveInputIter end, PointOutIter iso_points, const Traits* tr) { + typedef typename Traits::Point_2 Point_2; + typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; + typedef boost::variant Make_x_monotone_result; + // Split the input curves into x-monotone objects. std::size_t num_of_curves = std::distance(begin, end); - std::vector object_vec; - CurveInputIter iter; - + std::vector object_vec; object_vec.reserve(num_of_curves); - for (iter = begin; iter != end; ++iter) { + for (auto iter = begin; iter != end; ++iter) { tr->make_x_monotone_2_object()(*iter, std::back_inserter(object_vec)); } // Transform each object to either a point or an x-monotone curve. - typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; - typedef typename Traits::Point_2 Point_2; - - const X_monotone_curve_2* xcv; - const Point_2* pt; - unsigned int i; - - for (i = 0 ; i < object_vec.size() ; ++i) { - xcv = object_cast (&(object_vec[i])); - + for (const auto& obj : object_vec) { + const X_monotone_curve_2* xcv = boost::get(&obj); if (xcv != nullptr) { // The object is an x-monotone curve. - *x_curves = *xcv; - ++x_curves; - } - else { - // The object is an isolated point. - pt = object_cast (&(object_vec[i])); - CGAL_assertion (pt != nullptr); - - *iso_points = *pt; - ++iso_points; + *x_curves++ = *xcv; + continue; } + // The object is an isolated point. + const Point_2* pt = boost::get(&obj); + CGAL_assertion(pt != nullptr); + *iso_points++ = *pt; } } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h index d10fa40fe45..f849baea079 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -86,11 +87,12 @@ void update_c3t3_facets(C3t3& c3t3, } } -template +template Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, C3t3& c3t3, const std::vector& vertices_around_edge, - const Flip_Criterion& criterion) + const Flip_Criterion& criterion, + IncCellsVectorMap& inc_cells) { typedef typename C3t3::Triangulation Tr; typedef typename C3t3::Facet Facet; @@ -186,19 +188,19 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, if (criterion == MIN_ANGLE_BASED) { //Current worst dihedral angle - FT curr_min_dh = min_dihedral_angle(tr, ch0); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, ch1)); - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, cell_to_remove)); + Dihedral_angle_cosine curr_max_cosdh = max_cos_dihedral_angle(tr, ch0); + curr_max_cosdh = (std::max)(curr_max_cosdh, max_cos_dihedral_angle(tr, ch1)); + curr_max_cosdh = (std::max)(curr_max_cosdh, max_cos_dihedral_angle(tr, cell_to_remove)); //Result worst dihedral angle - if (curr_min_dh > min_dihedral_angle(tr, vh2, + if (curr_max_cosdh < max_cos_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - || curr_min_dh > min_dihedral_angle(tr, vh3, - ch1->vertex(indices(vh1_id, 0)), - ch1->vertex(indices(vh1_id, 1)), - ch1->vertex(indices(vh1_id, 2)))) + || curr_max_cosdh < max_cos_dihedral_angle(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) return NO_BEST_CONFIGURATION; } else if (criterion == AVERAGE_ANGLE_BASED) @@ -214,7 +216,7 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, (min_dihedral_angle(tr, vh2, ch0->vertex(indices(vh0_id, 0)), ch0->vertex(indices(vh0_id, 1)), ch0->vertex(indices(vh0_id, 2))) - + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), + + min_dihedral_angle(tr, vh3, ch1->vertex(indices(vh1_id, 0)), ch1->vertex(indices(vh1_id, 1)), ch1->vertex(indices(vh1_id, 2)))); //Result worst dihedral angle @@ -312,6 +314,9 @@ Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, ch->set_neighbor(v, mirror_facet.first); } ch->vertex(v)->set_cell(ch); + + inc_cells[ch->vertex(v)] = boost::none; + ch->reset_cache_validity(); } } @@ -372,7 +377,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, typename C3t3::Vertex_handle vh2, typename C3t3::Vertex_handle vh3, CandidatesQueue& candidates, - double curr_min_dh, + const Dihedral_angle_cosine& curr_max_cos_dh, bool is_sliver_well_oriented = true, int e_id = 0) { @@ -382,8 +387,6 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, typedef typename C3t3::Facet Facet; typedef typename Tr::Facet_circulator Facet_circulator; typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; // std::cout << "find_best_flip_to_improve_dh boundary " << std::endl; Tr& tr = c3t3.triangulation(); @@ -451,12 +454,12 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, Cell_circulator cell_circulator = tr.incident_cells(edge); Cell_circulator done = cell_circulator; + boost::container::small_vector facets; for (std::size_t i = 0; i < opposite_vertices.size(); ++i) { Vertex_handle vh = opposite_vertices[i]; bool keep = true; - std::vector facets; do { //Store it if it do not have vh @@ -474,7 +477,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, } while (++cell_circulator != done); - FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + Dihedral_angle_cosine max_flip_cos_dh(CGAL::NEGATIVE, 1., 1.); for (const Facet& fi : facets) { if (!tr.is_infinite(fi.first)) @@ -483,32 +486,75 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) { - min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); + max_flip_cos_dh = (std::max)( + max_flip_cos_dh, + max_cos_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); } else { keep = false; break; } + + if (max_flip_cos_dh.is_one())//it will not get worse than 1. + { + keep = false; + break; + } } } + facets.clear(); - if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) + if (keep && (max_flip_cos_dh < curr_max_cos_dh || !is_sliver_well_oriented)) { - //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; - candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); + //std::cout << "vh " << vh->info() <<" old " << curr_max_cos_dh << " min " << min_flip_tan_dh << std::endl; + candidates.push(std::make_pair(max_flip_cos_dh, std::make_pair(vh, e_id))); } } } -template +template +bool is_edge_uv(Vertex_handle u, + Vertex_handle v, + const CellVector& cells_incident_to_u, + Cell_handle& cell, + int& i, + int& j) +{ + if (u == v) + return false; + + for (typename CellVector::value_type c : cells_incident_to_u) + { + if (c->has_vertex(v, j)) + { + cell = c; + i = cell->index(u); + return true; + } + } + return false; +} + +template +bool is_edge_uv(Vertex_handle u, + Vertex_handle v, + const CellVector& cells_incident_to_u) +{ + typename CellVector::value_type c; + int i, j; + return is_edge_uv(u, v, cells_incident_to_u, c, i, j); +} + +template void find_best_flip_to_improve_dh(C3t3& c3t3, typename C3t3::Edge& edge, CandidatesQueue& candidates, - double curr_min_dh, + const Dihedral_angle_cosine& curr_max_cosdh, + IncCellsVectorMap& inc_cells, bool is_sliver_well_oriented = true, int e_id = 0) { @@ -518,8 +564,6 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, typedef typename C3t3::Facet Facet; typedef typename Tr::Facet_circulator Facet_circulator; typedef typename Tr::Cell_circulator Cell_circulator; - typedef typename Tr::Geom_traits Gt; - typedef typename Gt::FT FT; Tr& tr = c3t3.triangulation(); @@ -547,6 +591,17 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, } } + if(tr.is_infinite(vh)) + continue; + + boost::optional>& o_inc_vh = inc_cells[vh]; + if (o_inc_vh == boost::none) + { + boost::container::small_vector inc_vec; + tr.incident_cells(vh, std::back_inserter(inc_vec)); + o_inc_vh = inc_vec; + } + Facet_circulator facet_circulator = curr_fcirc; Facet_circulator facet_done = curr_fcirc; @@ -563,15 +618,16 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, indices(facet_circulator->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { - Cell_handle ch; - int i0, i1; - if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + if (is_edge_uv(vh, curr_vertex, boost::get(o_inc_vh))) + { is_edge = true; + break; + } } } } while (++facet_circulator != facet_done); - if (!is_edge && !tr.is_infinite(vh)) + if (!is_edge) opposite_vertices.push_back(vh); nb_cells_around_edge++; @@ -589,12 +645,10 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, Cell_circulator cell_circulator = tr.incident_cells(edge); Cell_circulator done = cell_circulator; - for (std::size_t i = 0; i < opposite_vertices.size(); ++i) + boost::container::small_vector facets; + for (Vertex_handle vh : opposite_vertices) { - Vertex_handle vh = opposite_vertices[i]; bool keep = true; - - std::vector facets; do { //Store it if it do not have vh @@ -612,7 +666,7 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, } while (++cell_circulator != done); - FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + Dihedral_angle_cosine max_flip_cos_dh(CGAL::NEGATIVE, 1., 1.); for (const Facet& fi : facets) { if (!tr.is_infinite(fi.first)) @@ -621,31 +675,39 @@ void find_best_flip_to_improve_dh(C3t3& c3t3, fi.first->vertex(indices(fi.second, 1)), fi.first->vertex(indices(fi.second, 2)))) { - min_flip_dihedral_angle = (std::min)(min_flip_dihedral_angle, - min_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), - fi.first->vertex(indices(fi.second, 1)), - fi.first->vertex(indices(fi.second, 2)))); + max_flip_cos_dh = (std::max)(max_flip_cos_dh, + max_cos_dihedral_angle(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))); } else { keep = false; break; } + + if (max_flip_cos_dh.is_one())//it will not get worse than 1. + { + keep = false; + break; + } } } + facets.clear(); - if (keep && (curr_min_dh < min_flip_dihedral_angle || !is_sliver_well_oriented)) + if (keep && (max_flip_cos_dh < curr_max_cosdh || !is_sliver_well_oriented)) { - //std::cout << "vh " << vh->info() <<" old " << curr_min_dh << " min " << min_flip_dihedral_angle << std::endl; - candidates.push(std::make_pair(min_flip_dihedral_angle, std::make_pair(vh, e_id))); + //std::cout << "vh " << vh->info() <<" old " << curr_max_cosdh << " min " << min_flip_tan_dh << std::endl; + candidates.push(std::make_pair(max_flip_cos_dh, std::make_pair(vh, e_id))); } } } -template +template Sliver_removal_result flip_n_to_m(C3t3& c3t3, typename C3t3::Edge& edge, typename C3t3::Vertex_handle vh, + IncCellsVectorMap& inc_cells, Visitor& visitor, bool check_validity = false) { @@ -693,7 +755,14 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, facet_circulator++; facet_circulator++; - std::vector vertices_around_edge; + boost::optional>& o_inc_vh = inc_cells[vh]; + if (o_inc_vh == boost::none) + { + boost::container::small_vector inc_vec; + tr.incident_cells(vh, std::back_inserter(inc_vec)); + o_inc_vh = inc_vec; + } + do { //Get the ids of the opposite vertices @@ -703,18 +772,13 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, indices(facet_circulator->second, i)); if (curr_vertex != vh0 && curr_vertex != vh1) { - Cell_handle ch; - int i0, i1; - if (tr.is_edge(curr_vertex, vh, ch, i0, i1)) + if (is_edge_uv(vh, curr_vertex, boost::get(o_inc_vh))) return NOT_FLIPPABLE; - - vertices_around_edge.push_back(curr_vertex); } } } while (++facet_circulator != facet_done); - std::vector cells_around_edge; boost::container::small_vector to_remove; //Neighbors that will need to be updated after flip @@ -733,8 +797,6 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, Cell_circulator done = cell_circulator; do { - cells_around_edge.push_back(cell_circulator); - //Facets opposite to vh0 Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); neighbor_facets.insert(tr.mirror_facet(facet_vh0)); @@ -877,6 +939,9 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, ch->set_neighbor(v, facet.first); } ch->vertex(v)->set_cell(ch); + + inc_cells[ch->vertex(v)] = boost::none; + ch->reset_cache_validity(); } } @@ -943,54 +1008,61 @@ Sliver_removal_result flip_n_to_m(C3t3& c3t3, } -template +template Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, C3t3& c3t3, - std::vector& boundary_vertices, + const std::vector& boundary_vertices, const Flip_Criterion& criterion, + IncCellsVectorMap& inc_cells, Visitor& visitor) { typedef typename C3t3::Vertex_handle Vertex_handle; typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; - typedef typename C3t3::Triangulation::Geom_traits Gt; - typedef typename Gt::FT FT; typename C3t3::Triangulation& tr = c3t3.triangulation(); Sliver_removal_result result = NOT_FLIPPABLE; - typedef std::pair > Angle_and_vertex; + typedef std::pair > CosAngle_and_vertex; //std::cout << "n_to_m_flip " << boundary_vertices.size() << std::endl; if (criterion == MIN_ANGLE_BASED) { - std::priority_queue candidates; + std::priority_queue, + std::greater + > candidates; Cell_circulator circ = c3t3.triangulation().incident_cells(edge); Cell_circulator done = circ; - FT curr_min_dh = min_dihedral_angle(tr, circ++); + Dihedral_angle_cosine curr_max_cosdh = max_cos_dihedral_angle(tr, circ++); while (circ != done) { - curr_min_dh = (std::min)(curr_min_dh, min_dihedral_angle(tr, circ++)); + curr_max_cosdh = (std::max)(curr_max_cosdh, max_cos_dihedral_angle(tr, circ++)); } if (boundary_vertices.size() == 2) find_best_flip_to_improve_dh(c3t3, edge, boundary_vertices[0], boundary_vertices[1], - candidates, curr_min_dh); + candidates, curr_max_cosdh); else - find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_min_dh); + find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_max_cosdh, + inc_cells); bool flip_performed = false; while (!candidates.empty() && !flip_performed) { - Angle_and_vertex curr_cost_vpair = candidates.top(); + CosAngle_and_vertex curr_cost_vpair = candidates.top(); candidates.pop(); - //std::cout << curr_min_dh << " old, current " << curr_cost_vpair.second.first->info() <<" and angle " << curr_cost_vpair.first << std::endl; +// std::cout << "\tcurrent cos = " << curr_max_cosdh +// << "\t angle = " << std::acos(curr_max_cosdh) * 180./CGAL_PI << std::endl; +// std::cout << "\tcandidate cos = " << curr_cost_vpair.first +// << "\t angle = " << std::acos(curr_cost_vpair.first) * 180./CGAL_PI << std::endl; +// std::cout << std::endl; - if (curr_min_dh >= curr_cost_vpair.first) + if (curr_max_cosdh <= curr_cost_vpair.first) return NO_BEST_CONFIGURATION; - result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, visitor); + result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, inc_cells, visitor); if (result != NOT_FLIPPABLE) flip_performed = true; @@ -1000,10 +1072,11 @@ Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, return result; } -template +template Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, C3t3& c3t3, const Flip_Criterion& criterion, + IncCellsVectorMap& inc_cells, Visitor& visitor) { typedef typename C3t3::Triangulation Tr; @@ -1066,7 +1139,7 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, { std::vector vertices; vertices.insert(vertices.end(), vertices_around_edge.begin(), vertices_around_edge.end()); - res = flip_3_to_2(edge, c3t3, vertices, criterion); + res = flip_3_to_2(edge, c3t3, vertices, criterion, inc_cells); } } else @@ -1078,12 +1151,11 @@ Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, { std::vector vertices; vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); - res = flip_n_to_m(edge, c3t3, vertices, criterion, visitor); + res = flip_n_to_m(edge, c3t3, vertices, criterion, inc_cells, visitor); //return n_to_m_flip(edge, boundary_vertices, flip_criterion); } } - return res; } @@ -1096,20 +1168,33 @@ std::size_t flip_all_edges(const std::vector& edges, { typedef typename C3t3::Triangulation Tr; typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Edge Edge; Tr& tr = c3t3.triangulation(); + std::unordered_map > > inc_cells; + std::size_t count = 0; - for (const VertexPair vp : edges) + for (const VertexPair& vp : edges) { + boost::optional>& + o_inc_vh = inc_cells[vp.first]; + if (o_inc_vh == boost::none) + { + boost::container::small_vector inc_vec; + tr.incident_cells(vp.first, std::back_inserter(inc_vec)); + o_inc_vh = inc_vec; + } + Cell_handle ch; int i0, i1; - if (tr.is_edge(vp.first, vp.second, ch, i0, i1)) + if (is_edge_uv(vp.first, vp.second, boost::get(o_inc_vh), ch, i0, i1)) { Edge edge(ch, i0, i1); - Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, visitor); + Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, inc_cells, visitor); if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) { std::cout << "FLIP PROBLEM!!!!" << std::endl; @@ -1126,6 +1211,10 @@ std::size_t flip_all_edges(const std::vector& edges, } } } + + for(Cell_handle c : c3t3.triangulation().finite_cell_handles()) + c->reset_cache_validity(); + return count; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h index fc9cf93d1dc..1d94ef35e1d 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -328,7 +328,12 @@ private: bool check_inversion_and_move(const typename Tr::Vertex_handle v, const typename Tr::Point& final_pos, const CellRange& inc_cells, - const Tr& /* tr */) + const Tr& /* tr */, +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + double& total_move) +#else + double&) +#endif { const typename Tr::Point backup = v->point(); //backup v's position const typename Tr::Geom_traits::Point_3 pv = point(backup); @@ -336,6 +341,7 @@ private: bool valid_orientation = false; double frac = 1.0; typename Tr::Geom_traits::Vector_3 move(pv, point(final_pos)); + do { v->set_point(typename Tr::Point(pv + frac * move)); @@ -354,15 +360,17 @@ private: } } valid_orientation = valid_try; - -// std::cout << std::boolalpha << "valid orientation = " << valid_orientation -// << "\tfrac = " << frac << std::endl; } while(!valid_orientation && frac > 0.1); if (!valid_orientation) //move failed v->set_point(backup); +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + else + total_move += CGAL::approximate_sqrt(CGAL::squared_distance(pv, point(v->point()))); +#endif + return valid_orientation; } @@ -407,7 +415,10 @@ public: std::cout << "Smooth vertices..."; std::cout.flush(); #endif - std::size_t nb_done = 0; + std::size_t nb_done_3d = 0; + std::size_t nb_done_2d = 0; + std::size_t nb_done_1d = 0; + FT total_move = 0.; Tr& tr = c3t3.triangulation(); @@ -521,8 +532,8 @@ public: #endif // move vertex const typename Tr::Point new_pos(final_position.x(), final_position.y(), final_position.z()); - if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr)) - nb_done++; + if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr, total_move)) + nb_done_1d++; } else if (neighbors[vid] > 0) { @@ -532,7 +543,7 @@ public: const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); const std::vector& v_surface_indices = vertices_surface_indices[v]; - for (const Surface_patch_index si : v_surface_indices) + for (const Surface_patch_index& si : v_surface_indices) { //Check if the mls surface exists to avoid degenerated cases @@ -555,8 +566,8 @@ public: #endif // move vertex const typename Tr::Point new_pos(final_position.x(), final_position.y(), final_position.z()); - if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr)) - nb_done++; + if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr, total_move)) + nb_done_1d++; } } } @@ -628,8 +639,8 @@ public: os_surf << "2 " << current_pos << " " << final_position << std::endl; #endif const typename Tr::Point new_pos(final_position.x(), final_position.y(), final_position.z()); - if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr)) - nb_done++; + if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr, total_move)) + nb_done_2d++; } else if (neighbors[vid] > 0) { @@ -641,8 +652,8 @@ public: if (boost::optional mls_projection = project(si, current_pos)) { const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); - if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr)) - nb_done++; + if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr, total_move)) + nb_done_2d++; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; @@ -693,8 +704,8 @@ public: #endif const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); typename Tr::Point new_pos(p.x(), p.y(), p.z()); - if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr)) - nb_done++; + if(check_inversion_and_move(v, new_pos, inc_cells[vid], tr, total_move)) + nb_done_3d++; #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG os_vol << " " << point(v->point()) << std::endl; @@ -704,7 +715,11 @@ public: CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << " done (" << nb_done << " vertices smoothed)." << std::endl; + std::size_t nb_done = nb_done_3d + nb_done_2d + nb_done_1d; + std::cout << " done (" + << nb_done_3d << "/" << nb_done_2d << "/" << nb_done_1d << " vertices smoothed," + << " average move = " << (total_move / nb_done) + << ")." << std::endl; #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h index fb942deddcf..9a76b54a9f8 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -368,8 +368,18 @@ public: CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "99-postprocess"); #endif #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE - std::cout << "(peeling removed " << nb_slivers_peel << " slivers)" << std::endl; - std::cout << "done." << std::endl; + mindh = 180.; + for (Cell_handle cit : tr().finite_cell_handles()) + { + if (m_c3t3.is_in_complex(cit)) + { + const double dh = min_dihedral_angle(tr(), cit); + mindh = (std::min)(dh, mindh); + } + } + std::cout << "Peeling done (removed " << nb_slivers_peel << " slivers, " + << "min dihedral angle = " << mindh << ")." << std::endl; + #endif return nb_slivers_peel; } diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h index ca81c66489d..cb83de5a777 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -98,7 +98,7 @@ typename Geom_traits::FT min_dihedral_angle(const Point& p, FT a = CGAL::abs(dihedral_angle(p, q, r, s, gt)); FT min_dh = a; - a = CGAL::abs(dihedral_angle(p, r, q, s, gt)); + a = CGAL::abs(dihedral_angle(p, r, s, q, gt)); min_dh = (std::min)(a, min_dh); a = CGAL::abs(dihedral_angle(p, s, q, r, gt)); @@ -107,7 +107,7 @@ typename Geom_traits::FT min_dihedral_angle(const Point& p, a = CGAL::abs(dihedral_angle(q, r, p, s, gt)); min_dh = (std::min)(a, min_dh); - a = CGAL::abs(dihedral_angle(q, s, p, r, gt)); + a = CGAL::abs(dihedral_angle(q, s, r, p, gt)); min_dh = (std::min)(a, min_dh); a = CGAL::abs(dihedral_angle(r, s, p, q, gt)); @@ -141,6 +141,179 @@ typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, c->vertex(3)); } +struct Dihedral_angle_cosine +{ + CGAL::Sign m_sgn; + double m_sq_num; + double m_sq_den; + + Dihedral_angle_cosine(const CGAL::Sign& sgn, const double& sq_num, const double& sq_den) + : m_sgn(sgn) + , m_sq_num(sq_num) + , m_sq_den(sq_den) + {} + + bool is_one() const + { + return m_sgn == CGAL::POSITIVE && m_sq_num == m_sq_den; + } + double signed_square_value() const + { + switch(m_sgn) + { + case CGAL::POSITIVE: + return m_sq_num / m_sq_den; + case CGAL::ZERO: + return 0.; + default: + CGAL_assertion(m_sgn == CGAL::NEGATIVE); + return -1. * m_sq_num / m_sq_den; + }; + } + + friend bool operator<(const Dihedral_angle_cosine& l, + const Dihedral_angle_cosine& r) + { + //if numerators have different signs + if (l.m_sgn == CGAL::NEGATIVE && r.m_sgn != CGAL::NEGATIVE) + return true; + + else if (l.m_sgn == CGAL::POSITIVE && r.m_sgn != CGAL::POSITIVE) + return false; + + else if (l.m_sgn == CGAL::ZERO) + return (r.m_sgn == CGAL::POSITIVE); + + //else numerators have the same sign + else if (l.m_sgn == CGAL::POSITIVE) //both angles are in [0; PI/2[ + { + CGAL_assertion(r.m_sgn == CGAL::POSITIVE); + + return (l.m_sq_num * r.m_sq_den < r.m_sq_num* l.m_sq_den); + } + else //both angles are in [PI/2; PI] + { + CGAL_assertion(l.m_sgn != CGAL::POSITIVE); + CGAL_assertion(r.m_sgn != CGAL::POSITIVE); + + return (l.m_sq_num * r.m_sq_den >= r.m_sq_num* l.m_sq_den); + } + } + + friend bool operator<=(const Dihedral_angle_cosine& l, + const Dihedral_angle_cosine& r) + { + if(l < r) + return true; + else + return l.m_sgn == r.m_sgn + && l.m_sq_num * r.m_sq_den == r.m_sq_num * l.m_sq_den; + } +}; + +template +Dihedral_angle_cosine cos_dihedral_angle(const typename Gt::Point_3& i, + const typename Gt::Point_3& j, + const typename Gt::Point_3& k, + const typename Gt::Point_3& l, + const Gt& gt) +{ + CGAL_assertion(CGAL::orientation(i, j, k, l) != CGAL::NEGATIVE); + + typename Gt::Construct_vector_3 vector = gt.construct_vector_3_object(); + typename Gt::Construct_cross_product_vector_3 cross_product = + gt.construct_cross_product_vector_3_object(); + typename Gt::Compute_scalar_product_3 scalar_product = + gt.compute_scalar_product_3_object(); + + typedef typename Gt::FT FT; + typedef typename Gt::Vector_3 Vector_3; + const Vector_3 ij = vector(i, j); + const Vector_3 ik = vector(i, k); + const Vector_3 il = vector(i, l); + + const Vector_3 ijik = cross_product(ij, ik); + if(CGAL::NULL_VECTOR == ijik) + return Dihedral_angle_cosine(CGAL::POSITIVE, 1.,1.); + + const Vector_3 ilij = cross_product(il, ij); + if (CGAL::NULL_VECTOR == ilij) + return Dihedral_angle_cosine(CGAL::POSITIVE, 1.,1.); + + const FT num = scalar_product(ijik, ilij); + if(num == 0.) + return Dihedral_angle_cosine(CGAL::ZERO, 0.,1.); + + const double sqden = CGAL::to_double( + scalar_product(ijik, ijik) * scalar_product(ilij, ilij)); + + return Dihedral_angle_cosine(CGAL::sign(num), CGAL::square(num), sqden); +} + +template +Dihedral_angle_cosine max_cos_dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Geom_traits& gt) +{ + Dihedral_angle_cosine a = cos_dihedral_angle(p, q, r, s, gt); + Dihedral_angle_cosine max_cos_dh = a; + if(max_cos_dh.is_one()) return max_cos_dh; + + a = cos_dihedral_angle(p, r, s, q, gt); + if(max_cos_dh < a) max_cos_dh = a; + if (max_cos_dh.is_one()) return max_cos_dh; + + a = cos_dihedral_angle(p, s, q, r, gt); + if (max_cos_dh < a) max_cos_dh = a; + if (max_cos_dh.is_one()) return max_cos_dh; + + a = cos_dihedral_angle(q, r, p, s, gt); + if (max_cos_dh < a) max_cos_dh = a; + if (max_cos_dh.is_one()) return max_cos_dh; + + a = cos_dihedral_angle(q, s, r, p, gt); + if (max_cos_dh < a) max_cos_dh = a; + if (max_cos_dh.is_one()) return max_cos_dh; + + a = cos_dihedral_angle(r, s, p, q, gt); + if (max_cos_dh < a) max_cos_dh = a; + + return max_cos_dh; +} + +template +Dihedral_angle_cosine max_cos_dihedral_angle(const Tr& tr, + const typename Tr::Vertex_handle v0, + const typename Tr::Vertex_handle v1, + const typename Tr::Vertex_handle v2, + const typename Tr::Vertex_handle v3) +{ + return max_cos_dihedral_angle(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point()), + tr.geom_traits()); +} + +template +Dihedral_angle_cosine max_cos_dihedral_angle(const Tr& tr, + const typename Tr::Cell_handle c) +{ + if (c->is_cache_valid()) + return Dihedral_angle_cosine(CGAL::sign(c->sliver_value()), + CGAL::abs(c->sliver_value()), 1.); + + Dihedral_angle_cosine cos_dh = max_cos_dihedral_angle(tr, + c->vertex(0), + c->vertex(1), + c->vertex(2), + c->vertex(3)); + c->set_sliver_value(cos_dh.signed_square_value()); + return cos_dh; +} + template bool is_peelable(const C3t3& c3t3, const typename C3t3::Cell_handle ch, @@ -955,7 +1128,7 @@ void dump_edges(const Bimap& edges, const char* filename) std::ofstream ofs(filename); ofs.precision(17); - BOOST_FOREACH(typename Bimap::left_const_reference it, edges.left) + for(typename Bimap::left_const_reference it : edges.left) { ofs << "2 " << point(it.first.first->point()) << " " << point(it.first.second->point()) << std::endl; diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h index cda012efc51..d09a0f42edf 100644 --- a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -10,6 +10,11 @@ // // Author(s) : Jane Tournois, Noura Faraj, Jean-Marc Thiery, Tamy Boubekeur +#ifndef CGAL_TETRAHEDRAL_REMESHING_IO_H +#define CGAL_TETRAHEDRAL_REMESHING_IO_H + +#include + #include #include @@ -52,4 +57,6 @@ bool save_ascii_triangulation(std::ostream& os, const T3& t3) return !!(os << t3); } -} \ No newline at end of file +} + +#endif // CGAL_TETRAHEDRAL_REMESHING_IO_H diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h index 115f735f128..b1818bbded1 100644 --- a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -244,12 +244,12 @@ void tetrahedral_isotropic_remeshing( No_facet()); typedef typename internal_np::Lookup_named_param_def < - internal_np::remeshing_visitor_t, + internal_np::visitor_t, NamedParameters, Tetrahedral_remeshing::internal::Default_remeshing_visitor > ::type Visitor; Visitor visitor - = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + = choose_parameter(get_parameter(np, internal_np::visitor), Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE @@ -439,12 +439,12 @@ void tetrahedral_isotropic_remeshing( No_facet()); typedef typename internal_np::Lookup_named_param_def < - internal_np::remeshing_visitor_t, + internal_np::visitor_t, NamedParameters, Tetrahedral_remeshing::internal::Default_remeshing_visitor > ::type Visitor; Visitor visitor - = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + = choose_parameter(get_parameter(np, internal_np::visitor), Tetrahedral_remeshing::internal::Default_remeshing_visitor()); #ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE diff --git a/Three/include/CGAL/Three/Scene_draw_interface.h b/Three/include/CGAL/Three/Scene_draw_interface.h index 401e6ca55fc..20701144d44 100644 --- a/Three/include/CGAL/Three/Scene_draw_interface.h +++ b/Three/include/CGAL/Three/Scene_draw_interface.h @@ -61,7 +61,7 @@ public: * \param z the Z coordinate of theTextItem's position. * \param viewer the viewer used to display the Scene. * \return true if the TextItem is visible. */ - virtual bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer) = 0; + virtual bool testDisplayId(double x, double y, double z, CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler) = 0; ///\brief displays all the vertices ids if there are less than max_textItems. virtual void printVertexIds() = 0; diff --git a/Three/include/CGAL/Three/Scene_print_item_interface.h b/Three/include/CGAL/Three/Scene_print_item_interface.h index 7a36ee942a4..dba3a8eec77 100644 --- a/Three/include/CGAL/Three/Scene_print_item_interface.h +++ b/Three/include/CGAL/Three/Scene_print_item_interface.h @@ -48,7 +48,7 @@ public: //! //! \returns true if the Id should be displayed //! \returns false if the Id should not be displayed (if it is hidden for example) - virtual bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*)const = 0; + virtual bool testDisplayId(double, double, double, CGAL::Three::Viewer_interface*, const QVector3D& scaler)const = 0; //! \brief tests if this item should display its ids. //! diff --git a/Three/include/CGAL/Three/TextRenderer.h b/Three/include/CGAL/Three/TextRenderer.h index 8b0b7d41c07..61c146718b9 100644 --- a/Three/include/CGAL/Three/TextRenderer.h +++ b/Three/include/CGAL/Three/TextRenderer.h @@ -139,7 +139,7 @@ public: { } //!Draws all the `TextItem`s - void draw(CGAL::Three::Viewer_interface* viewer); + void draw(CGAL::Three::Viewer_interface* viewer, const QVector3D& scaler); //!\brief Adds a single TextItem to TextRenderer::local_textItems //! //! @see addText(float p_x, float p_y, float p_z, QString p_text, bool p_3D = true, QFont font = QFont(), QColor p_color = Qt::black) diff --git a/Triangulation/include/CGAL/Triangulation_full_cell.h b/Triangulation/include/CGAL/Triangulation_full_cell.h index 66250784d89..b806ab6baf4 100644 --- a/Triangulation/include/CGAL/Triangulation_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_full_cell.h @@ -42,7 +42,7 @@ public: typedef typename TriangulationTraits::Point_d Point_d; private: // DATA MEMBERS - Data data_; + CGAL_NO_UNIQUE_ADDRESS Data data_; public: diff --git a/Triangulation/include/CGAL/Triangulation_vertex.h b/Triangulation/include/CGAL/Triangulation_vertex.h index 99910d52dfc..5cbbeb76977 100644 --- a/Triangulation/include/CGAL/Triangulation_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_vertex.h @@ -45,7 +45,7 @@ public: private: // DATA MEMBERS Point point_; - Data data_; + CGAL_NO_UNIQUE_ADDRESS Data data_; public: template< typename T > diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index 3f73f238eae..88e246f0f85 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -2976,9 +2976,9 @@ exact_locate(const Point& p, Face_handle start) const #endif // no CGAL_NO_STRUCTURAL_FILTERING { + li = 4; //general init to avoid warnings. + lt = OUTSIDE_AFFINE_HULL; //same if (dimension() < 0) { - lt = OUTSIDE_AFFINE_HULL; - li = 4; // li should not be used in this case return Face_handle(); } if( dimension() == 0) { @@ -2987,10 +2987,6 @@ exact_locate(const Point& p, if (xy_equal(p,finite_vertex()->face()->vertex(0)->point())){ lt = VERTEX ; } - else{ - lt = OUTSIDE_AFFINE_HULL; - } - li = 4; // li should not be used in this case return Face_handle(); } if(dimension() == 1){ diff --git a/Triangulation_3/include/CGAL/Robust_weighted_circumcenter_filtered_traits_3.h b/Triangulation_3/include/CGAL/Robust_weighted_circumcenter_filtered_traits_3.h index 4e8f9ebc2a1..d57b548a793 100644 --- a/Triangulation_3/include/CGAL/Robust_weighted_circumcenter_filtered_traits_3.h +++ b/Triangulation_3/include/CGAL/Robust_weighted_circumcenter_filtered_traits_3.h @@ -49,27 +49,7 @@ public: traits(k) { } -#ifndef CGAL_CFG_MATCHING_BUG_6 using Base::operator(); -#else // CGAL_CFG_MATCHING_BUG_6 - typedef typename Kernel::Sphere_3 Sphere_3; - typedef typename Kernel::Circle_3 Circle_3; - - result_type operator()(const Sphere_3& s) const - { return this->Base::operator()(s); } - - result_type operator()(const Circle_3& c) const - { return this->Base::operator()(c); } - - result_type operator()(const Point_3& p, const Point_3& q, const Point_3& r) const - { return this->Base::operator()(p,q,r); } - - result_type operator()(const Point_3& p, const Point_3& q) const - { return this->Base::operator()(p,q); } - - result_type operator()(const Point_3& p) const - { return this->Base::operator()(p); } -#endif // CGAL_CFG_MATCHING_BUG_6 FT operator()(const Point_3& p, const Point_3& q,