diff --git a/.gitattributes b/.gitattributes index 35a3066ee9c..ccb9bc4d4b5 100644 --- a/.gitattributes +++ b/.gitattributes @@ -18,7 +18,6 @@ *.js text *.hmtl text *.bib text -*.sh text *.css text *.ui text *.qrc text @@ -36,6 +35,7 @@ *.pdb text # Declare files that will always have LF line endings on checkout. +*.sh text eol=lf Documentation/Doxyfile text eol=lf Documentation/pkglist_filter text eol=lf Installation/update_CHANGES text eol=lf diff --git a/.travis.yml b/.travis.yml index 67ef61cbf57..26946424096 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,34 @@ sudo: required git: depth: 3 env: + matrix: + PACKAGES_MATRIX + +compiler: clang +install: + - echo "$PWD" + - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh + - export CXX=clang++ CC=clang; +before_script: + - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe + - sudo mv doxygen_exe /usr/bin/doxygen + - sudo chmod +x /usr/bin/doxygen + - mkdir -p build + - cd build + - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. + - /usr/bin/time -f 'Spend time of %C -- %E (real)' make + - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null + - cd .. +script: + - cd ./.travis + - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE +notifications: + email: + on_success: change + # default: always + on_failure: always + # default: always matrix: - PACKAGE='CHECK' - PACKAGE='AABB_tree Advancing_front_surface_reconstruction Algebraic_foundations ' @@ -49,32 +77,7 @@ env: - PACKAGE='Surface_mesh_parameterization Surface_mesh_segmentation Surface_mesh_shortest_path ' - PACKAGE='Surface_mesh_simplification Surface_mesh_skeletonization Surface_mesh_topology ' - PACKAGE='Surface_mesher Surface_sweep_2 TDS_2 ' - - PACKAGE='TDS_3 Testsuite Three ' - - PACKAGE='Triangulation Triangulation_2 Triangulation_3 ' - - PACKAGE='Union_find Visibility_2 Voronoi_diagram_2 ' - - PACKAGE='wininst ' -compiler: clang -install: - - echo "$PWD" - - if [ -n "$TRAVIS_PULL_REQUEST_BRANCH" ] && [ "$PACKAGE" != CHECK ]; then DO_IGNORE=FALSE; for ARG in $(echo "$PACKAGE");do if [ "$ARG" = "Maintenance" ]; then continue; fi; . $PWD/.travis/test_package.sh "$PWD" "$ARG"; echo "DO_IGNORE is $DO_IGNORE"; if [ "$DO_IGNORE" = "FALSE" ]; then break; fi; done; if [ "$DO_IGNORE" = "TRUE" ]; then travis_terminate 0; fi;fi - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash .travis/install.sh - - export CXX=clang++ CC=clang; -before_script: - - wget -O doxygen_exe https://cgal.geometryfactory.com/~mgimeno/doxygen_exe - - sudo mv doxygen_exe /usr/bin/doxygen - - sudo chmod +x /usr/bin/doxygen - - mkdir -p build - - cd build - - /usr/bin/time -f 'Spend time of %C -- %E (real)' cmake -DCMAKE_CXX_FLAGS="-std=c++1y" -DCGAL_HEADER_ONLY=ON -DCMAKE_CXX_FLAGS_RELEASE=-DCGAL_NDEBUG -DWITH_examples=ON -DWITH_demos=ON -DWITH_tests=ON .. - - /usr/bin/time -f 'Spend time of %C -- %E (real)' make - - /usr/bin/time -f 'Spend time of %C -- %E (real)' sudo make install &>/dev/null - - cd .. -script: - - cd ./.travis - - /usr/bin/time -f 'Spend time of %C -- %E (real)' bash ./build_package.sh $PACKAGE -notifications: - email: - on_success: change - # default: always - on_failure: always - # default: always + - PACKAGE='TDS_3 Testsuite Tetrahedral_remeshing ' + - PACKAGE='Three Triangulation Triangulation_2 ' + - PACKAGE='Triangulation_3 Union_find Visibility_2 ' + - PACKAGE='Voronoi_diagram_2 wininst ' diff --git a/.travis/build_package.sh b/.travis/build_package.sh index 7fbe3c29aa2..cb046d1e29f 100755 --- a/.travis/build_package.sh +++ b/.travis/build_package.sh @@ -28,7 +28,7 @@ function build_demo { EXTRA_CXX_FLAGS="-Werror=inconsistent-missing-override" ;; esac - mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. + mytime cmake -DCGAL_DIR="/usr/local/lib/cmake/CGAL" -DCGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=ON -DCMAKE_CXX_FLAGS="${CXX_FLAGS} ${EXTRA_CXX_FLAGS}" .. mytime make -j2 VERBOSE=1 } old_IFS=$IFS @@ -57,41 +57,41 @@ cd $ROOT cd .. IFS=$old_IFS mytime zsh $ROOT/Scripts/developer_scripts/test_merge_of_branch HEAD - #test dependencies + #test dependencies cd $ROOT mytime bash Scripts/developer_scripts/cgal_check_dependencies.sh --check_headers /usr/bin/doxygen cd .travis - #parse current matrix and check that no package has been forgotten + #parse current matrix and check that no package has been forgotten - IFS=$'\n' - COPY=0 - MATRIX=() - for LINE in $(cat "$PWD/packages.txt") - do - MATRIX+="$LINE " - done - - PACKAGES=() - cd .. - for f in * - do - if [ -d "$f/package_info/$f" ] - then - PACKAGES+="$f " - fi - done - - DIFFERENCE=$(echo ${MATRIX[@]} ${PACKAGES[@]} | tr ' ' '\n' | sort | uniq -u) - IFS=$' ' - if [ "${DIFFERENCE[0]}" != "" ] - then - echo "The matrix and the actual package list differ : ." - echo ${DIFFERENCE[*]} + IFS=$'\n' + COPY=0 + MATRIX=() + for LINE in $(cat "$PWD/packages.txt") + do + MATRIX+="$LINE " + done + + PACKAGES=() + cd .. + for f in * + do + if [ -d "$f/package_info/$f" ] + then + PACKAGES+="$f " + fi + done + + DIFFERENCE=$(echo ${MATRIX[@]} ${PACKAGES[@]} | tr ' ' '\n' | sort | uniq -u) + IFS=$' ' + if [ "${DIFFERENCE[0]}" != "" ] + then + echo "The matrix and the actual package list differ : ." + echo ${DIFFERENCE[*]} echo "You should run generate_travis.sh." - exit 1 - fi - echo "Matrix is up to date." + exit 1 + fi + echo "Matrix is up to date." #check if non standard cgal installation works cd $ROOT mkdir build_test @@ -126,7 +126,7 @@ cd $ROOT fi IFS=$' ' EXAMPLES="$ARG/examples/$ARG" - TEST="$ARG/test/$ARG" + TEST="$ARG/test/$ARG" DEMOS=$ROOT/$ARG/demo/* if [ -d "$ROOT/$EXAMPLES" ] @@ -168,17 +168,17 @@ cd $ROOT for DEMO in $DEMOS; do DEMO=${DEMO#"$ROOT"} echo $DEMO - #If there is no demo subdir, try in GraphicsView + #If there is no demo subdir, try in GraphicsView if [ ! -d "$ROOT/$DEMO" ] || [ ! -f "$ROOT/$DEMO/CMakeLists.txt" ]; then DEMO="GraphicsView/demo/$ARG" fi - if [ "$ARG" != Polyhedron ] && [ -d "$ROOT/$DEMO" ] - then + if [ "$ARG" != Polyhedron ] && [ -d "$ROOT/$DEMO" ] + then cd $ROOT/$DEMO build_demo elif [ "$ARG" != Polyhedron_demo ]; then echo "No demo found for $ARG" - fi + fi done if [ "$ARG" = Polyhedron_demo ]; then DEMO=Polyhedron/demo/Polyhedron diff --git a/.travis/packages.txt b/.travis/packages.txt index 69e4f85c73a..6e75cd0ad14 100644 --- a/.travis/packages.txt +++ b/.travis/packages.txt @@ -129,6 +129,7 @@ Surface_sweep_2 TDS_2 TDS_3 Testsuite +Tetrahedral_remeshing Three Triangulation Triangulation_2 diff --git a/.travis/windows.h b/.travis/windows.h new file mode 100644 index 00000000000..a774a068df3 --- /dev/null +++ b/.travis/windows.h @@ -0,0 +1,12 @@ +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define max(a,b) (((a) > (b)) ? (a) : (b)) + +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#define min(a,b) (((a) < (b)) ? (a) : (b)) + + +#define FAR #error named reserved in windows.h +#define far #error named reserved in windows.h + +#define Polyline #error named reserved in windows.h +#define Polygon #error named reserved in windows.h diff --git a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h index 53cb0fcb76e..00b841f2d6f 100644 --- a/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h +++ b/Arrangement_on_surface_2/demo/Arrangement_on_surface_2/VerticalRayShootCallback.h @@ -127,7 +127,11 @@ protected: void highlightPointLocation( QGraphicsSceneMouseEvent *event ); Face_const_handle getFace( const CGAL::Object& o ); CGAL::Object rayShootUp( const Kernel_point_2& point ); + CGAL::Object rayShootUp( const Kernel_point_2& point, CGAL::Tag_true ); + CGAL::Object rayShootUp( const Kernel_point_2& point, CGAL::Tag_false ); CGAL::Object rayShootDown( const Kernel_point_2& point ); + CGAL::Object rayShootDown( const Kernel_point_2& point, CGAL::Tag_true ); + CGAL::Object rayShootDown( const Kernel_point_2& point, CGAL::Tag_false ); using Superclass::scene; using Superclass::shootingUp; @@ -304,6 +308,14 @@ VerticalRayShootCallback< Arr_ >::getFace( const CGAL::Object& obj ) template < typename Arr_ > CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt ) +{ + typename Supports_landmarks< Arrangement >::Tag supportsLandmarks; + return this->rayShootUp( pt, supportsLandmarks ); +} + +template < typename Arr_ > +CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt, + CGAL::Tag_true ) { CGAL::Object pointLocationResult; Walk_pl_strategy* walkStrategy; @@ -334,9 +346,48 @@ VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt ) return pointLocationResult; } +template < typename Arr_ > +CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootUp( const Kernel_point_2& pt, + CGAL::Tag_false ) +{ + CGAL::Object pointLocationResult; + Walk_pl_strategy* walkStrategy; + TrapezoidPointLocationStrategy* trapezoidStrategy; + SimplePointLocationStrategy* simpleStrategy; + + Point_2 point = this->toArrPoint( pt ); + + if ( CGAL::assign( walkStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = walkStrategy->ray_shoot_up( point ); + } + else if ( CGAL::assign( trapezoidStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = trapezoidStrategy->ray_shoot_up( point ); + } + else if ( CGAL::assign( simpleStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = simpleStrategy->ray_shoot_up( point ); + } + else + { + std::cout<<"Didn't find the right strategy\n"; + } + + return pointLocationResult; +} + template < typename Arr_ > CGAL::Object VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt ) +{ + typename Supports_landmarks< Arrangement >::Tag supportsLandmarks; + return this->rayShootDown( pt, supportsLandmarks ); +} + +template < typename Arr_ > +CGAL::Object +VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt, CGAL::Tag_true ) { CGAL::Object pointLocationResult; Walk_pl_strategy* walkStrategy; @@ -367,4 +418,30 @@ VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt ) return pointLocationResult; } +template < typename Arr_ > +CGAL::Object +VerticalRayShootCallback< Arr_ >::rayShootDown( const Kernel_point_2& pt, CGAL::Tag_false ) +{ + CGAL::Object pointLocationResult; + Walk_pl_strategy* walkStrategy; + TrapezoidPointLocationStrategy* trapezoidStrategy; + SimplePointLocationStrategy* simpleStrategy; + + Point_2 point = this->toArrPoint( pt ); + + if ( CGAL::assign( walkStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = walkStrategy->ray_shoot_down( point ); + } + else if ( CGAL::assign( trapezoidStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = trapezoidStrategy->ray_shoot_down( point ); + } + else if ( CGAL::assign( simpleStrategy, this->pointLocationStrategy ) ) + { + pointLocationResult = simpleStrategy->ray_shoot_down( point ); + } + return pointLocationResult; +} + #endif // VERTICAL_RAY_SHOOT_CALLBACK_H diff --git a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h index 3af9a106877..146eb151548 100644 --- a/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h +++ b/Arrangement_on_surface_2/doc/Arrangement_on_surface_2/Concepts/ArrTraits--Intersect_2.h @@ -16,21 +16,19 @@ public: /// A model of this concept must provide: /// @{ -/*! -computes the intersections of `xc1` and `xc2` and -inserts them in an ascending lexicographic \f$ xy\f$-order into the -output iterator `oi`. The value-type of `Output_iterator` is -`CGAL::Object`, where each `Object` wraps either a -`pair` object, which -represents an intersection point with its multiplicity (in case the -multiplicity is undefined or unknown, it should be set to \f$ 0\f$) or an -`ArrTraits::X_monotone_curve_2` object, representing an -overlapping subcurve of `xc1` and `xc2`. The operator -returns a past-the-end iterator for the output sequence. -*/ -Output_iterator operator()(ArrTraits::X_monotone_curve_2 xc1, -ArrTraits::X_monotone_curve_2 xc2, -Output_iterator& oi); +/*! computes the intersections of `xc1` and `xc2` and inserts them in an + * ascending lexicographic \f$ xy\f$-order into a range begining at + * `oi`. The type `OutputIterator` dereferences a `boost::variant` of either the + * type `pair` or the type + * `ArrTraits::X_monotone_curve_2`. An object of the former type represents an + * intersection point with its multiplicity (in case the multiplicity is + * undefined or unknown, it should be set to \f$ 0\f$). An object of the latter + * type representing an overlapping subcurve of `xc1` and `xc2`. The operator + * returns a past-the-end iterator of the destination range. + */ +OutputIterator operator()(ArrTraits::X_monotone_curve_2 xc1, + ArrTraits::X_monotone_curve_2 xc2, + Output_iterator& oi); /// @} 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 dc8dc0d5e78..2b5a25cd5e0 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 @@ -7,9 +7,10 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Baruch Zukerman -// Waqar Khan +// Author(s): Ron Wein +// Baruch Zukerman +// Waqar Khan +// Efi Fogel #ifndef CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H #define CGAL_ARR_CIRCLE_SEGMENT_TRAITS_2_H @@ -546,21 +547,15 @@ public: return Split_2(); } - class Intersect_2 - { + class Intersect_2 { private: - - Intersection_map& _inter_map; // The map of intersection points. + Intersection_map& _inter_map; // The map of intersection points. public: - /*! Constructor. */ - Intersect_2 (Intersection_map& map) : - _inter_map (map) - {} + Intersect_2(Intersection_map& map) : _inter_map(map) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. * \param cv1 The first curve. @@ -568,20 +563,15 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const - { - return (cv1.intersect (cv2, oi, &_inter_map)); - } + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const + { return (cv1.intersect(cv2, oi, &_inter_map)); } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (inter_map)); - } + Intersect_2 intersect_2_object() const { return (Intersect_2(inter_map)); } class Are_mergeable_2 { @@ -706,14 +696,11 @@ public: friend class Arr_circle_segment_traits_2; public: - /*!\brief - * Returns a trimmed version of an arc - * + /*! Obtain a trimmed version of an arc * \param xcv The arc * \param src the new first endpoint * \param tgt the new second endpoint * \return The trimmed arc - * * \pre src != tgt * \pre both points must be interior and must lie on \c cv */ 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 654f86e3e30..eb9acae74a8 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 @@ -22,7 +22,6 @@ #include - /*! \file * This file was developed at Inria, France, and copied over to the * Arrangement_2 package, which it is now part of. It contains a traits @@ -30,12 +29,13 @@ * It is based on the circular kernel. */ -#include -#include -#include - #include +#include + +#include +#include + namespace CGAL { namespace VariantFunctors{ @@ -47,9 +47,9 @@ namespace CGAL { 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)){ + 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); } @@ -64,29 +64,27 @@ namespace CGAL { return res2; } - - template - class In_x_range_2 + template + OutputIterator + object_to_object_variant1(const std::vector& res, + OutputIterator oi) { - public: - typedef typename CircularKernel::Circular_arc_point_2 - Circular_arc_point_2; - typedef bool result_type; + typedef IntersectionPoint Intersection_point; + typedef XMonotoneCurve X_monotone_curve_2; + typedef boost::variant + Intersection_result; - result_type - operator()(const boost::variant< Arc1, Arc2 > &a, - const Circular_arc_point_2 &p) const - { - if ( const Arc1* arc1 = boost::get( &a ) ){ - return CircularKernel().in_x_range_2_object()(*arc1, p); - } - else { - const Arc2* arc2 = boost::get( &a ); - return CircularKernel().in_x_range_2_object()(*arc2, p); + 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 @@ -277,7 +275,7 @@ namespace CGAL { CircularKernel() .make_x_monotone_2_object()(*arc1,std::back_inserter(container)); return object_to_object_variant - (container, res); + (container, res); } else { const Arc2* arc2 = boost::get( &A ); @@ -285,65 +283,42 @@ namespace CGAL { CircularKernel() .make_x_monotone_2_object()(*arc2,std::back_inserter(container)); return object_to_object_variant - (container, res); + (container, res); } } }; - - template class Intersect_2 { public: - typedef typename CircularKernel::Circular_arc_point_2 - Circular_arc_point_2; + typedef typename CircularKernel::Circular_arc_point_2 + Circular_arc_point_2; template < class OutputIterator > OutputIterator operator()(const boost::variant< Arc1, Arc2 > &c1, const boost::variant< Arc1, Arc2 > &c2, - OutputIterator res) const + OutputIterator oi) const { if ( const Arc1* arc1 = boost::get( &c1 ) ){ if ( const Arc1* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); - } - else if ( const Arc2* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); - } - } - else { - const Arc2* arc1e = boost::get( &c1 ); - if ( const Arc1* arc2 = boost::get( &c2 ) ){ - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1e,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); + return CircularKernel().intersect_2_object()(*arc1, *arc2, oi); } const Arc2* arc2 = boost::get( &c2 ); - std::vector container; - CircularKernel() - .intersect_2_object()(*arc1e,*arc2,std::back_inserter(container)); - return object_to_object_variant - (container, res); + return CircularKernel().intersect_2_object()(*arc1, *arc2, oi); } - CGAL_error(); - return res;//for no warning + + const Arc2* arc1e = boost::get( &c1 ); + if ( const Arc1* arc2 = boost::get( &c2 ) ){ + return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi); + } + const Arc2* arc2 = boost::get( &c2 ); + return CircularKernel().intersect_2_object()(*arc1e, *arc2, oi); } }; - template class Split_2 { @@ -533,7 +508,7 @@ namespace CGAL { 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; 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 f1640b280b0..cc26c045a84 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 @@ -8,8 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Waqar Khan +// Author(s): Ron Wein +// Waqar Khan #ifndef CGAL_ARR_CONIC_TRAITS_2_H #define CGAL_ARR_CONIC_TRAITS_2_H @@ -22,6 +22,8 @@ * The conic traits-class for the arrangement package. */ +#include + #include #include #include @@ -29,8 +31,6 @@ #include #include -#include - namespace CGAL { /*! @@ -88,8 +88,7 @@ private: // Type definition for the intersection points mapping. typedef typename X_monotone_curve_2::Conic_id Conic_id; - typedef typename X_monotone_curve_2::Intersection_point_2 - Intersection_point_2; + typedef typename X_monotone_curve_2::Intersection_point Intersection_point; typedef typename X_monotone_curve_2::Intersection_map Intersection_map; mutable Intersection_map inter_map; // Mapping conic pairs to their @@ -604,21 +603,15 @@ public: return Split_2(); } - class Intersect_2 - { + class Intersect_2 { private: - - Intersection_map& _inter_map; // The map of intersection points. + Intersection_map& _inter_map; // The map of intersection points. public: - /*! Constructor. */ - Intersect_2 (Intersection_map& map) : - _inter_map (map) - {} + Intersect_2(Intersection_map& map) : _inter_map(map) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. As two segments may itersect only once, only a * single will be contained in the iterator. * \param cv1 The first curve. @@ -626,20 +619,15 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const - { - return (cv1.intersect (cv2, _inter_map, oi)); - } + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const + { return (cv1.intersect(cv2, _inter_map, oi)); } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (inter_map)); - } + Intersect_2 intersect_2_object () const { return (Intersect_2(inter_map)); } class Are_mergeable_2 { 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 877444cb066..7ed8e459334 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 @@ -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_CURVE_DATA_TRAITS_2_H #define CGAL_ARR_CURVE_DATA_TRAITS_2_H @@ -22,6 +22,8 @@ */ #include + +#include #include #include @@ -193,35 +195,40 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template + template OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::variant + Intersection_base_result; + // Use the base functor to obtain all intersection objects. - std::list base_objects; + std::list base_objects; m_base.intersect_2_object()(cv1, cv2, std::back_inserter(base_objects)); // Stop if the list is empty: if (base_objects.empty()) return oi; // Go over all intersection objects and prepare the output. - const Base_x_monotone_curve_2* base_cv; - for (typename std::list::const_iterator it = - base_objects.begin(); it != base_objects.end(); ++it) - { - if ((base_cv = object_cast(&(*it))) != nullptr) { + for (const auto& item : base_objects) { + const Base_x_monotone_curve_2* base_cv = + boost::get(&item); + if (base_cv != nullptr) { // The current intersection object is an overlapping x-monotone // curve: Merge the data fields of both intersecting curves and // associate the result with the overlapping curve. - X_monotone_curve_2 cv(*base_cv, Merge() (cv1.data(), cv2.data())); - *oi++ = make_object(cv); - } - else { - // The current intersection object is an intersection point: - // Copy it as is. - *oi++ = *it; + X_monotone_curve_2 cv(*base_cv, Merge()(cv1.data(), cv2.data())); + *oi++ = Intersection_result(cv); + continue; } + // The current intersection object is an intersection point: + // Copy it as is. + const Intersection_point* ip = boost::get(&item); + *oi++ = Intersection_result(*ip); } return oi; 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 3c21ac9026d..6ccd5d249bc 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 @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel +// Author(s) : Efi Fogel #ifndef CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H #define CGAL_ARR_GEODESIC_ARC_ON_SPHERE_TRAITS_2_H @@ -25,6 +25,8 @@ #include +#include + #include #include #include @@ -1646,7 +1648,10 @@ public: Project project, OutputIterator oi) const { - typedef std::pair Point_2_pair; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + const Kernel* kernel = m_traits; typename Kernel::Equal_2 equal = kernel->equal_2_object(); @@ -1658,7 +1663,7 @@ public: if (equal(l1, l2)) { const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } @@ -1668,29 +1673,29 @@ public: if (l1_eq_start || (!l2_eq_start && in_between(l1, start, l2))) { // The following applies only to full circles: if (l1_eq_start && equal(r2, start)) - *oi++ = make_object(Point_2_pair(r2_3, 1)); + *oi++ = Intersection_result(Intersection_point(r2_3, 1)); if (in_between(r1, l1, l2)) return oi; // no intersection if (equal(r1, l2)) { - *oi++ = make_object(Point_2_pair(r1_3, 1)); + *oi++ = Intersection_result(Intersection_point(r1_3, 1)); return oi; } const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l2_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } CGAL_assertion(l2_eq_start || in_between(l2, start, l1)); // The following applies only to full circles: if (l2_eq_start && equal(r1, start)) - *oi++ = make_object(Point_2_pair(r1_3, 1)); + *oi++ = Intersection_result(Intersection_point(r1_3, 1)); if (in_between(r2, l2, l1)) return oi; // no intersection if (equal(r2, l1)) { - *oi++ = make_object(Point_2_pair(r2_3, 1)); + *oi++ = Intersection_result(Intersection_point(r2_3, 1)); return oi; } const Point_2& trg = (in_between(r1, l2, r2)) ? r1_3 : r2_3; X_monotone_curve_2 xc(l1_3, trg, normal, vertical, true); - *oi++ = make_object(xc); + *oi++ = Intersection_result(xc); return oi; } @@ -1784,9 +1789,12 @@ public: typedef Arr_geodesic_arc_on_sphere_traits_2 Traits; typedef typename Kernel::Counterclockwise_in_between_2 Counterclockwise_in_between_2; - typedef typename Kernel::Equal_3 Equal_3; + typedef typename Kernel::Equal_3 Equal_3; + + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; - typedef std::pair Point_2_pair; const Kernel* kernel = m_traits; Equal_3 equal_3 = kernel->equal_3_object(); @@ -1810,9 +1818,9 @@ public: (res && (xc1.is_directed_right() != xc2.is_directed_right()))) { if (xc1.left().is_min_boundary() && xc2.left().is_min_boundary()) - *oi++ = make_object(Point_2_pair(xc1.left(), 1)); + *oi++ = Intersection_result(Intersection_point(xc1.left(), 1)); if (xc1.right().is_max_boundary() && xc2.right().is_max_boundary()) - *oi++ = make_object(Point_2_pair(xc1.right(), 1)); + *oi++ = Intersection_result(Intersection_point(xc1.right(), 1)); return oi; } @@ -1820,11 +1828,11 @@ public: * the other arc is completely overlapping. */ if (xc1.left().is_min_boundary() && xc1.right().is_max_boundary()) { - *oi++ = make_object(xc2); + *oi++ = Intersection_result(xc2); return oi; } if (xc2.left().is_min_boundary() && xc2.right().is_max_boundary()) { - *oi++ = make_object(xc1); + *oi++ = Intersection_result(xc1); return oi; } /*! Find an endpoint that does not coincide with a pole, and project @@ -1877,14 +1885,14 @@ public: // Determine which one of the two directions: Point_2 ed(v.direction()); if (is_in_between(ed, xc1) && is_in_between(ed, xc2)) { - *oi++ = make_object(Point_2_pair(ed, 1)); + *oi++ = Intersection_result(Intersection_point(ed, 1)); return oi; } Vector_3 vo(kernel->construct_opposite_vector_3_object()(v)); Point_2 edo(vo.direction()); if (is_in_between(edo, xc1) && is_in_between(edo, xc2)) { - *oi++ = make_object(Point_2_pair(edo, 1)); + *oi++ = Intersection_result(Intersection_point(edo, 1)); return oi; } return oi; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h index 87a104c032f..3910c36249d 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_cache.h @@ -52,11 +52,11 @@ public: /// \name Type definitions for the intersection-point mapping. //@{ - /*! \struct Intersection_point_2 + /*! \struct Intersection_point * Representation of an intersection point (in both parameter and physical * spaces). */ - struct Intersection_point_2 + struct Intersection_point { Algebraic s; // The parameter for the first curve. Algebraic t; // The parameter for the second curve. @@ -64,7 +64,7 @@ public: Algebraic y; // The y-coordinate. /*! Constructor. */ - Intersection_point_2 (const Algebraic& _s, const Algebraic& _t, + Intersection_point (const Algebraic& _s, const Algebraic& _t, const Algebraic& _x, const Algebraic& _y) : s(_s), t(_t), x(_x), y(_y) @@ -73,7 +73,7 @@ public: typedef std::pair Curve_pair; typedef std::pair Parameter_pair; - typedef std::list Intersection_list; + typedef std::list Intersection_list; typedef typename Intersection_list::const_iterator Intersection_iter; @@ -378,7 +378,7 @@ _Bezier_cache::get_intersections CGAL::compare (nt_traits.evaluate_at (polyY_1, *t_it), y) == EQUAL) { - info.first.push_back (Intersection_point_2 (*s_it, *t_it, + info.first.push_back (Intersection_point (*s_it, *t_it, x / denX, y / denY)); } } @@ -535,10 +535,8 @@ _Bezier_cache::get_intersections CGAL_assertion(CGAL::sign (s) != NEGATIVE && CGAL::compare (s, one) != LARGER && CGAL::sign (t) != NEGATIVE && CGAL::compare (t, one) != LARGER); - if (!swapt) - info.first.push_back (Intersection_point_2 (s, t,pit1->x, pit1->y)); - else - info.first.push_back (Intersection_point_2 (t, s,pit1->x, pit1->y)); + if (!swapt) info.first.push_back(Intersection_point(s, t,pit1->x, pit1->y)); + else info.first.push_back(Intersection_point(t, s,pit1->x, pit1->y)); } info.second = false; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h index 25a1c51dbab..5397a42062f 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Bezier_x_monotone_2.h @@ -7,8 +7,8 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Iddo Hanniel +// Author(s): Ron Wein +// Iddo Hanniel #ifndef CGAL_BEZIER_X_MONOTONE_2_H #define CGAL_BEZIER_X_MONOTONE_2_H @@ -85,27 +85,24 @@ private: typedef typename Bezier_cache::Intersection_iter Intersect_iter; // Representation of an intersection point with its multiplicity: - typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; /*! \class Less_intersection_point * Comparison functor for intersection points. */ - class Less_intersection_point - { + class Less_intersection_point { private: - Bezier_cache *p_cache; + Bezier_cache* p_cache; public: - Less_intersection_point (Bezier_cache& cache) : - p_cache (&cache) - {} + Less_intersection_point(Bezier_cache& cache) : p_cache(&cache) {} - bool operator() (const Intersection_point_2& ip1, - const Intersection_point_2& ip2) const + bool operator()(const Intersection_point& ip1, + const Intersection_point& ip2) const { // Use an xy-lexicographic comparison. - return (ip1.first.compare_xy (ip2.first, *p_cache) == SMALLER); + return (ip1.first.compare_xy(ip2.first, *p_cache) == SMALLER); } }; @@ -117,7 +114,7 @@ private: */ struct Less_curve_pair { - bool operator() (const Curve_pair& cp1, const Curve_pair& cp2) const + bool operator()(const Curve_pair& cp1, const Curve_pair& cp2) const { // Compare the pairs of IDs lexicographically. return (cp1.first < cp2.first || @@ -128,34 +125,32 @@ private: /*! \struct Subcurve * For the usage of the _exact_vertical_position() function. */ - struct Subcurve - { - std::list control_points; - Rational t_min; - Rational t_max; + struct Subcurve { + std::list control_points; + Rational t_min; + Rational t_max; /*! Get the rational bounding box of the subcurve. */ - void bbox (Rational& x_min, Rational& y_min, - Rational& x_max, Rational& y_max) const + void bbox(Rational& x_min, Rational& y_min, + Rational& x_max, Rational& y_max) const { - typename std::list::const_iterator pit = + typename std::list::const_iterator pit = control_points.begin(); - CGAL_assertion (pit != control_points.end()); + CGAL_assertion(pit != control_points.end()); x_min = x_max = pit->x(); y_min = y_max = pit->y(); - for (++pit; pit != control_points.end(); ++pit) - { - if (CGAL::compare (x_min, pit->x()) == LARGER) + for (++pit; pit != control_points.end(); ++pit) { + if (CGAL::compare(x_min, pit->x()) == LARGER) x_min = pit->x(); - else if (CGAL::compare (x_max, pit->x()) == SMALLER) + else if (CGAL::compare(x_max, pit->x()) == SMALLER) x_max = pit->x(); - if (CGAL::compare (y_min, pit->y()) == LARGER) + if (CGAL::compare(y_min, pit->y()) == LARGER) y_min = pit->y(); - else if (CGAL::compare (y_max, pit->y()) == SMALLER) + else if (CGAL::compare(y_max, pit->y()) == SMALLER) y_max = pit->y(); } @@ -189,10 +184,10 @@ private: public: /*! Default constructor. */ - _Bezier_x_monotone_2 () : + _Bezier_x_monotone_2() : _xid(0), - _dir_right (false), - _is_vert (false) + _dir_right(false), + _is_vert(false) {} /*! @@ -209,80 +204,56 @@ public: * \pre B should be an originator of both ps and pt. * \pre xid is a non-zero serial number. */ - _Bezier_x_monotone_2 (const Curve_2& B, unsigned int xid, - const Point_2& ps, const Point_2& pt, - Bezier_cache& cache); + _Bezier_x_monotone_2(const Curve_2& B, unsigned int xid, + const Point_2& ps, const Point_2& pt, + Bezier_cache& cache); /*! * Get the supporting Bezier curve. */ - const Curve_2& supporting_curve () const - { - return (_curve); - } + const Curve_2& supporting_curve() const { return (_curve); } /*! * Get the x-monotone ID of the curve. */ - unsigned int xid () const - { - return (_xid); - } + unsigned int xid() const { return (_xid); } /*! * Get the source point. */ - const Point_2& source () const - { - return (_ps); - } + const Point_2& source() const { return (_ps); } /*! * Get the target point. */ - const Point_2& target () const - { - return (_pt); - } + const Point_2& target() const { return (_pt); } /*! * Get the left endpoint (the lexicographically smaller one). */ - const Point_2& left () const - { - return (_dir_right ? _ps : _pt); - } + const Point_2& left() const { return (_dir_right ? _ps : _pt); } /*! * Get the right endpoint (the lexicographically larger one). */ - const Point_2& right () const - { - return (_dir_right ? _pt : _ps); - } + const Point_2& right() const { return (_dir_right ? _pt : _ps); } /*! * Check if the subcurve is a vertical segment. */ - bool is_vertical () const - { - return (_is_vert); - } + bool is_vertical() const { return (_is_vert); } /*! * Check if the subcurve is directed from left to right. */ - bool is_directed_right () const - { - return (_dir_right); - } + bool is_directed_right() const { return (_dir_right); } /*! * Get the approximate parameter range defining the curve. * \return A pair of t_src and t_trg, where B(t_src) is the source point * and B(t_trg) is the target point. */ - std::pair parameter_range () const; + std::pair parameter_range() const; /*! * Get the relative position of the query point with respect to the subcurve. @@ -293,8 +264,8 @@ public: * LARGER if the point is above the arc; * EQUAL if p lies on the arc. */ - Comparison_result point_position (const Point_2& p, - Bezier_cache& cache) const; + Comparison_result point_position(const Point_2& p, + Bezier_cache& cache) const; /*! * Compare the relative y-position of two x-monotone subcurve to the right @@ -307,9 +278,9 @@ public: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv to the right of p. */ - Comparison_result compare_to_right (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result compare_to_right(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; /*! * Compare the relative y-position of two x-monotone subcurve to the left @@ -322,106 +293,90 @@ public: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv to the right of p. */ - Comparison_result compare_to_left (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result compare_to_left(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; - /*! - * Check whether the two subcurves are equal (have the same graph). + /*! Check whether the two subcurves are equal (have the same graph). * \param cv The other subcurve. * \param cache Caches the vertical tangency points and intersection points. * \return (true) if the two subcurves have the same graph; * (false) otherwise. */ - bool equals (const Self& cv, - Bezier_cache& cache) const; + bool equals(const Self& cv, Bezier_cache& cache) const; - /*! - * Compute the intersections with the given subcurve. + /*! Compute the intersections with the given subcurve. * \param cv The other subcurve. * \param inter_map Caches the bounded intersection points. * \param cache Caches the vertical tangency points and intersection points. * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator intersect (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - OutputIterator oi) const + template + OutputIterator intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + OutputIterator oi) const { + typedef boost::variant Intersection_result; + // In case we have two x-monotone subcurves of the same Bezier curve, // check if they have a common left endpoint. - if (_curve.is_same (cv._curve)) - { - if (left().is_same (cv.left()) || left().is_same (cv.right())) - { - *oi = CGAL::make_object (Intersection_point_2 (left(), 0)); - ++oi; - } + if (_curve.is_same(cv._curve)) { + if (left().is_same(cv.left()) || left().is_same(cv.right())) + *oi++ = Intersection_result(Intersection_point(left(), 0)); } // Compute the intersections of the two sucurves. Note that for caching // purposes we always apply the _intersect() function on the subcurve whose // curve ID is smaller. - std::vector ipts; - Self ovlp_cv; - bool do_ovlp; + std::vector ipts; + Self ovlp_cv; + bool do_ovlp; if (_curve.id() <= cv._curve.id()) - do_ovlp = _intersect (cv, inter_map, cache, ipts, ovlp_cv); + do_ovlp = _intersect(cv, inter_map, cache, ipts, ovlp_cv); else - do_ovlp = cv._intersect (*this, inter_map, cache, ipts, ovlp_cv); + do_ovlp = cv._intersect(*this, inter_map, cache, ipts, ovlp_cv); // In case of overlap, just report the overlapping subcurve. - if (do_ovlp) - { - *oi = CGAL::make_object (ovlp_cv); - ++oi; - return (oi); + if (do_ovlp) { + *oi++ = Intersection_result(ovlp_cv); + return oi; } // If we have a set of intersection points, sort them in ascending // xy-lexicorgraphical order, and insert them to the output iterator. - typename std::vector::const_iterator ip_it; - - std::sort (ipts.begin(), ipts.end(), Less_intersection_point (cache)); - for (ip_it = ipts.begin(); ip_it != ipts.end(); ++ip_it) - { - *oi = CGAL::make_object (*ip_it); - ++oi; + std::sort(ipts.begin(), ipts.end(), Less_intersection_point(cache)); + for (auto ip_it = ipts.begin(); ip_it != ipts.end(); ++ip_it) { + *oi++ = Intersection_result(*ip_it); } // In case we have two x-monotone subcurves of the same Bezier curve, // check if they have a common right endpoint. - if (_curve.is_same (cv._curve)) - { - if (right().is_same (cv.left()) || right().is_same (cv.right())) - { - *oi = CGAL::make_object (Intersection_point_2 (right(), 0)); - ++oi; + if (_curve.is_same(cv._curve)) { + if (right().is_same(cv.left()) || right().is_same(cv.right())) { + *oi++ = Intersection_result(Intersection_point(right(), 0)); } } - return (oi); + return oi; } - /*! - * Split the subcurve into two at a given split point. + /*! Split the subcurve into two at a given split point. * \param p The split point. * \param c1 Output: The first resulting arc, lying to the left of p. * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the subcurve (not one of its endpoints). */ - void split (const Point_2& p, - Self& c1, Self& c2) const; + void split(const Point_2& p, Self& c1, Self& c2) const; /*! * Check if the two subcurves are mergeable. * \param cv The other subcurve. * \return Whether the two subcurves can be merged. */ - bool can_merge_with (const Self& cv) const; + bool can_merge_with(const Self& cv) const; /*! * Merge the current arc with the given arc. @@ -429,13 +384,13 @@ public: * \pre The two arcs are mergeable. * \return The merged arc. */ - Self merge (const Self& cv) const; + Self merge(const Self& cv) const; /*! * Flip the subcurve (swap its source and target points). * \return The flipped subcurve. */ - Self flip () const + Self flip() const { // Note that we just swap the source and target of the original subcurve // and do not touch the supporting Beizer curve. @@ -445,7 +400,7 @@ public: cv._pt = this->_ps; cv._dir_right = ! this->_dir_right; - return (cv); + return cv; } Self trim(const Point_2& src, const Point_2& tgt) const @@ -460,26 +415,21 @@ public: } private: - - /*! - * Check if the given t-value is in the range of the subcurve. + /*! Check if the given t-value is in the range of the subcurve. * \param t The parameter value. * \param cache Caches the vertical tangency points and intersection points. * \return If t in the parameter-range of the subcurve. */ - bool _is_in_range (const Algebraic& t, - Bezier_cache& cache) const; + bool _is_in_range(const Algebraic& t, Bezier_cache& cache) const; - /*! - * Check if the given point lies in the range of this x-monotone subcurve. + /*! Check if the given point lies in the range of this x-monotone subcurve. * \param p The point, which lies on the supporting Bezier curve. * \param is_certain Output: Is the answer we provide is certain. * \return Whether p is on the x-monotone subcurve. */ - bool _is_in_range (const Point_2& p, bool& is_certain) const; + bool _is_in_range(const Point_2& p, bool& is_certain) const; - /*! - * Given a point p that lies on the supporting Bezier curve (X(t), Y(t)), + /*! Given a point p that lies on the supporting Bezier curve (X(t), Y(t)), * determine whether p lies within the t-range of the x-monotone subcurve. * If so, the value t0 such that p = (X(t0), Y(t0)) is also computed. * \param p The point, which lies on the supporting Bezier curve. @@ -488,23 +438,20 @@ private: * \param is_endpoint Output: Whether p equals on the of the endpoints. * \return Whether p lies in the t-range of the subcurve. */ - bool _is_in_range (const Point_2& p, - Bezier_cache& cache, - Algebraic& t0, - bool& is_endpoint) const; + bool _is_in_range(const Point_2& p, + Bezier_cache& cache, + Algebraic& t0, + bool& is_endpoint) const; - /*! - * Compute a y-coordinate of a point on the x-monotone subcurve with a + /*! Compute a y-coordinate of a point on the x-monotone subcurve with a * given x-coordinate. * \param x0 The given x-coodinate. * \param cache Caches the vertical tangency points and intersection points. * \return The y-coordinate. */ - Algebraic _get_y (const Rational& x0, - Bezier_cache& cache) const; + Algebraic _get_y(const Rational& x0, Bezier_cache& cache) const; - /*! - * Compare the slopes of the subcurve with another given Bezier subcurve at + /*! Compare the slopes of the subcurve with another given Bezier subcurve at * their given intersection point. * \param cv The other subcurve. * \param p The intersection point. @@ -515,20 +462,18 @@ private: * EQUAL if the two slopes are equal; * LARGER if (*this) slope is greater than cv's. */ - Comparison_result _compare_slopes (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const; + Comparison_result _compare_slopes(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const; - /*! - * Get the range of t-value over which the subcurve is defined. + /*! Get the range of t-value over which the subcurve is defined. * \param cache Caches the vertical tangency points and intersection points. * \return A pair comprised of the t-value for the source point and the * t-value for the target point. */ - std::pair _t_range (Bezier_cache& cache) const; + std::pair _t_range(Bezier_cache& cache) const; - /*! - * Compare the relative y-position of two x-monotone subcurve to the right + /*! Compare the relative y-position of two x-monotone subcurve to the right * (or to the left) of their intersection point, whose multiplicity is * greater than 1. * \param cv The other subcurve. @@ -543,25 +488,22 @@ private: * EQUAL in case of an overlap (should not happen); * LARGER if (*this) lies above cv next to p. */ - Comparison_result _compare_to_side (const Self& cv, - const Point_2& p, - bool to_right, - Bezier_cache& cache) const; + Comparison_result _compare_to_side(const Self& cv, + const Point_2& p, + bool to_right, + Bezier_cache& cache) const; - /*! - * Clip the control polygon of the supporting Bezier curve such that it + /*! Clip the control polygon of the supporting Bezier curve such that it * fits the current x-monotone subcurve. * \param ctrl Output: The clipped control polygon. * \param t_min Output: The minimal t-value of the clipped curve. * \param t_max Output: The maximal t-value of the clipped curve. */ - void _clip_control_polygon - (typename Bounding_traits::Control_points& ctrl, - typename Bounding_traits::NT& t_min, - typename Bounding_traits::NT& t_max) const; + void _clip_control_polygon(typename Bounding_traits::Control_points& ctrl, + typename Bounding_traits::NT& t_min, + typename Bounding_traits::NT& t_max) const; - /*! - * Approximate the intersection points between the supporting Bezier curves + /*! Approximate the intersection points between the supporting Bezier curves * of the given x-monotone curves. * \param cv The x-monotone curve we intersect. * \param inter_pts Output: An output list of intersection points between @@ -571,11 +513,10 @@ private: * between the subcurves are approximated. * \return Whether all intersection points where successfully approximated. */ - bool _approximate_intersection_points (const Self& cv, - std::list& inter_pts) const; + bool _approximate_intersection_points(const Self& cv, + std::list& inter_pts) const; - /*! - * Compute the intersections with the given subcurve. + /*! Compute the intersections with the given subcurve. * \param cv The other subcurve. * \param inter_map Caches the bounded intersection points. * \param cache Caches the vertical tangency points and intersection points. @@ -583,14 +524,13 @@ private: * \param ovlp_cv Output: An overlapping subcurve (if exists). * \return Whether an overlap has occurred. */ - bool _intersect (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - std::vector& ipts, - Self& ovlp_cv) const; + bool _intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + std::vector& ipts, + Self& ovlp_cv) const; - /*! - * Compute the exact vertical position of the given point with respect to + /*! Compute the exact vertical position of the given point with respect to * the x-monotone curve. * \param p The point. * \param force_exact Sould we force an exact result. @@ -598,64 +538,63 @@ private: * LARGER if the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result _exact_vertical_position (const Point_2& p, - bool + Comparison_result _exact_vertical_position(const Point_2& p, + bool #if !defined(CGAL_NO_ASSERTIONS) - force_exact + force_exact #endif - ) const; + ) const; }; /*! * Exporter for Bezier curves. */ -template +template std::ostream& -operator<< (std::ostream& os, - const _Bezier_x_monotone_2& cv) +operator<<(std::ostream& os, + const _Bezier_x_monotone_2 + & cv) { os << cv.supporting_curve() << " [" << cv.xid() << "] | " << cv.source() << " --> " << cv.target(); - return (os); + return os; } // --------------------------------------------------------------------------- // Constructor given two endpoints. // -template -_Bezier_x_monotone_2::_Bezier_x_monotone_2 - (const Curve_2& B, unsigned int xid, - const Point_2& ps, const Point_2& pt, - Bezier_cache& cache) : - _curve (B), - _xid (xid), - _ps (ps), - _pt (pt), - _is_vert (false) +template +_Bezier_x_monotone_2:: +_Bezier_x_monotone_2(const Curve_2& B, unsigned int xid, + const Point_2& ps, const Point_2& pt, + Bezier_cache& cache) : + _curve(B), + _xid(xid), + _ps(ps), + _pt(pt), + _is_vert(false) { - CGAL_precondition (xid > 0); + CGAL_precondition(xid > 0); // Get the originators of the point that correspond to the curve B. - Originator_iterator ps_org = ps.get_originator (B, _xid); - CGAL_precondition (ps_org != ps.originators_end()); + Originator_iterator ps_org = ps.get_originator(B, _xid); + CGAL_precondition(ps_org != ps.originators_end()); - Originator_iterator pt_org = pt.get_originator (B, _xid); - CGAL_precondition (pt_org != pt.originators_end()); + Originator_iterator pt_org = pt.get_originator(B, _xid); + CGAL_precondition(pt_org != pt.originators_end()); // Check if the subcurve is directed left or right. - const Comparison_result res = _ps.compare_x (_pt, cache); + const Comparison_result res = _ps.compare_x(_pt, cache); - if (res == EQUAL) - { + if (res == EQUAL) { // We have a vertical segment. Check if the source is below the target. _is_vert = true; - _dir_right = (CGAL::compare (_ps.y(), _pt.y()) == SMALLER); + _dir_right = (CGAL::compare(_ps.y(), _pt.y()) == SMALLER); } else { @@ -665,89 +604,83 @@ _Bezier_x_monotone_2::_Bezier_x_monotone_2 // Check if the value of the parameter t increases when we traverse the // curve from left to right: If the curve is directed to the right, we // check if t_src < t_trg, otherwise we check whether t_src > t_trg. - Comparison_result t_res; + Comparison_result t_res; - if (CGAL::compare (ps_org->point_bound().t_max, - pt_org->point_bound().t_min) == SMALLER || - CGAL::compare (ps_org->point_bound().t_min, - pt_org->point_bound().t_max) == LARGER) + if (CGAL::compare(ps_org->point_bound().t_max, + pt_org->point_bound().t_min) == SMALLER || + CGAL::compare(ps_org->point_bound().t_min, + pt_org->point_bound().t_max) == LARGER) { // Perform the comparison assuming that the possible parameter // values do not overlap. - t_res = CGAL::compare (ps_org->point_bound().t_min, + t_res = CGAL::compare(ps_org->point_bound().t_min, pt_org->point_bound().t_min); } - else - { + else { // In this case both exact parameter values must be known. // We use them to perform an exact comparison. - CGAL_assertion (ps_org->has_parameter() && pt_org->has_parameter()); + CGAL_assertion(ps_org->has_parameter() && pt_org->has_parameter()); - t_res = CGAL::compare (ps_org->parameter(), pt_org->parameter()); + t_res = CGAL::compare(ps_org->parameter(), pt_org->parameter()); } - CGAL_precondition (t_res != EQUAL); + CGAL_precondition(t_res != EQUAL); - if (_dir_right) - _inc_to_right = (t_res == SMALLER); - else - _inc_to_right = (t_res == LARGER); + if (_dir_right) _inc_to_right = (t_res == SMALLER); + else _inc_to_right = (t_res == LARGER); } // --------------------------------------------------------------------------- // Get the approximate parameter range defining the curve. // -template +template std::pair -_Bezier_x_monotone_2::parameter_range () const +_Bezier_x_monotone_2::parameter_range() const { // First try to use the approximate representation of the endpoints. - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - double t_src = (CGAL::to_double (s_org->point_bound().t_min) + - CGAL::to_double (s_org->point_bound().t_max)) / 2; - double t_trg = (CGAL::to_double (t_org->point_bound().t_min) + - CGAL::to_double (t_org->point_bound().t_max)) / 2; + double t_src = (CGAL::to_double(s_org->point_bound().t_min) + + CGAL::to_double(s_org->point_bound().t_max)) / 2; + double t_trg = (CGAL::to_double(t_org->point_bound().t_min) + + CGAL::to_double(t_org->point_bound().t_max)) / 2; - return (std::make_pair (t_src, t_trg)); + return (std::make_pair(t_src, t_trg)); } // --------------------------------------------------------------------------- // Get the relative position of the query point with respect to the subcurve. // -template +template Comparison_result -_Bezier_x_monotone_2::point_position - (const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +point_position(const Point_2& p, Bezier_cache& cache) const { Nt_traits nt_traits; //First check if the bezier is a vertical segment - if (is_vertical()) - { - if (! p.is_exact()) p.make_exact (cache); - if (! _ps.is_exact()) _ps.make_exact (cache); - if (! _pt.is_exact()) _ps.make_exact (cache); + if (is_vertical()) { + if (! p.is_exact()) p.make_exact(cache); + if (! _ps.is_exact()) _ps.make_exact(cache); + if (! _pt.is_exact()) _ps.make_exact(cache); - if (p.is_rational() && _ps.is_rational() && _pt.is_rational()) - { + if (p.is_rational() && _ps.is_rational() && _pt.is_rational()) { const Rat_point_2& rat_p = (Rat_point_2) p; const Rat_point_2& rat_ps = (Rat_point_2) _ps; const Rat_point_2& rat_pt = (Rat_point_2) _pt; - Comparison_result res1 = (CGAL::compare (rat_p.y(), rat_ps.y())); - Comparison_result res2 = (CGAL::compare (rat_p.y(), rat_pt.y())); - return (res1==res2 ? res1:EQUAL); + Comparison_result res1 = (CGAL::compare(rat_p.y(), rat_ps.y())); + Comparison_result res2 = (CGAL::compare(rat_p.y(), rat_pt.y())); + return (res1== res2 ? res1:EQUAL); } - Comparison_result res1 = (CGAL::compare (p.y(), _ps.y())); - Comparison_result res2 = (CGAL::compare (p.y(), _pt.y())); - return (res1==res2 ? res1:EQUAL); + Comparison_result res1 = (CGAL::compare(p.y(), _ps.y())); + Comparison_result res2 = (CGAL::compare(p.y(), _pt.y())); + return (res1== res2 ? res1:EQUAL); } if (p.identical(_ps)) { @@ -757,106 +690,99 @@ _Bezier_x_monotone_2::point_position // Then check whether the bezier is an horizontal segment or // if p has the same x-coordinate as one of the endpoint - const Comparison_result res1 = p.compare_x (_ps, cache); + const Comparison_result res1 = p.compare_x(_ps, cache); if (res1 == EQUAL || nt_traits.degree(_curve.y_polynomial()) <= 0) { - if (! p.is_exact()) p.make_exact (cache); - if (! _ps.is_exact()) _ps.make_exact (cache); + if (! p.is_exact()) p.make_exact(cache); + if (! _ps.is_exact()) _ps.make_exact(cache); // If both point are rational, compare their rational y-coordinates. if (p.is_rational() && _ps.is_rational()) { - const Rat_point_2& rat_p = (Rat_point_2) p; - const Rat_point_2& rat_ps = (Rat_point_2) _ps; + const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_ps = (Rat_point_2) _ps; - return (CGAL::compare (rat_p.y(), rat_ps.y())); + return (CGAL::compare(rat_p.y(), rat_ps.y())); } // Compare the algebraic y-coordinates. - return (CGAL::compare (p.y(), _ps.y())); + return (CGAL::compare(p.y(), _ps.y())); } - if (p.identical(_pt)) { - return EQUAL; - } + if (p.identical(_pt)) return EQUAL; - const Comparison_result res2 = p.compare_x (_pt, cache); + const Comparison_result res2 = p.compare_x(_pt, cache); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { // In this case both points must be exact. - CGAL_assertion (p.is_exact() && _pt.is_exact()); + CGAL_assertion(p.is_exact() && _pt.is_exact()); // If both point are rational, compare their rational y-coordinates. - if (p.is_rational() && _pt.is_rational()) - { - const Rat_point_2& rat_p = (Rat_point_2) p; - const Rat_point_2& rat_pt = (Rat_point_2) _pt; + if (p.is_rational() && _pt.is_rational()) { + const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_pt = (Rat_point_2) _pt; - return (CGAL::compare (rat_p.y(), rat_pt.y())); + return (CGAL::compare(rat_p.y(), rat_pt.y())); } // Compare the algebraic y-coordinates. - return (CGAL::compare (p.y(), _pt.y())); + return (CGAL::compare(p.y(), _pt.y())); } // Make sure that p is in the x-range of our subcurve. - CGAL_precondition (res1 != res2); + CGAL_precondition(res1 != res2); // Check for the case when curve is an originator of the point. - Originator_iterator p_org = p.get_originator (_curve, _xid); + Originator_iterator p_org = p.get_originator(_curve, _xid); - if (p_org != p.originators_end()) - { + if (p_org != p.originators_end()) { CGAL_assertion_code - (Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + (Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); CGAL_assertion(pt_org != _pt.originators_end())); // Check if the point is in the parameter range of this subcurve. // First try an approximate check of the parameter bounds. - bool correct_res; - bool in_range = false; + bool correct_res; + bool in_range = false; - in_range = _is_in_range (p, correct_res); + in_range = _is_in_range(p, correct_res); - if (! correct_res) - { + if (! correct_res) { // Perform the comparsion in an exact manner. if (! p.is_exact()) - p.make_exact (cache); + p.make_exact(cache); - CGAL_assertion (p_org->has_parameter()); + CGAL_assertion(p_org->has_parameter()); - in_range = _is_in_range (p_org->parameter(), cache); + in_range = _is_in_range(p_org->parameter(), cache); } - if (in_range) - return (EQUAL); + if (in_range) return (EQUAL); } // Call the vertical-position function that uses the bounding-boxes // to evaluate the comparsion result. - typename Bounding_traits::Control_points cp; + typename Bounding_traits::Control_points cp; - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter(cp)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(cp)); - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (ps_org != _ps.originators_end()); + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (pt_org != _pt.originators_end()); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(pt_org != _pt.originators_end()); - Comparison_result res_bound = EQUAL; - typename Bounding_traits::NT x_min, y_min, x_max, y_max; - bool can_refine; + Comparison_result res_bound = EQUAL; + typename Bounding_traits::NT x_min, y_min, x_max, y_max; + bool can_refine; - p.get_bbox (x_min, y_min, x_max, y_max); + p.get_bbox(x_min, y_min, x_max, y_max); - if (CGAL::compare (ps_org->point_bound().t_max, + if (CGAL::compare(ps_org->point_bound().t_max, pt_org->point_bound().t_min) == SMALLER) { // Examine the parameter range of the originator of the source point @@ -866,14 +792,13 @@ _Bezier_x_monotone_2::point_position can_refine = ! _ps.is_exact(); do { - const Rat_point_2& ps = _curve (ps_org->point_bound().t_max); + const Rat_point_2& ps = _curve(ps_org->point_bound().t_max); - if ((_dir_right && CGAL::compare (ps.x(), x_min) != LARGER) || - (! _dir_right && CGAL::compare (ps.x(), x_max) != SMALLER)) + if ((_dir_right && CGAL::compare(ps.x(), x_min) != LARGER) || + (! _dir_right && CGAL::compare(ps.x(), x_max) != SMALLER)) break; - if (can_refine) - can_refine = _ps.refine(); + if (can_refine) can_refine = _ps.refine(); } while (can_refine); // Examine the parameter range of the originator of the target point @@ -883,10 +808,10 @@ _Bezier_x_monotone_2::point_position can_refine = ! _pt.is_exact(); do { - const Rat_point_2& pt = _curve (pt_org->point_bound().t_min); + const Rat_point_2& pt = _curve(pt_org->point_bound().t_min); - if ((_dir_right && CGAL::compare (pt.x(), x_max) != SMALLER) || - (! _dir_right && CGAL::compare (pt.x(), x_min) != LARGER)) + if ((_dir_right && CGAL::compare(pt.x(), x_max) != SMALLER) || + (! _dir_right && CGAL::compare(pt.x(), x_min) != LARGER)) break; if (can_refine) @@ -896,11 +821,11 @@ _Bezier_x_monotone_2::point_position // In this case the parameter value of the source is smaller than the // target's, so we compare the point with the subcurve of B defined over // the proper parameter range. - res_bound = p.vertical_position (cp, + res_bound = p.vertical_position(cp, ps_org->point_bound().t_max, pt_org->point_bound().t_min); } - else if (CGAL::compare (pt_org->point_bound().t_max, + else if (CGAL::compare(pt_org->point_bound().t_max, ps_org->point_bound().t_min) == SMALLER) { // Examine the parameter range of the originator of the source point @@ -908,12 +833,11 @@ _Bezier_x_monotone_2::point_position // lies to the left of p if the curve is directed from left to right // (or to the right of p, if the subcurve is directed from right to left). can_refine = ! _ps.is_exact(); - do - { - const Rat_point_2& ps = _curve (ps_org->point_bound().t_min); + do { + const Rat_point_2& ps = _curve(ps_org->point_bound().t_min); - if ((_dir_right && CGAL::compare (ps.x(), x_min) != LARGER) || - (! _dir_right && CGAL::compare (ps.x(), x_max) != SMALLER)) + if ((_dir_right && CGAL::compare(ps.x(), x_min) != LARGER) || + (! _dir_right && CGAL::compare(ps.x(), x_max) != SMALLER)) break; if (can_refine) @@ -925,12 +849,11 @@ _Bezier_x_monotone_2::point_position // lies to the right of p if the curve is directed from left to right // (or to the left of p, if the subcurve is directed from right to left). can_refine = ! _pt.is_exact(); - do - { - const Rat_point_2& pt = _curve (pt_org->point_bound().t_max); + do { + const Rat_point_2& pt = _curve(pt_org->point_bound().t_max); - if ((_dir_right && CGAL::compare (pt.x(), x_max) != SMALLER) || - (! _dir_right && CGAL::compare (pt.x(), x_min) != LARGER)) + if ((_dir_right && CGAL::compare(pt.x(), x_max) != SMALLER) || + (! _dir_right && CGAL::compare(pt.x(), x_min) != LARGER)) break; if (can_refine) @@ -940,7 +863,7 @@ _Bezier_x_monotone_2::point_position // In this case the parameter value of the source is large than the // target's, so we compare the point with the subcurve of B defined over // the proper parameter range. - res_bound = p.vertical_position (cp, + res_bound = p.vertical_position(cp, pt_org->point_bound().t_max, ps_org->point_bound().t_min); } @@ -960,13 +883,14 @@ _Bezier_x_monotone_2::point_position std::vector roots; std::pair prange = parameter_range(); - nt_traits.compute_polynomial_roots (poly_x,prange.first,prange.second,std::back_inserter(roots)); + nt_traits.compute_polynomial_roots(poly_x,prange.first,prange.second, std::back_inserter(roots)); - CGAL_assertion(roots.size()==1); //p is in the range and the curve is x-monotone + //p is in the range and the curve is x-monotone + CGAL_assertion(roots.size() == 1); return CGAL::compare( ((Rat_point_2) p).y(), - nt_traits.evaluate_at (_curve.y_polynomial(), *roots.begin()) + nt_traits.evaluate_at(_curve.y_polynomial(), *roots.begin()) ); } @@ -974,22 +898,22 @@ _Bezier_x_monotone_2::point_position // p lies of the given subcurve. We take one of p's originating curves and // compute its intersections with our x-monotone curve. if (! p.is_exact()) - p.make_exact (cache); + p.make_exact(cache); - CGAL_assertion (p.originators_begin() != p.originators_end()); + CGAL_assertion(p.originators_begin() != p.originators_end()); Originator org = *(p.originators_begin()); bool do_ovlp; bool swap_order = (_curve.id() > org.curve().id()); const Intersect_list& inter_list = (! swap_order ? - (cache.get_intersections (_curve.id(), + (cache.get_intersections(_curve.id(), _curve.x_polynomial(), _curve.x_norm(), _curve.y_polynomial(), _curve.y_norm(), org.curve().id(), org.curve().x_polynomial(), org.curve().x_norm(), org.curve().y_polynomial(), org.curve().y_norm(), do_ovlp)) : - (cache.get_intersections (org.curve().id(), + (cache.get_intersections(org.curve().id(), org.curve().x_polynomial(), org.curve().x_norm(), org.curve().y_polynomial(), org.curve().y_norm(), _curve.id(), @@ -997,29 +921,24 @@ _Bezier_x_monotone_2::point_position _curve.y_polynomial(), _curve.y_norm(), do_ovlp))); - if (do_ovlp) - return (EQUAL); + if (do_ovlp) return EQUAL; // Go over the intersection points and look for p there. - Intersect_iter iit; - - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { + for (auto iit = inter_list.begin(); iit != inter_list.end(); ++iit) { // Get the parameter of the originator and compare it to p's parameter. - const Algebraic& s = swap_order ? iit->s : iit->t; + const Algebraic& s = swap_order ? iit->s : iit->t; - if (CGAL::compare (s, org.parameter()) == EQUAL) - { + if (CGAL::compare(s, org.parameter()) == EQUAL) { // Add this curve as an originator for p. - const Algebraic& t = swap_order ? iit->t : iit->s; + const Algebraic& t = swap_order ? iit->t : iit->s; - CGAL_assertion (_is_in_range (t, cache)); + CGAL_assertion(_is_in_range(t, cache)); - Point_2& pt = const_cast (p); + Point_2& pt = const_cast(p); pt.add_originator (Originator (_curve, _xid, t)); // The point p lies on the subcurve. - return (EQUAL); + return EQUAL; } } @@ -1028,21 +947,14 @@ _Bezier_x_monotone_2::point_position // between the curve and the point. (This case should be very rare.) // Note that we first try to work with inexact endpoint representation, and // only if we fail we make the endpoints of the x-monotone curves exact. - if (! p.is_exact()) - p.make_exact (cache); + if (! p.is_exact()) p.make_exact (cache); - Comparison_result exact_res = _exact_vertical_position (p, false); + Comparison_result exact_res = _exact_vertical_position(p, false); + if (exact_res != EQUAL) return (exact_res); + if (! _ps.is_exact()) _ps.make_exact(cache); + if (! _pt.is_exact()) _pt.make_exact(cache); - if (exact_res != EQUAL) - return (exact_res); - - if (! _ps.is_exact()) - _ps.make_exact (cache); - - if (! _pt.is_exact()) - _pt.make_exact (cache); - - return (_exact_vertical_position (p, true)); + return (_exact_vertical_position(p, true)); } // --------------------------------------------------------------------------- @@ -1051,57 +963,45 @@ _Bezier_x_monotone_2::point_position // template Comparison_result -_Bezier_x_monotone_2::compare_to_right - (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +compare_to_right(const Self& cv, + const Point_2& p, + Bezier_cache& cache) const { CGAL_precondition (p.compare_xy (right(), cache) != LARGER); CGAL_precondition (p.compare_xy (cv.right(), cache) != LARGER); - if (this == &cv) - return (EQUAL); + if (this == &cv) return EQUAL; // Make sure that p is incident to both curves (either equals the left // endpoint or lies in the curve interior). Note that this is important to // carry out these tests, as it assures us the eventually both curves are // originators of p. - if (! p.equals (left(), cache)) - { - if (point_position (p, cache) != EQUAL) - { + if (! p.equals (left(), cache)) { + if (point_position (p, cache) != EQUAL) { CGAL_precondition_msg (false, "p is not on cv1"); } } - if (! p.equals (cv.left(), cache)) - { - if (cv.point_position (p, cache) != EQUAL) - { + if (! p.equals (cv.left(), cache)) { + if (cv.point_position (p, cache) != EQUAL) { CGAL_precondition_msg (false, "p is not on cv2"); } } // Check for vertical subcurves. A vertical segment is above any other // x-monotone subcurve to the right of their common endpoint. - if (is_vertical()) - { - if (cv.is_vertical()) - // Both are vertical segments with a common endpoint, so they overlap: - return (EQUAL); - + if (is_vertical()) { + // Both are vertical segments with a common endpoint, so they overlap: + if (cv.is_vertical()) return (EQUAL); return (LARGER); } - else if (cv.is_vertical()) - { - return (SMALLER); - } + else if (cv.is_vertical()) return (SMALLER); // Check if both subcurves originate from the same Bezier curve. - Nt_traits nt_traits; + Nt_traits nt_traits; - if (_curve.is_same (cv._curve)) - { + if (_curve.is_same (cv._curve)) { // Get the originator, and check whether p is a vertical tangency // point of this originator (otherwise it is a self-intersection point, // and we proceed as if it is a regular intersection point). @@ -1109,24 +1009,20 @@ _Bezier_x_monotone_2::compare_to_right CGAL_assertion (org != p.originators_end()); - if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) - { + if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) { CGAL_assertion (_inc_to_right != cv._inc_to_right); - if (! p.is_exact()) - { + if (! p.is_exact()) { // Comparison based on the control polygon of the bounded vertical // tangency point, using the fact this polygon is y-monotone. const typename Bounding_traits::Control_points& cp = org->point_bound().ctrl; - if (_inc_to_right) - { - return (CGAL::compare (cp.back().y(), cp.front().y())); + if (_inc_to_right) { + return (CGAL::compare(cp.back().y(), cp.front().y())); } - else - { - return (CGAL::compare (cp.front().y(), cp.back().y())); + else { + return (CGAL::compare(cp.front().y(), cp.back().y())); } } @@ -1135,14 +1031,14 @@ _Bezier_x_monotone_2::compare_to_right // In this case we know that we have a vertical tangency at t0, so // X'(t0) = 0. We evaluate the sign of Y'(t0) in order to find the // vertical position of the two subcurves to the right of this point. - CGAL_assertion (org->has_parameter()); + CGAL_assertion(org->has_parameter()); - const Algebraic& t0 = org->parameter(); - Polynomial polyY_der = nt_traits.derive (_curve.y_polynomial()); - const CGAL::Sign sign_der = - CGAL::sign (nt_traits.evaluate_at (polyY_der, t0)); + const Algebraic& t0 = org->parameter(); + Polynomial polyY_der = nt_traits.derive(_curve.y_polynomial()); + const CGAL::Sign sign_der = + CGAL::sign(nt_traits.evaluate_at(polyY_der, t0)); - CGAL_assertion (sign_der != CGAL::ZERO); + CGAL_assertion(sign_der != CGAL::ZERO); if (_inc_to_right) return ((sign_der == CGAL::POSITIVE) ? LARGER : SMALLER); @@ -1154,28 +1050,27 @@ _Bezier_x_monotone_2::compare_to_right // Compare the slopes of the two supporting curves at p. In the general // case, the slopes are not equal and their comparison gives us the // vertical order to p's right. - Comparison_result slope_res = _compare_slopes (cv, p, cache); + Comparison_result slope_res = _compare_slopes(cv, p, cache); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Compare the two subcurves by choosing some point to the right of p // and comparing the vertical position there. Comparison_result right_res; - if (right().compare_x (cv.right(), cache) != LARGER) + if (right().compare_x(cv.right(), cache) != LARGER) { - right_res = _compare_to_side (cv, p, + right_res = _compare_to_side(cv, p, true, // Compare to p's right. cache); } else { - right_res = cv._compare_to_side (*this, p, + right_res = cv._compare_to_side(*this, p, true, // Compare to p's right. cache); - right_res = CGAL::opposite (right_res); + right_res = CGAL::opposite(right_res); } return (right_res); @@ -1192,8 +1087,8 @@ _Bezier_x_monotone_2::compare_to_left const Point_2& p, Bezier_cache& cache) const { - CGAL_precondition (p.compare_xy (left(), cache) != SMALLER); - CGAL_precondition (p.compare_xy (cv.left(), cache) != SMALLER); + CGAL_precondition(p.compare_xy(left(), cache) != SMALLER); + CGAL_precondition(p.compare_xy(cv.left(), cache) != SMALLER); if (this == &cv) return (EQUAL); @@ -1202,19 +1097,19 @@ _Bezier_x_monotone_2::compare_to_left // endpoint or lies in the curve interior). Note that this is important to // carry out these tests, as it assures us the eventually both curves are // originators of p. - if (! p.equals (right(), cache)) + if (! p.equals(right(), cache)) { - if (point_position (p, cache) != EQUAL) + if (point_position(p, cache) != EQUAL) { - CGAL_precondition_msg (false, "p is not on cv1"); + CGAL_precondition_msg(false, "p is not on cv1"); } } - if (! p.equals (cv.right(), cache)) + if (! p.equals(cv.right(), cache)) { - if (cv.point_position (p, cache) != EQUAL) + if (cv.point_position(p, cache) != EQUAL) { - CGAL_precondition_msg (false, "p is not on cv2"); + CGAL_precondition_msg(false, "p is not on cv2"); } } @@ -1236,15 +1131,15 @@ _Bezier_x_monotone_2::compare_to_left // Check if both subcurves originate from the same Bezier curve. Nt_traits nt_traits; - if (_curve.is_same (cv._curve)) + if (_curve.is_same(cv._curve)) { // Get the originator, and check whether p is a vertical tangency // point of this originator (otherwise it is a self-intersection point, // and we proceed as if it is a regular intersection point). - Originator_iterator org = p.get_originator (_curve, _xid); + Originator_iterator org = p.get_originator(_curve, _xid); - CGAL_assertion (org != p.originators_end()); - CGAL_assertion (_inc_to_right != cv._inc_to_right); + CGAL_assertion(org != p.originators_end()); + CGAL_assertion(_inc_to_right != cv._inc_to_right); if (org->point_bound().type == Bez_point_bound::VERTICAL_TANGENCY_PT) { @@ -1270,14 +1165,14 @@ _Bezier_x_monotone_2::compare_to_left // In this case we know that we have a vertical tangency at t0, so // X'(t0) = 0. We evaluate the sign of Y'(t0) in order to find the // vertical position of the two subcurves to the right of this point. - CGAL_assertion (org->has_parameter()); + CGAL_assertion(org->has_parameter()); const Algebraic& t0 = org->parameter(); - Polynomial polyY_der = nt_traits.derive (_curve.y_polynomial()); + Polynomial polyY_der = nt_traits.derive(_curve.y_polynomial()); const CGAL::Sign sign_der = - CGAL::sign (nt_traits.evaluate_at (polyY_der, t0)); + CGAL::sign(nt_traits.evaluate_at(polyY_der, t0)); - CGAL_assertion (sign_der != CGAL::ZERO); + CGAL_assertion(sign_der != CGAL::ZERO); if (_inc_to_right) return ((sign_der == CGAL::NEGATIVE) ? LARGER : SMALLER); @@ -1290,7 +1185,7 @@ _Bezier_x_monotone_2::compare_to_left // case, the slopes are not equal and their comparison gives us the // vertical order to p's right; note that we swap the order of the curves // to obtains their position to the left. - Comparison_result slope_res = cv._compare_slopes (*this, p, cache); + Comparison_result slope_res = cv._compare_slopes(*this, p, cache); if (slope_res != EQUAL) return (slope_res); @@ -1299,18 +1194,18 @@ _Bezier_x_monotone_2::compare_to_left // and compareing the vertical position there. Comparison_result left_res; - if (left().compare_x (cv.left(), cache) != SMALLER) + if (left().compare_x(cv.left(), cache) != SMALLER) { - left_res = _compare_to_side (cv, p, + left_res = _compare_to_side(cv, p, false, // Compare to p's left. cache); } else { - left_res = cv._compare_to_side (*this, p, + left_res = cv._compare_to_side(*this, p, false, // Compare to p's left. cache); - left_res = CGAL::opposite (left_res); + left_res = CGAL::opposite(left_res); } return (left_res); @@ -1325,7 +1220,7 @@ bool _Bezier_x_monotone_2::equals Bezier_cache& cache) const { // Check if the two subcurves have overlapping supporting curves. - if (! _curve.is_same (cv._curve)) + if (! _curve.is_same(cv._curve)) { //special case when curves are vertical if (cv.is_vertical()){ @@ -1335,7 +1230,7 @@ bool _Bezier_x_monotone_2::equals } // Check whether the two curves have the same support: - if (! _curve.has_same_support (cv._curve)) + if (! _curve.has_same_support(cv._curve)) return (false); // Mark that the two curves overlap in the cache. @@ -1343,14 +1238,14 @@ bool _Bezier_x_monotone_2::equals const Curve_id id2 = cv._curve.id(); if (id1 < id2) - cache.mark_as_overlapping (id1, id2); + cache.mark_as_overlapping(id1, id2); else - cache.mark_as_overlapping (id2, id1); + cache.mark_as_overlapping(id2, id1); } // Check for equality of the endpoints. - return (left().equals (cv.left(), cache) && - right().equals (cv.right(), cache)); + return (left().equals(cv.left(), cache) && + right().equals(cv.right(), cache)); } // --------------------------------------------------------------------------- @@ -1406,9 +1301,9 @@ bool _Bezier_x_monotone_2::can_merge_with { // Note that we only allow merging subcurves of the same originating // Bezier curve (overlapping curves will not do in this case). - return (_curve.is_same (cv._curve) && + return (_curve.is_same(cv._curve) && _xid == cv._xid && - (right().is_same (cv.left()) || left().is_same (cv.right()))); + (right().is_same(cv.left()) || left().is_same(cv.right()))); return (false); } @@ -1421,28 +1316,22 @@ typename _Bezier_x_monotone_2::Self _Bezier_x_monotone_2::merge (const Self& cv) const { - CGAL_precondition (_curve.is_same (cv._curve)); - CGAL_precondition (_xid == cv._xid); + CGAL_precondition(_curve.is_same(cv._curve)); + CGAL_precondition(_xid == cv._xid); - Self res = *this; + Self res = *this; - if (right().is_same (cv.left())) - { + if (right().is_same(cv.left())) { // Extend the subcurve to the right. - if (_dir_right) - res._pt = cv.right(); - else - res._ps = cv.right(); + if (_dir_right) res._pt = cv.right(); + else res._ps = cv.right(); } - else - { - CGAL_precondition (left().is_same (cv.right())); + else { + CGAL_precondition(left().is_same(cv.right())); // Extend the subcurve to the left. - if (_dir_right) - res._ps = cv.left(); - else - res._pt = cv.left(); + if (_dir_right) res._ps = cv.left(); + else res._pt = cv.left(); } return (res); @@ -1451,42 +1340,35 @@ _Bezier_x_monotone_2::merge // --------------------------------------------------------------------------- // Check if the given t-value is in the range of the subcurve. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Algebraic& t, - Bezier_cache& cache) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Algebraic& t, Bezier_cache& cache) const { // First try to use the approximate representation of the endpoints. - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator (_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - Nt_traits nt_traits; + Nt_traits nt_traits; - bool p_lt_ps = - (CGAL::compare (t, nt_traits.convert (s_org->point_bound().t_min)) == - SMALLER); - bool p_gt_ps = - (CGAL::compare (t, nt_traits.convert (s_org->point_bound().t_max)) == - LARGER); - bool p_lt_pt = - (CGAL::compare (t, nt_traits.convert (t_org->point_bound().t_min)) == - SMALLER); - bool p_gt_pt = - (CGAL::compare (t, nt_traits.convert (t_org->point_bound().t_max)) == - LARGER); + bool p_lt_ps = + CGAL::compare(t, nt_traits.convert(s_org->point_bound().t_min)) == SMALLER; + bool p_gt_ps = + CGAL::compare(t, nt_traits.convert(s_org->point_bound().t_max)) == LARGER; + bool p_lt_pt = + CGAL::compare(t, nt_traits.convert(t_org->point_bound().t_min)) == SMALLER; + bool p_gt_pt = + CGAL::compare(t, nt_traits.convert(t_org->point_bound().t_max)) == LARGER; - if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) - { + if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) { // The point p is definitely in the x-range of the subcurve, as its // parameter is between the source and target parameters. - return (true); + return true; } - if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) - { + if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) { // The point p is definitely not in the x-range of the subcurve, // as its parameter is smaller than both source and target parameter // (or greater than both of them). @@ -1507,60 +1389,54 @@ bool _Bezier_x_monotone_2::_is_in_range // --------------------------------------------------------------------------- // Check if the given point lies in the range of this x-monotone subcurve. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Point_2& p, - bool& is_certain) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Point_2& p, bool& is_certain) const { is_certain = true; // Check the easy case that p is one of the subcurve endpoints. - if (p.is_same(_ps) || p.is_same(_pt)) - return true; + if (p.is_same(_ps) || p.is_same(_pt)) return true; // Compare the parameter of p with the parameters of the endpoints. - Originator_iterator p_org = p.get_originator (_curve, _xid); + Originator_iterator p_org = p.get_originator(_curve, _xid); - if (p_org == p.originators_end()) - { - CGAL_assertion (p.get_originator (_curve) != p.originators_end()); + if (p_org == p.originators_end()) { + CGAL_assertion(p.get_originator(_curve) != p.originators_end()); // In this case a different x-monotone curve of the supporting Bezier // curve is an originator of the point, so we know that p does not // lie in the range of our x-monotone subcurve. - return (false); + return false; } - Originator_iterator s_org = _ps.get_originator (_curve, _xid); - CGAL_assertion (s_org != _ps.originators_end()); + Originator_iterator s_org = _ps.get_originator(_curve, _xid); + CGAL_assertion(s_org != _ps.originators_end()); - Originator_iterator t_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (t_org != _pt.originators_end()); + Originator_iterator t_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(t_org != _pt.originators_end()); - bool can_refine_p = ! p.is_exact(); - bool can_refine_s = ! _ps.is_exact(); - bool can_refine_t = ! _pt.is_exact(); + bool can_refine_p = ! p.is_exact(); + bool can_refine_s = ! _ps.is_exact(); + bool can_refine_t = ! _pt.is_exact(); - while (can_refine_p || can_refine_s || can_refine_t) - { - bool p_lt_ps = (CGAL::compare (p_org->point_bound().t_max, - s_org->point_bound().t_min) == SMALLER); - bool p_gt_ps = (CGAL::compare (p_org->point_bound().t_min, - s_org->point_bound().t_max) == LARGER); - bool p_lt_pt = (CGAL::compare (p_org->point_bound().t_max, - t_org->point_bound().t_min) == SMALLER); - bool p_gt_pt = (CGAL::compare (p_org->point_bound().t_min, - t_org->point_bound().t_max) == LARGER); + while (can_refine_p || can_refine_s || can_refine_t) { + bool p_lt_ps = (CGAL::compare(p_org->point_bound().t_max, + s_org->point_bound().t_min) == SMALLER); + bool p_gt_ps = (CGAL::compare(p_org->point_bound().t_min, + s_org->point_bound().t_max) == LARGER); + bool p_lt_pt = (CGAL::compare(p_org->point_bound().t_max, + t_org->point_bound().t_min) == SMALLER); + bool p_gt_pt = (CGAL::compare(p_org->point_bound().t_min, + t_org->point_bound().t_max) == LARGER); - if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) - { + if ((p_gt_ps && p_lt_pt) || (p_lt_ps && p_gt_pt)) { // The point p is definitely in the x-range of the subcurve, as its // parameter is between the source and target parameters. return (true); } - if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) - { + if ((p_lt_ps && p_lt_pt) || (p_gt_ps && p_gt_pt)) { // The point p is definitely not in the x-range of the subcurve, // as its parameter is smaller than both source and target parameter // (or greater than both of them). @@ -1568,19 +1444,14 @@ bool _Bezier_x_monotone_2::_is_in_range } // Try to refine the points. - if (can_refine_p) - can_refine_p = p.refine(); - - if (can_refine_s) - can_refine_s = _ps.refine(); - - if (can_refine_t) - can_refine_t = _pt.refine(); + if (can_refine_p) can_refine_p = p.refine(); + if (can_refine_s) can_refine_s = _ps.refine(); + if (can_refine_t) can_refine_t = _pt.refine(); } // If we reached here, we do not have a certain answer. is_certain = false; - return (false); + return false; } // --------------------------------------------------------------------------- @@ -1588,35 +1459,32 @@ bool _Bezier_x_monotone_2::_is_in_range // determine whether p lies within the t-range of the x-monotone subcurve. // If so, the value t0 such that p = (X(t0), Y(t0)) is also computed. // -template -bool _Bezier_x_monotone_2::_is_in_range - (const Point_2& p, - Bezier_cache& cache, - Algebraic& t0, - bool& is_endpoint) const +template +bool _Bezier_x_monotone_2:: +_is_in_range(const Point_2& p, + Bezier_cache& cache, + Algebraic& t0, + bool& is_endpoint) const { // The given point p must be rational, otherwise there is no point checking // whether it lies in the interior of the curve. - if (! p.is_rational()) - { + if (! p.is_rational()) { is_endpoint = false; - return (false); + return false; } - const Rat_point_2& rat_p = (Rat_point_2) p; + const Rat_point_2& rat_p = (Rat_point_2) p; // Determine the parameter range [t_min, t_max] for our x-monotone // subcurve. - std::pair t_range = _t_range (cache); - Algebraic t_min, t_max; + std::pair t_range = _t_range (cache); + Algebraic t_min, t_max; - if ((_dir_right && _inc_to_right) || (! _dir_right && ! _inc_to_right)) - { + if ((_dir_right && _inc_to_right) || (! _dir_right && ! _inc_to_right)) { t_min = t_range.first; t_max = t_range.second; } - else - { + else { t_min = t_range.second; t_max = t_range.first; } @@ -1624,90 +1492,78 @@ bool _Bezier_x_monotone_2::_is_in_range // The given point p must lie on (X(t), Y(t)) for some t-value. Obtain the // parameter value t0 for that point. We start by computing all t-values // such that X(t) equals the x-coordinate of p. - Nt_traits nt_traits; - std::list t_vals; - typename std::list::iterator t_iter; - Comparison_result res1, res2; - Algebraic y0; + Nt_traits nt_traits; + std::list t_vals; + typename std::list::iterator t_iter; + Comparison_result res1, res2; + Algebraic y0; - if ( is_vertical() ){ - if ( compare(rat_p.x(),left().x())==EQUAL ){ - _curve.get_t_at_y (rat_p.y(), std::back_inserter(t_vals)); + if (is_vertical()){ + if ( compare(rat_p.x(),left().x()) == EQUAL) { + _curve.get_t_at_y(rat_p.y(), std::back_inserter(t_vals)); - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { // Compare the current t-value with t_min. - res1 = CGAL::compare (t_min, *t_iter); + res1 = CGAL::compare(t_min, *t_iter); - if (res1 == LARGER) - continue; + if (res1 == LARGER) continue; - - if (res1 == EQUAL) - { + if (res1 == EQUAL) { t0 = t_min; is_endpoint = true; return (true); } // Compare the current t-value with t_max. - res2 = CGAL::compare (t_max, *t_iter); + res2 = CGAL::compare(t_max, *t_iter); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { t0 = t_max; is_endpoint = true; - return (true); + return true; } - if (res2 == LARGER) - { + if (res2 == LARGER) { t0 = *t_iter; is_endpoint = false; - return (true); + return true; } } } is_endpoint = false; - return (false); + return false; } - _curve.get_t_at_x (rat_p.x(), std::back_inserter(t_vals)); - CGAL_assertion (! t_vals.empty() ); + _curve.get_t_at_x(rat_p.x(), std::back_inserter(t_vals)); + CGAL_assertion(! t_vals.empty() ); - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { // Compare the current t-value with t_min. res1 = CGAL::compare (t_min, *t_iter); - if (res1 == LARGER) - continue; + if (res1 == LARGER) continue; // Make sure the y-coordinates match. - y0 = nt_traits.evaluate_at (_curve.y_polynomial(), *t_iter) / - nt_traits.convert (_curve.y_norm()); + y0 = nt_traits.evaluate_at(_curve.y_polynomial(), *t_iter) / + nt_traits.convert(_curve.y_norm()); - if (CGAL::compare (nt_traits.convert (rat_p.y()), y0) == EQUAL) - { - if (res1 == EQUAL) - { + if (CGAL::compare(nt_traits.convert(rat_p.y()), y0) == EQUAL) { + if (res1 == EQUAL) { t0 = t_min; is_endpoint = true; - return (true); + return true; } // Compare the current t-value with t_max. res2 = CGAL::compare (t_max, *t_iter); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { t0 = t_max; is_endpoint = true; return (true); } - if (res2 == LARGER) - { + if (res2 == LARGER) { t0 = *t_iter; is_endpoint = false; return (true); @@ -1718,53 +1574,48 @@ bool _Bezier_x_monotone_2::_is_in_range // In this case, we have not found a t-value in the range of our subcurve, // so p does not lie on the subcurve: is_endpoint = false; - return (false); + return false; } // --------------------------------------------------------------------------- // Compute a y-coordinate of a point on the x-monotone subcurve with a // given x-coordinate. // -template +template typename _Bezier_x_monotone_2::Algebraic -_Bezier_x_monotone_2::_get_y - (const Rational& x0, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_get_y(const Rational& x0, Bezier_cache& cache) const { // Obtain the t-values for with the x-coordinates of the supporting // curve equal x0. - std::list t_vals; + std::list t_vals; - _curve.get_t_at_x (x0, std::back_inserter(t_vals)); + _curve.get_t_at_x(x0, std::back_inserter(t_vals)); // Find a t-value that is in the range of the current curve. - Nt_traits nt_traits; - typename std::list::iterator t_iter; - std::pair t_range = _t_range (cache); - const Algebraic& t_src = t_range.first; - const Algebraic& t_trg = t_range.second; - Comparison_result res1, res2; + Nt_traits nt_traits; + typename std::list::iterator t_iter; + std::pair t_range = _t_range (cache); + const Algebraic& t_src = t_range.first; + const Algebraic& t_trg = t_range.second; + Comparison_result res1, res2; - for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) - { + for (t_iter = t_vals.begin(); t_iter != t_vals.end(); ++t_iter) { res1 = CGAL::compare (*t_iter, t_src); - if (res1 == EQUAL) - { + if (res1 == EQUAL) { // Return the y-coordinate of the source point: return (_ps.y()); } res2 = CGAL::compare (*t_iter, t_trg); - if (res2 == EQUAL) - { + if (res2 == EQUAL) { // Return the y-coordinate of the source point: return (_pt.y()); } - if (res1 != res2) - { + if (res1 != res2) { // We found a t-value in the range of our x-monotone subcurve. // Use this value to compute the y-coordinate. return (nt_traits.evaluate_at (_curve.y_polynomial(), *t_iter) / @@ -1774,42 +1625,38 @@ _Bezier_x_monotone_2::_get_y // If we reached here, x0 is not in the x-range of our subcurve. CGAL_error(); - return (0); + return 0; } // --------------------------------------------------------------------------- // Compare the slopes of the subcurve with another given Bezier subcurve at // their given intersection point. // -template +template Comparison_result -_Bezier_x_monotone_2::_compare_slopes - (const Self& cv, - const Point_2& p, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_compare_slopes(const Self& cv, const Point_2& p, Bezier_cache& cache) const { // Get the originators of p. - Originator_iterator org1 = p.get_originator (_curve, _xid); - const bool valid_org1 = (org1 != p.originators_end()); + Originator_iterator org1 = p.get_originator(_curve, _xid); + const bool valid_org1 = (org1 != p.originators_end()); - Originator_iterator org2 = p.get_originator (cv._curve, cv._xid); - const bool valid_org2 = (org2 != p.originators_end()); + Originator_iterator org2 = p.get_originator(cv._curve, cv._xid); + const bool valid_org2 = (org2 != p.originators_end()); - CGAL_assertion (valid_org1 || valid_org2); + CGAL_assertion(valid_org1 || valid_org2); // If the point is only approximated, we can carry out a comparison using // an approximate number type. - if (valid_org1 && valid_org2 && ! p.is_exact()) - { + if (valid_org1 && valid_org2 && ! p.is_exact()) { // If the point is inexact, we assume it is a bounded intersection // point of two curves, and therefore the bounding angle these curves // span do not overlap. - const Bez_point_bound& bound1 = org1->point_bound(); - const Bez_point_bound& bound2 = org2->point_bound(); - Bounding_traits bound_tr; + const Bez_point_bound& bound1 = org1->point_bound(); + const Bez_point_bound& bound2 = org2->point_bound(); + Bounding_traits bound_tr; - return (bound_tr.compare_slopes_at_intersection_point (bound1, - bound2)); + return (bound_tr.compare_slopes_at_intersection_point(bound1, bound2)); } // Obtain the parameter values t1 and t2 that correspond to the point p. @@ -1818,17 +1665,15 @@ _Bezier_x_monotone_2::_compare_slopes // it must be a ratioal point!) and lies in its interior. In this // (degenerate) case we compute the parameter value and set the appropriate // originator for p. - Nt_traits nt_traits; - Algebraic t1; - Algebraic t2; + Nt_traits nt_traits; + Algebraic t1; + Algebraic t2; - if (valid_org1) - { + if (valid_org1) { CGAL_assertion (org1->has_parameter()); t1 = org1->parameter(); } - else - { + else { bool is_endpoint1; CGAL_assertion_code (bool in_range1 =) _is_in_range (p, cache, t1, is_endpoint1); @@ -1836,66 +1681,60 @@ _Bezier_x_monotone_2::_compare_slopes p.add_originator (Originator (_curve, _xid, t1)); } - if (valid_org2) - { + if (valid_org2) { CGAL_assertion (org2->has_parameter()); t2 = org2->parameter(); } - else - { - bool is_endpoint2; - CGAL_assertion_code (bool in_range2 =) - cv._is_in_range (p, cache, t2, is_endpoint2); - CGAL_assertion (in_range2); - p.add_originator (Originator (cv._curve, cv._xid, t2)); + else { + bool is_endpoint2; + CGAL_assertion_code(bool in_range2 =) + cv._is_in_range(p, cache, t2, is_endpoint2); + CGAL_assertion(in_range2); + p.add_originator(Originator (cv._curve, cv._xid, t2)); } // The slope of (X(t), Y(t)) at t0 is given by Y'(t0)/X'(t0). // Compute the slope of (*this). // Note that we take special care of the case X'(t0) = 0, when the tangent // is vertical and its slope is +/- oo. - Polynomial derivX = nt_traits.derive (_curve.x_polynomial()); - Polynomial derivY = nt_traits.derive (_curve.y_polynomial()); - Algebraic numer1 = nt_traits.evaluate_at (derivY, t1) * - nt_traits.convert (_curve.x_norm()); - Algebraic denom1 = nt_traits.evaluate_at (derivX, t1) * - nt_traits.convert (_curve.y_norm()); - CGAL::Sign inf_slope1 = CGAL::ZERO; - Algebraic slope1; + Polynomial derivX = nt_traits.derive(_curve.x_polynomial()); + Polynomial derivY = nt_traits.derive(_curve.y_polynomial()); + Algebraic numer1 = nt_traits.evaluate_at(derivY, t1) * + nt_traits.convert (_curve.x_norm()); + Algebraic denom1 = nt_traits.evaluate_at(derivX, t1) * + nt_traits.convert (_curve.y_norm()); + CGAL::Sign inf_slope1 = CGAL::ZERO; + Algebraic slope1; - if (CGAL::sign (denom1) == CGAL::ZERO) - { - inf_slope1 = is_directed_right() ? CGAL::sign (numer1) : CGAL::opposite( CGAL::sign (numer1) ); + if (CGAL::sign (denom1) == CGAL::ZERO) { + inf_slope1 = is_directed_right() ? + CGAL::sign(numer1) : CGAL::opposite(CGAL::sign(numer1)); // If both derivatives are zero, we cannot perform the comparison: - if (inf_slope1 == CGAL::ZERO) - return (EQUAL); + if (inf_slope1 == CGAL::ZERO) return EQUAL; } - else - { + else { slope1 = numer1 / denom1; } // Compute the slope of the other subcurve. derivX = nt_traits.derive (cv._curve.x_polynomial()); derivY = nt_traits.derive (cv._curve.y_polynomial()); - Algebraic numer2 = nt_traits.evaluate_at (derivY, t2) * - nt_traits.convert (cv._curve.x_norm()); - Algebraic denom2 = nt_traits.evaluate_at (derivX, t2) * - nt_traits.convert (cv._curve.y_norm()); - CGAL::Sign inf_slope2 = CGAL::ZERO; - Algebraic slope2; + Algebraic numer2 = nt_traits.evaluate_at (derivY, t2) * + nt_traits.convert (cv._curve.x_norm()); + Algebraic denom2 = nt_traits.evaluate_at (derivX, t2) * + nt_traits.convert (cv._curve.y_norm()); + CGAL::Sign inf_slope2 = CGAL::ZERO; + Algebraic slope2; - if (CGAL::sign (denom2) == CGAL::ZERO) - { - inf_slope2 = cv.is_directed_right() ? CGAL::sign (numer2) : CGAL::opposite( CGAL::sign (numer2) ); + if (CGAL::sign (denom2) == CGAL::ZERO) { + inf_slope2 = cv.is_directed_right() ? + CGAL::sign (numer2) : CGAL::opposite( CGAL::sign (numer2) ); // If both derivatives are zero, we cannot perform the comparison: - if (inf_slope2 == CGAL::ZERO) - return (EQUAL); + if (inf_slope2 == CGAL::ZERO) return (EQUAL); } - else - { + else { slope2 = numer2 / denom2; } @@ -1906,11 +1745,9 @@ _Bezier_x_monotone_2::_compare_slopes if (inf_slope1 == CGAL::NEGATIVE) return (inf_slope2 == CGAL::NEGATIVE ? EQUAL : SMALLER); - if (inf_slope2 == CGAL::POSITIVE) - return (SMALLER); + if (inf_slope2 == CGAL::POSITIVE) return (SMALLER); - if (inf_slope2 == CGAL::NEGATIVE) - return (LARGER); + if (inf_slope2 == CGAL::NEGATIVE) return (LARGER); // Compare the slopes. return (CGAL::compare (slope1, slope2)); @@ -1919,29 +1756,25 @@ _Bezier_x_monotone_2::_compare_slopes // --------------------------------------------------------------------------- // Get the range of t-value over which the subcurve is defined. // -template +template std::pair::Algebraic, typename _Bezier_x_monotone_2::Algebraic> -_Bezier_x_monotone_2::_t_range - (Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_t_range(Bezier_cache& cache) const { - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion(ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); CGAL_assertion(pt_org != _pt.originators_end()); // Make sure that the two endpoints are exact. - if (! ps_org->has_parameter()) - _ps.make_exact (cache); + if (! ps_org->has_parameter()) _ps.make_exact (cache); + if (! pt_org->has_parameter()) _pt.make_exact (cache); - if (! pt_org->has_parameter()) - _pt.make_exact (cache); - - return (std::make_pair (ps_org->parameter(), - pt_org->parameter())); + return (std::make_pair(ps_org->parameter(), pt_org->parameter())); } // --------------------------------------------------------------------------- @@ -1949,18 +1782,18 @@ _Bezier_x_monotone_2::_t_range // (or to the left) of their intersection point, whose multiplicity is // greater than 1. // -template +template Comparison_result -_Bezier_x_monotone_2::_compare_to_side - (const Self& cv, - const Point_2& p, - bool to_right, - Bezier_cache& cache) const +_Bezier_x_monotone_2:: +_compare_to_side(const Self& cv, + const Point_2& p, + bool to_right, + Bezier_cache& cache) const { // Get the intersection points of the two curves from the cache. Note that // we make sure that the ID of this->_curve is smaller than of cv's curve ID. - const bool no_swap_curves = (_curve.id() <= cv._curve.id()); - bool do_ovlp; + const bool no_swap_curves = (_curve.id() <= cv._curve.id()); + bool do_ovlp; const Intersect_list& inter_list = (no_swap_curves ? (cache.get_intersections (_curve.id(), @@ -1984,40 +1817,36 @@ _Bezier_x_monotone_2::_compare_to_side CGAL_assertion (org != p.originators_end()); CGAL_assertion (org->has_parameter()); - const Algebraic& t0 = org->parameter(); + const Algebraic& t0 = org->parameter(); // Get the parameter range of the curve. - const std::pair& range = _t_range (cache); - const Algebraic& t_src = range.first; - const Algebraic& t_trg = range.second; + const std::pair& range = _t_range (cache); + const Algebraic& t_src = range.first; + const Algebraic& t_trg = range.second; // Find the next intersection point that lies to the right of p. - Intersect_iter iit; - Algebraic next_t; - Comparison_result res = CGAL::EQUAL; - bool found = false; + Intersect_iter iit; + Algebraic next_t; + Comparison_result res = CGAL::EQUAL; + bool found = false; - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { + for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) { // Check if the current point lies to the right (left) of p. We do so by // considering its originating parameter value s (or t, if we swapped // the curves). - const Algebraic& t = (no_swap_curves ? (iit->s) : iit->t); + const Algebraic& t = (no_swap_curves ? (iit->s) : iit->t); - res = CGAL::compare (t, t0); + res = CGAL::compare(t, t0); if ((to_right && ((_inc_to_right && res == LARGER) || (! _inc_to_right && res == SMALLER))) || (! to_right && ((_inc_to_right && res == SMALLER) || (! _inc_to_right && res == LARGER)))) { - if (! found) - { + if (! found) { next_t = t; found = true; } - else - { + else { // If we have already located an intersection point to the right // (left) of p, choose the leftmost (rightmost) of the two points. res = CGAL::compare (t, next_t); @@ -2035,12 +1864,9 @@ _Bezier_x_monotone_2::_compare_to_side // If the next intersection point occurs before the right (left) endpoint // of the subcurve, keep it. Otherwise, take the parameter value at // the endpoint. - if (found) - { - if (to_right == _dir_right) - res = CGAL::compare (t_trg, next_t); - else - res = CGAL::compare (t_src, next_t); + if (found) { + if (to_right == _dir_right) res = CGAL::compare (t_trg, next_t); + else res = CGAL::compare (t_src, next_t); } if (! found || @@ -2055,10 +1881,10 @@ _Bezier_x_monotone_2::_compare_to_side // Find a rational value between t0 and t_next. Using this value, we // a point with rational coordinates on our subcurve. We also locate a point // on the other curve with the same x-coordinates. - Nt_traits nt_traits; - const Rational& mid_t = nt_traits.rational_in_interval (t0, next_t); - const Rat_point_2& q1 = _curve (mid_t); - const Algebraic& y2 = cv._get_y (q1.x(), cache); + Nt_traits nt_traits; + const Rational& mid_t = nt_traits.rational_in_interval(t0, next_t); + const Rat_point_2& q1 = _curve(mid_t); + const Algebraic& y2 = cv._get_y(q1.x(), cache); // We now just have to compare the y-coordinates of the two points we have // computed. @@ -2069,33 +1895,32 @@ _Bezier_x_monotone_2::_compare_to_side // Clip the control polygon of the supporting Bezier curve such that it fits // the current x-monotone subcurve. // -template -void _Bezier_x_monotone_2::_clip_control_polygon - (typename Bounding_traits::Control_points& ctrl, - typename Bounding_traits::NT& t_min, - typename Bounding_traits::NT& t_max) const +template +void _Bezier_x_monotone_2:: +_clip_control_polygon(typename Bounding_traits::Control_points& ctrl, + typename Bounding_traits::NT& t_min, + typename Bounding_traits::NT& t_max) const { // Start from the control polygon of the supporting curve. ctrl.clear(); - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter (ctrl)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(ctrl)); // The x-monotone subcurve is defined over a parameter range // 0 <= t_min < t_max <= 1. Determine the endpoint with minimal t-value and // the one with maximal t-value. - const Point_2& p_min = (_inc_to_right ? left() : right()); - Originator_iterator org_min = p_min.get_originator (_curve, _xid); - const Point_2& p_max = (_inc_to_right ? right() : left()); - Originator_iterator org_max = p_max.get_originator (_curve, _xid); - bool clipped_min = false; + const Point_2& p_min = (_inc_to_right ? left() : right()); + Originator_iterator org_min = p_min.get_originator(_curve, _xid); + const Point_2& p_max = (_inc_to_right ? right() : left()); + Originator_iterator org_max = p_max.get_originator(_curve, _xid); + bool clipped_min = false; - CGAL_assertion (org_min != p_min.originators_end()); - CGAL_assertion (org_max != p_max.originators_end()); + CGAL_assertion(org_min != p_min.originators_end()); + CGAL_assertion(org_max != p_max.originators_end()); // Check if t_min = 0. If so, there is no need to clip. if (! (org_min->point_bound().type == Bez_point_bound::RATIONAL_PT && - CGAL::sign (org_min->point_bound().t_min) == CGAL::ZERO)) + CGAL::sign(org_min->point_bound().t_min) == CGAL::ZERO)) { // It is possible that the paramater range of the originator is too large. // We therefore make sure it fits the current bounding box of the point @@ -2104,22 +1929,20 @@ void _Bezier_x_monotone_2point_bound().t_max; - de_Casteljau_2 (ctrl.begin(), ctrl.end(), - t_min, - std::back_inserter(cp_a), - std::front_inserter(cp_b)); + de_Casteljau_2(ctrl.begin(), ctrl.end(), + t_min, + std::back_inserter(cp_a), + std::front_inserter(cp_b)); ctrl.clear(); - std::copy (cp_b.begin(), cp_b.end(), - std::back_inserter (ctrl)); + std::copy(cp_b.begin(), cp_b.end(), std::back_inserter (ctrl)); clipped_min = true; } - else - { + else { t_min = 0; } @@ -2137,27 +1960,21 @@ void _Bezier_x_monotone_2point_bound().t_min - t_min) / (1 - t_min); } - else - { + else { t_max = org_max->point_bound().t_min; } - de_Casteljau_2 (ctrl.begin(), ctrl.end(), - t_max, - std::back_inserter(cp_a), - std::front_inserter(cp_b)); + de_Casteljau_2(ctrl.begin(), ctrl.end(), t_max, + std::back_inserter(cp_a), std::front_inserter(cp_b)); ctrl.clear(); - std::copy (cp_a.begin(), cp_a.end(), - std::back_inserter (ctrl)); + std::copy(cp_a.begin(), cp_a.end(), std::back_inserter (ctrl)); t_max = org_max->point_bound().t_min; } - else - { + else { t_max = 1; } @@ -2167,11 +1984,10 @@ void _Bezier_x_monotone_2 -bool _Bezier_x_monotone_2::_approximate_intersection_points - (const Self& cv, - std::list& inter_pts) const +template +bool _Bezier_x_monotone_2:: +_approximate_intersection_points(const Self& cv, + std::list& inter_pts) const { typedef typename Bounding_traits::Intersection_point Intersection_point; @@ -2179,16 +1995,15 @@ bool _Bezier_x_monotone_2_curve; - const Curve_2& B2 = cv._curve; - typename Bounding_traits::Control_points cp1; - typename Bounding_traits::NT t_min1 = 0, t_max1 = 1; + const Curve_2& B1 = this->_curve; + const Curve_2& B2 = cv._curve; + typename Bounding_traits::Control_points cp1; + typename Bounding_traits::NT t_min1 = 0, t_max1 = 1; typename Bounding_traits::Control_points cp2; - typename Bounding_traits::NT t_min2 = 0, t_max2 = 1; - bool is_self_intersection = false; + typename Bounding_traits::NT t_min2 = 0, t_max2 = 1; + bool is_self_intersection = false; - if (! B1.is_same (B2)) - { + if (! B1.is_same (B2)) { // In case B1 and B2 are different curves, use their full control polygons // in order to approximate all intersection points between the two // supporting Bezier curves. @@ -2197,8 +2012,7 @@ bool _Bezier_x_monotone_2 ipt_bounds; + Bounding_traits bound_tr; + std::list ipt_bounds; - bound_tr.compute_intersection_points (cp1, cp2, - std::back_inserter (ipt_bounds)); + bound_tr.compute_intersection_points(cp1, cp2, std::back_inserter(ipt_bounds)); // Construct the approximated points. - typename std::list::const_iterator iter; - - for (iter = ipt_bounds.begin(); iter != ipt_bounds.end(); ++iter) - { + for (auto iter = ipt_bounds.begin(); iter != ipt_bounds.end(); ++iter) { const Bez_point_bound& bound1 = iter->bound1; const Bez_point_bound& bound2 = iter->bound2; const Bez_point_bbox& bbox = iter->bbox; // In case it is impossible to further refine the point, stop here. - if (! bound1.can_refine || ! bound2.can_refine) - return (false); + if (! bound1.can_refine || ! bound2.can_refine) return false; // Create the approximated intersection point. - Point_2 pt; + Point_2 pt; if (bound1.type == Bounding_traits::Bez_point_bound::RATIONAL_PT && bound2.type == Bounding_traits::Bez_point_bound::RATIONAL_PT) { - CGAL_assertion (CGAL::compare (bound1.t_min, bound1.t_max) == EQUAL); - CGAL_assertion (CGAL::compare (bound2.t_min, bound2.t_max) == EQUAL); - Rational t1 = bound1.t_min; - Rational t2 = bound2.t_min; - Nt_traits nt_traits; + CGAL_assertion (CGAL::compare(bound1.t_min, bound1.t_max) == EQUAL); + CGAL_assertion (CGAL::compare(bound2.t_min, bound2.t_max) == EQUAL); + Rational t1 = bound1.t_min; + Rational t2 = bound2.t_min; + Nt_traits nt_traits; - if (is_self_intersection) - { + if (is_self_intersection) { // Set the originators with the curve x-monotone IDs. // Note that the parameter values we have computed relate to the // parameter range [t_min1, t_max1] and [t_min2, t_max2], respectively, @@ -2249,63 +2057,60 @@ bool _Bezier_x_monotone_2 -bool _Bezier_x_monotone_2::_intersect - (const Self& cv, - Intersection_map& inter_map, - Bezier_cache& cache, - std::vector& ipts, - Self& ovlp_cv) const +template +bool _Bezier_x_monotone_2:: +_intersect(const Self& cv, + Intersection_map& inter_map, + Bezier_cache& cache, + std::vector& ipts, + Self& ovlp_cv) const { - CGAL_precondition (_curve.id() <= cv._curve.id()); + CGAL_precondition(_curve.id() <= cv._curve.id()); ipts.clear(); @@ -2313,115 +2118,96 @@ bool _Bezier_x_monotone_2::_intersect // first check if this base curve is not self-intersecting. If this is the // case we can avoid any attempt of computing intersection points between // the two subcurves. - const bool self_intersect = (_curve.id() == cv._curve.id()); + const bool self_intersect = (_curve.id() == cv._curve.id()); - if (self_intersect) - { - if (_xid == cv._xid) - return (false); - - if (_curve.has_no_self_intersections()) - return (false); + if (self_intersect) { + if (_xid == cv._xid) return false; + if (_curve.has_no_self_intersections()) return false; } // Construct the pair of curve IDs and look for it in the intersection map. - Curve_pair curve_pair (_curve.id(), cv._curve.id()); - Intersection_map_iterator map_iter = inter_map.find (curve_pair); - std::list inter_pts; - bool app_ok = true; + Curve_pair curve_pair(_curve.id(), cv._curve.id()); + Intersection_map_iterator map_iter = inter_map.find(curve_pair); + std::list inter_pts; + bool app_ok = true; - if (map_iter != inter_map.end()) - { + if (map_iter != inter_map.end()) { // Get the intersection points between the two supporting curves as stored // in the map. inter_pts = map_iter->second; } - else - { + else { // Approximate the intersection points and store them in the map. // Note that we do not store approximated self-intersections in the map, // as they realte only to the pecific x-monotone curves, and not to the // entire curve. - app_ok = _approximate_intersection_points (cv, - inter_pts); + app_ok = _approximate_intersection_points(cv, inter_pts); - if (app_ok && ! self_intersect) - inter_map[curve_pair] = inter_pts; + if (app_ok && ! self_intersect) inter_map[curve_pair] = inter_pts; } // Try to approximate the intersection points. - bool in_range1, in_range2; - bool correct_res; + bool in_range1, in_range2; + bool correct_res; - if (app_ok) - { + if (app_ok) { // Approximations are computed using de Casteljau subdivision and // filtering using skewed bounding boxes. A property of these bboxes - // if that it can fail in the following cases: (i) there are two intersection - // points lying very close together, (ii) there exists an intersection point - // whose multiplicity is greater than 1, or (iii) the curves overlap. - // If the approximation went OK, then we know that we have a simple - // intersection point (with multiplicity 1) if intersection point - // is not rational (otherwise it is unknown: at this point, an intersection point - // is rational if it was found as a control point during the de Casteljau subdivision) + // if that it can fail in the following cases: (i) there are two + // intersection points lying very close together, (ii) there exists an + // intersection point whose multiplicity is greater than 1, or (iii) the + // curves overlap. If the approximation went OK, then we know that we have + // a simple intersection point (with multiplicity 1) if intersection point + // is not rational (otherwise it is unknown: at this point, an intersection + // point is rational if it was found as a control point during the de + // Casteljau subdivision) // We go over the points and report the ones lying in the parameter // ranges of both curves. Note that in case of self-intersections, // all points we get are in the respective parameter range of the curves. typename std::list::iterator pit; - for (pit = inter_pts.begin(); pit != inter_pts.end(); ++pit) - { + for (pit = inter_pts.begin(); pit != inter_pts.end(); ++pit) { // Check if the point is in the range of this curve - first using // its parameter bounds, and if we fail we perform an exact check. - if (! self_intersect) - { - in_range1 = _is_in_range (*pit, correct_res); + if (! self_intersect) { + in_range1 = _is_in_range(*pit, correct_res); } - else - { + else { in_range1 = true; correct_res = true; } - if (! correct_res) - { - if (! pit->is_exact()) - pit->make_exact (cache); + if (! correct_res) { + if (! pit->is_exact()) pit->make_exact(cache); - Originator_iterator p_org = pit->get_originator (_curve, _xid); + Originator_iterator p_org = pit->get_originator (_curve, _xid); CGAL_assertion (p_org != pit->originators_end()); - in_range1 = _is_in_range (p_org->parameter(), cache); + in_range1 = _is_in_range(p_org->parameter(), cache); } - if (! in_range1) - continue; + if (! in_range1) continue; // Check if the point is in the range of the other curve - first using // its parameter bounds, and if we fail we perform an exact check. - if (! self_intersect) - { + if (! self_intersect) { in_range2 = cv._is_in_range (*pit, correct_res); } - else - { + else { in_range2 = true; correct_res = true; } - if (! correct_res) - { - if (! pit->is_exact()) - pit->make_exact (cache); + if (! correct_res) { + if (! pit->is_exact()) pit->make_exact (cache); Originator_iterator p_org = pit->get_originator (cv._curve, cv._xid); - CGAL_assertion (p_org != pit->originators_end()); + CGAL_assertion(p_org != pit->originators_end()); - in_range2 = cv._is_in_range (p_org->parameter(), cache); + in_range2 = cv._is_in_range(p_org->parameter(), cache); } - if (in_range1 && in_range2) - { + if (in_range1 && in_range2) { // In case the originators of the intersection point are not marked // with x-monotone identifiers, mark them now as we know in which // subcurves they lie. @@ -2429,17 +2215,17 @@ bool _Bezier_x_monotone_2::_intersect CGAL_assertion (p_org1 != pit->originators_end()); if (p_org1->xid() == 0) - pit->update_originator_xid (*p_org1, _xid); + pit->update_originator_xid(*p_org1, _xid); Originator_iterator p_org2 = pit->get_originator (cv._curve, cv._xid); CGAL_assertion (p_org2 != pit->originators_end()); if (p_org2->xid() == 0) - pit->update_originator_xid (*p_org2, cv._xid); + pit->update_originator_xid(*p_org2, cv._xid); // The point lies within the parameter range of both curves, so we // report it as a valid intersection point with multiplicity 1 or unknown. - ipts.push_back (Intersection_point_2 (*pit, pit->is_rational()?0:1)); + ipts.push_back(Intersection_point(*pit, pit->is_rational() ? 0 : 1)); } } @@ -2449,34 +2235,30 @@ bool _Bezier_x_monotone_2::_intersect // We did not succeed in isolate the approximate intersection points. // We therefore resort to the exact procedure and exactly compute them. - bool do_ovlp; - const Intersect_list& inter_list = - cache.get_intersections (_curve.id(), - _curve.x_polynomial(), _curve.x_norm(), - _curve.y_polynomial(), _curve.y_norm(), - cv._curve.id(), - cv._curve.x_polynomial(), cv._curve.x_norm(), - cv._curve.y_polynomial(), cv._curve.y_norm(), - do_ovlp); + bool do_ovlp; + const Intersect_list& inter_list = + cache.get_intersections(_curve.id(), + _curve.x_polynomial(), _curve.x_norm(), + _curve.y_polynomial(), _curve.y_norm(), + cv._curve.id(), + cv._curve.x_polynomial(), cv._curve.x_norm(), + cv._curve.y_polynomial(), cv._curve.y_norm(), + do_ovlp); - if (do_ovlp) - { + if (do_ovlp) { // Check the case of co-inciding endpoints - if (left().equals (cv.left(), cache)) - { - if (right().equals (cv.right(), cache)) - { + if (left().equals (cv.left(), cache)) { + if (right().equals (cv.right(), cache)) { // The two curves entirely overlap one another: ovlp_cv = cv; - return (true); + return true; } - Algebraic t_right; - bool is_endpoint; + Algebraic t_right; + bool is_endpoint; - if (_is_in_range (cv.right(), cache, t_right, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + if (_is_in_range(cv.right(), cache, t_right, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 1 - *this: s +-----------+ t // cv: s'+=====+ t' @@ -2484,13 +2266,12 @@ bool _Bezier_x_monotone_2::_intersect // Take cv as the overlapping subcurve, and add originators for its // right endpoint referring to *this. ovlp_cv = cv; - ovlp_cv.right().add_originator (Originator (_curve, _xid, t_right)); + ovlp_cv.right().add_originator(Originator(_curve, _xid, t_right)); - return (true); + return true; } - else if (cv._is_in_range (right(), cache, t_right, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + else if (cv._is_in_range(right(), cache, t_right, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 2 - *this: s +----+ t // cv: s'+==========+ t' @@ -2498,24 +2279,21 @@ bool _Bezier_x_monotone_2::_intersect // Take this as the overlapping subcurve, and add originators for its // right endpoint referring to cv. ovlp_cv = *this; - ovlp_cv.right().add_originator (Originator (cv._curve, cv._xid, - t_right)); + ovlp_cv.right().add_originator(Originator(cv._curve, cv._xid, t_right)); - return (true); + return true; } // In this case the two curves do not overlap, but have a common left // endpoint. - ipts.push_back (Intersection_point_2 (left(), 0)); + ipts.push_back(Intersection_point(left(), 0)); return (false); } - else if (right().equals (cv.right(), cache)) - { - Algebraic t_left; - bool is_endpoint; + else if (right().equals (cv.right(), cache)) { + Algebraic t_left; + bool is_endpoint; - if (_is_in_range (cv.left(), cache, t_left, is_endpoint)) - { + if (_is_in_range (cv.left(), cache, t_left, is_endpoint)) { CGAL_assertion (! is_endpoint); // Case 3 - *this: s +-----------+ t @@ -2528,9 +2306,8 @@ bool _Bezier_x_monotone_2::_intersect return (true); } - else if (cv._is_in_range (left(), cache, t_left, is_endpoint)) - { - CGAL_assertion (! is_endpoint); + else if (cv._is_in_range(left(), cache, t_left, is_endpoint)) { + CGAL_assertion(! is_endpoint); // Case 4 - *this: s +----+ t // cv: s'+==========+ t' @@ -2538,30 +2315,26 @@ bool _Bezier_x_monotone_2::_intersect // Take this as the overlapping subcurve, and add originators for its // left endpoint referring to cv. ovlp_cv = *this; - ovlp_cv.left().add_originator (Originator (cv._curve, cv._xid, - t_left)); + ovlp_cv.left().add_originator(Originator(cv._curve, cv._xid, t_left)); - return (true); + return true; } // In this case the two curves do not overlap, but have a common right // endpoint. - ipts.push_back (Intersection_point_2 (right(), 0)); - return (false); + ipts.push_back(Intersection_point(right(), 0)); + return false; } // If we reached here, none of the endpoints coincide. // Check the possible overlap scenarios. - Point_2 ovrp_src, ovlp_trg; - Algebraic t_cv_src; - Algebraic t_cv_trg; - bool is_endpoint = false; + Point_2 ovrp_src, ovlp_trg; + Algebraic t_cv_src; + Algebraic t_cv_trg; + bool is_endpoint = false; - if (_is_in_range (cv._ps, cache, t_cv_src, is_endpoint) && - ! is_endpoint) - { - if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && - ! is_endpoint) + if (_is_in_range (cv._ps, cache, t_cv_src, is_endpoint) && ! is_endpoint) { + if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && ! is_endpoint) { // Case 5 - *this: s +-----------+ t // cv: s' +=====+ t' @@ -2569,32 +2342,30 @@ bool _Bezier_x_monotone_2::_intersect // Take cv as the overlapping subcurve, and add originators for its // endpoints referring to *this. ovlp_cv = cv; - ovlp_cv._ps.add_originator (Originator (_curve, _xid, t_cv_src)); - ovlp_cv._pt.add_originator (Originator (_curve, _xid, t_cv_trg)); + ovlp_cv._ps.add_originator(Originator (_curve, _xid, t_cv_src)); + ovlp_cv._pt.add_originator(Originator (_curve, _xid, t_cv_trg)); - return (true); + return true; } - else - { + else { // Case 6 - *this: s +-----------+ t // cv: s' +=====+ t' // // Use *this as a base, and replace its source point. ovlp_cv = *this; ovlp_cv._ps = cv._ps; - ovlp_cv._ps.add_originator (Originator (_curve, _xid, t_cv_src)); + ovlp_cv._ps.add_originator(Originator (_curve, _xid, t_cv_src)); // Add an originator to the target point, referring to cv: - CGAL_assertion_code (bool pt_in_cv_range =) - cv._is_in_range (ovlp_cv._pt, cache, t_cv_trg, is_endpoint); - CGAL_assertion (pt_in_cv_range); - ovlp_cv._pt.add_originator (Originator (cv._curve, cv._xid, t_cv_trg)); + CGAL_assertion_code(bool pt_in_cv_range =) + cv._is_in_range(ovlp_cv._pt, cache, t_cv_trg, is_endpoint); + CGAL_assertion(pt_in_cv_range); + ovlp_cv._pt.add_originator(Originator(cv._curve, cv._xid, t_cv_trg)); - return (true); + return true; } } - else if (_is_in_range (cv._pt, cache, t_cv_trg, is_endpoint) && - ! is_endpoint) + else if (_is_in_range(cv._pt, cache, t_cv_trg, is_endpoint) && ! is_endpoint) { // Case 7 - *this: s +-----------+ t // cv: s' +=====+ t' @@ -2606,14 +2377,14 @@ bool _Bezier_x_monotone_2::_intersect // Add an originator to the source point, referring to cv: CGAL_assertion_code (bool ps_in_cv_range =) - cv._is_in_range (ovlp_cv._ps, cache, t_cv_src, is_endpoint); + cv._is_in_range(ovlp_cv._ps, cache, t_cv_src, is_endpoint); CGAL_assertion (ps_in_cv_range); - ovlp_cv._ps.add_originator (Originator (cv._curve, cv._xid, t_cv_src)); + ovlp_cv._ps.add_originator(Originator(cv._curve, cv._xid, t_cv_src)); return (true); } - else if (cv._is_in_range (_ps, cache, t_cv_src, is_endpoint) && - cv._is_in_range (_pt, cache, t_cv_trg, is_endpoint)) + else if (cv._is_in_range(_ps, cache, t_cv_src, is_endpoint) && + cv._is_in_range(_pt, cache, t_cv_trg, is_endpoint)) { // Case 8 - *this: s +---------+ t // cv: s' +================+ t' @@ -2621,38 +2392,32 @@ bool _Bezier_x_monotone_2::_intersect // Take *this as the overlapping subcurve, and add originators for its // endpoints referring to cv. ovlp_cv = *this; - ovlp_cv._ps.add_originator (Originator (cv._curve, cv._xid, t_cv_src)); - ovlp_cv._pt.add_originator (Originator (cv._curve, cv._xid, t_cv_trg)); + ovlp_cv._ps.add_originator(Originator(cv._curve, cv._xid, t_cv_src)); + ovlp_cv._pt.add_originator(Originator(cv._curve, cv._xid, t_cv_trg)); - return (true); + return true; } // If we reached here, there are no overlaps: - return (false); + return false; } // Go over the points and report the ones lying in the parameter ranges // of both curves. - Intersect_iter iit; - - for (iit = inter_list.begin(); iit != inter_list.end(); ++iit) - { - if (_is_in_range (iit->s, cache) && - cv._is_in_range (iit->t, cache)) - { + for (auto iit = inter_list.begin(); iit != inter_list.end(); ++iit) { + if (_is_in_range (iit->s, cache) && cv._is_in_range(iit->t, cache)) { // Construct an intersection point with unknown multiplicity. - Point_2 pt (iit->x, iit->y, - true); // Dummy parameter. + Point_2 pt (iit->x, iit->y, true); // Dummy parameter. - pt.add_originator (Originator (_curve, _xid, iit->s)); - pt.add_originator (Originator (cv._curve, cv._xid, iit->t)); + pt.add_originator(Originator(_curve, _xid, iit->s)); + pt.add_originator(Originator(cv._curve, cv._xid, iit->t)); - ipts.push_back (Intersection_point_2 (pt, 0)); + ipts.push_back(Intersection_point(pt, 0)); } } // Mark that there is no overlap: - return (false); + return false; } // --------------------------------------------------------------------------- @@ -2676,23 +2441,22 @@ _exact_vertical_position(const Point_2& p, rat_p = (Rat_point_2) p; // Get a rational approximation of the parameter values at the endpoints. - Nt_traits nt_traits; - Originator_iterator ps_org = _ps.get_originator (_curve, _xid); + Nt_traits nt_traits; + Originator_iterator ps_org = _ps.get_originator(_curve, _xid); CGAL_assertion (ps_org != _ps.originators_end()); - Originator_iterator pt_org = _pt.get_originator (_curve, _xid); - CGAL_assertion (pt_org != _pt.originators_end()); + Originator_iterator pt_org = _pt.get_originator(_curve, _xid); + CGAL_assertion(pt_org != _pt.originators_end()); - Rational my_t_min; - Rational my_t_max; + Rational my_t_min; + Rational my_t_max; - - bool can_refine_s = ! _ps.is_exact(); - bool can_refine_t = ! _pt.is_exact(); + bool can_refine_s = ! _ps.is_exact(); + bool can_refine_t = ! _pt.is_exact(); do { - if (CGAL::compare (ps_org->point_bound().t_max, - pt_org->point_bound().t_min) == SMALLER) + if (CGAL::compare(ps_org->point_bound().t_max, + pt_org->point_bound().t_min) == SMALLER) { // In case the parameter value of the source is smaller than the target's. my_t_min = ps_org->point_bound().t_max; @@ -2719,14 +2483,14 @@ _exact_vertical_position(const Point_2& p, while(can_refine_s || can_refine_t); // Start the subdivision process from the entire supporting curve. - std::list subcurves; - Subcurve init_scv; - Rational x_min, y_min, x_max, y_max; - bool no_x_ovlp; - Comparison_result res_y_min, res_y_max; + std::list subcurves; + Subcurve init_scv; + Rational x_min, y_min, x_max, y_max; + bool no_x_ovlp; + Comparison_result res_y_min, res_y_max; - std::copy (_curve.control_points_begin(), _curve.control_points_end(), - std::back_inserter (init_scv.control_points)); + std::copy(_curve.control_points_begin(), _curve.control_points_end(), + std::back_inserter(init_scv.control_points)); init_scv.t_min = 0; init_scv.t_max = 1; subcurves.push_back (init_scv); @@ -2735,13 +2499,12 @@ _exact_vertical_position(const Point_2& p, { // Go over the list of subcurves and consider only those lying in the // given [t_min, t_max] bound. - typename std::list::iterator iter = subcurves.begin(); - bool is_fully_in_range; + typename std::list::iterator iter = subcurves.begin(); + bool is_fully_in_range; - while (iter != subcurves.end()) - { - if (CGAL::compare (iter->t_max, my_t_min) == SMALLER || - CGAL::compare (iter->t_min, my_t_max) == LARGER) + while (iter != subcurves.end()) { + if (CGAL::compare(iter->t_max, my_t_min) == SMALLER || + CGAL::compare(iter->t_min, my_t_max) == LARGER) { // Subcurve out of bounds of the x-monotone curve we consider - erase // it and continue to next subcurve. @@ -2753,43 +2516,37 @@ _exact_vertical_position(const Point_2& p, // the bounding box of the point. iter->bbox (x_min, y_min, x_max, y_max); - if (p.is_rational()) - { - no_x_ovlp = (CGAL::compare (x_min, rat_p.x()) == LARGER || - CGAL::compare (x_max, rat_p.x()) == SMALLER); + if (p.is_rational()) { + no_x_ovlp = (CGAL::compare(x_min, rat_p.x()) == LARGER || + CGAL::compare(x_max, rat_p.x()) == SMALLER); } - else - { - no_x_ovlp = (CGAL::compare (nt_traits.convert (x_min), - p.x()) == LARGER || - CGAL::compare (nt_traits.convert (x_max), - p.x()) == SMALLER); + else { + no_x_ovlp = (CGAL::compare(nt_traits.convert (x_min), + p.x()) == LARGER || + CGAL::compare(nt_traits.convert (x_max), + p.x()) == SMALLER); } - if (no_x_ovlp) - { + if (no_x_ovlp) { // Subcurve out of x-bounds - erase it and continue to next subcurve. subcurves.erase(iter++); continue; } // In this case, check if there is an overlap in the y-range. - if (p.is_rational()) - { - res_y_min = CGAL::compare (rat_p.y(), y_min); - res_y_max = CGAL::compare (rat_p.y(), y_max); + if (p.is_rational()) { + res_y_min = CGAL::compare(rat_p.y(), y_min); + res_y_max = CGAL::compare(rat_p.y(), y_max); } - else - { - res_y_min = CGAL::compare (p.y(), nt_traits.convert (y_min)); - res_y_max = CGAL::compare (p.y(), nt_traits.convert (y_max)); + else { + res_y_min = CGAL::compare(p.y(), nt_traits.convert (y_min)); + res_y_max = CGAL::compare(p.y(), nt_traits.convert (y_max)); } - is_fully_in_range = (CGAL::compare (iter->t_min, my_t_min) != SMALLER) && - (CGAL::compare (iter->t_max, my_t_max) != LARGER); + is_fully_in_range = (CGAL::compare(iter->t_min, my_t_min) != SMALLER) && + (CGAL::compare(iter->t_max, my_t_max) != LARGER); - if (res_y_min != res_y_max || ! is_fully_in_range) - { + if (res_y_min != res_y_max || ! is_fully_in_range) { // Subdivide the current subcurve and replace iter with the two // resulting subcurves using de Casteljau's algorithm. Subcurve scv_l, scv_r; @@ -2798,21 +2555,20 @@ _exact_vertical_position(const Point_2& p, scv_r.t_max = iter->t_max; scv_l.t_max = scv_r.t_min = (iter->t_min + iter->t_max) / 2; - bisect_control_polygon_2 (iter->control_points.begin(), - iter->control_points.end(), - std::back_inserter(scv_l.control_points), - std::front_inserter(scv_r.control_points)); + bisect_control_polygon_2(iter->control_points.begin(), + iter->control_points.end(), + std::back_inserter(scv_l.control_points), + std::front_inserter(scv_r.control_points)); - subcurves.insert (iter, scv_l); - subcurves.insert (iter, scv_r); + subcurves.insert(iter, scv_l); + subcurves.insert(iter, scv_r); subcurves.erase(iter++); continue; } - if (res_y_min == res_y_max) - { - CGAL_assertion (res_y_min != EQUAL); + if (res_y_min == res_y_max) { + CGAL_assertion(res_y_min != EQUAL); // We reached a separation, as p is either strictly above or strictly // below the bounding box of the current subcurve. @@ -2826,8 +2582,8 @@ _exact_vertical_position(const Point_2& p, } // We can reach here only if we do not force an exact result. - CGAL_assertion (! force_exact); - return (EQUAL); + CGAL_assertion(! force_exact); + return EQUAL; } } //namespace CGAL diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h index f1bdb72d62b..2d94e51f820 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Circle_segment_2.h @@ -8,16 +8,16 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// Baruch Zukerman -// Waqar Khan +// Author(s): Ron Wein +// Baruch Zukerman +// Waqar Khan +// Efi Fogel #ifndef CGAL_CIRCLE_SEGMENT_2_H #define CGAL_CIRCLE_SEGMENT_2_H #include - /*! \file * Header file for the _Circle_segment_2 class. */ @@ -31,126 +31,103 @@ namespace CGAL { // Forward declaration: -template class _One_root_point_2; +template class _One_root_point_2; /*! \class * Representation of a point whose coordinates are one-root numbers. */ -template -class _One_root_point_2_rep //: public Ref_counted -{ +template +class _One_root_point_2_rep { friend class _One_root_point_2; public: - typedef NumberType_ NT; typedef _One_root_point_2_rep Self; - typedef Sqrt_extension > CoordNT; + typedef Sqrt_extension > CoordNT; private: - - CoordNT _x; // The coordinates. - CoordNT _y; + CoordNT _x; // The coordinates. + CoordNT _y; public: - /*! Default constructor. */ - _One_root_point_2_rep () : - _x (0), - _y (0) + _One_root_point_2_rep() : + _x(0), + _y(0) {} /*! Constructor of a point with one-root coefficients. This constructor of a point can also be used with rational coefficients thanks to convertor of CoordNT. */ - _One_root_point_2_rep (const CoordNT& x, const CoordNT& y) : - _x (x), - _y (y) + _One_root_point_2_rep(const CoordNT& x, const CoordNT& y) : + _x(x), + _y(y) {} }; /*! \class * A handle for a point whose coordinates are one-root numbers. */ -template +template class _One_root_point_2 : public Handle_for<_One_root_point_2_rep > { public: - typedef NumberType_ NT; typedef _One_root_point_2 Self; private: - typedef _One_root_point_2_rep Point_rep; typedef Handle_for Point_handle; public: - typedef typename Point_rep::CoordNT CoordNT; /*! Default constructor. */ - _One_root_point_2 () : - Point_handle (Point_rep()) - {} + _One_root_point_2() : Point_handle(Point_rep()) {} /*! Copy constructor. */ - _One_root_point_2 (const Self& p) : - Point_handle (p) - {} + _One_root_point_2(const Self& p) : Point_handle(p) {} _One_root_point_2& operator=(const _One_root_point_2&)=default; /*! Constructor of a point with one-root coefficients. This constructor of a point can also be used with rational coefficients thanks to convertor of CoordNT. */ - _One_root_point_2 (const CoordNT& x, const CoordNT& y) : - Point_handle (Point_rep (x, y)) + _One_root_point_2(const CoordNT& x, const CoordNT& y) : + Point_handle(Point_rep(x, y)) {} /*! Get the x-coordinate. */ - const CoordNT& x () const - { - return (this->ptr()->_x); - } + const CoordNT& x() const { return (this->ptr()->_x); } /*! Get the y-coordinate. */ - const CoordNT& y () const - { - return (this->ptr()->_y); - } + const CoordNT& y() const { return (this->ptr()->_y); } /*! Check for equality. */ - bool equals (const Self& p) const + bool equals(const Self& p) const { - if (this->identical (p)) - return (true); + if (this->identical(p)) return (true); - return (CGAL::compare (this->ptr()->_x, p.ptr()->_x) == EQUAL && - CGAL::compare (this->ptr()->_y, p.ptr()->_y) == EQUAL); + return (CGAL::compare(this->ptr()->_x, p.ptr()->_x) == EQUAL && + CGAL::compare(this->ptr()->_y, p.ptr()->_y) == EQUAL); } - bool operator != (const Self& p) const - { - return !equals(p); - } + bool operator != (const Self& p) const { return ! equals(p); } + + bool operator == (const Self& p) const { return equals(p); } - bool operator == (const Self& p) const - { - return equals(p); - } /*! Set the point coordinates. */ - void set (const NT& x, const NT& y) + void set(const NT& x, const NT& y) { this->copy_on_write(); - this->ptr()->_x = CoordNT (x); - this->ptr()->_y = CoordNT (y); + this->ptr()->_x = CoordNT(x); + this->ptr()->_y = CoordNT(y); return; } /*! Set the point coordinates. */ - void set (const CoordNT& x, const CoordNT& y) + void set(const CoordNT& x, const CoordNT& y) { this->copy_on_write(); this->ptr()->_x = x; @@ -162,10 +139,9 @@ public: /*! * Exporter for conic arcs. */ -template -std::ostream& -operator<< (std::ostream& os, - const _One_root_point_2& p) +template +std::ostream& operator<<(std::ostream& os, + const _One_root_point_2& p) { os << CGAL::to_double(p.x()) << ' ' << CGAL::to_double(p.y()); return (os); @@ -186,11 +162,9 @@ std::istream & operator >> (std::istream & is, /*! \class * Representation of a circle, a circular arc or a line segment. */ -template -class _Circle_segment_2 -{ +template +class _Circle_segment_2 { public: - typedef Kernel_ Kernel; typedef typename Kernel::FT NT; typedef _One_root_point_2 Point_2; @@ -199,114 +173,101 @@ public: typedef typename Kernel::Line_2 Line_2; protected: - typedef typename Point_2::CoordNT CoordNT; // Data members: - Line_2 _line; // The supporting line (for line segments). - Circle_2 _circ; // The supporting circle (for circular arcs). - bool _is_full; // Whether we have a full circle. - bool _has_radius; // Is the radius (not just the squared radius) + Line_2 m_line; // The supporting line (for line segments). + Circle_2 m_circ; // The supporting circle (for circular arcs). + bool m_is_full; // Whether we have a full circle. + bool m_has_radius; // Is the radius (not just the squared radius) // explicitly specified). - NT _radius; // The radius, in case it is specified. - Point_2 _source; // The source point. - Point_2 _target; // The target point. - Orientation _orient; // The orientation (COLLINEAR for line segments). + NT m_radius; // The radius, in case it is specified. + Point_2 m_source; // The source point. + Point_2 m_target; // The target point. + Orientation m_orient; // The orientation (COLLINEAR for line segments). public: - /*! Default constructor. */ - _Circle_segment_2 () : - _is_full (false), - _has_radius (false), - _orient (COLLINEAR) + _Circle_segment_2() : + m_is_full(false), + m_has_radius(false), + m_orient(COLLINEAR) {} - /*! - * Constructor from a line segment. + /*! Constructor from a line segment. * \param seg The segment. */ - _Circle_segment_2 (const Segment_2& seg) : - _line (seg), - _is_full (false), - _has_radius (false), - _source (seg.source().x(), seg.source().y()), - _target (seg.target().x(), seg.target().y()), - _orient (COLLINEAR) + _Circle_segment_2(const Segment_2& seg) : + m_line(seg), + m_is_full(false), + m_has_radius(false), + m_source(seg.source().x(), seg.source().y()), + m_target(seg.target().x(), seg.target().y()), + m_orient(COLLINEAR) {} - /*! - * Constructor from of a line segment. + /*! Constructor from of a line segment. * \param ps The source point. * \param pt The target point. */ - _Circle_segment_2 (const typename Kernel::Point_2& ps, - const typename Kernel::Point_2& pt) : - _line (ps, pt), - _is_full (false), - _has_radius (false), - _source (ps.x(), ps.y()), - _target (pt.x(), pt.y()), - _orient (COLLINEAR) + _Circle_segment_2(const typename Kernel::Point_2& ps, + const typename Kernel::Point_2& pt) : + m_line(ps, pt), + m_is_full(false), + m_has_radius(false), + m_source(ps.x(), ps.y()), + m_target(pt.x(), pt.y()), + m_orient(COLLINEAR) {} - /*! - * Constructor of a segment, given a supporting line and two endpoints, + /*! Constructor of a segment, given a supporting line and two endpoints, * which need not necessarily have rational coordinates. * \param line The supporting line. * \param source The source point. * \param target The target point. * \pre Both endpoints lie on the supporting line. */ - _Circle_segment_2 (const Line_2& line, - const Point_2& source, const Point_2& target) : - _line (line), - _is_full (false), - _has_radius (false), - _source (source), - _target (target), - _orient (COLLINEAR) + _Circle_segment_2(const Line_2& line, + const Point_2& source, const Point_2& target) : + m_line(line), + m_is_full(false), + m_has_radius(false), + m_source(source), + m_target(target), + m_orient(COLLINEAR) { - CGAL_precondition (CGAL::compare (source.x()*line.a() + line.c(), - -source.y()*line.b()) == EQUAL); + CGAL_precondition(CGAL::compare(source.x() * line.a() + line.c(), + -source.y() * line.b()) == EQUAL); - CGAL_precondition (CGAL::compare (target.x()*line.a() + line.c(), - -target.y()*line.b()) == EQUAL); + CGAL_precondition(CGAL::compare(target.x() * line.a() + line.c(), + -target.y() * line.b()) == EQUAL); } - /*! - * Constructor from a circle. + /*! Constructor from a circle. * \param circ The circle. */ - _Circle_segment_2 (const Circle_2& circ) : - _circ (circ), - _is_full (true), - _has_radius (false), - _orient (circ.orientation()) - { - CGAL_assertion (_orient != COLLINEAR); - } + _Circle_segment_2(const Circle_2& circ) : + m_circ(circ), + m_is_full(true), + m_has_radius(false), + m_orient(circ.orientation()) + { CGAL_assertion(m_orient != COLLINEAR); } - /*! - * Constructor from a circle. + /*! Constructor from a circle. * \param c The circle center. * \param r The radius. * \param orient The orientation of the circle. */ - _Circle_segment_2 (const typename Kernel::Point_2& c, - const NT& r, - Orientation orient = COUNTERCLOCKWISE) : - _circ (c, r*r, orient), - _is_full (true), - _has_radius (true), - _radius (r), - _orient (orient) - { - CGAL_assertion (orient != COLLINEAR); - } + _Circle_segment_2(const typename Kernel::Point_2& c, const NT& r, + Orientation orient = COUNTERCLOCKWISE) : + m_circ(c, r*r, orient), + m_is_full(true), + m_has_radius(true), + m_radius(r), + m_orient(orient) + { CGAL_assertion (orient != COLLINEAR); } - /*! - * Constructor of a circular arc, given a supporting circle and two + /*! Constructor of a circular arc, given a supporting circle and two * endpoints, which need not necessarily have rational coordinates. * The orientation of the circle determines the orientation of the arc. * \param circ The supporting circle. @@ -314,30 +275,29 @@ public: * \param target The target point. * \pre Both endpoints lie on the supporting circle. */ - _Circle_segment_2 (const Circle_2& circ, - const Point_2& source, const Point_2& target) : - _circ (circ), - _is_full (false), - _has_radius (false), - _source (source), - _target (target), - _orient (circ.orientation()) + _Circle_segment_2(const Circle_2& circ, + const Point_2& source, const Point_2& target) : + m_circ(circ), + m_is_full(false), + m_has_radius(false), + m_source(source), + m_target(target), + m_orient(circ.orientation()) { - CGAL_assertion (_orient != COLLINEAR); + CGAL_assertion(m_orient != COLLINEAR); CGAL_precondition - (CGAL::compare (CGAL::square (source.x() - circ.center().x()), - circ.squared_radius() - - CGAL::square (source.y() - circ.center().y())) == EQUAL); + (CGAL::compare(CGAL::square(source.x() - circ.center().x()), + circ.squared_radius() - + CGAL::square(source.y() - circ.center().y())) == EQUAL); CGAL_precondition - (CGAL::compare (CGAL::square (target.x() - circ.center().x()), - circ.squared_radius() - - CGAL::square (target.y() - circ.center().y())) == EQUAL); + (CGAL::compare(CGAL::square(target.x() - circ.center().x()), + circ.squared_radius() - + CGAL::square(target.y() - circ.center().y())) == EQUAL); } - /*! - * Constructor of a circular arc, given a supporting circle and two + /*! Constructor of a circular arc, given a supporting circle and two * endpoints, which need not necessarily have rational coordinates. * \param c The circle center. * \param r The radius. @@ -346,86 +306,83 @@ public: * \param target The target point. * \pre Both endpoints lie on the supporting circle. */ - _Circle_segment_2 (const typename Kernel::Point_2& c, - const NT& r, Orientation orient, - const Point_2& source, const Point_2& target) : - _circ (c, r*r, orient), - _is_full (false), - _has_radius (true), - _radius (r), - _source (source), - _target (target), - _orient (orient) + _Circle_segment_2(const typename Kernel::Point_2& c, + const NT& r, Orientation orient, + const Point_2& source, const Point_2& target) : + m_circ(c, r*r, orient), + m_is_full(false), + m_has_radius(true), + m_radius(r), + m_source(source), + m_target(target), + m_orient(orient) { - CGAL_assertion (orient != COLLINEAR); + CGAL_assertion(orient != COLLINEAR); CGAL_precondition - (CGAL::compare (CGAL::square (source.x() - c.x()), - CGAL::square (r) - - CGAL::square (source.y() - c.y())) == EQUAL); + (CGAL::compare(CGAL::square(source.x() - c.x()), + CGAL::square(r) - + CGAL::square(source.y() - c.y())) == EQUAL); CGAL_precondition - (CGAL::compare (CGAL::square (target.x() - c.x()), - CGAL::square (r) - - CGAL::square (target.y() - c.y())) == EQUAL); + (CGAL::compare(CGAL::square(target.x() - c.x()), + CGAL::square(r) - + CGAL::square(target.y() - c.y())) == EQUAL); } - /*! - * Constructor of a circular arc, from the given three points, in case of + /*! Constructor of a circular arc, from the given three points, in case of * three collinear points, a segment will be constructed. * \param p1 The arc source. * \param p2 A point in the interior of the arc. * \param p3 The arc target. * \pre p1 and p3 are not equal. */ - _Circle_segment_2 (const typename Kernel::Point_2& p1, - const typename Kernel::Point_2& p2, - const typename Kernel::Point_2& p3) : - _is_full(false), - _has_radius(false), - _source(p1.x(), p1.y()), - _target(p3.x(), p3.y()) + _Circle_segment_2(const typename Kernel::Point_2& p1, + const typename Kernel::Point_2& p2, + const typename Kernel::Point_2& p3) : + m_is_full(false), + m_has_radius(false), + m_source(p1.x(), p1.y()), + m_target(p3.x(), p3.y()) { // Set the source and target. - NT x1 = p1.x(); - NT y1 = p1.y(); - NT x2 = p2.x(); - NT y2 = p2.y(); - NT x3 = p3.x(); - NT y3 = p3.y(); - + NT x1 = p1.x(); + NT y1 = p1.y(); + NT x2 = p2.x(); + NT y2 = p2.y(); + NT x3 = p3.x(); + NT y3 = p3.y(); // Make sure that the source and the target are not the same. - CGAL_precondition (Kernel().compare_xy_2_object() (p1, p3) != EQUAL); + CGAL_precondition(Kernel().compare_xy_2_object()(p1, p3) != EQUAL); // Compute the lines: A1*x + B1*y + C1 = 0, // and: A2*x + B2*y + C2 = 0, // where: - const NT _two = 2; + const NT _two = 2; - const NT A1 = _two*(x1 - x2); - const NT B1 = _two*(y1 - y2); - const NT C1 = CGAL::square(y2) - CGAL::square(y1) + - CGAL::square(x2) - CGAL::square(x1); + const NT A1 = _two*(x1 - x2); + const NT B1 = _two*(y1 - y2); + const NT C1 = + CGAL::square(y2) - CGAL::square(y1) + CGAL::square(x2) - CGAL::square(x1); - const NT A2 = _two*(x2 - x3); - const NT B2 = _two*(y2 - y3); - const NT C2 = CGAL::square(y3) - CGAL::square(y2) + - CGAL::square(x3) - CGAL::square(x2); + const NT A2 = _two*(x2 - x3); + const NT B2 = _two*(y2 - y3); + const NT C2 = + CGAL::square(y3) - CGAL::square(y2) + CGAL::square(x3) - CGAL::square(x2); // Compute the coordinates of the intersection point between the // two lines, given by (Nx / D, Ny / D), where: - const NT Nx = B1*C2 - B2*C1; - const NT Ny = A2*C1 - A1*C2; - const NT D = A1*B2 - A2*B1; + const NT Nx = B1*C2 - B2*C1; + const NT Ny = A2*C1 - A1*C2; + const NT D = A1*B2 - A2*B1; // Make sure the three points are not collinear. - const bool points_collinear = (CGAL::sign (D) == ZERO); + const bool points_collinear = (CGAL::sign (D) == ZERO); - if (points_collinear) - { - _line = Line_2(p1, p3); - _orient = COLLINEAR; + if (points_collinear) { + m_line = Line_2(p1, p3); + m_orient = COLLINEAR; return; } @@ -436,145 +393,118 @@ public: typename Kernel::Point_2 circ_center(x_center, y_center); - - - NT sqr_rad = (CGAL::square(D*x2 - Nx) + CGAL::square(D*y2 - Ny)) / - CGAL::square(D); + NT sqr_rad = + (CGAL::square(D*x2 - Nx) + CGAL::square(D*y2 - Ny)) / CGAL::square(D); // Determine the orientation: If the mid-point forms a left-turn with // the source and the target points, the orientation is positive (going // counterclockwise). // Otherwise, it is negative (going clockwise). - Kernel ker; + Kernel ker; typename Kernel::Orientation_2 orient_f = ker.orientation_2_object(); - if (orient_f(p1, p2, p3) == LEFT_TURN) - _orient = COUNTERCLOCKWISE; - else - _orient = CLOCKWISE; - - _circ = Circle_2(circ_center, sqr_rad, _orient); + if (orient_f(p1, p2, p3) == LEFT_TURN) m_orient = COUNTERCLOCKWISE; + else m_orient = CLOCKWISE; + m_circ = Circle_2(circ_center, sqr_rad, m_orient); } - /*! - * Get the orientation of the curve. + /*! Get the orientation of the curve. * \return COLLINEAR in case of a line segment, * CLOCKWISE or COUNTERCLOCKWISE for circular curves. */ - inline Orientation orientation () const - { - return (_orient); - } + inline Orientation orientation() const { return (m_orient); } /*! Check if the arc is linear. */ - inline bool is_linear () const - { - return (_orient == COLLINEAR); - } + inline bool is_linear() const { return (m_orient == COLLINEAR); } /*! Check if the arc is circular. */ - inline bool is_circular () const - { - return (_orient != COLLINEAR); - } + inline bool is_circular() const { return (m_orient != COLLINEAR); } - /*! - * Get the supporting line. + /*! Obtain the supporting line. * \pre The curve orientation is COLLINEAR. */ - const Line_2& supporting_line () const + const Line_2& supporting_line() const { - CGAL_precondition (_orient == COLLINEAR); - return (_line); + CGAL_precondition(m_orient == COLLINEAR); + return m_line; } - /*! - * Get the supporting circle. + /*! Obtain the supporting circle. * \pre The curve orientation is not COLLINEAR. */ - const Circle_2& supporting_circle () const + const Circle_2& supporting_circle() const { - CGAL_precondition (_orient != COLLINEAR); - return (_circ); + CGAL_precondition(m_orient != COLLINEAR); + return m_circ; } /*! Check if the curve is a full circle. */ - bool is_full () const - { - return (_is_full); - } + bool is_full() const { return (m_is_full); } /*! * Get the source point. * \pre The curve is not a full circle. */ - const Point_2& source () const + const Point_2& source() const { - CGAL_precondition (! _is_full); - return (_source); + CGAL_precondition(! m_is_full); + return (m_source); } /*! * Get the target point. * \pre The curve is not a full circle. */ - const Point_2& target () const + const Point_2& target() const { - CGAL_precondition (! _is_full); - return (_target); + CGAL_precondition(! m_is_full); + return (m_target); } - /*! - * Get the vertical tangency points the arc contains. + /*! Get the vertical tangency points the arc contains. * \param vpts Output: The vertical tangency points. * \pre The curve is circular. * \return The number of points (0, 1, or 2). */ - unsigned int vertical_tangency_points (Point_2 *vpts) const + unsigned int vertical_tangency_points(Point_2* vpts) const { - CGAL_precondition (_orient != COLLINEAR); - unsigned int n_vpts = 0; + CGAL_precondition(m_orient != COLLINEAR); + unsigned int n_vpts = 0; - if (_is_full) - { + if (m_is_full) { // In case of a full circle, create both vertical tangency points: - const NT& x0 = _circ.center().x(); - const NT& y0 = _circ.center().y(); - CoordNT xv_left; - CoordNT xv_right; + const NT& x0 = m_circ.center().x(); + const NT& y0 = m_circ.center().y(); + CoordNT xv_left; + CoordNT xv_right; - if (_has_radius) - { + if (m_has_radius) { // In case the radius is explicitly given: - xv_left = CoordNT (x0 - _radius); - xv_right = CoordNT (x0 + _radius); + xv_left = CoordNT(x0 - m_radius); + xv_right = CoordNT(x0 + m_radius); } - else - { + else { // In case only the squared root is given: - xv_left = CoordNT (x0, NT(-1), _circ.squared_radius()); - xv_right = CoordNT (x0, NT(1), _circ.squared_radius()); + xv_left = CoordNT(x0, NT(-1), m_circ.squared_radius()); + xv_right = CoordNT(x0, NT(1), m_circ.squared_radius()); } - vpts[0] = Point_2 (xv_left, y0); - vpts[1] = Point_2 (xv_right, y0); + vpts[0] = Point_2(xv_left, y0); + vpts[1] = Point_2(xv_right, y0); return (2); } - if (_orient == COUNTERCLOCKWISE) - { + if (m_orient == COUNTERCLOCKWISE) { // Compute the vertical tangency points for the arc: - n_vpts = _ccw_vertical_tangency_points (_source, _target, vpts); + n_vpts = _ccw_vertical_tangency_points(m_source, m_target, vpts); } - else - { + else { // Compute the vertical tangency points for the opposite arc: - n_vpts = _ccw_vertical_tangency_points (_target, _source, vpts); + n_vpts = _ccw_vertical_tangency_points(m_target, m_source, vpts); // Swap their order, if necessary. - if (n_vpts == 2) - { - Point_2 temp = vpts[0]; + if (n_vpts == 2) { + Point_2 temp = vpts[0]; vpts[0] = vpts[1]; vpts[1] = temp; } @@ -584,69 +514,62 @@ public: } private: - - /*! - * Get the vertical tangency points the arc contains, assuming it is + /*! Obtain the vertical tangency points the arc contains, assuming it is * counterclockwise oriented. * \param vpts Output: The vertical tangency points. * \return The number of points (0, 1, or 2). */ - unsigned int _ccw_vertical_tangency_points (const Point_2& src, - const Point_2& trg, - Point_2 *vpts) const + unsigned int _ccw_vertical_tangency_points(const Point_2& src, + const Point_2& trg, + Point_2* vpts) const { - unsigned int n_vpts = 0; - const NT& x0 = _circ.center().x(); - const NT& y0 = _circ.center().y(); - int qs = _quart_index (src); - int qt = _quart_index (trg); + unsigned int n_vpts = 0; + const NT& x0 = m_circ.center().x(); + const NT& y0 = m_circ.center().y(); + int qs = _quart_index(src); + int qt = _quart_index(trg); - if (qs == qt) - { - if ((qs == 0 || qs == 1) && CGAL::compare (src.x(), trg.x()) == LARGER) + if (qs == qt) { + if ((qs == 0 || qs == 1) && CGAL::compare(src.x(), trg.x()) == LARGER) // We have an x-monotone arc lying on the upper half of the circle: return (0); - if ((qs == 2 || qs == 3) && CGAL::compare (src.x(), trg.x()) == SMALLER) + if ((qs == 2 || qs == 3) && CGAL::compare(src.x(), trg.x()) == SMALLER) // We have an x-monotone arc lying on the lower half of the circle: return (0); } // Make sure the target quarter is larger than the source quarter, by // adding 4 to its index, if necessary. - if (qt <= qs) - qt += 4; + if (qt <= qs) qt += 4; // Start traversing the quarter-planes and collect the vertical tangency // points we encounter. - while (qs < qt) - { - if ((qs % 4) == 1) - { + while (qs < qt) { + if ((qs % 4) == 1) { // We collect the left tangency point when going from Q[1] to Q[2]: - if (CGAL::compare (x0, trg.x()) != LARGER || - CGAL::compare (y0, trg.y()) != EQUAL) + if (CGAL::compare(x0, trg.x()) != LARGER || + CGAL::compare(y0, trg.y()) != EQUAL) { - if (_has_radius) - vpts[n_vpts] = Point_2 (CoordNT (x0 - _radius), y0); + if (m_has_radius) + vpts[n_vpts] = Point_2(CoordNT(x0 - m_radius), y0); else - vpts[n_vpts] = Point_2 (CoordNT (x0, NT(-1), _circ.squared_radius()), - y0); + vpts[n_vpts] = + Point_2(CoordNT(x0, NT(-1), m_circ.squared_radius()), y0); n_vpts++; } } - else if ((qs % 4) == 3) - { + else if ((qs % 4) == 3) { // We collect the right tangency point when going from Q[3] to Q[0]: - if (CGAL::compare (x0, trg.x()) != SMALLER || - CGAL::compare (y0, trg.y()) != EQUAL) + if (CGAL::compare(x0, trg.x()) != SMALLER || + CGAL::compare(y0, trg.y()) != EQUAL) { - if (_has_radius) - vpts[n_vpts] = Point_2 (CoordNT (x0 + _radius), y0); + if (m_has_radius) + vpts[n_vpts] = Point_2(CoordNT(x0 + m_radius), y0); else - vpts[n_vpts] = Point_2 (CoordNT (x0, NT(1), _circ.squared_radius()), - y0); + vpts[n_vpts] = + Point_2(CoordNT(x0, NT(1), m_circ.squared_radius()), y0); n_vpts++; } } @@ -657,11 +580,10 @@ private: return (n_vpts); } - /*! - * Get the index of the quarter-plane containing the given point, + /*! Obtain the index of the quarter-plane containing the given point, * where the circle center is considered to be the origin. */ - int _quart_index (const Point_2& p) const + int _quart_index(const Point_2& p) const { // The plane looks like: // @@ -673,44 +595,32 @@ private: // x < 0 | x >= 0 // y <= 0 | y < 0 // - const CGAL::Sign sign_x = CGAL::sign (p.x() - _circ.center().x()); - const CGAL::Sign sign_y = CGAL::sign (p.y() - _circ.center().y()); + const CGAL::Sign sign_x = CGAL::sign(p.x() - m_circ.center().x()); + const CGAL::Sign sign_y = CGAL::sign(p.y() - m_circ.center().y()); - if (sign_x == POSITIVE) - { - return ((sign_y == NEGATIVE) ? 3 : 0); - } - else if (sign_x == NEGATIVE) - { - return ((sign_y == POSITIVE) ? 1 : 2); - } + if (sign_x == POSITIVE) return ((sign_y == NEGATIVE) ? 3 : 0); + else if (sign_x == NEGATIVE) return ((sign_y == POSITIVE) ? 1 : 2); CGAL_assertion (sign_y != ZERO); return ((sign_y == POSITIVE) ? 1 : 3); } }; -/*! - * Exporter for line segments and circular arcs. +/*! Exporter for line segments and circular arcs. */ -template +template std::ostream& -operator<< (std::ostream& os, - const _Circle_segment_2& c) +operator<<(std::ostream& os, const _Circle_segment_2& c) { - if (c.orientation() == COLLINEAR) - { + if (c.orientation() == COLLINEAR) { os<< "segment: " << c.source() << " -> " << c.target(); } - else - { - if(!c.is_full()) - { + else { + if (! c.is_full()) { os << "circular arc: " << c.supporting_circle() << ' ' << c.source() << " -> " << c.target(); } - else - { + else { os << "circular arc: " << c.supporting_circle(); } } @@ -721,11 +631,9 @@ operator<< (std::ostream& os, /*! \class * Representation of an x-monotone circular arc. */ -template -class _X_monotone_circle_segment_2 -{ +template +class _X_monotone_circle_segment_2 { public: - typedef Kernel_ Kernel; typedef _X_monotone_circle_segment_2 Self; typedef typename Kernel::FT NT; @@ -735,17 +643,16 @@ public: typedef typename Point_2::CoordNT CoordNT; // Type definition for the intersection points mapping. - typedef std::pair Curve_id_pair; - typedef unsigned int Multiplicity; - typedef std::pair Intersection_point_2; - typedef std::list Intersection_list; + typedef std::pair Curve_id_pair; + typedef unsigned int Multiplicity; + typedef std::pair Intersection_point; + typedef std::list Intersection_list; /*! * \struct Less functor for Curve_id_pair. */ - struct Less_id_pair - { - bool operator() (const Curve_id_pair& ip1, const Curve_id_pair& ip2) const + struct Less_id_pair { + bool operator()(const Curve_id_pair& ip1, const Curve_id_pair& ip2) const { // Compare the pairs of IDs lexicographically. return (ip1.first < ip2.first || @@ -753,25 +660,20 @@ public: } }; - typedef std::map Intersection_map; + typedef std::map + Intersection_map; typedef typename Intersection_map::value_type Intersection_map_entry; typedef typename Intersection_map::iterator Intersection_map_iterator; protected: - - NT _first; // The x-coordinate of the circle center. - // Or: the coefficient of x in the line equation. - - NT _second; // The y-coordinate of the circle center. - // Or: the coefficient of y in the line equation. - - NT _third; // The squared radius of the supporting circle. - // Or: the free coefficient in the line equation. - - Point_2 _source; // The source point. - Point_2 _target; // The target point. + NT m_first; // The x-coordinate of the circle center. + // Or: the coefficient of x in the line equation. + NT m_second; // The y-coordinate of the circle center. + // Or: the coefficient of y in the line equation. + NT m_third; // The squared radius of the supporting circle. + // Or: the free coefficient in the line equation. + Point_2 m_source; // The source point. + Point_2 m_target; // The target point. enum { IS_DIRECTED_RIGHT_MASK = 1, @@ -782,7 +684,7 @@ protected: INDEX_SHIFT_BITS = 4 }; - unsigned int _info; // A bit vector, where: + unsigned int m_info; // A bit vector, where: // Bit 0 (the LSB): marks if the arc is directed // from left to right. // Bit 1: marks if the arc is a vertical segment. @@ -790,408 +692,321 @@ protected: // The rest of the bits represent the curve index. public: - - /*! - * Default constructor. + /*! Default constructor. */ - _X_monotone_circle_segment_2 () : - _first(), - _second(), - _third(), - _source(), - _target(), - _info (0) + _X_monotone_circle_segment_2() : + m_first(), + m_second(), + m_third(), + m_source(), + m_target(), + m_info(0) {} - /*! - * Construct an arc from a line segment. + /*! Construct an arc from a line segment. * \param line The supporting line. * \param source The source point. * \param target The target point. */ - _X_monotone_circle_segment_2 (const Line_2& line, - const Point_2& source, const Point_2& target, - unsigned int index = 0) : - _first (line.a()), - _second (line.b()), - _third (line.c()), - _source (source), - _target(target), - _info (index << INDEX_SHIFT_BITS) + _X_monotone_circle_segment_2(const Line_2& line, + const Point_2& source, const Point_2& target, + unsigned int index = 0) : + m_first(line.a()), + m_second(line.b()), + m_third(line.c()), + m_source(source), + m_target(target), + m_info(index << INDEX_SHIFT_BITS) { // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare(source.x(), target.x()); - if (res == EQUAL) - { - CGAL_precondition (CGAL::sign(_second) == ZERO); + if (res == EQUAL) { + CGAL_precondition(CGAL::sign(m_second) == ZERO); // We have a vertical segment - compare the points by their // y-coordinates: - _info = (_info | IS_VERTICAL_SEGMENT_MASK); - res = CGAL::compare (source.y(), target.y()); + m_info = (m_info | IS_VERTICAL_SEGMENT_MASK); + res = CGAL::compare(source.y(), target.y()); } - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); } - /*! - * Construct a segment arc from two kernel points + /*! Construct a segment arc from two kernel points * \param source the source point. * \ param target the target point. * \pre source and target are not equal. */ - _X_monotone_circle_segment_2 (const typename Kernel::Point_2& source, - const typename Kernel::Point_2& target) : - _source(source.x(), source.y()), - _target(target.x(), target.y()), - _info (0) + _X_monotone_circle_segment_2(const typename Kernel::Point_2& source, + const typename Kernel::Point_2& target) : + m_source(source.x(), source.y()), + m_target(target.x(), target.y()), + m_info(0) { Line_2 line(source, target); - _first = line.a(); - _second = line.b(); - _third = line.c(); + m_first = line.a(); + m_second = line.b(); + m_third = line.c(); // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare(source.x(), target.x()); - if (res == EQUAL) - { - CGAL_precondition (CGAL::sign(_second) == ZERO); + if (res == EQUAL) { + CGAL_precondition(CGAL::sign(m_second) == ZERO); // We have a vertical segment - compare the points by their // y-coordinates: - _info = (_info | IS_VERTICAL_SEGMENT_MASK); - res = CGAL::compare (source.y(), target.y()); + m_info = (m_info | IS_VERTICAL_SEGMENT_MASK); + res = CGAL::compare(source.y(), target.y()); } - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); } - /*! - * Construct a circular arc. + /*! Construct a circular arc. * \param line The supporting line. * \param source The source point. * \param target The target point. * \param orient The orientation of the arc. */ - _X_monotone_circle_segment_2 (const Circle_2& circ, - const Point_2& source, const Point_2& target, - Orientation orient, - unsigned int index = 0) : - _first (circ.center().x()), - _second (circ.center().y()), - _third (circ.squared_radius()), - _source (source), - _target(target), - _info (index << INDEX_SHIFT_BITS) + _X_monotone_circle_segment_2(const Circle_2& circ, + const Point_2& source, const Point_2& target, + Orientation orient, + unsigned int index = 0) : + m_first(circ.center().x()), + m_second(circ.center().y()), + m_third(circ.squared_radius()), + m_source(source), + m_target(target), + m_info(index << INDEX_SHIFT_BITS) { // Check if the segment is directed left or right: - Comparison_result res = CGAL::compare (source.x(), target.x()); + Comparison_result res = CGAL::compare (source.x(), target.x()); - CGAL_precondition (res != EQUAL); - if (res == SMALLER) - _info = (_info | IS_DIRECTED_RIGHT_MASK); + CGAL_precondition(res != EQUAL); + if (res == SMALLER) m_info = (m_info | IS_DIRECTED_RIGHT_MASK); // Set the orientation. CGAL_precondition (orient != COLLINEAR); - if (orient == COUNTERCLOCKWISE) - _info = (_info | COUNTERCLOCKWISE_CODE); - else - _info = (_info | CLOCKWISE_CODE); + if (orient == COUNTERCLOCKWISE) m_info = (m_info | COUNTERCLOCKWISE_CODE); + else m_info = (m_info | CLOCKWISE_CODE); } /*! Check if the arc is linear. */ - inline bool is_linear () const - { - return ((_info & ORIENTATION_MASK) == 0); - } + inline bool is_linear () const { return ((m_info & ORIENTATION_MASK) == 0); } /*! Check if the arc is circular. */ inline bool is_circular () const - { - return ((_info & ORIENTATION_MASK) != 0); - } + { return ((m_info & ORIENTATION_MASK) != 0); } - /*! - * Get the supporting line. + /*! Obtain the supporting line. * \pre The arc is linear (a line segment). */ - Line_2 supporting_line () const + Line_2 supporting_line() const { CGAL_precondition (is_linear()); - return (Line_2 (a(), b(), c())); } - /*! - * Get the supporting circle. + /*! Obtain the supporting circle. * \pre The arc is circular. */ - Circle_2 supporting_circle () const + Circle_2 supporting_circle() const { CGAL_precondition (is_circular()); - typename Kernel::Point_2 center (x0(), y0()); - return (Circle_2 (center , sqr_r(), orientation())); + typename Kernel::Point_2 center(x0(), y0()); + return (Circle_2(center , sqr_r(), orientation())); } /*! Get the source point. */ - inline const Point_2& source () const - { - return (_source); - } + inline const Point_2& source() const { return (m_source); } /*! Get the target point. */ - inline const Point_2& target () const - { - return (_target); - } + inline const Point_2& target() const { return (m_target); } /*! True if the arc is directed right, false otherwise. */ - bool is_directed_right () const - { - return ((_info & IS_DIRECTED_RIGHT_MASK) != 0); - } + bool is_directed_right() const + { return ((m_info & IS_DIRECTED_RIGHT_MASK) != 0); } - bool has_left() const - { - return true; - } + bool has_left() const { return true; } - bool has_right() const - { - return true; - } + bool has_right() const { return true; } /*! Get the left endpoint of the arc. */ - inline const Point_2& left () const - { - return (((_info & IS_DIRECTED_RIGHT_MASK) != 0) ? _source : _target); - } + inline const Point_2& left() const + { return (((m_info & IS_DIRECTED_RIGHT_MASK) != 0) ? m_source : m_target); } /*! Get the right endpoint of the arc. */ - inline const Point_2& right () const - { - return (((_info & IS_DIRECTED_RIGHT_MASK) != 0) ? _target : _source); - } + inline const Point_2& right() const + { return (((m_info & IS_DIRECTED_RIGHT_MASK) != 0) ? m_target : m_source); } - /*! - * Check whether the given point is in the x-range of the arc. + /*! Check whether the given point is in the x-range of the arc. */ - bool is_in_x_range (const Point_2& p) const + bool is_in_x_range(const Point_2& p) const { - Comparison_result res = CGAL::compare (p.x(), left().x()); + Comparison_result res = CGAL::compare (p.x(), left().x()); - if (res == SMALLER) - return (false); - else if (res == EQUAL) - return (true); + if (res == SMALLER) return false; + else if (res == EQUAL) return true; return (CGAL::compare (p.x(), right().x()) != LARGER); } /*! Check if the arc is a vertical segment. */ - inline bool is_vertical () const - { - return ((_info & IS_VERTICAL_SEGMENT_MASK) != 0); - } + inline bool is_vertical() const + { return ((m_info & IS_VERTICAL_SEGMENT_MASK) != 0); } /*! Get the orientation of the arc. */ inline Orientation orientation() const { - unsigned int _or = (_info & ORIENTATION_MASK); + unsigned int or_ = (m_info & ORIENTATION_MASK); + if (or_ == COUNTERCLOCKWISE_CODE) return (CGAL::COUNTERCLOCKWISE); + else if (or_ == CLOCKWISE_CODE) return (CGAL::CLOCKWISE); - if (_or == COUNTERCLOCKWISE_CODE) - return (CGAL::COUNTERCLOCKWISE); - else if (_or == CLOCKWISE_CODE) - return (CGAL::CLOCKWISE); - - CGAL_assertion (_or == 0); + CGAL_assertion(or_ == 0); return (CGAL::COLLINEAR); } - /*! - * Check the position of a given point with respect to the arc. + /*! Check the position of a given point with respect to the arc. */ - Comparison_result point_position (const Point_2& p) const + Comparison_result point_position(const Point_2& p) const { - if (is_linear()) - return (_line_point_position (p)); - else - return (_circ_point_position (p)); + if (is_linear()) return (_line_point_position(p)); + else return (_circ_point_position (p)); } - - /*! - * Compare the two arcs to the right of their intersection point. + /*! Compare the two arcs to the right of their intersection point. */ - Comparison_result compare_to_right (const Self& cv, const Point_2& p) const + Comparison_result compare_to_right(const Self& cv, const Point_2& p) const { - if (is_linear()) - { - if (cv.is_linear()) - return (_lines_compare_to_right (cv, p)); - - Comparison_result res = cv._circ_line_compare_to_right (*this, p); - - if (res != EQUAL) - res = (res == SMALLER) ? LARGER : SMALLER; - + if (is_linear()) { + if (cv.is_linear()) return (_lines_compare_to_right (cv, p)); + Comparison_result res = cv._circ_line_compare_to_right (*this, p); + if (res != EQUAL) res = (res == SMALLER) ? LARGER : SMALLER; return (res); } - else - { - if (cv.is_linear()) - return (_circ_line_compare_to_right (cv, p)); - + else { + if (cv.is_linear()) return (_circ_line_compare_to_right (cv, p)); return (_circs_compare_to_right (cv, p)); } } - /*! - * Compare the two arcs to the left of their intersection point. + /*! Compare the two arcs to the left of their intersection point. */ - Comparison_result compare_to_left (const Self& cv, const Point_2& p) const + Comparison_result compare_to_left(const Self& cv, const Point_2& p) const { - if (is_linear()) - { - if (cv.is_linear()) - return (_lines_compare_to_left (cv, p)); - - Comparison_result res = cv._circ_line_compare_to_left (*this, p); - - if (res != EQUAL) - res = (res == SMALLER) ? LARGER : SMALLER; - + if (is_linear()) { + if (cv.is_linear()) return (_lines_compare_to_left (cv, p)); + Comparison_result res = cv._circ_line_compare_to_left(*this, p); + if (res != EQUAL) res = (res == SMALLER) ? LARGER : SMALLER; return (res); } - else - { - if (cv.is_linear()) - return (_circ_line_compare_to_left (cv, p)); - + else { + if (cv.is_linear()) return (_circ_line_compare_to_left(cv, p)); return (_circs_compare_to_left (cv, p)); } } - /*! - * Check whether the two arcs have the same supporting curve. + /*! Check whether the two arcs have the same supporting curve. */ - bool has_same_supporting_curve (const Self& cv) const + bool has_same_supporting_curve(const Self& cv) const { // Check if the curve indices are the same. - if (_index() != 0 && _index() == cv._index()) - return (true); + if (_index() != 0 && _index() == cv._index()) return true; // Make sure that the supporting curves are of the same type. - if (is_linear() && ! cv.is_linear()) - return (false); + if (is_linear() && ! cv.is_linear()) return false; - if (! is_linear() && cv.is_linear()) - return (false); + if (! is_linear() && cv.is_linear()) return false; // Compare the curve coefficients. - if (! is_linear()) - { + if (! is_linear()) { // The two circles must have the same center and the same radius. - return (CGAL::compare (x0(), cv.x0()) == EQUAL && - CGAL::compare (y0(), cv.y0()) == EQUAL && - CGAL::compare (sqr_r(), cv.sqr_r()) == EQUAL); + return (CGAL::compare(x0(), cv.x0()) == EQUAL && + CGAL::compare(y0(), cv.y0()) == EQUAL && + CGAL::compare(sqr_r(), cv.sqr_r()) == EQUAL); } // Compare the line equations: Note that these may be scaled. - NT fact1; - NT fact2; + NT fact1; + NT fact2; - if (is_vertical()) - { - if (! cv.is_vertical()) - return (false); + if (is_vertical()) { + if (! cv.is_vertical()) return false; fact1 = a(); fact2 = cv.a(); } - else - { + else { fact1 = b(); fact2 = cv.b(); } - return (CGAL::compare (fact2*a(), fact1*cv.a()) == EQUAL && - CGAL::compare (fact2*b(), fact1*cv.b()) == EQUAL && - CGAL::compare (fact2*c(), fact1*cv.c()) == EQUAL); + return (CGAL::compare(fact2*a(), fact1*cv.a()) == EQUAL && + CGAL::compare(fact2*b(), fact1*cv.b()) == EQUAL && + CGAL::compare(fact2*c(), fact1*cv.c()) == EQUAL); } - /*! - * Check if the two curves are equal. + /*! Check whether the two curves are equal. */ - bool equals (const Self& cv) const + bool equals(const Self& cv) const { - if (! this->has_same_supporting_curve (cv)) - return (false); + if (! this->has_same_supporting_curve(cv)) return false; - if (is_linear()) - { + if (is_linear()) { // In case of line segments we can swap the source and target: - return ((_source.equals (cv._source) && _target.equals (cv._target)) || - (_source.equals (cv._target) && _target.equals (cv._source))); + return ((m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || + (m_source.equals(cv.m_target) && m_target.equals(cv.m_source))); } // Once again, opposite circular arcs are considered to be equal: return ((orientation() == cv.orientation() && - _source.equals (cv._source) && _target.equals (cv._target)) || + m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || (orientation() != cv.orientation() && - _source.equals (cv._target) && _target.equals (cv._source))); + m_source.equals(cv.m_target) && m_target.equals(cv.m_source))); } - /*! - * Split the curve at a given point into two sub-arcs. + /*! Split the curve at a given point into two sub-arcs. */ - void split (const Point_2& p, Self& c1, Self& c2) const + void split(const Point_2& p, Self& c1, Self& c2) const { // Copy the properties of this arc to the sub-arcs. c1 = *this; c2 = *this; // Change the endpoint, such that c1 lies to the right of c2: - if (is_directed_right()) - { - c1._target = p; - c2._source = p; + if (is_directed_right()) { + c1.m_target = p; + c2.m_source = p; } - else - { - c1._source = p; - c2._target = p; + else { + c1.m_source = p; + c2.m_target = p; } - - return; } - /*! - * Compute the intersections between the two arcs or segments. + /*! Compute the intersections between the two arcs or segments. */ - template - OutputIterator intersect (const Self& cv, OutputIterator oi, - Intersection_map *inter_map = nullptr) const + template + OutputIterator intersect(const Self& cv, OutputIterator oi, + Intersection_map* inter_map = nullptr) const { - // First check whether the two arcs have the same supporting curve. - if (has_same_supporting_curve (cv)) - { - // Check for overlaps between the two arcs. - Self overlap; + typedef std::pair Intersection_point; + typedef boost::variant Intersection_result; - if (_compute_overlap (cv, overlap)) - { + // First check whether the two arcs have the same supporting curve. + if (has_same_supporting_curve(cv)) { + // Check for overlaps between the two arcs. + Self overlap; + + if (_compute_overlap(cv, overlap)) { // There can be just a single overlap between two x-monotone arcs: - *oi = CGAL::make_object (overlap); - ++oi; - return (oi); + *oi++ = Intersection_result(overlap); + return oi; } // In case there is not overlap and the supporting curves are the same, @@ -1199,155 +1014,121 @@ public: // a common end point. // Note that in this case we do not define the multiplicity of the // intersection points we report. - unsigned int mult = 0; - if (left().equals (cv.left()) || left().equals(cv.right())) - { - *oi = CGAL::make_object (std::make_pair (left(), mult)); - ++oi; + Multiplicity mult = 0; + if (left().equals(cv.left()) || left().equals(cv.right())) { + *oi++ = Intersection_result(std::make_pair(left(), mult)); } - if (right().equals (cv.right()) || right().equals(cv.left())) - { - *oi = CGAL::make_object (std::make_pair (right(), mult)); - ++oi; + if (right().equals(cv.right()) || right().equals(cv.left())) { + *oi++ = Intersection_result(std::make_pair(right(), mult)); } - return (oi); + return oi; } // Before computing the intersection points between the two supporting // curves, check if their intersection has already been computed and // cached. - Curve_id_pair id_pair; - Intersection_map_iterator map_iter; - Intersection_list inter_list; - bool invalid_ids = false; + Curve_id_pair id_pair; + Intersection_map_iterator map_iter; + Intersection_list inter_list; + bool invalid_ids = false; - if (inter_map != nullptr && _index() != 0 && cv._index() != 0) - { + if (inter_map != nullptr && _index() != 0 && cv._index() != 0) { if (_index() < cv._index()) id_pair = Curve_id_pair (_index(), cv._index()); - else - id_pair = Curve_id_pair (cv._index(), _index()); + else id_pair = Curve_id_pair (cv._index(), _index()); - map_iter = inter_map->find (id_pair); + map_iter = inter_map->find(id_pair); } - else - { + else { // In case one of the IDs is invalid, we do not look in the map neither // we cache the results. - if (inter_map != nullptr) - map_iter = inter_map->end(); + if (inter_map != nullptr) map_iter = inter_map->end(); invalid_ids = true; } - if (inter_map == nullptr || map_iter == inter_map->end()) - { + if ((inter_map == nullptr) || (map_iter == inter_map->end())) { // Compute the intersections points between the two supporting curves. - if (is_linear()) - { - if (cv.is_linear()) - _lines_intersect (cv, inter_list); - else - cv._circ_line_intersect (*this, inter_list); + if (is_linear()) { + if (cv.is_linear()) _lines_intersect(cv, inter_list); + else cv._circ_line_intersect(*this, inter_list); } - else - { - if (cv.is_linear()) - _circ_line_intersect (cv, inter_list); - else - _circs_intersect (cv, inter_list); + else { + if (cv.is_linear()) _circ_line_intersect(cv, inter_list); + else _circs_intersect(cv, inter_list); } // Cache the result. - if (! invalid_ids) - (*inter_map)[id_pair] = inter_list; + if (! invalid_ids) (*inter_map)[id_pair] = inter_list; } - else - { + else { // Obtain the precomputed intersection points from the map. inter_list = (*map_iter).second; } // Report only the intersection points that lie on both arcs. - typename Intersection_list::const_iterator iter; - - for (iter = inter_list.begin(); iter != inter_list.end(); ++iter) - { + for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { if (this->_is_between_endpoints (iter->first) && cv._is_between_endpoints (iter->first)) { - *oi = CGAL::make_object (*iter); - ++oi; + *oi++ = Intersection_result(*iter); } } - return (oi); + return oi; } - /*! - * Check whether it is possible to merge our arc with the given arc. + /*! Check whether it is possible to merge our arc with the given arc. */ - bool can_merge_with (const Self& cv) const + bool can_merge_with(const Self& cv) const { // In order to merge the two arcs, they should have the same supporting // curve. - if (! this->has_same_supporting_curve (cv)) - return (false); + if (! this->has_same_supporting_curve(cv)) return false; // Check if the left endpoint of one curve is the right endpoint of the // other. - return (right().equals (cv.left()) || - left().equals (cv.right())); + return (right().equals(cv.left()) || left().equals(cv.right())); } - /*! - * Merge our arc with the given arc. + /*! Merge our arc with the given arc. * \pre The two arcs are mergeable. */ - void merge (const Self& cv) + void merge(const Self& cv) { - CGAL_precondition (this->can_merge_with (cv)); + CGAL_precondition(this->can_merge_with (cv)); // Check if we should extend the arc to the left or to the right. - if (right().equals (cv.left())) - { + if (right().equals(cv.left())) { // Extend the arc to the right. - if (is_directed_right()) - this->_target = cv.right(); - else - this->_source = cv.right(); + if (is_directed_right()) this->m_target = cv.right(); + else this->m_source = cv.right(); } - else - { - CGAL_precondition (left().equals (cv.right())); + else { + CGAL_precondition(left().equals(cv.right())); // Extend the arc to the left. - if (is_directed_right()) - this->_source = cv.left(); - else - this->_target = cv.left(); + if (is_directed_right()) this->m_source = cv.left(); + else this->m_target = cv.left(); } - - return; } /*! construct an opposite arc. */ Self construct_opposite() const { Self opp_cv; - opp_cv._first = this->_first; - opp_cv._second = this-> _second; - opp_cv._third = this-> _third; - opp_cv._source = this->_target; - opp_cv._target = this->_source; + opp_cv.m_first = this->m_first; + opp_cv.m_second = this->m_second; + opp_cv.m_third = this->m_third; + opp_cv.m_source = this->m_target; + opp_cv.m_target = this->m_source; // Take care of the information bits: We flip the orientation bits and // the bits that marks the direction. - if (is_linear()) - opp_cv._info = (this->_info ^ IS_DIRECTED_RIGHT_MASK); + if (is_linear()) opp_cv.m_info = (this->m_info ^ IS_DIRECTED_RIGHT_MASK); else - opp_cv._info = (this->_info ^ IS_DIRECTED_RIGHT_MASK ^ ORIENTATION_MASK); + opp_cv.m_info = (this->m_info ^ IS_DIRECTED_RIGHT_MASK ^ ORIENTATION_MASK); return (opp_cv); } @@ -1358,65 +1139,47 @@ public: double x_max = to_double(right().x()); double y_min = to_double(left().y()); double y_max = to_double(right().y()); - if(y_min > y_max) - std::swap(y_min, y_max); - if(is_circular()) - { + if (y_min > y_max) std::swap(y_min, y_max); + if (is_circular()) { const Circle_2& circ = this->supporting_circle(); - if(_is_upper()) - { + if (_is_upper()) { y_max = to_double(circ.center().y())+ - std::sqrt(to_double(circ.squared_radius())); + std::sqrt(to_double(circ.squared_radius())); } - else - { + else { y_min = to_double(circ.center().y()) - - std::sqrt(to_double(circ.squared_radius())); + std::sqrt(to_double(circ.squared_radius())); } } - return Bbox_2(x_min, y_min, x_max, y_max); } protected: - /*! Get the curve index. */ - inline unsigned int _index () const - { - return (_info >> INDEX_SHIFT_BITS); - } + inline unsigned int _index() const { return (m_info >> INDEX_SHIFT_BITS); } /// \name Accessors for circular arcs. //@{ /*! Get the x-coordinate of the center of the supporting circle. */ - inline const NT& x0 () const - { - return (_first); - } + inline const NT& x0() const { return (m_first); } /*! Get the y-coordinate of the center of the supporting circle. */ - inline const NT& y0 () const - { - return (_second); - } + inline const NT& y0() const { return (m_second); } /*! Get the squared radius of the supporting circle. */ - inline const NT& sqr_r () const - { - return (_third); - } + inline const NT& sqr_r() const { return (m_third); } /*! * Check if the circular arc lies on the upper half of the supporting circle. */ - inline bool _is_upper () const + inline bool _is_upper() const { - Orientation orient = orientation(); - bool dir_right = ((_info & IS_DIRECTED_RIGHT_MASK) != 0); + Orientation orient = orientation(); + bool dir_right = ((m_info & IS_DIRECTED_RIGHT_MASK) != 0); - CGAL_precondition (orient != COLLINEAR); + CGAL_precondition(orient != COLLINEAR); return ((orient == COUNTERCLOCKWISE && !dir_right) || (orient == CLOCKWISE && dir_right)); @@ -1427,22 +1190,13 @@ protected: //@{ /*! Get the coefficient of x in the equation of the supporting line. */ - inline const NT& a () const - { - return (_first); - } + inline const NT& a() const { return (m_first); } /*! Get the coefficient of y in the equation of the supporting line. */ - inline const NT& b () const - { - return (_second); - } + inline const NT& b() const { return (m_second); } /*! Get the free coefficient in the equation of the supporting line. */ - inline const NT& c () const - { - return (_third); - } + inline const NT& c() const { return (m_third); } //@} /// \name Auxiliary functions for the point_position predicate. @@ -1451,27 +1205,24 @@ protected: /*! * Check the position of a given point with respect to a line segment. */ - Comparison_result _line_point_position (const Point_2& p) const + Comparison_result _line_point_position(const Point_2& p) const { // Check if we have a vertical segment. - CGAL_precondition (is_in_x_range(p)); + CGAL_precondition(is_in_x_range(p)); - Comparison_result res; + Comparison_result res; - if (is_vertical()) - { + if (is_vertical()) { // left() is the lower endpoint: - res = CGAL::compare (p.y(), left().y()); + res = CGAL::compare(p.y(), left().y()); - if (res != LARGER) - return (res); + if (res != LARGER) return (res); // left() is the upper endpoint: res = CGAL::compare (p.y(), right().y()); - if (res != SMALLER) - return (res); + if (res != SMALLER) return (res); // p lies in the interior of the vertical segment: return (EQUAL); @@ -1487,19 +1238,17 @@ protected: /*! * Check the position of a given point with respect to a circular arc. */ - Comparison_result _circ_point_position (const Point_2& p) const + Comparison_result _circ_point_position(const Point_2& p) const { - Comparison_result c_res = CGAL::compare (p.y(), y0()); + Comparison_result c_res = CGAL::compare (p.y(), y0()); - if (_is_upper()) - { + if (_is_upper()) { // Check if p lies below the "equator" (while the arc lies above it): if (c_res == SMALLER) return (SMALLER); } - else - { + else { // Check if p lies above the "equator" (while the arc lies below it): if (c_res == LARGER) return (LARGER); @@ -1507,21 +1256,18 @@ protected: // Check if p lies inside the supporting circle, namely we have to check // whether (p.x() - x0)^2 + (p.y() - y0)^2 < r^2: - Comparison_result res = - CGAL::compare (CGAL::square (p.x() - x0()), - sqr_r() - CGAL::square (p.y() - y0())); + Comparison_result res = + CGAL::compare(CGAL::square (p.x() - x0()), + sqr_r() - CGAL::square (p.y() - y0())); - if (res == EQUAL) - // p lies on the circle: - return (EQUAL); + // p lies on the circle: + if (res == EQUAL) return (EQUAL); - if (_is_upper()) - { + if (_is_upper()) { // If p is inside the circle, it lies below the upper arc: return (res); } - else - { + else { // If p is inside the circle, it lies above the lower arc: return (res == SMALLER ? LARGER : SMALLER); } @@ -1534,25 +1280,18 @@ protected: /*! * Compare two line segments to the right of their intersection point. */ - Comparison_result _lines_compare_to_right (const Self& cv, - const Point_2& /* p */) const + Comparison_result _lines_compare_to_right(const Self& cv, + const Point_2& /* p */) const { - if (_index() != 0 && _index() == cv._index()) - return (EQUAL); + if (_index() != 0 && _index() == cv._index()) return (EQUAL); // Special treatment for vertical segments: a vertical segment is larger // than any other non-vertical segment. - if (is_vertical()) - { - if (cv.is_vertical()) - return (EQUAL); - + if (is_vertical()) { + if (cv.is_vertical()) return (EQUAL); return (LARGER); } - else if (cv.is_vertical()) - { - return (SMALLER); - } + else if (cv.is_vertical()) return (SMALLER); // Compare the slopes: -A1/B1 and -A2/B2. We actually negate the slopes // and swap the result. @@ -1563,12 +1302,11 @@ protected: * Compare a circular arcs (this) and a line segment (cv) to the right of * their intersection point. */ - Comparison_result _circ_line_compare_to_right (const Self& cv, - const Point_2& p) const + Comparison_result _circ_line_compare_to_right(const Self& cv, + const Point_2& p) const { // A vertical segment lies above any other circle to the right of p: - if (cv.is_vertical()) - return (SMALLER); + if (cv.is_vertical()) return (SMALLER); // We have to compare the slopes of the supporting circles and the // supporting line at p: @@ -1580,8 +1318,7 @@ protected: const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); // Check the case of a vertical tangent. - if (sign_denom1 == ZERO) - { + if (sign_denom1 == ZERO) { // The arc lies above any line segment if it is an upper arc, or below // any segment if it is a lower arc. return (_is_upper() ? LARGER : SMALLER); @@ -1589,16 +1326,13 @@ protected: // Compare (p.x() - x0(1)) and (A(2)/B(2)*(p.y() - y0(1)). // Note that if the denominator is negative, we have to swap the result. - const bool swap_res = (sign_denom1 == NEGATIVE); - Comparison_result slope_res = CGAL::compare (p.x() - x0(), - (p.y() - y0())*cv.a()/cv.b()); - - if (slope_res != EQUAL) - { - if (swap_res) - // Swap the comparison result, if necessary: - slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; + const bool swap_res = (sign_denom1 == NEGATIVE); + Comparison_result slope_res = + CGAL::compare (p.x() - x0(), (p.y() - y0())*cv.a()/cv.b()); + if (slope_res != EQUAL) { + // Swap the comparison result, if necessary: + if (swap_res) slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; return (slope_res); } @@ -1608,23 +1342,18 @@ protected: return (_is_upper() ? SMALLER : LARGER); } - /*! - * Compare two circular arcs to the right of their intersection point. + /*! Compare two circular arcs to the right of their intersection point. */ - Comparison_result _circs_compare_to_right (const Self& cv, - const Point_2& p) const + Comparison_result _circs_compare_to_right(const Self& cv, + const Point_2& p) const { - if (_index() != 0 && _index() == cv._index()) - { + if (_index() != 0 && _index() == cv._index()) { // Check the case of comparing two circular arcs that originate from the // same supporting circle. Their comparison result is not EQUAL only if // one is an upper arc and the other is a lower arc. - if (_is_upper() && ! cv._is_upper()) - return (LARGER); - else if (! _is_upper() && cv._is_upper()) - return (SMALLER); - else - return (EQUAL); + if (_is_upper() && ! cv._is_upper()) return (LARGER); + else if (! _is_upper() && cv._is_upper()) return (SMALLER); + else return (EQUAL); } // We have to compare the slopes of the two supporting circles at p: @@ -1633,39 +1362,31 @@ protected: // --------------- and --------------- // y0(1) - p.y() y0(2) - p.y() // - const CGAL::Sign sign_numer1 = CGAL::sign (p.x() - x0()); - const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); - const CGAL::Sign sign_numer2 = CGAL::sign (p.x() - cv.x0()); - const CGAL::Sign sign_denom2 = CGAL::sign (cv.y0() - p.y()); + const CGAL::Sign sign_numer1 = CGAL::sign(p.x() - x0()); + const CGAL::Sign sign_denom1 = CGAL::sign(y0() - p.y()); + const CGAL::Sign sign_numer2 = CGAL::sign(p.x() - cv.x0()); + const CGAL::Sign sign_denom2 = CGAL::sign(cv.y0() - p.y()); // Check the case of vertical tangents. - if (sign_denom1 == ZERO) - { - if (sign_denom2 == ZERO) - { - if (_is_upper()) - { - if (cv._is_upper()) - { + if (sign_denom1 == ZERO) { + if (sign_denom2 == ZERO) { + if (_is_upper()) { + if (cv._is_upper()) { // The two circles have a vertical tangent: // The one with a larger radius is above the other. return (CGAL::compare (sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is directed downwards: return (LARGER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // The other curve is directed upwards: return (SMALLER); } - else - { + else { // The two circles have a vertical tangent: // The one with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); @@ -1676,28 +1397,21 @@ protected: // The other arc does not have a vertical tangent. return (_is_upper() ? LARGER : SMALLER); } - else if (sign_denom2 == ZERO) - { + else if (sign_denom2 == ZERO) { return (cv._is_upper() ? SMALLER : LARGER); } // Try to act according to the slope signs. - CGAL::Sign sign_slope1; - CGAL::Sign sign_slope2; + CGAL::Sign sign_slope1; + CGAL::Sign sign_slope2; - if (sign_numer1 == sign_denom1) - sign_slope1 = POSITIVE; - else if (sign_numer1 == ZERO) - sign_slope1 = ZERO; - else - sign_slope1 = NEGATIVE; + if (sign_numer1 == sign_denom1) sign_slope1 = POSITIVE; + else if (sign_numer1 == ZERO) sign_slope1 = ZERO; + else sign_slope1 = NEGATIVE; - if (sign_numer2 == sign_denom2) - sign_slope2 = POSITIVE; - else if (sign_numer2 == ZERO) - sign_slope2 = ZERO; - else - sign_slope2 = NEGATIVE; + if (sign_numer2 == sign_denom2) sign_slope2 = POSITIVE; + else if (sign_numer2 == ZERO) sign_slope2 = ZERO; + else sign_slope2 = NEGATIVE; if ((sign_slope1 == POSITIVE && sign_slope2 != POSITIVE) || (sign_slope1 == ZERO && sign_slope2 == NEGATIVE)) @@ -1718,46 +1432,38 @@ protected: else { // Actually compare the slopes. - const bool swap_res = (sign_denom1 != sign_denom2); + const bool swap_res = (sign_denom1 != sign_denom2); const CoordNT A = (cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0()); const CoordNT B = (cv.x0() - x0())*p.y(); slope_res = CGAL::compare (A, B); - if (slope_res != EQUAL && swap_res) - { + if (slope_res != EQUAL && swap_res) { // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; } } // In case the two circles have different tangent slopes at p: - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // In this case we have a tangency point at p. - if (_is_upper()) - { - if (cv._is_upper()) - { + if (_is_upper()) { + if (cv._is_upper()) { // The circle with a larger radius is above the other. - return (CGAL::compare (sqr_r(), cv.sqr_r())); + return (CGAL::compare(sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is above our curve: return (SMALLER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // Out curve is above the other curve: return (LARGER); } - else - { + else { // The circle with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); } @@ -1771,23 +1477,18 @@ protected: /*! * Compare two line segments to the left of their intersection point. */ - Comparison_result _lines_compare_to_left (const Self& cv, - const Point_2& ) const + Comparison_result _lines_compare_to_left(const Self& cv, + const Point_2& ) const { - if (_index() != 0 && _index() == cv._index()) - return (EQUAL); + if (_index() != 0 && _index() == cv._index()) return (EQUAL); // Special treatment for vertical segments: a vertical segment is smaller // than any other non-vertical segment. - if (is_vertical()) - { - if (cv.is_vertical()) - return (EQUAL); - + if (is_vertical()) { + if (cv.is_vertical()) return (EQUAL); return (SMALLER); } - else if (cv.is_vertical()) - { + else if (cv.is_vertical()) { return (LARGER); } @@ -1796,16 +1497,14 @@ protected: return (CGAL::compare (a()/b(), cv.a()/cv.b())); } - /*! - * Compare a circular arcs (this) and a line segment (cv) to the left of + /*! Compare a circular arcs (this) and a line segment (cv) to the left of * their intersection point. */ - Comparison_result _circ_line_compare_to_left (const Self& cv, - const Point_2& p) const + Comparison_result _circ_line_compare_to_left(const Self& cv, + const Point_2& p) const { // A vertical segment lies below any other circle to the left of p: - if (cv.is_vertical()) - return (LARGER); + if (cv.is_vertical()) return (LARGER); // We have to compare the slopes of the supporting circles and the // supporting line at p, and return the swapped result: @@ -1817,8 +1516,7 @@ protected: const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); // Check the case of a vertical tangent. - if (sign_denom1 == ZERO) - { + if (sign_denom1 == ZERO) { // The arc lies above any line segment if it is an upper arc, or below // any segment if it is a lower arc. return (_is_upper() ? LARGER : SMALLER); @@ -1826,12 +1524,11 @@ protected: // Compare (p.x() - x0(1)) and (A(2)/B(2)*(p.y() - y0(1)). // Note that if the denominator is negative, we have to swap the result. - const bool swap_res = (sign_denom1 == NEGATIVE); - Comparison_result slope_res = CGAL::compare (p.x() - x0(), - (p.y() - y0())*cv.a()/cv.b()); + const bool swap_res = (sign_denom1 == NEGATIVE); + Comparison_result slope_res = + CGAL::compare(p.x() - x0(), (p.y() - y0()) * cv.a() / cv.b()); - if (slope_res != EQUAL) - { + if (slope_res != EQUAL) { if (swap_res) // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; @@ -1849,20 +1546,16 @@ protected: /*! * Compare the two arcs to the left of their intersection point. */ - Comparison_result _circs_compare_to_left (const Self& cv, - const Point_2& p) const + Comparison_result _circs_compare_to_left(const Self& cv, + const Point_2& p) const { - if (_index() != 0 && _index() == cv._index()) - { + if (_index() != 0 && _index() == cv._index()) { // Check the case of comparing two circular arcs that originate from the // same supporting circle. Their comparison result is not EQUAL only if // one is an upper arc and the other is a lower arc. - if (_is_upper() && ! cv._is_upper()) - return (LARGER); - else if (! _is_upper() && cv._is_upper()) - return (SMALLER); - else - return (EQUAL); + if (_is_upper() && ! cv._is_upper()) return (LARGER); + else if (! _is_upper() && cv._is_upper()) return (SMALLER); + else return (EQUAL); } // We have to compare the slopes of the two supporting circles at p: @@ -1872,39 +1565,31 @@ protected: // y0(1) - p.y() y0(2) - p.y() // // Eventually, we should take the opposite result. - const CGAL::Sign sign_numer1 = CGAL::sign (p.x() - x0()); - const CGAL::Sign sign_denom1 = CGAL::sign (y0() - p.y()); - const CGAL::Sign sign_numer2 = CGAL::sign (p.x() - cv.x0()); - const CGAL::Sign sign_denom2 = CGAL::sign (cv.y0() - p.y()); + const CGAL::Sign sign_numer1 = CGAL::sign(p.x() - x0()); + const CGAL::Sign sign_denom1 = CGAL::sign(y0() - p.y()); + const CGAL::Sign sign_numer2 = CGAL::sign(p.x() - cv.x0()); + const CGAL::Sign sign_denom2 = CGAL::sign(cv.y0() - p.y()); // Check the case of vertical tangents. - if (sign_denom1 == ZERO) - { - if (sign_denom2 == ZERO) - { - if (_is_upper()) - { - if (cv._is_upper()) - { + if (sign_denom1 == ZERO) { + if (sign_denom2 == ZERO) { + if (_is_upper()) { + if (cv._is_upper()) { // The two circles have a vertical tangent: // The one with a larger radius is above the other. return (CGAL::compare (sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is directed downwards: return (LARGER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // The other curve is directed upwards: return (SMALLER); } - else - { + else { // The two circles have a vertical tangent: // The one with a smaller radius is above the other. return (CGAL::compare (cv.sqr_r(), sqr_r())); @@ -1915,28 +1600,21 @@ protected: // The other arc does not have a vertical tangent. return (_is_upper() ? LARGER : SMALLER); } - else if (sign_denom2 == ZERO) - { + else if (sign_denom2 == ZERO) { return (cv._is_upper() ? SMALLER : LARGER); } // Try to act according to the slope signs. - CGAL::Sign sign_slope1; - CGAL::Sign sign_slope2; + CGAL::Sign sign_slope1; + CGAL::Sign sign_slope2; - if (sign_numer1 == sign_denom1) - sign_slope1 = POSITIVE; - else if (sign_numer1 == ZERO) - sign_slope1 = ZERO; - else - sign_slope1 = NEGATIVE; + if (sign_numer1 == sign_denom1) sign_slope1 = POSITIVE; + else if (sign_numer1 == ZERO) sign_slope1 = ZERO; + else sign_slope1 = NEGATIVE; - if (sign_numer2 == sign_denom2) - sign_slope2 = POSITIVE; - else if (sign_numer2 == ZERO) - sign_slope2 = ZERO; - else - sign_slope2 = NEGATIVE; + if (sign_numer2 == sign_denom2) sign_slope2 = POSITIVE; + else if (sign_numer2 == ZERO) sign_slope2 = ZERO; + else sign_slope2 = NEGATIVE; if ((sign_slope1 == POSITIVE && sign_slope2 != POSITIVE) || (sign_slope1 == ZERO && sign_slope2 == NEGATIVE)) @@ -1954,17 +1632,15 @@ protected: // Special case were both circles have a horizontal tangent: slope_res = EQUAL; } - else - { + else { // Actually compare the slopes. - const bool swap_res = (sign_denom1 != sign_denom2); + const bool swap_res = (sign_denom1 != sign_denom2); const CoordNT A = (cv.y0() - y0())*p.x() + (y0()*cv.x0() - cv.y0()*x0()); const CoordNT B = (cv.x0() - x0())*p.y(); - slope_res = CGAL::compare (A, B); + slope_res = CGAL::compare(A, B); - if (slope_res != EQUAL && swap_res) - { + if (slope_res != EQUAL && swap_res) { // Swap the comparison result, if necessary: slope_res = (slope_res == SMALLER) ? LARGER : SMALLER; } @@ -1973,34 +1649,27 @@ protected: // In case the two circles have different tangent slopes at p, return // the opposite of the slope result (since the slope result is the // comparison result to the right of the intersection point): - if (slope_res != EQUAL) - return ((slope_res == SMALLER) ? LARGER : SMALLER); + if (slope_res != EQUAL) return ((slope_res == SMALLER) ? LARGER : SMALLER); // In this case we have a tangency point at p. - if (_is_upper()) - { - if (cv._is_upper()) - { + if (_is_upper()) { + if (cv._is_upper()) { // The circle with a larger radius is above the other. - return (CGAL::compare (sqr_r(), cv.sqr_r())); + return (CGAL::compare(sqr_r(), cv.sqr_r())); } - else - { + else { // The other curve is above our curve: return (SMALLER); } } - else - { - if (cv._is_upper()) - { + else { + if (cv._is_upper()) { // Out curve is above the other curve: return (LARGER); } - else - { + else { // The circle with a smaller radius is above the other. - return (CGAL::compare (cv.sqr_r(), sqr_r())); + return (CGAL::compare(cv.sqr_r(), sqr_r())); } } } @@ -2009,11 +1678,10 @@ protected: /// \name Auxiliary functions for computing intersections. //@{ - /*! - * Compute the intersections between two line segments. + /*! Compute the intersections between two line segments. */ - void _lines_intersect (const Self& cv, - Intersection_list& inter_list) const + void _lines_intersect(const Self& cv, + Intersection_list& inter_list) const { // The intersection of the lines: // a1*x + b1*y + c1 = 0 and a2*x + b2*y + c2 = 0 , @@ -2023,53 +1691,47 @@ protected: // ( --------------- , --------------- ) // a1*b2 - b1*a2 a1*b2 - b1*a2 // - unsigned int mult = 1; - const NT denom = a()*cv.b() - b()*cv.a(); + unsigned int mult = 1; + const NT denom = a()*cv.b() - b()*cv.a(); // Make sure the supporting lines are not parallel. - if (CGAL::sign(denom) == ZERO) - return; + if (CGAL::sign(denom) == ZERO) return; - const NT x = (b()*cv.c() - c()*cv.b()) / denom; - const NT y = (c()*cv.a() - a()*cv.c()) / denom; - Point_2 p (x, y); + const NT x = (b()*cv.c() - c()*cv.b()) / denom; + const NT y = (c()*cv.a() - a()*cv.c()) / denom; + Point_2 p (x, y); - inter_list.push_back (Intersection_point_2 (p, mult)); - return; + inter_list.push_back(Intersection_point(p, mult)); } - /*! - * Compute the intersections between the supporting circle of (*this) and + /*! Compute the intersections between the supporting circle of (*this) and * the supporting line of the segement cv. */ - void _circ_line_intersect (const Self& cv, - Intersection_list& inter_list) const + void _circ_line_intersect(const Self& cv, + Intersection_list& inter_list) const { - Point_2 p; - unsigned int mult; + Point_2 p; + unsigned int mult; // First check the special cases of vertical and horizontal lines. - if (cv.is_vertical()) - { + if (cv.is_vertical()) { // The equation of the vertical line is x = -c / a. // The y-coordinates of the intersection points are: // y = y0 +/- sqrt(r^2 - (x - x0)^2) // - const NT vx = -cv.c() / cv.a(); - const NT vdisc = sqr_r() - CGAL::square (vx - x0()); + const NT vx = -cv.c() / cv.a(); + const NT vdisc = sqr_r() - CGAL::square (vx - x0()); CGAL::Sign sign_vdisc = CGAL::sign (vdisc); - if (sign_vdisc == NEGATIVE) - { + if (sign_vdisc == NEGATIVE) { // The circle and the vertical line do not intersect. return; } - else if (sign_vdisc == ZERO) - { + else if (sign_vdisc == ZERO) { // A single tangency point, given by: mult = 2; p = Point_2 (vx, y0()); - inter_list.push_back (Intersection_point_2 (p, mult)); + inter_list.push_back(Intersection_point(p, mult)); return; } @@ -2077,37 +1739,30 @@ protected: // Compute the two intersection points: mult = 1; - p = Point_2 (CoordNT (vx), - CoordNT (y0(), NT(-1), vdisc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT (vx), CoordNT (y0(), NT(-1), vdisc)); + inter_list.push_back (Intersection_point(p, mult)); - p = Point_2 (CoordNT (vx), - CoordNT (y0(), NT(1), vdisc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT (vx), CoordNT (y0(), NT(1), vdisc)); + inter_list.push_back(Intersection_point(p, mult)); return; } - else if (CGAL::sign (cv.a()) == ZERO) - { + else if (CGAL::sign (cv.a()) == ZERO) { // The equation of the horizontal line is y = -c / b. // The y-coordinates of the intersection points are: // x = x0 +/- sqrt(r^2 - (y - y0)^2) // - const NT hy = -cv.c() / cv.b(); - const NT hdisc = sqr_r() - CGAL::square (hy - y0()); + const NT hy = -cv.c() / cv.b(); + const NT hdisc = sqr_r() - CGAL::square (hy - y0()); CGAL::Sign sign_hdisc = CGAL::sign (hdisc); - if (sign_hdisc == NEGATIVE) - { - // The circle and the vertical line do not intersect. - return; - } - else if (sign_hdisc == ZERO) - { + // The circle and the vertical line do not intersect. + if (sign_hdisc == NEGATIVE) return; + else if (sign_hdisc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x0(), hy); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(x0(), hy); + inter_list.push_back(Intersection_point (p, mult)); return; } @@ -2115,287 +1770,246 @@ protected: // Compute the two intersection points: mult = 1; - p = Point_2 (CoordNT (x0(), NT(-1), hdisc), - CoordNT (hy)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x0(), NT(-1), hdisc), CoordNT (hy)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x0(), NT(1), hdisc), - CoordNT (hy)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x0(), NT(1), hdisc), CoordNT(hy)); + inter_list.push_back(Intersection_point (p, mult)); return; } // Compute the squared distance between the line and the circle center, // inducing the discriminant of the quadratic equations we have to solve. - const NT line_factor = CGAL::square(cv.a()) + CGAL::square(cv.b()); - const NT disc = line_factor*sqr_r() - - CGAL::square(cv.a()*x0() + cv.b()*y0() + cv.c()); + const NT line_factor = CGAL::square(cv.a()) + CGAL::square(cv.b()); + const NT disc = + line_factor*sqr_r() - CGAL::square(cv.a()*x0() + cv.b()*y0() + cv.c()); CGAL::Sign sign_disc = CGAL::sign (disc); - if (sign_disc == NEGATIVE) - { - // The circle and the line do not intersect: - return; - } + // The circle and the line do not intersect: + if (sign_disc == NEGATIVE) return; // Compare the square-free part of the solution: - const NT aux = cv.b()*x0() - cv.a()*y0(); - const NT x_base = (aux*cv.b() - cv.a()*cv.c()) / line_factor; - const NT y_base = (-aux*cv.a() - cv.b()*cv.c()) / line_factor; + const NT aux = cv.b()*x0() - cv.a()*y0(); + const NT x_base = (aux*cv.b() - cv.a()*cv.c()) / line_factor; + const NT y_base = (-aux*cv.a() - cv.b()*cv.c()) / line_factor; - if (sign_disc == ZERO) - { + if (sign_disc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x_base, y_base); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(x_base, y_base); + inter_list.push_back(Intersection_point(p, mult)); return; } // We have two intersection points, whose coordinates are one-root numbers. - bool minus_root_first = (CGAL::sign(cv.b()) == POSITIVE); - const NT x_root_coeff = cv.b() / line_factor; - const NT y_root_coeff = cv.a() / line_factor; + bool minus_root_first = (CGAL::sign(cv.b()) == POSITIVE); + const NT x_root_coeff = cv.b() / line_factor; + const NT y_root_coeff = cv.a() / line_factor; mult = 1; - if (minus_root_first) - { - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + if (minus_root_first) { + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - else - { - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + else { + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - - return; } - /*! - * Compute the intersections between two circles. + /*! Compute the intersections between two circles. */ - void _circs_intersect (const Self& cv, - Intersection_list& inter_list) const + void _circs_intersect(const Self& cv, Intersection_list& inter_list) const { - Point_2 p; - unsigned int mult; + Point_2 p; + unsigned int mult; // Compute the squared distance between the circle centers, inducing the // discriminant of the quadratic equations we have to solve. - const NT diff_x = cv.x0() - x0(); - const NT diff_y = cv.y0() - y0(); - const NT sqr_dist = CGAL::square(diff_x) + CGAL::square(diff_y); - const NT diff_sqr_rad = sqr_r() - cv.sqr_r(); - const NT disc = 2*sqr_dist*(sqr_r() + cv.sqr_r()) - - (CGAL::square(diff_sqr_rad) + CGAL::square(sqr_dist)); + const NT diff_x = cv.x0() - x0(); + const NT diff_y = cv.y0() - y0(); + const NT sqr_dist = CGAL::square(diff_x) + CGAL::square(diff_y); + const NT diff_sqr_rad = sqr_r() - cv.sqr_r(); + const NT disc = 2 * sqr_dist * (sqr_r() + cv.sqr_r()) - + (CGAL::square(diff_sqr_rad) + CGAL::square(sqr_dist)); CGAL::Sign sign_disc = CGAL::sign (disc); - if (sign_disc == NEGATIVE) - { - // The two circles do not intersect. - return; - } + // The two circles do not intersect. + if (sign_disc == NEGATIVE) return; // Compare the square-free part of the solution: - const NT x_base = ((x0() + cv.x0()) + diff_x*diff_sqr_rad/sqr_dist) / 2; - const NT y_base = ((y0() + cv.y0()) + diff_y*diff_sqr_rad/sqr_dist) / 2; + const NT x_base = ((x0() + cv.x0()) + diff_x * diff_sqr_rad / sqr_dist) / 2; + const NT y_base = ((y0() + cv.y0()) + diff_y * diff_sqr_rad / sqr_dist) / 2; - if (sign_disc == ZERO) - { + if (sign_disc == ZERO) { // A single tangency point, given by: mult = 2; - p = Point_2 (x_base, y_base); - inter_list.push_back (Intersection_point_2 (p, mult)); - + p = Point_2(x_base, y_base); + inter_list.push_back(Intersection_point(p, mult)); return; } // We have two intersection points, whose coordinates are one-root numbers. CGAL::Sign sign_diff_y = CGAL::sign (diff_y); - bool minus_root_first; + bool minus_root_first; if (sign_diff_y == ZERO) minus_root_first = (CGAL::sign (diff_x) == NEGATIVE); else minus_root_first = (sign_diff_y == POSITIVE); - const NT x_root_coeff = diff_y / (2 * sqr_dist); - const NT y_root_coeff = diff_x / (2 * sqr_dist); + const NT x_root_coeff = diff_y / (2 * sqr_dist); + const NT y_root_coeff = diff_x / (2 * sqr_dist); mult = 1; - if (minus_root_first) - { - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + if (minus_root_first) { + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); } - else - { - p = Point_2 (CoordNT (x_base, x_root_coeff, disc), - CoordNT (y_base, -y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + else { + p = Point_2(CoordNT(x_base, x_root_coeff, disc), + CoordNT(y_base, -y_root_coeff, disc)); + inter_list.push_back(Intersection_point (p, mult)); - p = Point_2 (CoordNT (x_base, -x_root_coeff, disc), - CoordNT (y_base, y_root_coeff, disc)); - inter_list.push_back (Intersection_point_2 (p, mult)); + p = Point_2(CoordNT(x_base, -x_root_coeff, disc), + CoordNT(y_base, y_root_coeff, disc)); + inter_list.push_back(Intersection_point(p, mult)); } - - return; } - /*! - * Check if the given point lies on the arc. + /*! Check if the given point lies on the arc. * \pre p lies on the supporting curve. */ - bool _is_between_endpoints (const Point_2& p) const + bool _is_between_endpoints(const Point_2& p) const { - if (is_linear()) - { - if (is_vertical()) - { + if (is_linear()) { + if (is_vertical()) { // Check if the point is in the y-range of the arc. // Note that left() is the lower endpoint and right() is the upper // endpoint of the segment in this case. - Comparison_result res = CGAL::compare (p.y(), left().y()); + Comparison_result res = CGAL::compare(p.y(), left().y()); - if (res == SMALLER) - return (false); - else if (res == EQUAL) - return (true); + if (res == SMALLER) return false; + else if (res == EQUAL) return true; - return (CGAL::compare (p.y(), right().y()) != LARGER); + return (CGAL::compare(p.y(), right().y()) != LARGER); } // For non-vertical segments, it is sufficient to check if the point // is in the x-range of the arc. - return (this->is_in_x_range (p)); + return (this->is_in_x_range(p)); } // The supporting curve is a circle: // Check whether p lies on the upper or on the lower part of the circle. - Comparison_result c_res = CGAL::compare (p.y(), y0()); + Comparison_result c_res = CGAL::compare(p.y(), y0()); - if ((_is_upper() && c_res == SMALLER) || - (! _is_upper() && c_res == LARGER)) + if ((_is_upper() && c_res == SMALLER) || (! _is_upper() && c_res == LARGER)) { // The point lies on the other half of the circle: - return (false); + return false; } // Check if the point is in the x-range of the arc. - return (this->is_in_x_range (p)); + return (this->is_in_x_range(p)); } - /*! - * Check if the given point lies in the interior of the arc. + /*! Check whether the given point lies in the interior of the arc. * \pre p lies on the supporting curve. */ - bool _is_strictly_between_endpoints (const Point_2& p) const + bool _is_strictly_between_endpoints(const Point_2& p) const { - if (p.equals (_source) || p.equals (_target)) - return (false); - - return (_is_between_endpoints (p)); + if (p.equals (m_source) || p.equals (m_target)) return false; + return (_is_between_endpoints(p)); } - /*! - * Compute the overlap with a given arc having the same supporting curve. + /*! Compute the overlap with a given arc having the same supporting curve. * \param cv The given arc. * \param overlap Output: The overlapping arc (if any). * \return Whether we found an overlap. */ - bool _compute_overlap (const Self& cv, Self& overlap) const + bool _compute_overlap(const Self& cv, Self& overlap) const { // Check if the two arcs are identical. - if (is_linear()) - { + if (is_linear()) { // In case of line segments we can swap the source and target: - if (((_source.equals (cv._source) && _target.equals (cv._target)) || - (_source.equals (cv._target) && _target.equals (cv._source)))) + if (((m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || + (m_source.equals(cv.m_target) && m_target.equals(cv.m_source)))) { overlap = cv; - return (true); + return true; } } - else - { + else { if ((orientation() == cv.orientation() && - _source.equals (cv._source) && _target.equals (cv._target)) || + m_source.equals(cv.m_source) && m_target.equals(cv.m_target)) || (orientation() != cv.orientation() && - _source.equals (cv._target) && _target.equals (cv._source))) + m_source.equals(cv.m_target) && m_target.equals(cv.m_source))) { overlap = cv; - return (true); + return true; } } // Check for other overlaps: - if (_is_strictly_between_endpoints (cv.left())) - { - if (_is_strictly_between_endpoints (cv.right())) - { + if (_is_strictly_between_endpoints(cv.left())) { + if (_is_strictly_between_endpoints(cv.right())) { // Case 1 - *this: +-----------> // cv: +=====> overlap = cv; - return (true); + return true; } - else - { + else { // Case 2 - *this: +-----------> // cv: +=====> overlap = *this; - if (overlap.is_directed_right()) - overlap._source = cv.left(); - else - overlap._target = cv.left(); + if (overlap.is_directed_right()) overlap.m_source = cv.left(); + else overlap.m_target = cv.left(); - return (true); + return true; } } - else if (_is_strictly_between_endpoints (cv.right())) - { + else if (_is_strictly_between_endpoints(cv.right())) { // Case 3 - *this: +-----------> // cv: +=====> overlap = *this; - if (overlap.is_directed_right()) - overlap._target = cv.right(); - else - overlap._source = cv.right(); + if (overlap.is_directed_right()) overlap.m_target = cv.right(); + else overlap.m_source = cv.right(); - return (true); + return true; } - else if (cv._is_between_endpoints (_source) && - cv._is_between_endpoints (_target) && - (cv._is_strictly_between_endpoints (_source) || - cv._is_strictly_between_endpoints (_target))) + else if (cv._is_between_endpoints(m_source) && + cv._is_between_endpoints(m_target) && + (cv._is_strictly_between_endpoints(m_source) || + cv._is_strictly_between_endpoints(m_target))) { // Case 4 - *this: +-----------> // cv: +================> overlap = *this; - return (true); + return true; } // If we reached here, there are no overlaps: - return (false); + return false; } public: @@ -2407,61 +2021,49 @@ protected: const double x_right = CGAL::to_double(this->target().x()); const double y_right = CGAL::to_double(this->target().y()); - if(this->is_linear()) - { - *oi = std::make_pair(x_left, y_left); - ++oi; - - *oi = std::make_pair(x_right, y_right); - ++oi; + if (this->is_linear()) { + *oi++ = std::make_pair(x_left, y_left); + *oi++ = std::make_pair(x_right, y_right); return; } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_xcenter = CGAL::to_double (this->_first); - const double app_ycenter = CGAL::to_double (this->_second); - const double app_sqr_rad = CGAL::to_double (this->_third); + const double app_xcenter = CGAL::to_double(this->m_first); + const double app_ycenter = CGAL::to_double(this->m_second); + const double app_sqr_rad = CGAL::to_double(this->m_third); - const double x_jump = (x_right - x_left) / n; - double x, y; - double disc; - unsigned int i; + const double x_jump = (x_right - x_left) / n; + double x, y; + double disc; + unsigned int i; const bool is_up = this->_is_upper(); - *oi = std::make_pair (x_left, y_left); // The left point. - ++oi; - for (i = 1; i < n; i++) - { + *oi++ = std::make_pair (x_left, y_left); // The left point. + for (i = 1; i < n; ++i) { x = x_left + x_jump*i; disc = app_sqr_rad - CGAL::square(x - app_xcenter); if (disc < 0) disc = 0; - if(is_up) - y = app_ycenter + std::sqrt(disc); - else - y = app_ycenter - std::sqrt(disc); + if(is_up) y = app_ycenter + std::sqrt(disc); + else y = app_ycenter - std::sqrt(disc); - *oi = std::make_pair(x, y); - ++oi; + *oi++ = std::make_pair(x, y); } - *oi = std::make_pair(x_right, y_right); // The right point. - ++oi; + *oi++ = std::make_pair(x_right, y_right); // The right point. } - /*! - * Trim the arc given its new endpoints. + /*! Trim the arc given its new endpoints. * \param ps The new source point. * \param pt The new target point. * \return The new trimmed arc. * \pre Both ps and pt lies on the arc and must conform with the current * direction of the arc. */ - Self trim (const Point_2& ps, - const Point_2& pt) const + Self trim(const Point_2& ps, const Point_2& pt) const { - Self arc = *this; + Self arc = *this; - arc._source = ps; - arc._target = pt; + arc.m_source = ps; + arc.m_target = pt; return arc; } @@ -2469,13 +2071,12 @@ protected: //@} }; -/*! - * Exporter for circular arcs (or line segments). +/*! Exporter for circular arcs (or line segments). */ template std::ostream& -operator<< (std::ostream& os, - const _X_monotone_circle_segment_2 & arc) +operator<<(std::ostream& os, + const _X_monotone_circle_segment_2 & arc) { if (! arc.is_linear()) os << "(" << arc.supporting_circle() << ") "; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h index 6fc3ecce08c..b6587f4e1ab 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Conic_x_monotone_arc_2.h @@ -7,34 +7,32 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// -// Author(s) : Ron Wein +// Author(s): Ron Wein #ifndef CGAL_CONIC_X_MONOTONE_ARC_2_H #define CGAL_CONIC_X_MONOTONE_ARC_2_H #include - /*! \file * Header file for the _Conic_x_monotone_arc_2 class. */ -#include - #include #include +#include + +#include + namespace CGAL { -/*! - * Representation of an x-monotone conic arc. +/*! Representation of an x-monotone conic arc. * The class is templated by a representation of a general bounded conic arc. */ -template -class _Conic_x_monotone_arc_2 : private Conic_arc_ -{ +template +class _Conic_x_monotone_arc_2 : private Conic_arc_ { public: typedef Conic_arc_ Conic_arc_2; @@ -49,8 +47,8 @@ public: // Type definition for the intersection points mapping. typedef typename Conic_point_2::Conic_id Conic_id; typedef std::pair Conic_pair; - typedef std::pair Intersection_point_2; - typedef std::list Intersection_list; + typedef std::pair Intersection_point; + typedef std::list Intersection_list; using Conic_arc_2::_sign_of_extra_data; using Conic_arc_2::_is_between_endpoints; @@ -59,13 +57,12 @@ public: /*! * \struct Less functor for Conic_pair. */ - struct Less_conic_pair - { - bool operator() (const Conic_pair& cp1, const Conic_pair& cp2) const + struct Less_conic_pair { + bool operator()(const Conic_pair& cp1, const Conic_pair& cp2) const { // Compare the pairs of IDs lexicographically. - return (cp1.first < cp2.first || - (cp1.first == cp2.first && cp1.second < cp2.second)); + return ((cp1.first < cp2.first) || + ((cp1.first == cp2.first) && (cp1.second < cp2.second))); } }; @@ -85,8 +82,7 @@ protected: // Bit masks for the _info field (the two least significant bits are already // used by the base class). - enum - { + enum { IS_VERTICAL_SEGMENT = 4, IS_DIRECTED_RIGHT = 8, DEGREE_1 = 16, @@ -99,14 +95,14 @@ protected: IS_SPECIAL_SEGMENT = 512 }; - Algebraic alg_r; // The coefficients of the supporting conic curve: - Algebraic alg_s; // - Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , - Algebraic alg_u; // - Algebraic alg_v; // converted to algebraic numbers. - Algebraic alg_w; // + Algebraic alg_r; // The coefficients of the supporting conic curve: + Algebraic alg_s; // + Algebraic alg_t; // r*x^2 + s*y^2 + t*xy + u*x + v*y +w = 0 , + Algebraic alg_u; // + Algebraic alg_v; // converted to algebraic numbers. + Algebraic alg_w; // - Conic_id _id; // The ID number of the supporting conic curve. + Conic_id _id; // The ID number of the supporting conic curve. public: @@ -117,68 +113,62 @@ public: * Default constructor. */ _Conic_x_monotone_arc_2 () : - Base (), - _id () + Base(), + _id() {} /*! * Copy constructor. * \param arc The copied arc. */ - _Conic_x_monotone_arc_2 (const Self& arc) : - Base (arc), - alg_r (arc.alg_r), - alg_s (arc.alg_s), - alg_t (arc.alg_t), - alg_u (arc.alg_u), - alg_v (arc.alg_v), - alg_w (arc.alg_w), - _id (arc._id) + _Conic_x_monotone_arc_2(const Self& arc) : + Base(arc), + alg_r(arc.alg_r), + alg_s(arc.alg_s), + alg_t(arc.alg_t), + alg_u(arc.alg_u), + alg_v(arc.alg_v), + alg_w(arc.alg_w), + _id(arc._id) {} - /*! - * Construct an x-monotone arc from a conic arc. + /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \pre The given arc is x-monotone. */ - _Conic_x_monotone_arc_2 (const Base& arc) : - Base (arc), - _id () + _Conic_x_monotone_arc_2(const Base& arc) : + Base(arc), + _id() { - CGAL_precondition (arc.is_valid() && arc.is_x_monotone()); - + CGAL_precondition(arc.is_valid() && arc.is_x_monotone()); _set (); } - /*! - * Construct an x-monotone arc from a conic arc. + /*! Construct an x-monotone arc from a conic arc. * \param arc The given (base) arc. * \param id The ID of the base arc. */ - _Conic_x_monotone_arc_2 (const Base& arc, - const Conic_id& id) : - Base (arc), - _id (id) + _Conic_x_monotone_arc_2(const Base& arc, const Conic_id& id) : + Base(arc), + _id(id) { - CGAL_precondition (arc.is_valid() && id.is_valid()); - + CGAL_precondition(arc.is_valid() && id.is_valid()); _set (); } - /*! - * Construct an x-monotone sub-arc from a conic arc. + /*! Construct an x-monotone sub-arc from a conic arc. * \param arc The given (base) arc. * \param source The source point. * \param target The target point. * \param id The ID of the base arc. */ - _Conic_x_monotone_arc_2 (const Base& arc, - const Point_2& source, const Point_2& target, - const Conic_id& id) : - Base (arc), - _id (id) + _Conic_x_monotone_arc_2(const Base& arc, + const Point_2& source, const Point_2& target, + const Conic_id& id) : + Base(arc), + _id(id) { - CGAL_precondition (arc.is_valid() && id.is_valid()); + CGAL_precondition(arc.is_valid() && id.is_valid()); // Set the two endpoints. this->_source = source; @@ -193,7 +183,7 @@ public: * \param source The source point. * \param target The target point. */ - _Conic_x_monotone_arc_2 (const Point_2& source, const Point_2& target) : + _Conic_x_monotone_arc_2(const Point_2& source, const Point_2& target) : Base() { // Set the basic properties and clear the _info bits. @@ -204,22 +194,21 @@ public: // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result dir_res = ker.compare_xy_2_object() (this->_source, - this->_target); + Alg_kernel ker; + Comparison_result dir_res = + ker.compare_xy_2_object()(this->_source, this->_target); CGAL_precondition (dir_res != EQUAL); - if (dir_res == EQUAL) - // Invalid arc: - return; + // Invalid arc: + if (dir_res == EQUAL) return; this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); if (dir_res == SMALLER) this->_info = (this->_info | IS_DIRECTED_RIGHT); // Compose the equation of the underlying line. - const Algebraic x1 = source.x(), y1 = source.y(); - const Algebraic x2 = target.x(), y2 = target.y(); + const Algebraic x1 = source.x(), y1 = source.y(); + const Algebraic x2 = target.x(), y2 = target.y(); // The supporting line is A*x + B*y + C = 0, where: // @@ -249,18 +238,18 @@ public: * \param source The source point. * \param target The target point. */ - _Conic_x_monotone_arc_2 (const Algebraic& a, - const Algebraic& b, - const Algebraic& c, - const Point_2& source, const Point_2& target) : + _Conic_x_monotone_arc_2(const Algebraic& a, + const Algebraic& b, + const Algebraic& c, + const Point_2& source, const Point_2& target) : Base() { // Make sure the two endpoints lie on the supporting line. - CGAL_precondition (CGAL::sign (a * source.x() + - b * source.y() + c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a * source.x() + + b * source.y() + c) == CGAL::ZERO); - CGAL_precondition (CGAL::sign (a * target.x() + - b * target.y() + c) == CGAL::ZERO); + CGAL_precondition(CGAL::sign(a * target.x() + + b * target.y() + c) == CGAL::ZERO); // Set the basic properties and clear the _info bits. this->_source = source; @@ -270,23 +259,20 @@ public: // Check if the arc is directed right (the target is lexicographically // greater than the source point), or to the left. - Alg_kernel ker; - Comparison_result res = ker.compare_x_2_object() (this->_source, - this->_target); + Alg_kernel ker; + Comparison_result res = + ker.compare_x_2_object()(this->_source, this->_target); this->_info = (Conic_arc_2::IS_VALID | DEGREE_1); - if (res == EQUAL) - { + if (res == EQUAL) { // Mark that the segment is vertical. this->_info = (this->_info | IS_VERTICAL_SEGMENT); // Compare the endpoints lexicographically. - res = ker.compare_y_2_object() (this->_source, - this->_target); + res = ker.compare_y_2_object()(this->_source, this->_target); CGAL_precondition (res != EQUAL); - if (res == EQUAL) - { + if (res == EQUAL) { // Invalid arc: this->_info = 0; return; @@ -313,12 +299,11 @@ public: * Assignment operator. * \param arc The copied arc. */ - const Self& operator= (const Self& arc) + const Self& operator=(const Self& arc) { CGAL_precondition (arc.is_valid()); - if (this == &arc) - return (*this); + if (this == &arc) return (*this); // Copy the base arc. Base::operator= (arc); @@ -343,49 +328,35 @@ public: /*! * Get the coefficients of the underlying conic. */ - const Integer& r () const {return (this->_r);} - const Integer& s () const {return (this->_s);} - const Integer& t () const {return (this->_t);} - const Integer& u () const {return (this->_u);} - const Integer& v () const {return (this->_v);} - const Integer& w () const {return (this->_w);} + const Integer& r() const { return (this->_r); } + const Integer& s() const { return (this->_s); } + const Integer& t() const { return (this->_t); } + const Integer& u() const { return (this->_u); } + const Integer& v() const { return (this->_v); } + const Integer& w() const { return (this->_w); } /*! * Get the arc's source. * \return The source point. */ - const Conic_point_2& source () const - { - return (this->_source); - } + const Conic_point_2& source() const { return (this->_source); } - /*! - * Get the arc's target. + /*! Get the arc's target. * \return The target point. */ - const Conic_point_2& target () const - { - return (this->_target); - } + const Conic_point_2& target() const { return (this->_target); } - /*! - * Get the orientation of the arc. + /*! Get the orientation of the arc. * \return The orientation. */ - Orientation orientation () const - { - return (this->_orient); - } + Orientation orientation() const { return (this->_orient); } - /*! - * Get the left endpoint of the arc. + /*! Get the left endpoint of the arc. */ const Conic_point_2& left () const { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - return (this->_source); - else - return (this->_target); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_source); + else return (this->_target); } /*! @@ -393,28 +364,21 @@ public: */ const Conic_point_2& right () const { - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - return (this->_target); - else - return (this->_source); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) return (this->_target); + else return (this->_source); } /*! * Return true iff the conic arc is directed right iexicographically. */ bool is_directed_right() const - { - return ((this->_info & IS_DIRECTED_RIGHT) != 0); - } + { return ((this->_info & IS_DIRECTED_RIGHT) != 0); } /*! * Get a bounding box for the conic arc. * \return The bounding box. */ - Bbox_2 bbox () const - { - return (Base::bbox()); - } + Bbox_2 bbox() const { return (Base::bbox()); } //@} /// \name Predicates. @@ -433,23 +397,20 @@ public: * \param p The qury point. * \param (true) if p lies on the arc; (false) otherwise. */ - bool contains_point (const Conic_point_2& p) const + bool contains_point(const Conic_point_2& p) const { // First check if p lies on the supporting conic. We first check whether // it is one of p's generating conic curves. bool p_on_conic = false; - if (p.is_generating_conic (_id)) - { + if (p.is_generating_conic(_id)) { p_on_conic = true; } - else - { + else { // Check whether p satisfies the supporting conic equation. - p_on_conic = _is_on_supporting_conic (p.x(), p.y()); + p_on_conic = _is_on_supporting_conic(p.x(), p.y()); - if (p_on_conic) - { + if (p_on_conic) { // As p lies on the supporting conic of our arc, add its ID to // the list of generating conics for p. Conic_point_2& p_non_const = const_cast (p); @@ -483,17 +444,16 @@ public: Alg_kernel ker; ); - CGAL_precondition (ker.compare_x_2_object() (p, left()) != SMALLER && - ker.compare_x_2_object() (p, right()) != LARGER); + CGAL_precondition(ker.compare_x_2_object() (p, left()) != SMALLER && + ker.compare_x_2_object() (p, right()) != LARGER); - if (_is_special_segment()) - { + if (_is_special_segment()) { // In case of a special segment, the equation of the supported line // (a*x + b*y + c) = 0 is stored with the extra data field, and we // simply have: - Algebraic _y = -(this->_extra_data_P->a*p.x() + - this->_extra_data_P->c) / - this->_extra_data_P->b; + Algebraic _y = -(this->_extra_data_P->a*p.x() + + this->_extra_data_P->c) / + this->_extra_data_P->b; // Return the computed point. return (Point_2 (p.x(), _y)); @@ -501,18 +461,16 @@ public: // Compute the y-coordinate according to the degree of the supporting // conic curve. - Nt_traits nt_traits; - Algebraic y; + Nt_traits nt_traits; + Algebraic y; - if ((this->_info & DEGREE_MASK) == DEGREE_1) - { + if ((this->_info & DEGREE_MASK) == DEGREE_1) { // In case of a linear curve, the y-coordinate is a simple linear // expression of x(p) (note that v is not 0 as the arc is not vertical): // y = -(u*x(p) + w) / v y = -(alg_u*p.x() + alg_w) / alg_v; } - else if (this->_orient == COLLINEAR) - { + else if (this->_orient == COLLINEAR) { CGAL_assertion (this->_extra_data_P != nullptr); // In this case the equation of the supporting line is given by the @@ -520,26 +478,23 @@ public: y = -(this->_extra_data_P->a * p.x() + this->_extra_data_P->c) / this->_extra_data_P->b; } - else - { - CGAL_assertion ((this->_info & DEGREE_MASK) == DEGREE_2); + else { + CGAL_assertion((this->_info & DEGREE_MASK) == DEGREE_2); // In this case the y-coordinate is one of solutions to the quadratic // equation: // s*y^2 + (t*x(p) + v)*y + (r*x(p)^2 + u*x(p) + w) = 0 - Algebraic A = alg_s; - Algebraic B = alg_t*p.x() + alg_v; - Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; + Algebraic A = alg_s; + Algebraic B = alg_t*p.x() + alg_v; + Algebraic C = (alg_r*p.x() + alg_u)*p.x() + alg_w; - if (CGAL::sign(this->_s) == ZERO) - { + if (CGAL::sign(this->_s) == ZERO) { // In this case A is 0 and we have a linear equation. CGAL_assertion (CGAL::sign (B) != ZERO); y = -C / B; } - else - { + else { // Solve the quadratic equation. Algebraic disc = B*B - 4*A*C; @@ -547,13 +502,10 @@ public: // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) - { + if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { y = (nt_traits.sqrt (disc) - B) / (2*A); } - else - - { + else { y = -(B + nt_traits.sqrt (disc)) / (2*A); } } @@ -579,169 +531,148 @@ public: { CGAL_precondition (n != 0); - const double x_left = CGAL::to_double (left().x()); - const double y_left = CGAL::to_double (left().y()); - const double x_right = CGAL::to_double (right().x()); - const double y_right = CGAL::to_double (right().y()); + const double x_left = CGAL::to_double (left().x()); + const double y_left = CGAL::to_double (left().y()); + const double x_right = CGAL::to_double (right().x()); + const double y_right = CGAL::to_double (right().y()); - if (this->_orient == COLLINEAR) - { + if (this->_orient == COLLINEAR) { // In case of a line segment, return the two endpoints. - *oi = std::pair (x_left, y_left); - ++oi; - *oi = std::pair (x_right, y_right); - ++oi; - return (oi); + *oi++ = std::pair (x_left, y_left); + *oi++ = std::pair (x_right, y_right); + return oi; } // Otherwise, sample (n - 1) equally-spaced points in between. - const double app_r = CGAL::to_double (this->_r); - const double app_s = CGAL::to_double (this->_s); - const double app_t = CGAL::to_double (this->_t); - const double app_u = CGAL::to_double (this->_u); - const double app_v = CGAL::to_double (this->_v); - const double app_w = CGAL::to_double (this->_w); - const double x_jump = (x_right - x_left) / n; - double x, y; - const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); - double A = app_s, B, C; - double disc; - size_t i; + const double app_r = CGAL::to_double (this->_r); + const double app_s = CGAL::to_double (this->_s); + const double app_t = CGAL::to_double (this->_t); + const double app_u = CGAL::to_double (this->_u); + const double app_v = CGAL::to_double (this->_v); + const double app_w = CGAL::to_double (this->_w); + const double x_jump = (x_right - x_left) / n; + double x, y; + const bool A_is_zero = (CGAL::sign(this->_s) == ZERO); + double A = app_s, B, C; + double disc; + size_t i; - *oi = std::pair (x_left, y_left); // The left point. + *oi = std::pair(x_left, y_left); // The left point. ++oi; - for (i = 1; i < n; i++) - { + for (i = 1; i < n; i++) { x = x_left + x_jump*i; // Solve the quadratic equation: A*x^2 + B*x + C = 0: B = app_t*x + app_v; C = (app_r*x + app_u)*x + app_w; - if (A_is_zero) - { + if (A_is_zero) { y = -C / B; } - else - { + else { disc = B*B - 4*A*C; - if (disc < 0) - disc = 0; + if (disc < 0) disc = 0; // We take either the root involving -sqrt(disc) or +sqrt(disc) // based on the information flags. - if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) - { + if ((this->_info & PLUS_SQRT_DISC_ROOT) != 0) { y = (std::sqrt(disc) - B) / (2*A); } - else - { + else { y = -(B + std::sqrt (disc)) / (2*A); } } - *oi = std::pair (x, y); - ++oi; + *oi++ = std::pair (x, y); } - *oi = std::pair (x_right, y_right); // The right point. - ++oi; + *oi++ = std::pair (x_right, y_right); // The right point. - return (oi); + return oi; } - /*! - * Compare to arcs immediately to the right of their intersection point. + /*! Compare to arcs immediately to the right of their intersection point. * \param arc The compared arc. * \param p The reference intersection point. * \return The relative position of the arcs to the right of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_right (const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_right(const Self& arc, + const Conic_point_2& p) const { - CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && + (arc._info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) - { + if (_has_same_supporting_conic (arc)) { if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP) != 0) - return (SMALLER); + return SMALLER; // In this case the two arcs overlap. - CGAL_assertion ((this->_info & FACING_MASK) == - (arc._info & FACING_MASK)); + CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); - return (EQUAL); + return EQUAL; } // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; _derive_by_x_at (p, 1, slope1_numer, slope1_denom); arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); + const bool is_vertical_slope1 = (CGAL::sign(slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign(slope2_denom) == ZERO); - if (!is_vertical_slope1 && !is_vertical_slope2) - { + if (!is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). - Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. - _derive_by_x_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 2, slope2_numer, slope2_denom); + _derive_by_x_at(p, 2, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 2, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); + _derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); // \todo Handle higher-order derivatives: CGAL_assertion (slope_res != EQUAL); return (slope_res); } - else if (!is_vertical_slope2) - { + else if (!is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((this->_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) - return (LARGER); - return (SMALLER); + if ((this->_info & FACING_UP) != 0) return (LARGER); + return SMALLER; } - else if (!is_vertical_slope1) - { + else if (!is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((arc._info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) - return (SMALLER); - return (LARGER); + if ((arc._info & FACING_UP) != 0) return (SMALLER); + return LARGER; } // The two arcs have vertical slopes at p_int: @@ -750,31 +681,29 @@ public: if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) return (LARGER); else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // Compute the second-order derivative by y and act according to it. _derive_by_y_at (p, 2, slope1_numer, slope1_denom); arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); - Comparison_result slope_res = CGAL::compare (slope1_numer*slope2_denom, - slope2_numer*slope1_denom); + Comparison_result slope_res = + CGAL::compare(slope1_numer*slope2_denom, slope2_numer*slope1_denom); // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) - { + if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); + _derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); } // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) - { + if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -789,50 +718,45 @@ public: * \return The relative position of the arcs to the left of p. * \pre Both arcs we compare are not vertical segments. */ - Comparison_result compare_to_left (const Self& arc, - const Conic_point_2& p) const + Comparison_result compare_to_left(const Self& arc, + const Conic_point_2& p) const { - CGAL_precondition ((this->_info & IS_VERTICAL_SEGMENT) == 0 && - (arc._info & IS_VERTICAL_SEGMENT) == 0); + CGAL_precondition((this->_info & IS_VERTICAL_SEGMENT) == 0 && + (arc._info & IS_VERTICAL_SEGMENT) == 0); // In case one arc is facing upwards and another facing downwards, it is // clear that the one facing upward is above the one facing downwards. - if (_has_same_supporting_conic (arc)) - { + if (_has_same_supporting_conic (arc)) { if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // In this case the two arcs overlap. - CGAL_assertion ((this->_info & FACING_MASK) == - (arc._info & FACING_MASK)); + CGAL_assertion((this->_info & FACING_MASK) == (arc._info & FACING_MASK)); - return (EQUAL); + return EQUAL; } // Compare the slopes of the two arcs at p, using their first-order // partial derivatives. - Algebraic slope1_numer, slope1_denom; - Algebraic slope2_numer, slope2_denom; + Algebraic slope1_numer, slope1_denom; + Algebraic slope2_numer, slope2_denom; - _derive_by_x_at (p, 1, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 1, slope2_numer, slope2_denom); + _derive_by_x_at(p, 1, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 1, slope2_numer, slope2_denom); // Check if any of the slopes is vertical. - const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope1 = (CGAL::sign (slope1_denom) == ZERO); + const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - const bool is_vertical_slope2 = (CGAL::sign (slope2_denom) == ZERO); - - if (!is_vertical_slope1 && !is_vertical_slope2) - { + if (!is_vertical_slope1 && !is_vertical_slope2) { // The two derivatives at p are well-defined: use them to determine // which arc is above the other (the one with a larger slope is below). Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the second-order derivative. _derive_by_x_at (p, 2, slope1_numer, slope1_denom); @@ -841,73 +765,66 @@ public: slope_res = CGAL::compare (slope1_numer*slope2_denom, slope2_numer*slope1_denom); - if (slope_res != EQUAL) - return (slope_res); + if (slope_res != EQUAL) return (slope_res); // Use the third-order derivative. - _derive_by_x_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_x_at (p, 3, slope2_numer, slope2_denom); + _derive_by_x_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_x_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = CGAL::compare(slope2_numer*slope1_denom, + slope1_numer*slope2_denom); // \todo Handle higher-order derivatives: CGAL_assertion (slope_res != EQUAL); return (slope_res); } - else if (!is_vertical_slope2) - { + else if (!is_vertical_slope2) { // The first arc has a vertical slope at p: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((this->_info & FACING_MASK) != 0); - if ((this->_info & FACING_UP) != 0) - return (LARGER); - return (SMALLER); + if ((this->_info & FACING_UP) != 0) return (LARGER); + return SMALLER; } - else if (!is_vertical_slope1) - { + else if (!is_vertical_slope1) { // The second arc has a vertical slope at p_int: check whether it is // facing upwards or downwards and decide accordingly. CGAL_assertion ((arc._info & FACING_MASK) != 0); - if ((arc._info & FACING_UP) != 0) - return (SMALLER); - return (LARGER); + if ((arc._info & FACING_UP) != 0) return (SMALLER); + return LARGER; } // The two arcs have vertical slopes at p_int: // First check whether one is facing up and one down. In this case the // comparison result is trivial. if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_DOWN) != 0) - return (LARGER); + return LARGER; else if ((this->_info & FACING_DOWN)!= 0 && (arc._info & FACING_UP)!= 0) - return (SMALLER); + return SMALLER; // Compute the second-order derivative by y and act according to it. - _derive_by_y_at (p, 2, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 2, slope2_numer, slope2_denom); + _derive_by_y_at(p, 2, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 2, slope2_numer, slope2_denom); - Comparison_result slope_res = CGAL::compare(slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + Comparison_result slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); // If necessary, use the third-order derivative by y. - if (slope_res == EQUAL) - { + if (slope_res == EQUAL) { // \todo Check this! - _derive_by_y_at (p, 3, slope1_numer, slope1_denom); - arc._derive_by_y_at (p, 3, slope2_numer, slope2_denom); + _derive_by_y_at(p, 3, slope1_numer, slope1_denom); + arc._derive_by_y_at(p, 3, slope2_numer, slope2_denom); - slope_res = CGAL::compare (slope2_numer*slope1_denom, - slope1_numer*slope2_denom); + slope_res = + CGAL::compare(slope2_numer*slope1_denom, slope1_numer*slope2_denom); } // \todo Handle higher-order derivatives: CGAL_assertion(slope_res != EQUAL); - if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) - { + if ((this->_info & FACING_UP) != 0 && (arc._info & FACING_UP) != 0) { // Both are facing up. return ((slope_res == LARGER) ? SMALLER : LARGER); } @@ -922,22 +839,21 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator intersect (const Self& arc, - Intersection_map& inter_map, - OutputIterator oi) const + template + OutputIterator intersect(const Self& arc, + Intersection_map& inter_map, + OutputIterator oi) const { - if (_has_same_supporting_conic (arc)) - { - // Check for overlaps between the two arcs. - Self overlap; + typedef boost::variant Intersection_result; - if (_compute_overlap (arc, overlap)) - { + if (_has_same_supporting_conic(arc)) { + // Check for overlaps between the two arcs. + Self overlap; + + if (_compute_overlap(arc, overlap)) { // There can be just a single overlap between two x-monotone arcs: - *oi = make_object (overlap); - oi++; - return (oi); + *oi++ = Intersection_result(overlap); + return oi; } // In case there is not overlap and the supporting conics are the same, @@ -947,80 +863,62 @@ public: // intersection points we report. Alg_kernel ker; - if (ker.equal_2_object() (left(), arc.left())) - { - Intersection_point_2 ip (left(), 0); - - *oi = make_object (ip); - oi++; + if (ker.equal_2_object()(left(), arc.left())) { + Intersection_point ip(left(), 0); + *oi++ = Intersection_result(ip); } - if (ker.equal_2_object() (right(), arc.right())) - { - Intersection_point_2 ip (right(), 0); - - *oi = make_object (ip); - oi++; + if (ker.equal_2_object()(right(), arc.right())) { + Intersection_point ip(right(), 0); + *oi++ = Intersection_result(ip); } - return (oi); + return oi; } // Search for the pair of supporting conics in the map (the first conic // ID in the pair should be smaller than the second one, to guarantee // uniqueness). - Conic_pair conic_pair; - Intersection_map_iterator map_iter; - Intersection_list inter_list; - bool invalid_ids = false; - - if (_id.is_valid() && arc._id.is_valid()) - { - if (_id < arc._id) - conic_pair = Conic_pair (_id, arc._id); - else - conic_pair = Conic_pair (arc._id, _id); + Conic_pair conic_pair; + Intersection_map_iterator map_iter; + Intersection_list inter_list; + bool invalid_ids = false; + if (_id.is_valid() && arc._id.is_valid()) { + if (_id < arc._id) conic_pair = Conic_pair (_id, arc._id); + else conic_pair = Conic_pair (arc._id, _id); map_iter = inter_map.find (conic_pair); } - else - { + else { // In case one of the IDs is invalid, we do not look in the map neither // we cache the results. map_iter = inter_map.end(); invalid_ids = true; } - if (map_iter == inter_map.end()) - { + if (map_iter == inter_map.end()) { // In case the intersection points between the supporting conics have // not been computed before, compute them now and store them in the map. - _intersect_supporting_conics (arc, inter_list); + _intersect_supporting_conics(arc, inter_list); - if (! invalid_ids) - inter_map[conic_pair] = inter_list; + if (! invalid_ids) inter_map[conic_pair] = inter_list; } - else - { + else { // Obtain the precomputed intersection points from the map. inter_list = (*map_iter).second; } // Go over the list of intersection points and report those that lie on // both x-monotone arcs. - typename Intersection_list::const_iterator iter; - - for (iter = inter_list.begin(); iter != inter_list.end(); ++iter) - { - if (_is_between_endpoints ((*iter).first) && - arc._is_between_endpoints ((*iter).first)) + for (auto iter = inter_list.begin(); iter != inter_list.end(); ++iter) { + if (_is_between_endpoints((*iter).first) && + arc._is_between_endpoints((*iter).first)) { - *oi = make_object (*iter); - ++oi; + *oi++ = Intersection_result(*iter); } } - return (oi); + return oi; } //@} @@ -1034,13 +932,10 @@ public: * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the arc (not one of its endpoints). */ - void split (const Conic_point_2& p, - Self& c1, Self& c2) const + void split(const Conic_point_2& p, Self& c1, Self& c2) const { // Make sure that p lies on the interior of the arc. - CGAL_precondition_code ( - Alg_kernel ker; - ); + CGAL_precondition_code(Alg_kernel ker); CGAL_precondition (this->contains_point (p) && ! ker.equal_2_object() (p, this->_source) && @@ -1058,8 +953,7 @@ public: c1._target = p; c2._source = p; - if (! p.is_generating_conic (_id)) - { + if (! p.is_generating_conic (_id)) { c1._target.set_generating_conic (_id); c2._source.set_generating_conic (_id); } @@ -1071,8 +965,7 @@ public: c1._source = p; c2._target = p; - if (! p.is_generating_conic (_id)) - { + if (! p.is_generating_conic (_id)) { c1._source.set_generating_conic (_id); c2._target.set_generating_conic (_id); } @@ -1085,16 +978,14 @@ public: * Flip the arc. * \return An arc with swapped source and target and a reverse orienation. */ - Self flip () const + Self flip() const { // Make a copy of the current arc. - Self arc = *this; + Self arc = *this; // Reverse the orientation. - if (this->_orient == CLOCKWISE) - arc._orient = COUNTERCLOCKWISE; - else if (this->_orient == COUNTERCLOCKWISE) - arc._orient = CLOCKWISE; + if (this->_orient == CLOCKWISE) arc._orient = COUNTERCLOCKWISE; + else if (this->_orient == COUNTERCLOCKWISE) arc._orient = CLOCKWISE; // Swap the source and the target. arc._source = this->_target; @@ -1103,7 +994,7 @@ public: // Change the direction bit among the information flags. arc._info = (this->_info ^ IS_DIRECTED_RIGHT); - return (arc); + return arc; } /*! @@ -1114,12 +1005,11 @@ public: * \pre Both ps and pt lies on the arc and must conform with the current * direction of the arc. */ - Self trim (const Conic_point_2& ps, - const Conic_point_2& pt) const + Self trim(const Conic_point_2& ps, const Conic_point_2& pt) const { // Make sure that both ps and pt lie on the arc. - CGAL_precondition (this->contains_point (ps) && - this->contains_point (pt)); + CGAL_precondition(this->contains_point (ps) && + this->contains_point (pt)); // Make sure that the endpoints conform with the direction of the arc. Self arc = *this; @@ -1136,8 +1026,7 @@ public: } // Make a copy of the current arc and assign its endpoints. - if (! ker.equal_2_object() (ps, this->_source)) - { + if (! ker.equal_2_object() (ps, this->_source)) { arc._source = ps; if (! ps.is_generating_conic (_id)) @@ -1164,46 +1053,41 @@ public: { // The two arc must have the same supporting conic curves. if (! _has_same_supporting_conic (arc)) - return (false); + return false; // Check that the arc endpoints are the same. - Alg_kernel ker; + Alg_kernel ker; - if(this->_orient == COLLINEAR) - { + if (this->_orient == COLLINEAR) { CGAL_assertion(arc._orient == COLLINEAR); - return((ker.equal_2_object() (this->_source, arc._source) && - ker.equal_2_object() (this->_target, arc._target)) || - (ker.equal_2_object() (this->_source, arc._target) && - ker.equal_2_object() (this->_target, arc._source))); + return((ker.equal_2_object()(this->_source, arc._source) && + ker.equal_2_object()(this->_target, arc._target)) || + (ker.equal_2_object()(this->_source, arc._target) && + ker.equal_2_object()(this->_target, arc._source))); } - if (this->_orient == arc._orient) - { + if (this->_orient == arc._orient) { // Same orientation - the source and target points must be the same. - return (ker.equal_2_object() (this->_source, arc._source) && - ker.equal_2_object() (this->_target, arc._target)); + return (ker.equal_2_object()(this->_source, arc._source) && + ker.equal_2_object()(this->_target, arc._target)); } - else - { + else { // Reverse orientation - the source and target points must be swapped. - return (ker.equal_2_object() (this->_source, arc._target) && - ker.equal_2_object() (this->_target, arc._source)); + return (ker.equal_2_object()(this->_source, arc._target) && + ker.equal_2_object()(this->_target, arc._source)); } } - /*! - * Check whether it is possible to merge the arc with the given arc. + /*! Check whether it is possible to merge the arc with the given arc. * \param arc The query arc. * \return (true) if it is possible to merge the two arcs; * (false) otherwise. */ - bool can_merge_with (const Self& arc) const + bool can_merge_with(const Self& arc) const { // In order to merge the two arcs, they should have the same supporting // conic. - if (! _has_same_supporting_conic (arc)) - return (false); + if (! _has_same_supporting_conic(arc)) return false; // Check if the left endpoint of one curve is the right endpoint of the // other. @@ -1213,28 +1097,23 @@ public: ker.equal_2_object() (left(), arc.right())); } - /*! - * Merge the current arc with the given arc. + /*! Merge the current arc with the given arc. * \param arc The arc to merge with. * \pre The two arcs are mergeable. */ - void merge (const Self& arc) + void merge(const Self& arc) { CGAL_precondition (this->can_merge_with (arc)); // Check if we should extend the arc to the left or to the right. Alg_kernel ker; - if (ker.equal_2_object() (right(), arc.left())) - { + if (ker.equal_2_object() (right(), arc.left())) { // Extend the arc to the right. - if ((this->_info & IS_DIRECTED_RIGHT) != 0) - this->_target = arc.right(); - else - this->_source = arc.right(); + if ((this->_info & IS_DIRECTED_RIGHT) != 0) this->_target = arc.right(); + else this->_source = arc.right(); } - else - { + else { CGAL_precondition (ker.equal_2_object() (left(), arc.right())); // Extend the arc to the left. @@ -1835,36 +1714,32 @@ private: * \param arc The arc to intersect with. * \param inter_list The list of intersection points. */ - void _intersect_supporting_conics (const Self& arc, - Intersection_list& inter_list) const + void _intersect_supporting_conics(const Self& arc, + Intersection_list& inter_list) const { - if (_is_special_segment() && ! arc._is_special_segment()) - { + if (_is_special_segment() && ! arc._is_special_segment()) { // If one of the arcs is a special segment, make sure it is (arc). - arc._intersect_supporting_conics (*this, inter_list); + arc._intersect_supporting_conics(*this, inter_list); return; } - const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; - Nt_traits nt_traits; - Algebraic xs[4]; - int n_xs = 0; - Algebraic ys[4]; - int n_ys = 0; + const int deg1 = ((this->_info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + const int deg2 = ((arc._info & DEGREE_MASK) == DEGREE_1) ? 1 : 2; + Nt_traits nt_traits; + Algebraic xs[4]; + int n_xs = 0; + Algebraic ys[4]; + int n_ys = 0; - if (arc._is_special_segment()) - { + if (arc._is_special_segment()) { // The second arc is a special segment (a*x + b*y + c = 0). - if (_is_special_segment()) - { + if (_is_special_segment()) { // Both arc are sepcial segment, so they have at most one intersection // point. - Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - - this->_extra_data_P->b * arc._extra_data_P->a; + Algebraic denom = this->_extra_data_P->a * arc._extra_data_P->b - + this->_extra_data_P->b * arc._extra_data_P->a; - if (CGAL::sign (denom) != CGAL::ZERO) - { + if (CGAL::sign (denom) != CGAL::ZERO) { xs[0] = (this->_extra_data_P->b * arc._extra_data_P->c - this->_extra_data_P->c * arc._extra_data_P->b) / denom; n_xs = 1; @@ -1874,8 +1749,7 @@ private: n_ys = 1; } } - else - { + else { // Compute the x-coordinates of the intersection points. n_xs = _compute_resultant_roots (nt_traits, alg_r, alg_s, alg_t, @@ -1899,8 +1773,7 @@ private: CGAL_assertion (n_ys <= 2); } } - else - { + else { // Compute the x-coordinates of the intersection points. n_xs = _compute_resultant_roots (nt_traits, this->_r, this->_s, this->_t, @@ -1921,7 +1794,7 @@ private: arc._v, arc._u, arc._w, deg2, ys); - CGAL_assertion (n_ys <= 4); + CGAL_assertion(n_ys <= 4); } // Pair the coordinates of the intersection points. As the vectors of @@ -1938,14 +1811,14 @@ private: if (n_xs == 1 && n_ys == 1) { // Single intersection. - Conic_point_2 ip (xs[0], ys[0]); + Conic_point_2 ip (xs[0], ys[0]); ip.set_generating_conic (_id); ip.set_generating_conic (arc._id); // In case the other curve is of degree 2, this is a tangency point. mult = (deg1 == 1 || _is_special_segment()) ? 1 : 2; - inter_list.push_back (Intersection_point_2 (ip, mult)); + inter_list.push_back(Intersection_point (ip, mult)); } else if (n_xs == 1 && n_ys == 2) { @@ -1954,14 +1827,14 @@ private: ip1.set_generating_conic (_id); ip1.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); Conic_point_2 ip2 (xs[0], ys[1]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point (ip2, 1)); } else if (n_xs == 2 && n_ys == 1) { @@ -1970,24 +1843,23 @@ private: ip1.set_generating_conic (_id); ip1.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); Conic_point_2 ip2 (xs[1], ys[0]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point (ip2, 1)); } - else - { + else { CGAL_assertion (n_xs == 2 && n_ys == 2); // The x-coordinates and the y-coordinates are given in ascending // order. If the slope of the segment is positive, we pair the // coordinates as is - otherwise, we swap the pairs. - int ind_first_y = 0, ind_second_y = 1; + int ind_first_y = 0, ind_second_y = 1; if (CGAL::sign (arc._extra_data_P->b) == CGAL::sign(arc._extra_data_P->a)) @@ -1996,45 +1868,41 @@ private: ind_second_y = 0; } - Conic_point_2 ip1 (xs[0], ys[ind_first_y]); + Conic_point_2 ip1(xs[0], ys[ind_first_y]); - ip1.set_generating_conic (_id); - ip1.set_generating_conic (arc._id); + ip1.set_generating_conic(_id); + ip1.set_generating_conic(arc._id); - inter_list.push_back (Intersection_point_2 (ip1, 1)); + inter_list.push_back(Intersection_point (ip1, 1)); - Conic_point_2 ip2 (xs[1], ys[ind_second_y]); + Conic_point_2 ip2(xs[1], ys[ind_second_y]); ip2.set_generating_conic (_id); ip2.set_generating_conic (arc._id); - inter_list.push_back (Intersection_point_2 (ip2, 1)); + inter_list.push_back(Intersection_point(ip2, 1)); } return; } - for (i = 0; i < n_xs; i++) - { - for (j = 0; j < n_ys; j++) - { + for (i = 0; i < n_xs; i++) { + for (j = 0; j < n_ys; j++) { if (_is_on_supporting_conic (xs[i], ys[j]) && arc._is_on_supporting_conic (xs[i], ys[j])) { // Create the intersection point and set its generating conics. - Conic_point_2 ip (xs[i], ys[j]); + Conic_point_2 ip(xs[i], ys[j]); ip.set_generating_conic (_id); ip.set_generating_conic (arc._id); // Compute the multiplicity of the intersection point. - if (deg1 == 1 && deg2 == 1) - mult = 1; - else - mult = _multiplicity_of_intersection_point (arc, ip); + if (deg1 == 1 && deg2 == 1) mult = 1; + else mult = _multiplicity_of_intersection_point(arc, ip); // Insert the intersection point to the output list. - inter_list.push_back (Intersection_point_2 (ip, mult)); + inter_list.push_back(Intersection_point(ip, mult)); } } } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h index f5db0ebbad7..b6c246eb583 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_geometry_traits/Rational_arc_2.h @@ -1830,7 +1830,7 @@ public: typedef typename Base::Rat_vector Rat_vector; typedef typename Base::Polynomial Polynomial; - typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; /// \name Constrcution methods. @@ -1967,138 +1967,118 @@ public: CGAL_precondition (this->is_valid() && this->is_continuous()); CGAL_precondition (arc.is_valid() && arc.is_continuous()); - if (this->_has_same_base (arc)) - { - Alg_kernel ker; + if (this->_has_same_base (arc)) { + Alg_kernel ker; // Get the left and right endpoints of (*this) and their information // bits. - const Point_2& left1 = (this->is_directed_right() ? - this->_ps : this->_pt); - const Point_2& right1 = (this->is_directed_right() ? - this->_pt : this->_ps); - int info_left1, info_right1; + const Point_2& left1 = + (this->is_directed_right() ? this->_ps : this->_pt); + const Point_2& right1 = + (this->is_directed_right() ? this->_pt : this->_ps); + int info_left1, info_right1; - if (this->is_directed_right()) - { + if (this->is_directed_right()) { info_left1 = (this->_info & this->SRC_INFO_BITS); info_right1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right1 = (this->_info & this->SRC_INFO_BITS); info_left1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } // Get the left and right endpoints of the other arc and their // information bits. - const Point_2& left2 = (arc.is_directed_right() ? arc._ps : arc._pt); - const Point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); - int info_left2, info_right2; + const Point_2& left2 = (arc.is_directed_right() ? arc._ps : arc._pt); + const Point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); + int info_left2, info_right2; - if (arc.is_directed_right()) - { + if (arc.is_directed_right()) { info_left2 = (arc._info & this->SRC_INFO_BITS); info_right2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right2 = (arc._info & this->SRC_INFO_BITS); info_left2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } // Locate the left curve-end with larger x-coordinate. - bool at_minus_infinity = false; - Arr_parameter_space inf_l1 = this->left_infinite_in_x(); - Arr_parameter_space inf_l2 = arc.left_infinite_in_x(); - Point_2 p_left; - int info_left; + bool at_minus_infinity = false; + Arr_parameter_space inf_l1 = this->left_infinite_in_x(); + Arr_parameter_space inf_l2 = arc.left_infinite_in_x(); + Point_2 p_left; + int info_left; - if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) - { + if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) { // Let p_left be the rightmost of the two left endpoints. - if (ker.compare_x_2_object() (left1, left2) == LARGER) - { + if (ker.compare_x_2_object() (left1, left2) == LARGER) { p_left = left1; info_left = info_left1; } - else - { + else { p_left = left2; info_left = info_left2; } } - else if (inf_l1 == ARR_INTERIOR) - { + else if (inf_l1 == ARR_INTERIOR) { // Let p_left be the left endpoint of (*this). p_left = left1; info_left = info_left1; } - else if (inf_l2 == ARR_INTERIOR) - { + else if (inf_l2 == ARR_INTERIOR) { // Let p_left be the left endpoint of the other arc. p_left = left2; info_left = info_left2; } - else - { + else { // Both arcs are defined at x = -oo. at_minus_infinity = true; info_left = info_left1; } // Locate the right curve-end with smaller x-coordinate. - bool at_plus_infinity = false; - Arr_parameter_space inf_r1 = this->right_infinite_in_x(); - Arr_parameter_space inf_r2 = arc.right_infinite_in_x(); - Point_2 p_right; - int info_right; + bool at_plus_infinity = false; + Arr_parameter_space inf_r1 = this->right_infinite_in_x(); + Arr_parameter_space inf_r2 = arc.right_infinite_in_x(); + Point_2 p_right; + int info_right; - if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) - { + if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) { // Let p_right be the rightmost of the two right endpoints. - if (ker.compare_x_2_object() (right1, right2) == SMALLER) - { + if (ker.compare_x_2_object() (right1, right2) == SMALLER) { p_right = right1; info_right = info_right1; } - else - { + else { p_right = right2; info_right = info_right2; } } - else if (inf_r1 == ARR_INTERIOR) - { + else if (inf_r1 == ARR_INTERIOR) { // Let p_right be the right endpoint of (*this). p_right = right1; info_right = info_right1; } - else if (inf_r2 == ARR_INTERIOR) - { + else if (inf_r2 == ARR_INTERIOR) { // Let p_right be the right endpoint of the other arc. p_right = right2; info_right = info_right2; } - else - { + else { // Both arcs are defined at x = +oo. at_plus_infinity = true; info_right = info_right2; } // Check the case of two bounded (in x) ends. - if (! at_minus_infinity && ! at_plus_infinity) - { + if (! at_minus_infinity && ! at_plus_infinity) { Comparison_result res = ker.compare_x_2_object() (p_left, p_right); - if (res == LARGER) - { + if (res == LARGER) { // The x-range of the overlap is empty, so there is no overlap. - return (oi); + return oi; } - else if (res == EQUAL) - { + if (res == EQUAL) { // We have a single overlapping point. Just make sure this point // is not at y = -/+ oo. if (info_left && @@ -2106,20 +2086,19 @@ public: info_right && (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0) { - Intersection_point_2 ip (p_left, 0); + Intersection_point ip (p_left, 0); - *oi = make_object (ip); - ++oi; + *oi++ = make_object (ip); } - return (oi); + return oi; } } // Create the overlapping portion of the rational arc by properly setting // the source (left) and target (right) endpoints and their information // bits. - Self overlap_arc (*this); + Self overlap_arc(*this); overlap_arc._ps = p_left; overlap_arc._pt = p_right; @@ -2128,10 +2107,9 @@ public: this->IS_DIRECTED_RIGHT | this->IS_CONTINUOUS | this->IS_VALID); - *oi = make_object (overlap_arc); - ++oi; + *oi++ = make_object(overlap_arc); - return (oi); + return oi; } // We wish to find the intersection points between: @@ -2140,39 +2118,34 @@ public: // // It is clear that the x-coordinates of the intersection points are // the roots of the polynomial: ip(x) = p1(x)*q2(x) - p2(x)*q1(x). - Nt_traits nt_traits; - Polynomial ipoly = this->_numer * arc._denom - - arc._numer * this->_denom; - std::list xs; + Nt_traits nt_traits; + Polynomial ipoly = this->_numer * arc._denom - arc._numer* this->_denom; + std::list xs; typename std::list::const_iterator x_iter; - nt_traits.compute_polynomial_roots (ipoly, - std::back_inserter(xs)); + nt_traits.compute_polynomial_roots(ipoly, std::back_inserter(xs)); // Go over the x-values we obtained. For each value produce an // intersection point if it is contained in the x-range of both curves. - unsigned int mult; + unsigned int mult; - for (x_iter = xs.begin(); x_iter != xs.end(); ++x_iter) - { + for (x_iter = xs.begin(); x_iter != xs.end(); ++x_iter) { if (this->_is_in_true_x_range (*x_iter) && arc._is_in_true_x_range (*x_iter)) { // Compute the intersection point and obtain its multiplicity. - Point_2 p (*x_iter, nt_traits.evaluate_at (this->_numer, *x_iter) / - nt_traits.evaluate_at (this->_denom, *x_iter)); + Point_2 p(*x_iter, nt_traits.evaluate_at (this->_numer, *x_iter) / + nt_traits.evaluate_at (this->_denom, *x_iter)); - this->compare_slopes (arc, p, mult); + this->compare_slopes(arc, p, mult); // Output the intersection point: - Intersection_point_2 ip (p, mult); - - *oi = make_object (ip); - ++oi; + Intersection_point ip(p, mult); + *oi++ = make_object(ip); } } - return (oi); + return oi; } /*! 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 2038cf0ad79..0e1262db0ec 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 @@ -8,8 +8,9 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Ron Wein -// : Waqar Khan +// Author(s): Ron Wein +// Waqar Khan +// Efi fogel #ifndef CGAL_ARR_LINEAR_TRAITS_2_H #define CGAL_ARR_LINEAR_TRAITS_2_H @@ -23,27 +24,29 @@ * in the arrangement package. */ +#include + +#include + #include #include #include #include #include -#include namespace CGAL { -template class Arr_linear_object_2; +template class Arr_linear_object_2; /*! \class * A traits class for maintaining an arrangement of linear objects (lines, * rays and segments), aoviding cascading of computations as much as possible. */ -template +template class Arr_linear_traits_2 : public Kernel_ { friend class Arr_linear_object_2; public: - typedef Kernel_ Kernel; typedef typename Kernel::FT FT; @@ -70,17 +73,14 @@ public: /*! * \class Representation of a linear with cached data. */ - class _Linear_object_cached_2 - { + class _Linear_object_cached_2 { public: - typedef typename Kernel::Line_2 Line_2; typedef typename Kernel::Ray_2 Ray_2; typedef typename Kernel::Segment_2 Segment_2; typedef typename Kernel::Point_2 Point_2; protected: - Line_2 l; // The supporting line. Point_2 ps; // The source point (if exists). Point_2 pt; // The target point (if exists). @@ -99,39 +99,36 @@ public: bool is_degen; // Is the object degenerate (a single point). public: - - /*! - * Default constructor. + /*! Default constructor. */ - _Linear_object_cached_2 () : - has_source (true), - has_target (true), - is_vert (false), - is_horiz (false), - has_pos_slope (false), - is_degen (true) + _Linear_object_cached_2() : + has_source(true), + has_target(true), + is_vert(false), + is_horiz(false), + has_pos_slope(false), + is_degen(true) {} - /*! - * Constructor for segment from two points. + /*! Constructor for segment from two points. * \param p1 source point. * \param p2 target point. * \pre The two points must not be equal. */ _Linear_object_cached_2(const Point_2& source, const Point_2& target) : - ps (source), - pt (target), - has_source (true), - has_target (true) + ps(source), + pt(target), + has_source(true), + has_target(true) { - Kernel kernel; + Kernel kernel; - Comparison_result res = kernel.compare_xy_2_object()(source, target); + Comparison_result res = kernel.compare_xy_2_object()(source, target); is_degen = (res == EQUAL); is_right = (res == SMALLER); - CGAL_precondition_msg (! is_degen, - "Cannot construct a degenerate segment."); + CGAL_precondition_msg(! is_degen, + "Cannot construct a degenerate segment."); l = kernel.construct_line_2_object()(source, target); is_vert = kernel.is_vertical_2_object()(l); @@ -139,29 +136,25 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a segment. + /*! Constructor from a segment. * \param seg The segment. * \pre The segment is not degenerate. */ - _Linear_object_cached_2 (const Segment_2& seg) + _Linear_object_cached_2(const Segment_2& seg) : + has_source(true), + has_target(true) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (seg), - "Cannot construct a degenerate segment."); - - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(seg), + "Cannot construct a degenerate segment."); + auto construct_vertex = kernel.construct_vertex_2_object(); ps = construct_vertex(seg, 0); - has_source = true; pt = construct_vertex(seg, 1); - has_target = true; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - - CGAL_assertion (res != EQUAL); + Comparison_result res = kernel.compare_xy_2_object()(ps, pt); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -171,28 +164,25 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a ray. + /*! Constructor from a ray. * \param ray The ray. * \pre The ray is not degenerate. */ - _Linear_object_cached_2 (const Ray_2& ray) + _Linear_object_cached_2(const Ray_2& ray) : + has_source(true), + has_target(false) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (ray), - "Cannot construct a degenerate ray."); - - typename Kernel_::Construct_point_on_2 - construct_vertex = kernel.construct_point_on_2_object(); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ray), + "Cannot construct a degenerate ray."); + auto construct_vertex = kernel.construct_point_on_2_object(); ps = construct_vertex(ray, 0); // The source point. - has_source = true; pt = construct_vertex(ray, 1); // Some point on the ray. - has_target = false; Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion (res != EQUAL); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -202,31 +192,26 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Constructor from a line. + /*! Constructor from a line. * \param ln The line. * \pre The line is not degenerate. */ - _Linear_object_cached_2 (const Line_2& ln) : - l (ln), - has_source (false), - has_target (false) + _Linear_object_cached_2(const Line_2& ln) : + l(ln), + has_source(false), + has_target(false) { - Kernel kernel; + Kernel kernel; - CGAL_assertion_msg (! kernel.is_degenerate_2_object() (ln), - "Cannot construct a degenerate line."); - - typename Kernel_::Construct_point_on_2 - construct_vertex = kernel.construct_point_on_2_object(); + CGAL_assertion_msg(! kernel.is_degenerate_2_object()(ln), + "Cannot construct a degenerate line."); + auto construct_vertex = kernel.construct_point_on_2_object(); ps = construct_vertex(ln, 0); // Some point on the line. - has_source = false; pt = construct_vertex(ln, 1); // Some point further on the line. - has_target = false; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - CGAL_assertion (res != EQUAL); + Comparison_result res = kernel.compare_xy_2_object()(ps, pt); + CGAL_assertion(res != EQUAL); is_degen = false; is_right = (res == SMALLER); @@ -235,31 +220,27 @@ public: has_pos_slope = _has_positive_slope(); } - /*! - * Check whether the x-coordinate of the left point is infinite. + /*! Check whether the x-coordinate of the left point is infinite. * \return ARR_LEFT_BOUNDARY if the left point is near the boundary; * ARR_INTERIOR if the x-coordinate is finite. */ - Arr_parameter_space left_infinite_in_x () const + Arr_parameter_space left_infinite_in_x() const { - if (is_vert || is_degen) - return (ARR_INTERIOR); + if (is_vert || is_degen) return (ARR_INTERIOR); return (is_right) ? (has_source ? ARR_INTERIOR : ARR_LEFT_BOUNDARY) : (has_target ? ARR_INTERIOR : ARR_LEFT_BOUNDARY); } - /*! - * Check whether the y-coordinate of the left point is infinite. + /*! Check whether the y-coordinate of the left point is infinite. * \return ARR_BOTTOM_BOUNDARY if the left point is at y = -oo; * ARR_INTERIOR if the y-coordinate is finite. * ARR_TOP_BOUNDARY if the left point is at y = +oo; */ - Arr_parameter_space left_infinite_in_y () const + Arr_parameter_space left_infinite_in_y() const { - if (is_horiz || is_degen) - return ARR_INTERIOR; + if (is_horiz || is_degen) return ARR_INTERIOR; if (is_vert) { return (is_right) ? @@ -268,100 +249,80 @@ public: } if ((is_right && has_source) || (! is_right && has_target)) - return ARR_INTERIOR; + return ARR_INTERIOR; return (has_pos_slope ? ARR_BOTTOM_BOUNDARY : ARR_TOP_BOUNDARY); } - /*! - * Check whether the left point is finite. + /*! Check whether the left point is finite. */ - bool has_left () const - { - if (is_right) - return (has_source); - else - return (has_target); - } + bool has_left() const { return (is_right ? has_source : has_target); } - /*! - * Obtain the (lexicographically) left endpoint. + /*! Obtain the (lexicographically) left endpoint. * \pre The left point is finite. */ - const Point_2& left () const + const Point_2& left() const { - CGAL_precondition (has_left()); + CGAL_precondition(has_left()); return (is_right ? ps : pt); } - /*! - * Set the (lexicographically) left endpoint. + /*! Set the (lexicographically) left endpoint. * \param p The point to set. * \pre p lies on the supporting line to the left of the right endpoint. */ - void set_left (const Point_2& p, bool CGAL_assertion_code(check_validity) = true) + void set_left(const Point_2& p, + bool CGAL_assertion_code(check_validity) = true) { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, l, Has_exact_division()) && (! check_validity || ! has_right() || - kernel.compare_xy_2_object() (p, right()) == SMALLER)); + kernel.compare_xy_2_object()(p, right()) == SMALLER)); - if (is_right) - { + if (is_right) { ps = p; has_source = true; } - else - { + else { pt = p; has_target = true; } } - /*! - * Set the (lexicographically) left endpoint as infinite. + /*! Set the (lexicographically) left endpoint as infinite. */ - void set_left () + void set_left() { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); - if (is_right) - has_source = false; - else - has_target = false; + if (is_right) has_source = false; + else has_target = false; } - /*! - * Check whether the x-coordinate of the right point is infinite. + /*! Check whether the x-coordinate of the right point is infinite. * \return ARR_RIGHT_BOUNDARY if the right point is near the boundary; * ARR_INTERIOR if the x-coordinate is finite. */ - Arr_parameter_space right_infinite_in_x () const + Arr_parameter_space right_infinite_in_x() const { - if (is_vert || is_degen) - return ARR_INTERIOR; + if (is_vert || is_degen) return ARR_INTERIOR; return (is_right) ? (has_target ? ARR_INTERIOR : ARR_RIGHT_BOUNDARY) : (has_source ? ARR_INTERIOR : ARR_RIGHT_BOUNDARY); } - /*! - * Check whether the y-coordinate of the right point is infinite. + /*! Check whether the y-coordinate of the right point is infinite. * \return ARR_BOTTOM_BOUNDARY if the right point is at y = -oo; * ARR_INTERIOR if the y-coordinate is finite. * ARR_TOP_BOUNDARY if the right point is at y = +oo; */ - Arr_parameter_space right_infinite_in_y () const + Arr_parameter_space right_infinite_in_y() const { - if (is_horiz || is_degen) - return ARR_INTERIOR; + if (is_horiz || is_degen) return ARR_INTERIOR; if (is_vert) { return (is_right) ? @@ -375,145 +336,108 @@ public: return (has_pos_slope ? ARR_TOP_BOUNDARY : ARR_BOTTOM_BOUNDARY); } - /*! - * Check whether the right point is finite. + /*! Check whether the right point is finite. */ - bool has_right () const - { - if (is_right) - return (has_target); - else - return (has_source); - } + bool has_right() const { return (is_right ? has_target : has_source); } - /*! - * Obtain the (lexicographically) right endpoint. + /*! Obtain the (lexicographically) right endpoint. * \pre The right endpoint is finite. */ - const Point_2& right () const + const Point_2& right() const { - CGAL_precondition (has_right()); + CGAL_precondition(has_right()); return (is_right ? pt : ps); } - /*! - * Set the (lexicographically) right endpoint. + /*! Set the (lexicographically) right endpoint. * \param p The point to set. * \pre p lies on the supporting line to the right of the left endpoint. */ - void set_right (const Point_2& p, bool CGAL_assertion_code(check_validity) = true) + void set_right(const Point_2& p, + bool CGAL_assertion_code(check_validity) = true) { - CGAL_precondition (! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition(! is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, l, Has_exact_division()) && (! check_validity || ! has_left() || - kernel.compare_xy_2_object() (p, left()) == LARGER)); + kernel.compare_xy_2_object()(p, left()) == LARGER)); - if (is_right) - { + if (is_right) { pt = p; has_target = true; } - else - { + else { ps = p; has_source = true; } } - /*! - * Set the (lexicographically) right endpoint as infinite. + /*! Set the (lexicographically) right endpoint as infinite. */ - void set_right () + void set_right() { CGAL_precondition (! is_degen); - if (is_right) - has_target = false; - else - has_source = false; + if (is_right) has_target = false; + else has_source = false; } - /*! - * Obtain the supporting line. + /*! Obtain the supporting line. */ - const Line_2& supp_line () const + const Line_2& supp_line() const { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); return (l); } - /*! - * Check whether the curve is vertical. + /*! Check whether the curve is vertical. */ - bool is_vertical () const + bool is_vertical() const { - CGAL_precondition (! is_degen); + CGAL_precondition(! is_degen); return (is_vert); } - /*! - * Check whether the curve is degenerate. + /*! Check whether the curve is degenerate. */ - bool is_degenerate () const - { - return (is_degen); - } + bool is_degenerate() const { return (is_degen); } - /*! - * Check whether the curve is directed lexicographic from left to right + /*! Check whether the curve is directed lexicographic from left to right */ - bool is_directed_right () const - { - return (is_right); - } + bool is_directed_right() const { return (is_right); } - /*! - * Check whether the given point is in the x-range of the object. + /*! Check whether the given point is in the x-range of the object. * \param p The query point. * \return (true) is in the x-range of the segment; (false) if it is not. */ - bool is_in_x_range (const Point_2& p) const + bool is_in_x_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); - Comparison_result res1; + Kernel kernel; + typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); + Comparison_result res1; - if (left_infinite_in_x() == ARR_INTERIOR) - { - if (left_infinite_in_y() != ARR_INTERIOR) - // Compare with some point on the curve. - res1 = compare_x (p, ps); - else - res1 = compare_x (p, left()); + if (left_infinite_in_x() == ARR_INTERIOR) { + // Compare with some point on the curve. + if (left_infinite_in_y() != ARR_INTERIOR) res1 = compare_x(p, ps); + else res1 = compare_x(p, left()); } - else - { + else { // p is obviously to the right. res1 = LARGER; } - if (res1 == SMALLER) - return (false); - else if (res1 == EQUAL) - return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - Comparison_result res2; + Comparison_result res2; - if (right_infinite_in_x() == ARR_INTERIOR) - { - if (right_infinite_in_y() != ARR_INTERIOR) - // Compare with some point on the curve. - res2 = compare_x (p, ps); - else - res2 = compare_x (p, right()); + if (right_infinite_in_x() == ARR_INTERIOR) { + // Compare with some point on the curve. + if (right_infinite_in_y() != ARR_INTERIOR) res2 = compare_x(p, ps); + else res2 = compare_x(p, right()); } - else - { + else { // p is obviously to the right. res2 = SMALLER; } @@ -521,68 +445,54 @@ public: return (res2 != LARGER); } - /*! - * Check whether the given point is in the y-range of the object. + /*! Check whether the given point is in the y-range of the object. * \param p The query point. * \pre The object is vertical. * \return (true) is in the y-range of the segment; (false) if it is not. */ - bool is_in_y_range (const Point_2& p) const + bool is_in_y_range(const Point_2& p) const { - CGAL_precondition (is_vertical()); + CGAL_precondition(is_vertical()); - Kernel kernel; - typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); - Arr_parameter_space inf = left_infinite_in_y(); - Comparison_result res1; + Kernel kernel; + typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); + Arr_parameter_space inf = left_infinite_in_y(); + Comparison_result res1; - CGAL_assertion (inf != ARR_TOP_BOUNDARY); - if (inf == ARR_INTERIOR) - res1 = compare_y (p, left()); - else - res1 = LARGER; // p is obviously above. + CGAL_assertion(inf != ARR_TOP_BOUNDARY); + if (inf == ARR_INTERIOR) res1 = compare_y (p, left()); + else res1 = LARGER; // p is obviously above. - if (res1 == SMALLER) - return (false); - else if (res1 == EQUAL) - return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - Comparison_result res2; + Comparison_result res2; inf = right_infinite_in_y(); - CGAL_assertion (inf != ARR_BOTTOM_BOUNDARY); - if (inf == ARR_INTERIOR) - res2 = compare_y (p, right()); - else - res2 = SMALLER; // p is obviously below. + CGAL_assertion(inf != ARR_BOTTOM_BOUNDARY); + if (inf == ARR_INTERIOR) res2 = compare_y(p, right()); + else res2 = SMALLER; // p is obviously below. return (res2 != LARGER); } private: - - /*! - * Determine if the supporting line has a positive slope. + /*! Determine if the supporting line has a positive slope. */ - bool _has_positive_slope () const + bool _has_positive_slope() const { - if (is_vert) - return (true); - - if (is_horiz) - return (false); + if (is_vert) return true; + if (is_horiz) return false; // Construct a horizontal line and compare its slope the that of l. - Kernel kernel; - Line_2 l_horiz = kernel.construct_line_2_object() (Point_2 (0, 0), - Point_2 (1, 0)); - - return (kernel.compare_slope_2_object() (l, l_horiz) == LARGER); + Kernel kernel; + Line_2 l_horiz = + kernel.construct_line_2_object()(Point_2(0, 0), Point_2(1, 0)); + return (kernel.compare_slope_2_object()(l, l_horiz) == LARGER); } }; public: - // Traits objects typedef typename Kernel::Point_2 Point_2; typedef Arr_linear_object_2 X_monotone_curve_2; @@ -590,12 +500,9 @@ public: typedef unsigned int Multiplicity; public: - - /*! - * Default constructor. + /*! Default constructor. */ - Arr_linear_traits_2 () - {} + Arr_linear_traits_2() {} /// \name Basic functor definitions. //@{ @@ -606,7 +513,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits * m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -614,32 +521,28 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_x_2(const Traits * traits) : m_traits(traits) {} + Compare_x_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - /*! - * Compare the x-coordinates of two points. + /*! Compare the x-coordinates of two points. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2); * SMALLER if x(p1) < x(p2); * EQUAL if x(p1) = x(p2). */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { - const Kernel * kernel = m_traits; - return (kernel->compare_x_2_object()(p1, p2)); + const Kernel& kernel = m_traits; + return (kernel.compare_x_2_object()(p1, p2)); } }; /*! Obtain a Compare_x_2 functor. */ - Compare_x_2 compare_x_2_object () const - { - return Compare_x_2(this); - } + Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); } /*! A functor that compares the he endpoints of an $x$-monotone curve. */ class Compare_endpoints_xy_2{ @@ -650,21 +553,19 @@ public: * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& xcv) const + Comparison_result operator()(const X_monotone_curve_2& xcv) const { return (xcv.is_directed_right()) ? (SMALLER) : (LARGER); } }; Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const - { - return Compare_endpoints_xy_2(); - } + { return Compare_endpoints_xy_2(); } - class Trim_2{ + class Trim_2 { protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -672,25 +573,25 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Trim_2(const Traits * traits) : m_traits(traits) {} + Trim_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - X_monotone_curve_2 operator()( const X_monotone_curve_2 xcv, - const Point_2 src, - const Point_2 tgt ) + X_monotone_curve_2 operator()(const X_monotone_curve_2 xcv, + const Point_2 src, + const Point_2 tgt) { /* * "Line_segment, line, and ray" will become line segments * when trimmed. - */ + */ Equal_2 equal = Equal_2(); - Compare_y_at_x_2 compare_y_at_x = m_traits->compare_y_at_x_2_object(); + Compare_y_at_x_2 compare_y_at_x = m_traits.compare_y_at_x_2_object(); //preconditions - //check if source and taget are two distinct points and they lie on the line. + //check if source and taget are distinct points and they lie on the line. CGAL_precondition(!equal(src, tgt)); CGAL_precondition(compare_y_at_x(src, xcv) == EQUAL); CGAL_precondition(compare_y_at_x(tgt, xcv) == EQUAL); @@ -698,33 +599,24 @@ public: //create trimmed line_segment X_monotone_curve_2 trimmed_segment; - if( xcv.is_directed_right() && tgt.x() < src.x() ) + if (xcv.is_directed_right() && (tgt.x() < src.x())) trimmed_segment = Segment_2(tgt, src); - - - else if( !xcv.is_directed_right() && tgt.x() > src.x()) + else if (! xcv.is_directed_right() && (tgt.x() > src.x())) trimmed_segment = Segment_2(tgt, src); - - else - trimmed_segment = Segment_2(src, tgt); + else trimmed_segment = Segment_2(src, tgt); return trimmed_segment; } - }; - Trim_2 trim_2_object() const - { - return Trim_2(this); - } - + Trim_2 trim_2_object() const { return Trim_2(*this); } class Construct_opposite_2{ protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -732,142 +624,111 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Construct_opposite_2(const Traits * traits) : m_traits(traits) {} + Construct_opposite_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - - X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv)const + X_monotone_curve_2 operator()(const X_monotone_curve_2& xcv) const { - CGAL_precondition (! xcv.is_degenerate()); + CGAL_precondition(! xcv.is_degenerate()); X_monotone_curve_2 opp_xcv; - if( xcv.is_segment() ) - { - opp_xcv = Segment_2(xcv.target(), xcv.source()); - } - - if( xcv.is_line() ) - { - opp_xcv = Line_2(xcv.get_pt(), xcv.get_ps()); - } - - if( xcv.is_ray() ) - { + if (xcv.is_segment()) opp_xcv = Segment_2(xcv.target(), xcv.source()); + if (xcv.is_line()) opp_xcv = Line_2(xcv.get_pt(), xcv.get_ps()); + if (xcv.is_ray()) { Point_2 opp_tgt = Point_2( -(xcv.get_pt().x()), -(xcv.get_pt().y())); opp_xcv = Ray_2( xcv.source(), opp_tgt); } return opp_xcv; - } - }; /*! Get a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const - { - return Construct_opposite_2(this); - } + { return Construct_opposite_2(*this); } /*! A functor that compares the x-coordinates of two points */ class Compare_xy_2 { public: - /*! - * Compare two points lexigoraphically: by x, then by y. + /*! Compare two points lexigoraphically: by x, then by y. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); * SMALLER if x(p1) < x(p2), or if x(p1) = x(p2) and y(p1) < y(p2); * EQUAL if the two points are equal. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { - Kernel kernel; + Kernel kernel; return (kernel.compare_xy_2_object()(p1, p2)); } }; /*! Obtain a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return Compare_xy_2(); - } + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(); } /*! A functor that obtains the left endpoint of a segment or a ray. */ - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { public: - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \pre The left end of cv is a valid (bounded) point. * \return The left endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.has_left()); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.has_left()); return (cv.left()); } }; /*! Obtain a Construct_min_vertex_2 functor object. */ - Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return Construct_min_vertex_2(); - } + Construct_min_vertex_2 construct_min_vertex_2_object() const + { return Construct_min_vertex_2(); } /*! A functor that obtains the right endpoint of a segment or a ray. */ - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { public: - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \pre The right end of cv is a valid (bounded) point. * \return The right endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.has_right()); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.has_right()); return (cv.right()); } }; /*! Obtain a Construct_max_vertex_2 functor object. */ - Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return Construct_max_vertex_2(); - } + Construct_max_vertex_2 construct_max_vertex_2_object() const + { return Construct_max_vertex_2(); } /*! A functor that checks whether a given linear curve is vertical. */ - class Is_vertical_2 - { + class Is_vertical_2 { public: - /*! - * Check whether the given x-monotone curve is a vertical segment. + /*! Check whether the given x-monotone curve is a vertical segment. * \param cv The curve. * \return (true) if the curve is a vertical segment; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv) const + bool operator()(const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); + CGAL_precondition(! cv.is_degenerate()); return (cv.is_vertical()); } }; /*! Obtain an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object () const - { - return Is_vertical_2(); - } + Is_vertical_2 is_vertical_2_object() const { return Is_vertical_2(); } /*! A functor that compares the y-coordinates of a point and a line at * the point x-coordinate @@ -877,7 +738,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -885,14 +746,13 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_y_at_x_2(const Traits * traits) : m_traits(traits) {} + Compare_y_at_x_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; public: - /*! - * Return the location of the given point with respect to the input curve. + /*! Obtain the location of the given point with respect to the input curve. * \param cv The curve. * \param p The point. * \pre p is in the x-range of cv. @@ -900,42 +760,38 @@ public: * LARGER if y(p) > cv(x(p)), i.e. the point is above the curve; * EQUAL if p lies on the curve. */ - Comparison_result operator() (const Point_2& p, - const X_monotone_curve_2& cv) const + Comparison_result operator()(const Point_2& p, + const X_monotone_curve_2& cv) const { - CGAL_precondition (! cv.is_degenerate()); - CGAL_precondition (cv.is_in_x_range (p)); + CGAL_precondition(! cv.is_degenerate()); + CGAL_precondition(cv.is_in_x_range(p)); - const Kernel * kernel = m_traits; + const Kernel& kernel = m_traits; if (! cv.is_vertical()) // Compare p with the segment's supporting line. - return (kernel->compare_y_at_x_2_object()(p, cv.supp_line())); + return (kernel.compare_y_at_x_2_object()(p, cv.supp_line())); // Compare with the vertical segment's end-points. - typename Kernel::Compare_y_2 compare_y = kernel->compare_y_2_object(); + typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); const Comparison_result res1 = - cv.has_left() ? compare_y (p, cv.left()) : LARGER; + cv.has_left() ? compare_y(p, cv.left()) : LARGER; const Comparison_result res2 = - cv.has_right() ? compare_y (p, cv.right()) : SMALLER; + cv.has_right() ? compare_y(p, cv.right()) : SMALLER; return (res1 == res2) ? res1 : EQUAL; } }; /*! Obtain a Compare_y_at_x_2 functor object. */ - Compare_y_at_x_2 compare_y_at_x_2_object () const - { - return Compare_y_at_x_2(this); - } + Compare_y_at_x_2 compare_y_at_x_2_object() const + { return Compare_y_at_x_2(*this); } /*! A functor that compares compares the y-coordinates of two linear * curves immediately to the left of their intersection point. */ - class Compare_y_at_x_left_2 - { + class Compare_y_at_x_left_2 { public: - /*! - * Compare the y value of two x-monotone curves immediately to the left + /*! Compare the y value of two x-monotone curves immediately to the left * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -945,31 +801,28 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the left of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& CGAL_precondition_code(p)) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& CGAL_precondition_code(p)) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); Kernel kernel; // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv1, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on (p, cv2, - Has_exact_division())); + (Segment_assertions::_assert_is_point_on(p, cv1, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(p, cv2, Has_exact_division())); - CGAL_precondition ((! cv1.has_left() || - compare_xy(cv1.left(), p) == SMALLER) && - (! cv2.has_left() || - compare_xy(cv2.left(), p) == SMALLER)); + CGAL_precondition((! cv1.has_left() || + compare_xy(cv1.left(), p) == SMALLER) && + (! cv2.has_left() || + compare_xy(cv2.left(), p) == SMALLER)); // Compare the slopes of the two segments to determine thir relative // position immediately to the left of q. @@ -981,19 +834,15 @@ public: }; /*! Obtain a Compare_y_at_x_left_2 functor object. */ - Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const - { - return Compare_y_at_x_left_2(); - } + Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const + { return Compare_y_at_x_left_2(); } /*! A functor that compares compares the y-coordinates of two linear * curves immediately to the right of their intersection point. */ - class Compare_y_at_x_right_2 - { + class Compare_y_at_x_right_2 { public: - /*! - * Compare the y value of two x-monotone curves immediately to the right + /*! Compare the y value of two x-monotone curves immediately to the right * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -1003,31 +852,28 @@ public: * \return The relative position of cv1 with respect to cv2 immdiately to * the right of p: SMALLER, LARGER or EQUAL. */ - Comparison_result operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - const Point_2& CGAL_precondition_code(p)) const + Comparison_result operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + const Point_2& CGAL_precondition_code(p)) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; + Kernel kernel; // Make sure that p lies on both curves, and that both are defined to its // right (so their right endpoint is lexicographically larger than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv1, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on (p, cv2, - Has_exact_division())); + (Segment_assertions::_assert_is_point_on(p, cv1, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(p, cv2, Has_exact_division())); - CGAL_precondition ((! cv1.has_right() || - compare_xy(cv1.right(), p) == LARGER) && - (! cv2.has_right() || - compare_xy(cv2.right(), p) == LARGER)); + CGAL_precondition((! cv1.has_right() || + compare_xy(cv1.right(), p) == LARGER) && + (! cv2.has_right() || + compare_xy(cv2.right(), p) == LARGER)); // Compare the slopes of the two segments to determine thir relative // position immediately to the left of q. @@ -1038,47 +884,43 @@ public: }; /*! Obtain a Compare_y_at_x_right_2 functor object. */ - Compare_y_at_x_right_2 compare_y_at_x_right_2_object () const - { - return Compare_y_at_x_right_2(); - } + Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const + { return Compare_y_at_x_right_2(); } /*! A functor that checks whether two points and two linear curves are * identical. */ - class Equal_2 - { + class Equal_2 { public: - /*! - * Check whether the two x-monotone curves are the same (have the same + /*! Check whether the two x-monotone curves are the same (have the same * graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); + Kernel kernel; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); // Check that the two supporting lines are the same. - if (! equal (cv1.supp_line(), cv2.supp_line()) && - ! equal (cv1.supp_line(), - kernel.construct_opposite_line_2_object()(cv2.supp_line()))) + if (! equal(cv1.supp_line(), cv2.supp_line()) && + ! equal(cv1.supp_line(), + kernel.construct_opposite_line_2_object()(cv2.supp_line()))) { - return (false); + return false; } // Check that either the two left endpoints are at infinity, or they // are bounded and equal. if ((cv1.has_left() != cv2.has_left()) || - (cv1.has_left() && ! equal (cv1.left(), cv2.left()))) + (cv1.has_left() && ! equal(cv1.left(), cv2.left()))) { - return (false); + return false; } // Check that either the two right endpoints are at infinity, or they @@ -1087,24 +929,20 @@ public: (! cv1.has_right() || equal (cv1.right(), cv2.right()))); } - /*! - * Check whether the two points are the same. + /*! Check whether the two points are the same. * \param p1 The first point. * \param p2 The second point. * \return (true) if the two point are the same; (false) otherwise. */ - bool operator() (const Point_2& p1, const Point_2& p2) const + bool operator()(const Point_2& p1, const Point_2& p2) const { - Kernel kernel; + Kernel kernel; return (kernel.equal_2_object()(p1, p2)); } }; /*! Obtain an Equal_2 functor object. */ - Equal_2 equal_2_object () const - { - return Equal_2(); - } + Equal_2 equal_2_object() const { return Equal_2(); } //@} /// \name Functor definitions to handle boundaries @@ -1130,7 +968,7 @@ public: Arr_parameter_space operator()(const X_monotone_curve_2 & xcv, Arr_curve_end ce) const { - CGAL_precondition (! xcv.is_degenerate()); + CGAL_precondition(! xcv.is_degenerate()); return (ce == ARR_MIN_END) ? xcv.left_infinite_in_x() : xcv.right_infinite_in_x(); } @@ -1140,9 +978,7 @@ public: * \return the parameter space at p. */ Arr_parameter_space operator()(const Point_2 ) const - { - return ARR_INTERIOR; - } + { return ARR_INTERIOR; } }; /*! Obtain a Parameter_space_in_x_2 function object */ @@ -1185,9 +1021,7 @@ public: * \return the parameter space at p. */ Arr_parameter_space operator()(const Point_2 ) const - { - return ARR_INTERIOR; - } + { return ARR_INTERIOR; } }; /*! Obtain a Parameter_space_in_y_2 function object */ @@ -1202,7 +1036,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -1210,7 +1044,7 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_x_at_limit_2(const Traits* traits) : m_traits(traits) {} + Compare_x_at_limit_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; @@ -1238,8 +1072,8 @@ public: CGAL_precondition(! xcv.is_degenerate()); CGAL_precondition(xcv.is_vertical()); - const Kernel* kernel = m_traits; - return (kernel->compare_x_at_y_2_object()(p, xcv.supp_line())); + const Kernel& kernel = m_traits; + return (kernel.compare_x_at_y_2_object()(p, xcv.supp_line())); } /*! Compare the x-limits of 2 arcs ends on the boundary of the @@ -1271,23 +1105,22 @@ public: CGAL_precondition(xcv1.is_vertical()); CGAL_precondition(xcv2.is_vertical()); - const Kernel* kernel = m_traits; - const Point_2 p = kernel->construct_point_2_object()(ORIGIN); - return (kernel->compare_x_at_y_2_object()(p, xcv1.supp_line(), - xcv2.supp_line())); + const Kernel& kernel = m_traits; + const Point_2 p = kernel.construct_point_2_object()(ORIGIN); + return (kernel.compare_x_at_y_2_object()(p, xcv1.supp_line(), + xcv2.supp_line())); } }; /*! Obtain a Compare_x_at_limit_2 function object */ Compare_x_at_limit_2 compare_x_at_limit_2_object() const - { return Compare_x_at_limit_2(this); } + { return Compare_x_at_limit_2(*this); } /*! A function object that compares the x-coordinates of arc ends near the * boundary of the parameter space */ class Compare_x_near_limit_2 { public: - /*! Compare the x-coordinates of 2 arcs ends near the boundary of the * parameter space at y = +/- oo. * \param xcv1 the first arc. @@ -1335,7 +1168,7 @@ public: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) @@ -1343,7 +1176,7 @@ public: * obtaining function, which is a member of the nesting class, * constructing it. */ - Compare_y_near_boundary_2(const Traits* traits) : m_traits(traits) {} + Compare_y_near_boundary_2(const Traits& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_linear_traits_2; @@ -1373,17 +1206,17 @@ public: xcv2.right_infinite_in_x() == ARR_RIGHT_BOUNDARY)); // Compare the slopes of the two supporting lines. - const Kernel* kernel = m_traits; + const Kernel& kernel = m_traits; const Comparison_result res_slopes = - kernel->compare_slope_2_object()(xcv1.supp_line(), xcv2.supp_line()); + kernel.compare_slope_2_object()(xcv1.supp_line(), xcv2.supp_line()); if (res_slopes == EQUAL) { // In case the two supporting line are parallel, compare their // relative position at x = 0, which is the same as their position // at infinity. - const Point_2 p = kernel->construct_point_2_object()(ORIGIN); - return (kernel->compare_y_at_x_2_object()(p, xcv1.supp_line(), - xcv2.supp_line())); + const Point_2 p = kernel.construct_point_2_object()(ORIGIN); + return (kernel.compare_y_at_x_2_object()(p, xcv1.supp_line(), + xcv2.supp_line())); } // Flip the slope result if we compare at x = -oo: @@ -1391,21 +1224,18 @@ public: } }; - /*! Obtain a Compare_y_limit_on_boundary_2 function object */ Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const - { return Compare_y_near_boundary_2(this); } + { return Compare_y_near_boundary_2(*this); } //@} /// \name Functor definitions for supporting intersections. //@{ - class Make_x_monotone_2 - { + class Make_x_monotone_2 { public: - /*! - * Cut the given curve into x-monotone subcurves and insert them into the + /*! 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. * \param cv The curve. @@ -1414,73 +1244,72 @@ public: * essentially the same as the input curve. * \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 { // Wrap the curve with an object. - *oi = make_object (cv); - ++oi; - - return (oi); + *oi++ = make_object(cv); + 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(); - } + Make_x_monotone_2 make_x_monotone_2_object() const + { return Make_x_monotone_2(); } - class Split_2 - { + class Split_2 { public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator() (const X_monotone_curve_2& cv, const Point_2& p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { CGAL_precondition (! cv.is_degenerate()); // Make sure that p lies on the interior of the curve. CGAL_precondition_code ( - Kernel kernel; + Kernel kernel; typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); ); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, cv, - Has_exact_division()) && + (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division()) && (! cv.has_left() || compare_xy(cv.left(), p) == SMALLER) && (! cv.has_right() || compare_xy(cv.right(), p) == LARGER)); // Perform the split. c1 = cv; - c1.set_right (p); + c1.set_right(p); c2 = cv; - c2.set_left (p); - - return; + c2.set_left(p); } }; /*! Obtain a Split_2 functor object. */ - Split_2 split_2_object () const - { - return Split_2(); - } + Split_2 split_2_object() const { return Split_2(); } + + class Intersect_2 { + protected: + typedef Arr_linear_traits_2 Traits; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits (in case it has state) + */ + Intersect_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_linear_traits_2; - class Intersect_2 - { public: - /*! - * Find the intersections of the two given curves and insert them into the + /*! Find the intersections of the two given curves and insert them into the * given output iterator. As two segments may itersect only once, only a * single intersection will be contained in the iterator. * \param cv1 The first curve. @@ -1488,195 +1317,170 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); // Intersect the two supporting lines. - Kernel kernel; - CGAL::Object obj = kernel.intersect_2_object()(cv1.supp_line(), - cv2.supp_line()); + const Kernel& kernel = m_traits; + auto res = kernel.intersect_2_object()(cv1.supp_line(), cv2.supp_line()); - if (obj.is_empty()) - { - // The supporting line are parallel lines and do not intersect: - return (oi); - } + // The supporting line are parallel lines and do not intersect: + if (! res) return oi; // Check whether we have a single intersection point. - const Point_2 *ip = object_cast (&obj); - - if (ip != nullptr) - { + const Point_2* ip = boost::get(&*res); + if (ip != nullptr) { // Check whether the intersection point ip lies on both segments. - const bool ip_on_cv1 = cv1.is_vertical() ? cv1.is_in_y_range(*ip) : - cv1.is_in_x_range(*ip); + const bool ip_on_cv1 = cv1.is_vertical() ? + cv1.is_in_y_range(*ip) : cv1.is_in_x_range(*ip); - if (ip_on_cv1) - { - const bool ip_on_cv2 = cv2.is_vertical() ? cv2.is_in_y_range(*ip) : - cv2.is_in_x_range(*ip); + if (ip_on_cv1) { + const bool ip_on_cv2 = cv2.is_vertical() ? + cv2.is_in_y_range(*ip) : cv2.is_in_x_range(*ip); - if (ip_on_cv2) - { + if (ip_on_cv2) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. - std::pair ip_mult (*ip, 1); - *oi = make_object (ip_mult); - oi++; + Intersection_point ip_mult(*ip, 1); + *oi++ = Intersection_result(ip_mult); } } - return (oi); + return oi; } // In this case, the two supporting lines overlap. // We start with the entire cv1 curve as the overlapping subcurve, // then clip it to form the true overlapping curve. - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - X_monotone_curve_2 ovlp = cv1; + auto compare_xy = kernel.compare_xy_2_object(); + X_monotone_curve_2 ovlp = cv1; - if (cv2.has_left()) - { + if (cv2.has_left()) { // If the left endpoint of cv2 is to the right of cv1's left endpoint, // clip the overlapping subcurve. - if (! cv1.has_left()) - { + if (! cv1.has_left()) { ovlp.set_left (cv2.left(), false); } - else - { - if (compare_xy (cv1.left(), cv2.left()) == SMALLER) - ovlp.set_left (cv2.left(), false); + else { + if (compare_xy(cv1.left(), cv2.left()) == SMALLER) + ovlp.set_left(cv2.left(), false); } } - if (cv2.has_right()) - { + if (cv2.has_right()) { // If the right endpoint of cv2 is to the left of cv1's right endpoint, // clip the overlapping subcurve. - if (! cv1.has_right()) - { - ovlp.set_right (cv2.right(), false); + if (! cv1.has_right()) { + ovlp.set_right(cv2.right(), false); } - else - { - if (compare_xy (cv1.right(), cv2.right()) == LARGER) - ovlp.set_right (cv2.right(), false); + else { + if (compare_xy(cv1.right(), cv2.right()) == LARGER) + ovlp.set_right(cv2.right(), false); } } // Examine the resulting subcurve. - Comparison_result res = SMALLER; + Comparison_result cmp_res = SMALLER; if (ovlp.has_left() && ovlp.has_right()) - res = compare_xy (ovlp.left(), ovlp.right()); + cmp_res = compare_xy(ovlp.left(), ovlp.right()); - if (res == SMALLER) - { + if (cmp_res == SMALLER) { // We have discovered a true overlapping subcurve: - *oi = make_object (ovlp); - oi++; + *oi++ = Intersection_result(ovlp); } - else if (res == EQUAL) - { + else if (cmp_res == EQUAL) { // The two objects have the same supporting line, but they just share // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. - std::pair ip_mult (ovlp.left(), 0); - *oi = make_object (ip_mult); - oi++; + Intersection_point ip_mult(ovlp.left(), 0); + *oi++ = Intersection_result(ip_mult); } - return (oi); + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return Intersect_2(); - } + Intersect_2 intersect_2_object () const { return Intersect_2(*this); } - class Are_mergeable_2 - { + class Are_mergeable_2 { public: - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable - if they are supported * by the same line and share a common endpoint; (false) otherwise. */ - bool operator() (const X_monotone_curve_2& cv1, + bool operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const { - CGAL_precondition (! cv1.is_degenerate()); - CGAL_precondition (! cv2.is_degenerate()); + CGAL_precondition(! cv1.is_degenerate()); + CGAL_precondition(! cv2.is_degenerate()); - Kernel kernel; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); + Kernel kernel; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); // Check whether the two curves have the same supporting line. - if (! equal (cv1.supp_line(), cv2.supp_line()) && - ! equal (cv1.supp_line(), - kernel.construct_opposite_line_2_object()(cv2.supp_line()))) - return (false); + if (! equal(cv1.supp_line(), cv2.supp_line()) && + ! equal(cv1.supp_line(), + kernel.construct_opposite_line_2_object()(cv2.supp_line()))) + return false; // Check whether the left endpoint of one curve is the right endpoint of the // other. return ((cv1.has_right() && cv2.has_left() && - equal (cv1.right(), cv2.left())) || + equal(cv1.right(), cv2.left())) || (cv2.has_right() && cv1.has_left() && - equal (cv2.right(), cv1.left()))); + equal(cv2.right(), cv1.left()))); } }; /*! Obtain an Are_mergeable_2 functor object. */ - Are_mergeable_2 are_mergeable_2_object () const - { - return Are_mergeable_2(); - } + Are_mergeable_2 are_mergeable_2_object () const { return Are_mergeable_2(); } /*! \class Merge_2 * A functor that merges two x-monotone arcs into one. */ - class Merge_2 - { + class Merge_2 { protected: typedef Arr_linear_traits_2 Traits; /*! The traits (in case it has state) */ - const Traits* m_traits; + const Traits& m_traits; /*! Constructor * \param traits the traits (in case it has state) */ - Merge_2(const Traits* traits) : m_traits(traits) {} + Merge_2(const Traits& traits) : m_traits(traits) {} friend class Arr_linear_traits_2; public: - /*! - * Merge two given x-monotone curves into a single curve (segment). + /*! Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - X_monotone_curve_2& c) const + void operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + X_monotone_curve_2& c) const { - CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); + CGAL_precondition(m_traits.are_mergeable_2_object()(cv2, cv1)); CGAL_precondition(!cv1.is_degenerate()); CGAL_precondition(!cv2.is_degenerate()); - Equal_2 equal = m_traits->equal_2_object(); + Equal_2 equal = m_traits.equal_2_object(); // Check which curve extends to the right of the other. if (cv1.has_right() && cv2.has_left() && @@ -1685,10 +1489,8 @@ public: // cv2 extends cv1 to the right. c = cv1; - if (cv2.has_right()) - c.set_right(cv2.right()); - else - c.set_right(); // Unbounded endpoint. + if (cv2.has_right()) c.set_right(cv2.right()); + else c.set_right(); // Unbounded endpoint. } else { CGAL_precondition(cv2.has_right() && cv1.has_left() && @@ -1697,87 +1499,67 @@ public: // cv1 extends cv2 to the right. c = cv2; - if (cv1.has_right()) - c.set_right(cv1.right()); - else - c.set_right(); // Unbounded endpoint. + if (cv1.has_right()) c.set_right(cv1.right()); + else c.set_right(); // Unbounded endpoint. } } }; /*! Obtain a Merge_2 functor object. */ - Merge_2 merge_2_object () const { return Merge_2(this); } + Merge_2 merge_2_object() const { return Merge_2(*this); } //@} /// \name Functor definitions for the landmarks point-location strategy. //@{ typedef double Approximate_number_type; - class Approximate_2 - { + class Approximate_2 { public: - - /*! - * Return an approximation of a point coordinate. + /*! Obtain an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. * \return An approximation of p's x-coordinate (if i == 0), or an * approximation of p's y-coordinate (if i == 1). */ - Approximate_number_type operator() (const Point_2& p, - int i) const + Approximate_number_type operator()(const Point_2& p, int i) const { - CGAL_precondition (i == 0 || i == 1); - - if (i == 0) - return (CGAL::to_double(p.x())); - else - return (CGAL::to_double(p.y())); + CGAL_precondition((i == 0) || (i == 1)); + return (i == 0) ? CGAL::to_double(p.x()) : CGAL::to_double(p.y()); } }; /*! Obtain an Approximate_2 functor object. */ - Approximate_2 approximate_2_object () const - { - return Approximate_2(); - } + Approximate_2 approximate_2_object() const { return Approximate_2(); } - class Construct_x_monotone_curve_2 - { + class Construct_x_monotone_curve_2 { public: - - /*! - * Return an x-monotone curve connecting the two given endpoints. + /*! Obtain an x-monotone curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. * \return A segment connecting p and q. */ - X_monotone_curve_2 operator() (const Point_2& p, - const Point_2& q) const + X_monotone_curve_2 operator()(const Point_2& p, const Point_2& q) const { - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (p, q); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(p, q); - return (X_monotone_curve_2 (seg)); + return (X_monotone_curve_2(seg)); } }; /*! Obtain a Construct_x_monotone_curve_2 functor object. */ - Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object () const - { - return Construct_x_monotone_curve_2(); - } + Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const + { return Construct_x_monotone_curve_2(); } //@} - }; /*! * \class A representation of a segment, as used by the Arr_segment_traits_2 * traits-class. */ -template +template class Arr_linear_object_2 : public Arr_linear_traits_2::_Linear_object_cached_2 { @@ -1785,7 +1567,6 @@ class Arr_linear_object_2 : Base; public: - typedef Kernel_ Kernel; typedef typename Kernel::Point_2 Point_2; @@ -1794,121 +1575,92 @@ public: typedef typename Kernel::Line_2 Line_2; public: - - /*! - * Default constructor. + /*! Default constructor. */ - Arr_linear_object_2 () : - Base() - {} + Arr_linear_object_2() : Base() {} - /*! - * Constructor from two points. + /*! Constructor from two points. * \param s The source point. * \param t The target point. * \pre The two points must not be the same. */ - Arr_linear_object_2(const Point_2& s, const Point_2& t): - Base(s, t) - {} + Arr_linear_object_2(const Point_2& s, const Point_2& t) : Base(s, t) {} - /*! - * Constructor from a segment. + /*! Constructor from a segment. * \param seg The segment. * \pre The segment is not degenerate. */ - Arr_linear_object_2 (const Segment_2& seg) : - Base (seg) - {} + Arr_linear_object_2(const Segment_2& seg) : Base(seg) {} - /*! - * Constructor from a ray. + /*! Constructor from a ray. * \param ray The segment. * \pre The ray is not degenerate. */ - Arr_linear_object_2 (const Ray_2& ray) : - Base (ray) - {} + Arr_linear_object_2(const Ray_2& ray) : Base(ray) {} - /*! - * Constructor from a line. + /*! Constructor from a line. * \param line The line. * \pre The line is not degenerate. */ - Arr_linear_object_2 (const Line_2& line) : - Base (line) - {} + Arr_linear_object_2(const Line_2& line) : Base(line) {} - /*! - * Check whether the object is actually a segment. + /*! Check whether the object is actually a segment. */ - bool is_segment () const - { - return (! this->is_degen && this->has_source && this->has_target); - } + bool is_segment() const + { return (! this->is_degen && this->has_source && this->has_target); } - /*! - * Cast to a segment. + /*! Cast to a segment. * \pre The linear object is really a segment. */ - Segment_2 segment () const + Segment_2 segment() const { - CGAL_precondition (is_segment()); + CGAL_precondition(is_segment()); - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (this->ps, this->pt); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); return seg; } - /*! - * Check whether the object is actually a ray. + /*! Check whether the object is actually a ray. */ - bool is_ray () const - { - return (! this->is_degen && (this->has_source != this->has_target)); - } + bool is_ray() const + { return (! this->is_degen && (this->has_source != this->has_target)); } - /*! - * Cast to a ray. + /*! Cast to a ray. * \pre The linear object is really a ray. */ - Ray_2 ray () const + Ray_2 ray() const { - CGAL_precondition (is_ray()); + CGAL_precondition(is_ray()); - Kernel kernel; - Ray_2 ray = (this->has_source) ? - kernel.construct_ray_2_object() (this->ps, this->l) : + Kernel kernel; + Ray_2 ray = (this->has_source) ? + kernel.construct_ray_2_object()(this->ps, this->l) : kernel.construct_ray_2_object() (this->pt, kernel.construct_opposite_line_2_object()(this->l)); return ray; } - /*! - * Check whether the object is actually a line. + /*! Check whether the object is actually a line. */ - bool is_line () const - { - return (! this->is_degen && ! this->has_source && ! this->has_target); - } + bool is_line() const + { return (! this->is_degen && ! this->has_source && ! this->has_target); } - /*! - * Cast to a line. + /*! Cast to a line. * \pre The linear object is really a line. */ - Line_2 line () const + Line_2 line() const { - CGAL_precondition (is_line()); + CGAL_precondition(is_line()); return (this->l); } - /*! - * Get the supporting line. + /*! Get the supporting line. * \pre The object is not a point. */ - const Line_2& supporting_line () const + const Line_2& supporting_line() const { - CGAL_precondition (! this->is_degen); + CGAL_precondition(! this->is_degen); return (this->l); } @@ -1918,37 +1670,30 @@ public: */ const Point_2& source() const { - CGAL_precondition (! is_line()); + CGAL_precondition(! is_line()); - if (this->is_degen) - return (this->ps); // For a point. - - if (this->has_source) - return (this->ps); // For a segment or a ray. - else - return (this->pt); // For a "flipped" ray. + if (this->is_degen) return (this->ps); // For a point. + if (this->has_source) return (this->ps); // For a segment or a ray. + else return (this->pt); // For a "flipped" ray. } - /*! - * Get the target point. + /*! Get the target point. * \pre The object is a point or a segment. */ const Point_2& target() const { - CGAL_precondition (! is_line() && ! is_ray()); - + CGAL_precondition(! is_line() && ! is_ray()); return (this->pt); } - /*! - * Create a bounding box for the linear object. + /*! Create a bounding box for the linear object. */ Bbox_2 bbox() const { CGAL_precondition(this->is_segment()); - Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object() (this->ps, this->pt); - return (kernel.construct_bbox_2_object() (seg)); + Kernel kernel; + Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); + return (kernel.construct_bbox_2_object()(seg)); } // Introducing casting operators instead from a curve to @@ -1962,58 +1707,49 @@ public: /*! * Exporter for the segment class used by the traits-class. */ -template -OutputStream& operator<< (OutputStream& os, - const Arr_linear_object_2& lobj) +template +OutputStream& operator<<(OutputStream& os, + const Arr_linear_object_2& lobj) { // Print a letter identifying the object type, then the object itself. - if (lobj.is_segment()) - os << " S " << lobj.segment(); - else if (lobj.is_ray()) - os << " R " << lobj.ray(); - else - os << " L " << lobj.line(); - - return (os); + if (lobj.is_segment()) os << " S " << lobj.segment(); + else if (lobj.is_ray()) os << " R " << lobj.ray(); + else os << " L " << lobj.line(); + return os; } -/*! - * Importer for the segment class used by the traits-class. +/*! Importer for the segment class used by the traits-class. */ -template -InputStream& operator>> (InputStream& is, Arr_linear_object_2& lobj) +template +InputStream& operator>>(InputStream& is, Arr_linear_object_2& lobj) { // Read the object type. - char c; + char c; - do - { + do { is >> c; } while ((c != 'S' && c != 's') && (c != 'R' && c != 'r') && (c != 'L' && c != 'l')); // Read the object accordingly. - if (c == 'S' || c == 's') - { + if (c == 'S' || c == 's') { typename Kernel::Segment_2 seg; is >> seg; lobj = seg; } - else if (c == 'R' || c == 'r') - { - typename Kernel::Ray_2 ray; + else if (c == 'R' || c == 'r') { + typename Kernel::Ray_2 ray; is >> ray; lobj = ray; } - else - { - typename Kernel::Line_2 line; + else { + typename Kernel::Line_2 line; is >> line; lobj = line; } - return (is); + return is; } } //namespace CGAL 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 2e567fc241a..3df642ba1e7 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 @@ -7,9 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel -// Ron Wein -// (base on old version by: Iddo Hanniel) +// Author(s): Efi Fogel +// Ron Wein +// (base on old version by: Iddo Hanniel) #ifndef CGAL_ARR_NON_CACHING_SEGMENT_TRAITS_H #define CGAL_ARR_NON_CACHING_SEGMENT_TRAITS_H @@ -27,6 +27,8 @@ * functors required by the concept it models. */ +#include + #include #include #include @@ -39,7 +41,7 @@ namespace CGAL { * A model of the ArrangementTraits_2 concept that handles general * line segments. */ -template +template class Arr_non_caching_segment_traits_2 : public Arr_non_caching_segment_basic_traits_2 { @@ -114,12 +116,10 @@ public: /*! \class * A functor for splitting curves into x-monotone pieces. */ - class Make_x_monotone_2 - { + class Make_x_monotone_2 { public: - /*! - * Cut the given segment into x-monotone subcurves and insert them into + /*! Cut the given segment into x-monotone subcurves and insert them into * the given output iterator. As segments are always x_monotone, only one * x-monotone curve is inserted into the output iterator. * \param cv The segment. @@ -127,54 +127,47 @@ public: * object is a wrapper of an X_monotone_curve_2 object. * \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 { - *oi = make_object (cv); - ++oi; - return (oi); + *oi++ = make_object(cv); + return oi; } }; - /*! Get a Make_x_monotone_2 functor object. */ + /*! 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(); } /*! \class * A functor for splitting a segment into two segements. */ - class Split_2 - { + class Split_2 { typedef Arr_non_caching_segment_traits_2 Self; - public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + public: + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). * \param c2 Output: The right resulting subcurve (p is its left endpoint). * \pre p lies on cv but is not one of its end-points. */ - void operator()(const X_monotone_curve_2 & cv, const Point_2 & p, - X_monotone_curve_2 & c1, X_monotone_curve_2 & c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { Base base; // Make sure that p lies on the interior of the curve. - CGAL_precondition_code ( - Compare_xy_2 compare_xy = base.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = base.compare_xy_2_object()); Construct_min_vertex_2 min_vertex = base.construct_min_vertex_2_object(); Construct_max_vertex_2 max_vertex = base.construct_max_vertex_2_object(); - const Point_2 & left = min_vertex(cv); - const Point_2 & right = max_vertex(cv); + const Point_2& left = min_vertex(cv); + const Point_2& right = max_vertex(cv); CGAL_precondition - (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division())&& + (Segment_assertions::_assert_is_point_on(p, cv, Has_exact_division()) && compare_xy(left, p) == SMALLER && compare_xy(right, p) == LARGER); @@ -182,31 +175,36 @@ public: base.construct_segment_2_object(); Self self; - if(self.compare_endpoints_xy_2_object()(cv) == SMALLER) - { + if (self.compare_endpoints_xy_2_object()(cv) == SMALLER) { c1 = construct_segment(left, p); c2 = construct_segment(p, right); } - else - { + else { c1 = construct_segment(p, left); c2 = construct_segment(right, p); } } }; - /*! Get a Split_2 functor object. */ - Split_2 split_2_object() const - { - return Split_2(); - } + /*! Obtain a Split_2 functor object. */ + Split_2 split_2_object() const { return Split_2(); } /*! \class * A functor for computing intersections. */ - class Intersect_2 - { - typedef Arr_non_caching_segment_traits_2 Self; + class Intersect_2 { + protected: + typedef Arr_non_caching_segment_traits_2 Traits; + + /*! The traits (in case it has state) */ + const Traits& m_traits; + + /*! Constructor + * \param traits the traits (in case it has state) + */ + Intersect_2(const Traits& traits) : m_traits(traits) {} + + friend class Arr_non_caching_segment_traits_2; public: /*! Find the intersections of the two given segments and insert them into @@ -217,67 +215,56 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2, + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, OutputIterator oi) const { - Base base; - Object res = base.intersect_2_object()(cv1, cv2); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + const Kernel& kernel = m_traits; + auto res = kernel.intersect_2_object()(cv1, cv2); // There is no intersection: - if (res.is_empty()) - return (oi); + if (! res) return oi; // Chack if the intersection is a point: - const Point_2 *ip; - - if ((ip = object_cast (&res)) != nullptr) - { + const Point_2* p_p = boost::get(&*res); + if (p_p != nullptr) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments for all practical purposes. // If the two segments intersect at their endpoints, then the // multiplicity is undefined, but we deliberately ignore it for // efficieny reasons. - std::pair ip_mult(*ip, 1); - *oi = make_object (ip_mult); - ++oi; + *oi++ = Intersection_result(Intersection_point(*p_p, 1)); + return oi; } - else - { - // The intersection is a segment. - const X_monotone_curve_2 *ov = object_cast(&res); - CGAL_assertion (ov != nullptr); + // The intersection is a segment. + const X_monotone_curve_2* cv_p = boost::get(&*res); + CGAL_assertion(cv_p != nullptr); - Self self; - Comparison_result cmp1 = self.compare_endpoints_xy_2_object()(cv1); - Comparison_result cmp2 = self.compare_endpoints_xy_2_object()(cv2); + Comparison_result cmp1 = m_traits.compare_endpoints_xy_2_object()(cv1); + Comparison_result cmp2 = m_traits.compare_endpoints_xy_2_object()(cv2); - if(cmp1 == cmp2) - { - // cv1 and cv2 have the same directions, maintain this direction - // in the overlap segment - if(self.compare_endpoints_xy_2_object()(*ov) != cmp1) - { - Kernel k; - res = make_object(k.construct_opposite_segment_2_object()(*ov)); - } + if (cmp1 == cmp2) { + // cv1 and cv2 have the same directions, maintain this direction + // in the overlap segment + if (m_traits.compare_endpoints_xy_2_object()(*cv_p) != cmp1) { + auto ctr_opposite = kernel.construct_opposite_segment_2_object(); + *oi++ = Intersection_result(ctr_opposite(*cv_p)); + return oi; } - - *oi = res; - ++oi; } - - return (oi); + *oi++ = Intersection_result(*cv_p); + return oi; } }; - /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const - { - return Intersect_2(); - } + /*! Obtain an Intersect_2 functor object. */ + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } /*! \class * A functor for testing whether two segments are mergeable. @@ -297,24 +284,22 @@ public: friend class Arr_non_caching_segment_traits_2; public: - - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable, that is, if they are * supported by the same line; (false) otherwise. * \pre cv1 and cv2 share a common endpoint. */ - bool operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2) const + bool operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2) const { const Base* base = m_traits; Equal_2 equal = base->equal_2_object(); Construct_min_vertex_2 min_vertex = base->construct_min_vertex_2_object(); Construct_max_vertex_2 max_vertex = base->construct_max_vertex_2_object(); - if (!equal(max_vertex(cv1), min_vertex(cv2)) && - !equal(max_vertex(cv2), min_vertex(cv1))) + if (! equal(max_vertex(cv1), min_vertex(cv2)) && + ! equal(max_vertex(cv2), min_vertex(cv1))) return false; // Check if the two curves have the same supporting line. @@ -344,16 +329,15 @@ public: friend class Arr_non_caching_segment_traits_2; public: - /*! - * Merge two given segments into a single segment. + /*! Merge two given segments into a single segment. * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. * \pre The two curves are mergeable. */ - void operator()(const X_monotone_curve_2 & cv1, - const X_monotone_curve_2 & cv2, - X_monotone_curve_2 & c) const + void operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + X_monotone_curve_2& c) const { CGAL_precondition(m_traits->are_mergeable_2_object()(cv2, cv1)); @@ -390,12 +374,9 @@ public: /*! Obtain a Construct_opposite_2 functor object */ Construct_opposite_2 construct_opposite_2_object() const - { - return Construct_opposite_2(); - } + { return Construct_opposite_2(); } - class Compare_endpoints_xy_2 - { + class Compare_endpoints_xy_2 { public: /*! * Compare the two endpoints of a given curve lexigoraphically. @@ -417,9 +398,7 @@ public: /*! Obtain a Compare_endpoints_xy_2 functor object */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const - { - return Compare_endpoints_xy_2(); - } + { return Compare_endpoints_xy_2(); } //@} }; diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h index a52f91db9d2..e7202ffe935 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_X_trapezoid.h @@ -142,7 +142,7 @@ public: private: - Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR.p); } + Trpz_parameter_space* ptr() const { return (Trpz_parameter_space*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -323,7 +323,7 @@ public: { //define the initial trapezoid: left, right, btm, top are at infinity. // its type is TD_TRAPEZOID ,it is on all boundaries, and has no neighbours - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (Traits::vtx_at_left_infinity(), Traits::vtx_at_right_infinity(), Traits::he_at_bottom_infinity(), @@ -353,7 +353,7 @@ public: else //tp == TD_VERTEX type_flag |= CGAL_TD_VERTEX; - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (l, r, b, t, type_flag | boundness_flag, lb, lt, rb, rt); m_dag_node = node; } @@ -370,7 +370,7 @@ public: Self* rb = 0, Self* rt = 0, Dag_node* node = 0) { - PTR.p = new Trpz_parameter_space + PTR = new Trpz_parameter_space (l ? *l : Traits::vtx_at_left_infinity(), r ? *r : Traits::vtx_at_right_infinity(), b ? *b : Traits::he_at_bottom_infinity(), @@ -436,7 +436,7 @@ public: /*! Access the trapezoid id (PTR). */ CGAL_TD_INLINE unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } /*! Access trapezoid left. */ diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h index 2cdeee6bca5..61259f33547 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_edge.h @@ -135,7 +135,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -194,7 +194,7 @@ public: Td_active_edge () { - PTR.p = new Data + PTR = new Data (Traits::empty_he_handle(), Td_map_item(0), nullptr); //m_dag_node = nullptr; } @@ -204,7 +204,7 @@ public: boost::optional next = boost::none) { - PTR.p = new Data(he, (next) ? *next : Td_map_item(0), node); + PTR = new Data(he, (next) ? *next : Td_map_item(0), node); //m_dag_node = node; } @@ -261,7 +261,7 @@ public: /*! Access the trapezoid id (PTR). */ CGAL_TD_INLINE unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h index 6bfb3d5e6f2..b75de1b9d97 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_fictitious_vertex.h @@ -129,7 +129,7 @@ public: }; private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -180,14 +180,14 @@ public: Td_active_fictitious_vertex() { - PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); + PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); } /*! Constructor given Vertex & Halfedge handles. */ Td_active_fictitious_vertex(Vertex_const_handle v, Halfedge_const_handle cw_he, Dag_node* node = 0) - { PTR.p = new Data(v, cw_he, node); } + { PTR = new Data(v, cw_he, node); } /*! Copy constructor. */ @@ -224,7 +224,7 @@ public: inline const Self& self() const { return *this; } /*! Access the trapezoid id (PTR). */ - inline unsigned long id() const { return (unsigned long) PTR.p; } + inline unsigned long id() const { return (unsigned long) PTR; } /*! Access trapezoid left. * filters out the infinite case which returns predefined dummy values diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h index 2b565adba74..8b92b739626 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_trapezoid.h @@ -144,7 +144,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } public: @@ -255,7 +255,7 @@ private: { //define the initial trapezoid: left, right, btm, top are at infinity. // has no neighbours - PTR.p = new Data + PTR = new Data (Traits::empty_vtx_handle(), Traits::empty_vtx_handle(), Traits::empty_he_handle(), @@ -274,7 +274,7 @@ private: boost::optional rt = boost::none, Dag_node* node = 0) { - PTR.p = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0), + PTR = new Data (l, r, b, t, (lb) ? *lb : Td_map_item(0), (lt) ? *lt : Td_map_item(0), (rb) ? *rb : Td_map_item(0), (rt) ? *rt : Td_map_item(0), node); //m_dag_node = node; } @@ -332,7 +332,7 @@ private: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } /*! Access trapezoid left. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h index de4000ebfd9..3b3e86aa0c6 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_active_vertex.h @@ -134,7 +134,7 @@ public: }; private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -184,14 +184,14 @@ public: Td_active_vertex() { - PTR.p = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); + PTR = new Data(Traits::empty_vtx_handle(), Traits::empty_he_handle(), nullptr); } /*! Constructor given Vertex & Halfedge handles. */ Td_active_vertex(Vertex_const_handle v, Halfedge_const_handle cw_he, Dag_node* node = 0) - { PTR.p = new Data(v, cw_he, node); } + { PTR = new Data(v, cw_he, node); } /*! Copy constructor. */ @@ -228,7 +228,7 @@ public: inline const Self& self() const { return *this; } /*! Access the trapezoid id (PTR). */ - inline unsigned long id() const { return (unsigned long) PTR.p; } + inline unsigned long id() const { return (unsigned long) PTR; } inline Vertex_const_handle vertex() const { return ptr()->v; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h index e5eee91e724..f8a47536c85 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag.h @@ -41,14 +41,14 @@ public: //iddo (for CC-7.2) maybe protected? typedef const T & const_reference; protected: - void init() { PTR.p = 0; } + void init() { PTR = 0; } public: Td_dag_base() {init();} Td_dag_base(const Td_dag_base & x) : Handle(x) {} Td_dag_base & operator=(const Td_dag_base & x) {Handle::operator=(x); return *this; } - bool operator!() const { return PTR.p == 0; } + bool operator!() const { return PTR == 0; } }; template @@ -96,9 +96,9 @@ public: Td_dag(){} Td_dag(const Td_dag_handle& dag):Td_dag_handle(dag){} Td_dag(const Self& dag):Td_dag_handle(dag){} - Td_dag(const T& rootValue){PTR.p = new node(rootValue);} + Td_dag(const T& rootValue){PTR = new node(rootValue);} Td_dag(const T& rootValue, const Self& left, const Self& right) - {PTR.p = new node(rootValue, left, right); rebalance_depth();} + {PTR = new node(rootValue, left, right); rebalance_depth();} ~Td_dag(){} /* --------information retrieval -------*/ @@ -145,7 +145,7 @@ public: } bool operator==(const Self& b) const { - return PTR.p==b.PTR.p; + return PTR==b.PTR; } bool operator!=(const Self& b) const { @@ -189,7 +189,7 @@ public: // detach left son,redirect to dummy set_left(dummy); // set left son pointer to 0 - ptr()->leftPtr.PTR.p=0; + ptr()->leftPtr.PTR=0; // delete dummy Td_dag delete dummy.ptr(); } @@ -204,7 +204,7 @@ public: // detach right son,redirect to dummy set_right(dummy); // set right son pointer to 0 - ptr()->rightPtr.PTR.p=0; + ptr()->rightPtr.PTR=0; // delete dummy Td_dag delete dummy.ptr(); } @@ -371,7 +371,7 @@ protected: } #endif private: - node* ptr() const {return (node*)PTR.p;} + node* ptr() const {return (node*)PTR;} }; template @@ -441,7 +441,7 @@ template std::ostream& operator<<(std::ostream& out, tech notes: The code is Handle designed. left(),right() are designed to cope with Handle(Handle& x) - precondition x.PTR.p!=0 + precondition x.PTR!=0 operator=() performs shallow copy operator*() returns data type output is done as a binary tree. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h index bbf45831519..ec4a961d8f1 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_dag_node.h @@ -39,7 +39,7 @@ template class Td_dag_node_base : public Handle { protected: - void init() { PTR.p = 0; } //MICHAL: I think it is not used - so need to be removed + void init() { PTR = 0; } //MICHAL: I think it is not used - so need to be removed public: //c'tors @@ -57,12 +57,12 @@ public: return *this; } - //bool operator!() const { return PTR.p == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar - bool is_null() const { return PTR.p == 0; } - Rep * ptr() const { return (Rep*) PTR.p; } + //bool operator!() const { return PTR == 0; } //MICHAL: maybe use ptr(), and also can change to is_null or something similar + bool is_null() const { return PTR == 0; } + Rep * ptr() const { return (Rep*) PTR; } protected: - //Rep *& ptr() { return (Rep*) PTR.p; } - void set_ptr(Rep* rep) { PTR.p = rep; } + //Rep *& ptr() { return (Rep*) PTR; } + void set_ptr(Rep* rep) { PTR = rep; } }; @@ -94,7 +94,7 @@ public: #ifndef CGAL_CFG_USING_BASE_MEMBER_BUG_2 public: - //using Td_dag_node_handle::PTR.p; + //using Td_dag_node_handle::PTR; //using Td_dag_node_handle::operator!; #endif //CGAL_CFG_USING_BASE_MEMBER_BUG_2 @@ -549,7 +549,7 @@ protected: private: - Node* node() const { return (Node*)Base::PTR.p; } + Node* node() const { return (Node*)Base::PTR; } }; @@ -629,7 +629,7 @@ std::ostream& operator<< (std::ostream& out, tech notes: The code is Handle designed. left_child(),right_child() are designed to cope with Handle(Handle& x) - precondition x.PTR.p!=0 + precondition x.PTR!=0 operator=() performs shallow copy operator*() returns data type output is done as a binary tree. diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h index 0d85f93f148..bb57f7c6d1c 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_edge.h @@ -128,7 +128,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -161,7 +161,7 @@ public: /*! Constructor given Vertex & Halfedge handles. */ Td_inactive_edge (boost::shared_ptr& cv, Dag_node* node = nullptr) { - PTR.p = new Data(cv,node); + PTR = new Data(cv,node); } /*! Copy constructor. */ @@ -215,7 +215,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } inline X_monotone_curve_2& curve() const diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h index cf2d75d79ec..03ca8d563c7 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_fictitious_vertex.h @@ -133,7 +133,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } Curve_end vtx_to_ce(Vertex_const_handle v) const { @@ -185,7 +185,7 @@ public: { Curve_end v_ce(vtx_to_ce(v_before_rem)); - PTR.p = new Data( v_ce.cv(), v_ce.ce(), node); + PTR = new Data( v_ce.cv(), v_ce.ce(), node); } @@ -241,7 +241,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h index 0c42b1e7669..409a6f576ee 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_point_location/Td_inactive_vertex.h @@ -127,7 +127,7 @@ public: private: - Data* ptr() const { return (Data*)(PTR.p); } + Data* ptr() const { return (Data*)(PTR); } #ifndef CGAL_TD_DEBUG @@ -162,7 +162,7 @@ public: /*! Constructor given Vertex & Halfedge handles. */ Td_inactive_vertex (Vertex_const_handle v_before_rem, Dag_node* node = nullptr) { - PTR.p = new Data(v_before_rem->point(), node); + PTR = new Data(v_before_rem->point(), node); } @@ -217,7 +217,7 @@ public: /*! Access the trapezoid id (PTR). */ inline unsigned long id() const { - return (unsigned long) PTR.p; + return (unsigned long) PTR; } inline Point& point() const 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 e99c306a1e0..6d61db9e61e 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 @@ -25,6 +25,8 @@ */ #include + +#include #include #include @@ -193,13 +195,12 @@ public: // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; - Construct_x_monotone_curve_2 ctr_x_curve = - m_poly_traits.construct_x_monotone_curve_2_object(); + auto ctr_x_curve = m_poly_traits.construct_x_monotone_curve_2_object(); - typename Subcurve_traits_2::Make_x_monotone_2 make_seg_x_monotone = + auto make_seg_x_monotone = m_poly_traits.subcurve_traits_2()->make_x_monotone_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = + auto cmp_seg_endpts = m_poly_traits.subcurve_traits_2()->compare_endpoints_xy_2_object(); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT @@ -238,12 +239,11 @@ public: ( // To be used in order to verify continuity and well-orientedness // of the input curve cv. - typename Subcurve_traits_2::Construct_min_vertex_2 min_seg_v = + auto min_seg_v = m_poly_traits.subcurve_traits_2()->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_seg_v = + auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - m_poly_traits.subcurve_traits_2()->equal_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 next_src; @@ -329,19 +329,18 @@ public: // If the polycurve is empty, return. if (cv.number_of_subcurves() == 0) return oi; - Construct_x_monotone_curve_2 ctr_x_curve = - m_poly_traits.construct_x_monotone_curve_2_object(); + auto ctr_x_curve = m_poly_traits.construct_x_monotone_curve_2_object(); - typename Subcurve_traits_2::Make_x_monotone_2 make_seg_x_monotone = + auto make_seg_x_monotone = m_poly_traits.subcurve_traits_2()->make_x_monotone_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = + auto cmp_seg_endpts = m_poly_traits.subcurve_traits_2()->compare_endpoints_xy_2_object(); - typename Subcurve_traits_2::Parameter_space_in_x_2 ps_x = - m_poly_traits.subcurve_traits_2()->parameter_space_in_x_2_object(); - typename Subcurve_traits_2::Parameter_space_in_y_2 ps_y = - m_poly_traits.subcurve_traits_2()->parameter_space_in_y_2_object(); + auto ps_x = + m_poly_traits.subcurve_traits_2()->parameter_space_in_x_2_object(); + auto ps_y = + m_poly_traits.subcurve_traits_2()->parameter_space_in_y_2_object(); #ifdef CGAL_ALWAYS_LEFT_TO_RIGHT typename Subcurve_traits_2::Construct_opposite_2 ctr_seg_opposite = @@ -379,12 +378,11 @@ public: ( // To be used in order to verify continuity and well-orientedness // of the input curve cv. - typename Subcurve_traits_2::Construct_min_vertex_2 min_seg_v = + auto min_seg_v = m_poly_traits.subcurve_traits_2()->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_seg_v = + auto max_seg_v = m_poly_traits.subcurve_traits_2()->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - m_poly_traits.subcurve_traits_2()->equal_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 next_src; @@ -498,9 +496,7 @@ public: public: /*! Constructor. */ - Push_back_2(const Polycurve_traits_2& traits) : - Base::Push_back_2(traits) - {} + Push_back_2(const Polycurve_traits_2& traits) : Base::Push_back_2(traits) {} // Normally, the moment the compiler finds a name, it stops looking. In // other words, the compiler first finds the operator() in the current @@ -584,20 +580,16 @@ public: X_monotone_curve_2& xcv1, X_monotone_curve_2& xcv2) const { const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); - typename Subcurve_traits_2::Construct_min_vertex_2 min_vertex = - geom_traits->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_vertex = - geom_traits->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - geom_traits->equal_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = - geom_traits->compare_endpoints_xy_2_object(); + auto min_vertex = geom_traits->construct_min_vertex_2_object(); + auto max_vertex = geom_traits->construct_max_vertex_2_object(); + auto equal = geom_traits->equal_2_object(); + auto cmp_seg_endpts = geom_traits->compare_endpoints_xy_2_object(); // Make sure the split point is not one of the curve endpoints. - CGAL_precondition((!equal(m_poly_traits. - construct_min_vertex_2_object()(xcv), p))); - CGAL_precondition((!equal(m_poly_traits. - construct_max_vertex_2_object()(xcv), p))); + CGAL_precondition((! equal(m_poly_traits. + construct_min_vertex_2_object()(xcv), p))); + CGAL_precondition((! equal(m_poly_traits. + construct_max_vertex_2_object()(xcv), p))); CGAL_precondition_msg(xcv.number_of_subcurves() > 0, "Cannot split a polycurve of length zero."); @@ -709,22 +701,20 @@ public: const X_monotone_curve_2& cv2, OutputIterator oi) const { - const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); - Compare_y_at_x_2 cmp_y_at_x = m_poly_traits.compare_y_at_x_2_object(); - typename Subcurve_traits_2::Equal_2 equal = - geom_traits->equal_2_object(); - typename Subcurve_traits_2::Construct_min_vertex_2 min_vertex = - geom_traits->construct_min_vertex_2_object(); - typename Subcurve_traits_2::Construct_max_vertex_2 max_vertex = - geom_traits->construct_max_vertex_2_object(); - typename Subcurve_traits_2::Intersect_2 intersect = - geom_traits->intersect_2_object(); - typename Subcurve_traits_2::Compare_endpoints_xy_2 cmp_seg_endpts = - geom_traits->compare_endpoints_xy_2_object(); - typename Subcurve_traits_2::Construct_opposite_2 construct_opposite = - geom_traits->construct_opposite_2_object(); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_base_result; + typedef boost::variant + Intersection_result; - typedef std::pair Point_2_pair; + const Subcurve_traits_2* geom_traits = m_poly_traits.subcurve_traits_2(); + auto cmp_y_at_x = m_poly_traits.compare_y_at_x_2_object(); + auto equal = geom_traits->equal_2_object(); + auto min_vertex = geom_traits->construct_min_vertex_2_object(); + auto max_vertex = geom_traits->construct_max_vertex_2_object(); + auto intersect = geom_traits->intersect_2_object(); + auto cmp_seg_endpts = geom_traits->compare_endpoints_xy_2_object(); + auto construct_opposite = geom_traits->construct_opposite_2_object(); Comparison_result dir1 = cmp_seg_endpts(cv1[0]); Comparison_result dir2 = cmp_seg_endpts(cv2[0]); @@ -737,7 +727,7 @@ public: X_monotone_curve_2 ocv; // Used to represent overlaps. - Compare_xy_2 compare_xy = m_poly_traits.compare_xy_2_object(); + auto compare_xy = m_poly_traits.compare_xy_2_object(); Comparison_result left_res = compare_xy(cv1[i1], ARR_MIN_END, cv2[i2], ARR_MIN_END); @@ -754,12 +744,13 @@ public: ((dir1 == LARGER) && (i1 == 0))){ // cv1's right endpoint equals cv2's left endpoint // Thus we can return this single(!) intersection point - std::pair p(max_vertex(cv1[i1]), 0); - *oi++ = make_object(p); + Intersection_point p(max_vertex(cv1[i1]), 0); + *oi++ = Intersection_result(p); return oi; } dir1 == SMALLER ? - ++i1 : (i1 != 0) ? --i1 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; + ++i1 : + (i1 != 0) ? --i1 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; left_res = EQUAL; } } @@ -776,13 +767,14 @@ public: ((dir2 == LARGER) && (i2 == 0))){ // cv2's right endpoint equals cv1's left endpoint // Thus we can return this single(!) intersection point - std::pair p(max_vertex(cv2[i2]), 0); - *oi++ = make_object(p); + Intersection_point p(max_vertex(cv2[i2]), 0); + *oi++ = Intersection_result(p); return oi; } dir2 == SMALLER ? - ++i2 : (i2 != 0) ? --i2 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; + ++i2 : + (i2 != 0) ? --i2 : (std::size_t) Polycurve_traits_2::INVALID_INDEX; left_res = EQUAL; } } @@ -823,48 +815,64 @@ public: right_overlap = false; - if (!right_coincides && !left_coincides) { + //! EF: the following code is abit suspicious. It may erroneously + // assume that the subcurves cannot overlap more than once. + if (! right_coincides && ! left_coincides) { // Non of the endpoints of the current subcurve of one polycurve // coincides with the curent subcurve of the other polycurve: // Output the intersection if exists. - oi = intersect(cv1[i1], cv2[i2], oi); + std::vector xections; + intersect(cv1[i1], cv2[i2], std::back_inserter(xections)); + for (const auto& xection : xections) { + const X_monotone_subcurve_2* subcv_p = + boost::get(&xection); + if (subcv_p != nullptr) { + ocv.push_back(*subcv_p); + *oi++ = Intersection_result(ocv); + ocv.clear(); + continue; + } + + const Intersection_point* p_p = + boost::get(&xection); + if (p_p != nullptr) *oi++ = Intersection_result(*p_p); + } } else if (right_coincides && left_coincides) { // An overlap exists between the current subcurves of the // polycurves: Output the overlapping subcurve. right_overlap = true; - std::vector int_seg; - intersect(cv1[i1], cv2[i2], std::back_inserter(int_seg)); + std::vector sub_xections; + intersect(cv1[i1], cv2[i2], std::back_inserter(sub_xections)); - for (size_t i = 0; i < int_seg.size(); ++i) { + for (const auto& item : sub_xections) { const X_monotone_subcurve_2* x_seg = - CGAL::object_cast (&(int_seg[i])); + boost::get(&item); if (x_seg != nullptr) { X_monotone_subcurve_2 seg = *x_seg; // If for some reason the subcurve intersection // results in left oriented curve. - if ( cmp_seg_endpts(seg) == LARGER) - seg = construct_opposite(seg); + if (cmp_seg_endpts(seg) == LARGER) seg = construct_opposite(seg); ocv.push_back(seg); } - const Point_2_pair* p_ptr = - CGAL::object_cast(&(int_seg[i])); + const Intersection_point* p_ptr = + boost::get(&item); if (p_ptr != nullptr) { // Any point that is not equal to the max_vertex of the // subcurve should be inserted into oi. // The max_vertex of the current subcurve (if intersecting) // will be taken care of as the min_vertex of in the next // iteration. - if (!equal(p_ptr->first, max_vertex(cv1[i1]))) - *oi++ = make_object(*p_ptr); + if (! equal(p_ptr->first, max_vertex(cv1[i1]))) + *oi++ = Intersection_result(*p_ptr); } } } - else if (left_coincides && !right_coincides) { + else if (left_coincides && ! right_coincides) { // std::cout << "Left is coinciding but right is not." << std::endl; // The left point of the current subcurve of one polycurve // coincides with the current subcurve of the other polycurve. @@ -872,7 +880,7 @@ public: // An overlap occurred at the previous iteration: // Output the overlapping polycurve. CGAL_assertion(ocv.number_of_subcurves() > 0); - *oi++ = make_object(ocv); + *oi++ = Intersection_result(ocv); ocv.clear(); } else { @@ -884,12 +892,12 @@ public: // polycurves is not defined at this point, so we give // it multiplicity 0. if (left_res == SMALLER) { - std::pair p(min_vertex(cv2[i2]), 0); - *oi++ = make_object(p); + Intersection_point p(min_vertex(cv2[i2]), 0); + *oi++ = Intersection_result(p); } else { - std::pair p(min_vertex(cv1[i1]), 0); - *oi++ = make_object(p); + Intersection_point p(min_vertex(cv1[i1]), 0); + *oi++ = Intersection_result(p); } } } @@ -919,7 +927,7 @@ public: // Output the remaining overlapping polycurve, if necessary. if (ocv.number_of_subcurves() > 0) { - *oi++ = make_object(ocv); + *oi++ = Intersection_result(ocv); } else if (right_coincides) { typedef std::pair return_point; @@ -930,7 +938,7 @@ public: (i1 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv1[i1+1]), 0) : return_point(max_vertex(cv1[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else if (right_res == LARGER) { ip = (dir2 == SMALLER) ? @@ -938,7 +946,7 @@ public: (i2 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv2[i2+1]), 0) : return_point(max_vertex(cv2[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else if (((i1 > 0) && (dir1 == SMALLER)) || ((i1 < n1) && (dir1 != SMALLER)) || @@ -950,7 +958,7 @@ public: (i1 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv1[i1+1]), 0) : return_point(max_vertex(cv1[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } else { CGAL_assertion_msg((dir2 == SMALLER && i2 > 0) || @@ -965,7 +973,7 @@ public: (i2 != Polycurve_traits_2::INVALID_INDEX) ? return_point(max_vertex(cv2[i2+1]), 0) : return_point(max_vertex(cv2[0]), 0); - *oi++ = make_object(ip); + *oi++ = Intersection_result(ip); } } diff --git a/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h b/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h index e2010a578ec..7d253018be3 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h +++ b/Arrangement_on_surface_2/include/CGAL/Arr_rat_arc/Rational_arc_d_1.h @@ -1848,8 +1848,8 @@ public: typedef typename Base::Cache Cache; - typedef std::pair Intersection_point_2; - //typedef std::pair Intersection_point_2; + typedef std::pair Intersection_point; + //typedef std::pair Intersection_point; /// \name Constrcution methods. @@ -2029,8 +2029,7 @@ public: /// \name Constructions of points and curves. //@{ - /*! - * Compute the intersections with the given arc. + /*! Compute the intersections with the given arc. * \param arc The given intersecting arc. * \param oi The output iterator. * \return The past-the-end iterator. @@ -2039,33 +2038,31 @@ public: OutputIterator intersect(const Self& arc, OutputIterator oi, const Cache& cache) const { + typedef boost::variant Intersection_result; + CGAL_precondition(this->is_valid() && this->is_continuous()); CGAL_precondition(arc.is_valid() && arc.is_continuous()); - if (this->equals(arc)) - { - Self overlap_arc(*this); - *oi++ = make_object(overlap_arc); - return (oi); + if (this->equals(arc)) { + Self overlap_arc(*this); + *oi++ = Intersection_result(overlap_arc); + return oi; } - if (this->_has_same_base(arc)) - { + if (this->_has_same_base(arc)) { // Get the left and right endpoints of (*this) and their information // bits. - const Algebraic_point_2& left1 = (this->is_directed_right() ? - this->_ps : this->_pt); - const Algebraic_point_2& right1 = (this->is_directed_right() ? - this->_pt : this->_ps); - int info_left1, info_right1; + const Algebraic_point_2& left1 = + (this->is_directed_right() ? this->_ps : this->_pt); + const Algebraic_point_2& right1 = + (this->is_directed_right() ? this->_pt : this->_ps); + int info_left1, info_right1; - if (this->is_directed_right()) - { + if (this->is_directed_right()) { info_left1 = (this->_info & this->SRC_INFO_BITS); info_right1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right1 = (this->_info & this->SRC_INFO_BITS); info_left1 = ((this->_info & this->TRG_INFO_BITS) >> 4); } @@ -2076,110 +2073,93 @@ public: (arc.is_directed_right() ? arc._ps : arc._pt); const Algebraic_point_2& right2 = (arc.is_directed_right() ? arc._pt : arc._ps); - int info_left2, info_right2; + int info_left2, info_right2; - if (arc.is_directed_right()) - { + if (arc.is_directed_right()) { info_left2 = (arc._info & this->SRC_INFO_BITS); info_right2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } - else - { + else { info_right2 = (arc._info & this->SRC_INFO_BITS); info_left2 = ((arc._info & this->TRG_INFO_BITS) >> 4); } // Locate the left curve-end with larger x-coordinate. - bool at_minus_infinity = false; - Arr_parameter_space inf_l1 = this->left_parameter_space_in_x(); - Arr_parameter_space inf_l2 = arc.left_parameter_space_in_x(); - Algebraic_point_2 p_left; - int info_left; + bool at_minus_infinity = false; + Arr_parameter_space inf_l1 = this->left_parameter_space_in_x(); + Arr_parameter_space inf_l2 = arc.left_parameter_space_in_x(); + Algebraic_point_2 p_left; + int info_left; - if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) - { + if (inf_l1 == ARR_INTERIOR && inf_l2 == ARR_INTERIOR) { // Let p_left be the rightmost of the two left endpoints. - if (left1.x() > left2.x()) - { + if (left1.x() > left2.x()) { p_left = left1; info_left = info_left1; } - else - { + else { p_left = left2; info_left = info_left2; } } - else if (inf_l1 == ARR_INTERIOR) - { + else if (inf_l1 == ARR_INTERIOR) { // Let p_left be the left endpoint of (*this). p_left = left1; info_left = info_left1; } - else if (inf_l2 == ARR_INTERIOR) - { + else if (inf_l2 == ARR_INTERIOR) { // Let p_left be the left endpoint of the other arc. p_left = left2; info_left = info_left2; } - else - { + else { // Both arcs are defined at x = -oo. at_minus_infinity = true; info_left = info_left1; } // Locate the right curve-end with smaller x-coordinate. - bool at_plus_infinity = false; - Arr_parameter_space inf_r1 = this->right_parameter_space_in_x(); - Arr_parameter_space inf_r2 = arc.right_parameter_space_in_x(); - Algebraic_point_2 p_right; - int info_right; + bool at_plus_infinity = false; + Arr_parameter_space inf_r1 = this->right_parameter_space_in_x(); + Arr_parameter_space inf_r2 = arc.right_parameter_space_in_x(); + Algebraic_point_2 p_right; + int info_right; - if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) - { + if (inf_r1 == ARR_INTERIOR && inf_r2 == ARR_INTERIOR) { // Let p_right be the rightmost of the two right endpoints. - if (right1.x() < right2.x()) - { + if (right1.x() < right2.x()) { p_right = right1; info_right = info_right1; } - else - { + else { p_right = right2; info_right = info_right2; } } - else if (inf_r1 == ARR_INTERIOR) - { + else if (inf_r1 == ARR_INTERIOR) { // Let p_right be the right endpoint of (*this). p_right = right1; info_right = info_right1; } - else if (inf_r2 == ARR_INTERIOR) - { + else if (inf_r2 == ARR_INTERIOR) { // Let p_right be the right endpoint of the other arc. p_right = right2; info_right = info_right2; } - else - { + else { // Both arcs are defined at x = +oo. at_plus_infinity = true; info_right = info_right2; } // Check the case of two bounded (in x) ends. - if (! at_minus_infinity && ! at_plus_infinity) - { + if (! at_minus_infinity && ! at_plus_infinity) { Comparison_result res = CGAL::compare(p_left.x(), p_right.x()); - if (res == LARGER) - { - // The x-range of the overlap is empty, so there is no overlap. - return (oi); - } - else if (res == EQUAL) - { + + // The x-range of the overlap is empty, so there is no overlap. + if (res == LARGER) return oi; + + if (res == EQUAL) { // We have a single overlapping point. Just make sure this point // is not at y = -/+ oo. if (info_left && @@ -2187,19 +2167,18 @@ public: info_right && (this->SRC_AT_Y_MINUS_INFTY | this->SRC_AT_Y_PLUS_INFTY) == 0) { - Intersection_point_2 ip(p_left, 0); - - *oi++ = make_object(ip); + Intersection_point ip(p_left, 0); + *oi++ = Intersection_result(ip); } - return (oi); + return oi; } } // Create the overlapping portion of the rational arc by properly setting // the source (left) and target (right) endpoints and their information // bits. - Self overlap_arc(*this); + Self overlap_arc(*this); overlap_arc._ps = p_left; overlap_arc._pt = p_right; @@ -2208,8 +2187,8 @@ public: this->IS_DIRECTED_RIGHT | this->IS_CONTINUOUS | this->IS_VALID); - *oi++ = make_object(overlap_arc); - return (oi); + *oi++ = Intersection_result(overlap_arc); + return oi; } // We wish to find the intersection points between: @@ -2237,15 +2216,14 @@ public: if (this->_is_in_true_x_range(*x_iter) && arc._is_in_true_x_range(*x_iter)) { // Compute the intersection point and obtain its multiplicity. - Algebraic_point_2 p(this->_f, *x_iter); + Algebraic_point_2 p(this->_f, *x_iter); // Output the intersection point: - Intersection_point_2 ip(p, *m_iter); - - *oi++ = make_object(ip); + Intersection_point ip(p, *m_iter); + *oi++ = Intersection_result(ip); } } - return (oi); + return oi; } /*! @@ -2255,7 +2233,8 @@ public: * \param c2 Output: The first resulting arc, lying to the right of p. * \pre p lies in the interior of the arc (not one of its endpoints). */ - void split(const Algebraic_point_2& p, Self& c1, Self& c2, const Cache& CGAL_assertion_code(cache)) const + void split(const Algebraic_point_2& p, Self& c1, Self& c2, + const Cache& CGAL_assertion_code(cache)) const { CGAL_precondition(this->is_valid() && this->is_continuous()); @@ -2598,4 +2577,3 @@ public: } //namespace CGAL { #endif //CGAL_RATIONAL_ARC_D_1_H - 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 a9f3506ea29..a671a741f80 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 @@ -7,9 +7,9 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Ron Wein -// Efi Fogel -// Waqar Khan +// Author(s): Ron Wein +// Efi Fogel +// Waqar Khan #ifndef CGAL_ARR_SEGMENT_TRAITS_2_H #define CGAL_ARR_SEGMENT_TRAITS_2_H @@ -22,21 +22,23 @@ * The segment traits-class for the arrangement package. */ +#include + +#include + #include #include #include #include #include #include -#include namespace CGAL { -template +template class Arr_segment_2; -/*! - * \class A traits class for maintaining an arrangement of segments, avoiding +/*! \class A traits class for maintaining an arrangement of segments, avoiding * cascading of computations as much as possible. * * The class is derived from the parameterized kernel to extend the traits @@ -79,17 +81,17 @@ public: typedef typename Kernel::Point_2 Point_2; protected: - Line_2 l; // The line that supports the segment. - Point_2 ps; // The source point of the segment. - Point_2 pt; // The target point of the segment. - bool is_pt_max; // Is the target (lexicographically) larger - // than the source. - bool is_vert; // Is this a vertical segment. - bool is_degen; // Is the segment degenerate (a single point). + Line_2 m_l; // The line that supports the segment. + Point_2 m_ps; // The source point of the segment. + Point_2 m_pt; // The target point of the segment. + bool m_is_pt_max; // Is the target (lexicographically) larger + // than the source. + bool m_is_vert; // Is this a vertical segment. + bool m_is_degen; // Is the segment degenerate (a single point). public: /*! Default constructor. */ - _Segment_cached_2() : is_vert(false), is_degen(true) {} + _Segment_cached_2() : m_is_vert(false), m_is_degen(true) {} /*! Constructor from a segment. * \param seg The segment. @@ -97,50 +99,46 @@ public: */ _Segment_cached_2(const Segment_2& seg) { - Kernel kernel; + Kernel kernel; + auto construct_vertex = kernel.construct_vertex_2_object(); - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); + m_ps = construct_vertex(seg, 0); + m_pt = construct_vertex(seg, 1); - ps = construct_vertex(seg, 0); - pt = construct_vertex(seg, 1); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); - - CGAL_precondition_msg (! is_degen, + CGAL_precondition_msg (! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(seg); - is_vert = kernel.is_vertical_2_object()(seg); + m_l = kernel.construct_line_2_object()(seg); + m_is_vert = kernel.is_vertical_2_object()(seg); } - /*! - * Construct a segment from two end-points. + /*! Construct a segment from two end-points. * \param source The source point. * \param target The target point. * \param The two points must not be equal. */ _Segment_cached_2(const Point_2& source, const Point_2& target) : - ps(source), - pt(target) + m_ps(source), + m_pt(target) { - Kernel kernel; + Kernel kernel; - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(source, target); - is_vert = kernel.is_vertical_2_object()(l); + m_l = kernel.construct_line_2_object()(source, target); + m_is_vert = kernel.is_vertical_2_object()(m_l); } - /*! - * Construct a segment from two end-points on a supporting line. + /*! Construct a segment from two end-points on a supporting line. * \param supp_line The supporting line. * \param source The source point. * \param target The target point. @@ -148,60 +146,56 @@ public: */ _Segment_cached_2(const Line_2& supp_line, const Point_2& source, const Point_2& target) : - l(supp_line), - ps(source), - pt(target) + m_l(supp_line), + m_ps(source), + m_pt(target) { - Kernel kernel; + Kernel kernel; - CGAL_precondition( - Segment_assertions::_assert_is_point_on(source, l, - Has_exact_division()) && - Segment_assertions::_assert_is_point_on(target,l, - Has_exact_division()) - ); + CGAL_precondition + (Segment_assertions::_assert_is_point_on(source, m_l, + Has_exact_division()) && + Segment_assertions::_assert_is_point_on(target, m_l, + Has_exact_division())); - is_vert = kernel.is_vertical_2_object()(l); + m_is_vert = kernel.is_vertical_2_object()(m_l); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); } - /*! - * Assignment operator. + /*! Assignment operator. * \param seg the source segment to copy from * \pre The segment is not degenerate. */ - const _Segment_cached_2& operator= (const Segment_2& seg) + const _Segment_cached_2& operator=(const Segment_2& seg) { - Kernel kernel; + Kernel kernel; + auto construct_vertex = kernel.construct_vertex_2_object(); - typename Kernel_::Construct_vertex_2 - construct_vertex = kernel.construct_vertex_2_object(); + m_ps = construct_vertex(seg, 0); + m_pt = construct_vertex(seg, 1); - ps = construct_vertex(seg, 0); - pt = construct_vertex(seg, 1); + Comparison_result res = kernel.compare_xy_2_object()(m_ps, m_pt); + m_is_degen = (res == EQUAL); + m_is_pt_max = (res == SMALLER); - Comparison_result res = kernel.compare_xy_2_object()(ps, pt); - is_degen = (res == EQUAL); - is_pt_max = (res == SMALLER); - - CGAL_precondition_msg(! is_degen, + CGAL_precondition_msg(! m_is_degen, "Cannot construct a degenerate segment."); - l = kernel.construct_line_2_object()(seg); - is_vert = kernel.is_vertical_2_object()(seg); + m_l = kernel.construct_line_2_object()(seg); + m_is_vert = kernel.is_vertical_2_object()(seg); return (*this); } /*! Obtain the (lexicographically) left endpoint. */ - const Point_2& left() const { return (is_pt_max ? ps : pt); } + const Point_2& left() const { return (m_is_pt_max ? m_ps : m_pt); } /*! Set the (lexicographically) left endpoint. * \param p The point to set. @@ -209,22 +203,19 @@ public: */ void set_left(const Point_2& p) { - CGAL_precondition (! is_degen); - CGAL_precondition_code ( - Kernel kernel; - ); + CGAL_precondition(! m_is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && - kernel.compare_xy_2_object() (p, right()) == SMALLER); + (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) && + (kernel.compare_xy_2_object()(p, right()) == SMALLER)); - if (is_pt_max) ps = p; - else pt = p; + if (m_is_pt_max) m_ps = p; + else m_pt = p; } /*! Obtain the (lexicographically) right endpoint. */ - const Point_2& right() const { return (is_pt_max ? pt : ps); } + const Point_2& right() const { return (m_is_pt_max ? m_pt : m_ps); } /*! Set the (lexicographically) right endpoint. * \param p The point to set. @@ -232,38 +223,35 @@ public: */ void set_right(const Point_2& p) { - CGAL_precondition(! is_degen); - CGAL_precondition_code( - Kernel kernel; - ); + CGAL_precondition(! m_is_degen); + CGAL_precondition_code(Kernel kernel); CGAL_precondition - (Segment_assertions::_assert_is_point_on (p, l, - Has_exact_division()) && - kernel.compare_xy_2_object() (p, left()) == LARGER); + (Segment_assertions::_assert_is_point_on(p, m_l, Has_exact_division()) && + (kernel.compare_xy_2_object()(p, left()) == LARGER)); - if (is_pt_max) pt = p; - else ps = p; + if (m_is_pt_max) m_pt = p; + else m_ps = p; } /*! Obtain the supporting line. */ const Line_2& line() const { - CGAL_precondition(! is_degen); - return (l); + CGAL_precondition(! m_is_degen); + return m_l; } /*! Determine whether the curve is vertical. */ bool is_vertical() const { - CGAL_precondition(! is_degen); - return (is_vert); + CGAL_precondition(! m_is_degen); + return m_is_vert; } /*! Determine whether the curve is directed lexicographic from left to right */ - bool is_directed_right() const { return (is_pt_max); } + bool is_directed_right() const { return (m_is_pt_max); } /*! Determine whether the given point is in the x-range of the segment. * \param p The query point. @@ -271,12 +259,12 @@ public: */ bool is_in_x_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); - const Comparison_result res1 = compare_x(p, left()); + Kernel kernel; + typename Kernel_::Compare_x_2 compare_x = kernel.compare_x_2_object(); + const Comparison_result res1 = compare_x(p, left()); - if (res1 == SMALLER) return (false); - else if (res1 == EQUAL) return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; const Comparison_result res2 = compare_x(p, right()); return (res2 != LARGER); @@ -288,14 +276,14 @@ public: */ bool is_in_y_range(const Point_2& p) const { - Kernel kernel; - typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); - const Comparison_result res1 = compare_y (p, left()); + Kernel kernel; + typename Kernel_::Compare_y_2 compare_y = kernel.compare_y_2_object(); + const Comparison_result res1 = compare_y(p, left()); - if (res1 == SMALLER) return (false); - else if (res1 == EQUAL) return (true); + if (res1 == SMALLER) return false; + else if (res1 == EQUAL) return true; - const Comparison_result res2 = compare_y (p, right()); + const Comparison_result res2 = compare_y(p, right()); return (res2 != LARGER); } }; @@ -329,23 +317,21 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the x-coordinates of two points. + /*! Compare the x-coordinates of two points. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2); * SMALLER if x(p1) < x(p2); * EQUAL if x(p1) = x(p2). */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { const Kernel& kernel = m_traits; - return (kernel.compare_x_2_object()(p1, p2)); } }; - /*! Get a Compare_x_2 functor object. */ + /*! Obtain a Compare_x_2 functor object. */ Compare_x_2 compare_x_2_object() const { return Compare_x_2(*this); } class Compare_xy_2 { @@ -363,8 +349,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare two points lexicographically: by x, then by y. + /*! Compare two points lexicographically: by x, then by y. * \param p1 The first point. * \param p2 The second point. * \return LARGER if x(p1) > x(p2), or if x(p1) = x(p2) and y(p1) > y(p2); @@ -378,13 +363,12 @@ public: } }; - /*! Get a Compare_xy_2 functor object. */ + /*! Obtain a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); } class Construct_min_vertex_2 { public: - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ @@ -392,29 +376,27 @@ public: { return (cv.left()); } }; - /*! Get a Construct_min_vertex_2 functor object. */ + /*! Obtain a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object() const { return Construct_min_vertex_2(); } class Construct_max_vertex_2 { public: - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The right endpoint. */ - const Point_2& operator() (const X_monotone_curve_2& cv) const + const Point_2& operator()(const X_monotone_curve_2& cv) const { return (cv.right()); } }; - /*! Get a Construct_max_vertex_2 functor object. */ + /*! Obtain a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object() const { return Construct_max_vertex_2(); } class Is_vertical_2 { public: - /*! - * Check whether the given x-monotone curve is a vertical segment. + /*! Check whether the given x-monotone curve is a vertical segment. * \param cv The curve. * \return (true) if the curve is a vertical segment; (false) otherwise. */ @@ -422,9 +404,8 @@ public: { return (cv.is_vertical()); } }; - /*! Get an Is_vertical_2 functor object. */ - Is_vertical_2 is_vertical_2_object () const - { return Is_vertical_2(); } + /*! Obtain an Is_vertical_2 functor object. */ + Is_vertical_2 is_vertical_2_object () const { return Is_vertical_2(); } class Compare_y_at_x_2 { protected: @@ -441,8 +422,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Return the location of the given point with respect to the input curve. + /*! Return the location of the given point with respect to the input curve. * \param cv The curve. * \param p The point. * \pre p is in the x-range of cv. @@ -453,27 +433,26 @@ public: Comparison_result operator()(const Point_2& p, const X_monotone_curve_2& cv) const { - CGAL_precondition (cv.is_in_x_range(p)); + CGAL_precondition(cv.is_in_x_range(p)); const Kernel& kernel = m_traits; if (! cv.is_vertical()) { // Compare p with the segment's supporting line. - CGAL_assertion( kernel.compare_x_2_object()(cv.left(), cv.right()) == SMALLER ); + CGAL_assertion_code(auto cmp_x = kernel.compare_x_2_object()); + CGAL_assertion(cmp_x(cv.left(), cv.right()) == SMALLER); return kernel.orientation_2_object()(cv.left(), cv.right(), p); } - else { - // Compare with the vertical segment's end-points. - typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); - Comparison_result res1 = compare_y(p, cv.left()); - Comparison_result res2 = compare_y(p, cv.right()); - return (res1 == res2) ? res1 : EQUAL; - } + // Compare with the vertical segment's end-points. + typename Kernel::Compare_y_2 compare_y = kernel.compare_y_2_object(); + Comparison_result res1 = compare_y(p, cv.left()); + Comparison_result res2 = compare_y(p, cv.right()); + return (res1 == res2) ? res1 : EQUAL; } }; - /*! Get a Compare_y_at_x_2 functor object. */ + /*! Obtain a Compare_y_at_x_2 functor object. */ Compare_y_at_x_2 compare_y_at_x_2_object() const { return Compare_y_at_x_2(*this); } @@ -492,8 +471,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the y value of two x-monotone curves immediately to the left + /*! Compare the y value of two x-monotone curves immediately to the left * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -511,14 +489,10 @@ public: // Make sure that p lies on both curves, and that both are defined to its // left (so their left endpoint is lexicographically smaller than p). - CGAL_precondition_code( - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && - (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && + (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); CGAL_precondition(compare_xy(cv1.left(), p) == SMALLER && compare_xy(cv2.left(), p) == SMALLER); @@ -532,8 +506,8 @@ public: } }; - /*! Get a Compare_y_at_x_left_2 functor object. */ - Compare_y_at_x_left_2 compare_y_at_x_left_2_object () const + /*! Obtain a Compare_y_at_x_left_2 functor object. */ + Compare_y_at_x_left_2 compare_y_at_x_left_2_object() const { return Compare_y_at_x_left_2(*this); } class Compare_y_at_x_right_2 { @@ -551,8 +525,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Compare the y value of two x-monotone curves immediately to the right + /*! Compare the y value of two x-monotone curves immediately to the right * of their intersection point. * \param cv1 The first curve. * \param cv2 The second curve. @@ -570,14 +543,10 @@ public: // Make sure that p lies on both curves, and that both are defined to its // right (so their right endpoint is lexicographically larger than p). - CGAL_precondition_code ( - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && - (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv1) == EQUAL) && + (m_traits.compare_y_at_x_2_object()(p, cv2) == EQUAL)); CGAL_precondition(compare_xy(cv1.right(), p) == LARGER && compare_xy(cv2.right(), p) == LARGER); @@ -589,7 +558,7 @@ public: } }; - /*! Get a Compare_y_at_x_right_2 functor object. */ + /*! Obtain a Compare_y_at_x_right_2 functor object. */ Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const { return Compare_y_at_x_right_2(*this); } @@ -608,8 +577,8 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Check if the two x-monotone curves are the same (have the same graph). + /*! Check whether the two x-monotone curves are the same (have the same + * graph). * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are the same; (false) otherwise. @@ -629,14 +598,14 @@ public: * \param p2 The second point. * \return (true) if the two point are the same; (false) otherwise. */ - bool operator() (const Point_2& p1, const Point_2& p2) const + bool operator()(const Point_2& p1, const Point_2& p2) const { const Kernel& kernel = m_traits; return (kernel.equal_2_object()(p1, p2)); } }; - /*! Get an Equal_2 functor object. */ + /*! Obtain an Equal_2 functor object. */ Equal_2 equal_2_object() const { return Equal_2(*this); } //@} @@ -645,25 +614,23 @@ public: class Make_x_monotone_2 { public: - /*! - * Cut the given curve into x-monotone subcurves and insert them into the + /*! 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. * \param cv The curve. - * \param oi The output iterator, whose value-type is Object. + * \param oi The output iterator, whose value-type is variant<.... * \return The past-the-end iterator. */ - template + template OutputIterator operator()(const Curve_2& cv, OutputIterator oi) const { // Wrap the segment with an object. - *oi = make_object (cv); - ++oi; - return (oi); + *oi++ = make_object(cv); + return oi; } }; - /*! Get a Make_x_monotone_2 functor object. */ + /*! Obtain a Make_x_monotone_2 functor object. */ Make_x_monotone_2 make_x_monotone_2_object() const { return Make_x_monotone_2(); } @@ -682,8 +649,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + /*! Split a given x-monotone curve at a given point into two sub-curves. * \param cv The curve to split * \param p The split point. * \param c1 Output: The left resulting subcurve (p is its right endpoint). @@ -694,28 +660,24 @@ public: X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { // Make sure that p lies on the interior of the curve. - CGAL_precondition_code ( - const Kernel& kernel = m_traits; - typename Kernel::Compare_xy_2 compare_xy = - kernel.compare_xy_2_object(); - ); + CGAL_precondition_code(const Kernel& kernel = m_traits; + auto compare_xy = kernel.compare_xy_2_object()); - CGAL_precondition( - (m_traits.compare_y_at_x_2_object()(p, cv) == EQUAL) && - compare_xy(cv.left(), p) == SMALLER && - compare_xy(cv.right(), p) == LARGER); + CGAL_precondition((m_traits.compare_y_at_x_2_object()(p, cv) == EQUAL) && + compare_xy(cv.left(), p) == SMALLER && + compare_xy(cv.right(), p) == LARGER); // Perform the split. c1 = cv; - c1.set_right (p); + c1.set_right(p); c2 = cv; - c2.set_left (p); + c2.set_left(p); } }; - /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const { return Split_2(*this); } + /*! Obtain a Split_2 functor object. */ + Split_2 split_2_object() const { return Split_2(*this); } class Intersect_2 { protected: @@ -732,8 +694,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Find the intersections of the two given curves and insert them into the + /*! Find the intersections of the two given curves and insert them into the * given output iterator. As two segments may intersect only once, only a * single intersection will be contained in the iterator. * \param cv1 The first curve. @@ -741,93 +702,90 @@ public: * \param oi The output iterator. * \return The past-the-end iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + // Intersect the two supporting lines. const Kernel& kernel = m_traits; - CGAL::Object obj = kernel.intersect_2_object()(cv1.line(), cv2.line()); + auto res = kernel.intersect_2_object()(cv1.line(), cv2.line()); - if (obj.is_empty()) { - // The supporting line are parallel lines and do not intersect: - return (oi); - } + // The supporting line are parallel lines and do not intersect: + if (! res) return oi; // Check if we have a single intersection point. - const Point_2 *ip = object_cast (&obj); - + const Point_2* ip = boost::get(&*res); if (ip != nullptr) { // Check if the intersection point ip lies on both segments. - const bool ip_on_cv1 = cv1.is_vertical() ? cv1.is_in_y_range(*ip) : - cv1.is_in_x_range(*ip); + const bool ip_on_cv1 = cv1.is_vertical() ? + cv1.is_in_y_range(*ip) : cv1.is_in_x_range(*ip); if (ip_on_cv1) { - const bool ip_on_cv2 = cv2.is_vertical() ? cv2.is_in_y_range(*ip) : - cv2.is_in_x_range(*ip); + const bool ip_on_cv2 = cv2.is_vertical() ? + cv2.is_in_y_range(*ip) : cv2.is_in_x_range(*ip); if (ip_on_cv2) { // Create a pair representing the point with its multiplicity, // which is always 1 for line segments. - std::pair ip_mult (*ip, 1); - *oi = make_object (ip_mult); - oi++; + Intersection_point ip_mult(*ip, 1); + *oi++ = Intersection_result(ip_mult); } } - return (oi); + return oi; } // In this case, the two supporting lines overlap. // The overlapping segment is therefore [p_l,p_r], where p_l is the // rightmost of the two left endpoints and p_r is the leftmost of the // two right endpoints. - typename Kernel::Compare_xy_2 compare_xy = kernel.compare_xy_2_object(); - Point_2 p_l, p_r; - - if (compare_xy (cv1.left(), cv2.left()) == SMALLER) p_l = cv2.left(); - else p_l = cv1.left(); - - if (compare_xy (cv1.right(), cv2.right()) == SMALLER) p_r = cv1.right(); - else p_r = cv2.right(); + auto compare_xy = kernel.compare_xy_2_object(); + Point_2 p_l = (compare_xy(cv1.left(), cv2.left()) == SMALLER) ? + cv2.left() : cv1.left(); + Point_2 p_r = (compare_xy(cv1.right(), cv2.right()) == SMALLER) ? + cv1.right() : cv2.right(); // Examine the resulting segment. - const Comparison_result res = compare_xy (p_l, p_r); + const Comparison_result cmp_res = compare_xy(p_l, p_r); - if (res == SMALLER) { + if (cmp_res == SMALLER) { // We have discovered an overlapping segment: if (cv1.is_directed_right() == cv2.is_directed_right()) { // cv1 and cv2 have the same directions, maintain this direction // in the overlap segment if (cv1.is_directed_right()) { - X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); - *oi++ = make_object(overlap_seg); - } - else { - X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l); - *oi++ = make_object(overlap_seg); + X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + *oi++ = Intersection_result(overlap_seg); + return oi; } + X_monotone_curve_2 overlap_seg(cv1.line(), p_r, p_l); + *oi++ = Intersection_result(overlap_seg); + return oi; } - else { - // cv1 and cv2 have opposite directions, the overlap segment - // will be directed from left to right - X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); - *oi++ = make_object(overlap_seg); - } + // cv1 and cv2 have opposite directions, the overlap segment + // will be directed from left to right + X_monotone_curve_2 overlap_seg(cv1.line(), p_l, p_r); + *oi++ = Intersection_result(overlap_seg); + return oi; } - else if (res == EQUAL) { + if (cmp_res == EQUAL) { // The two segment have the same supporting line, but they just share // a common endpoint. Thus we have an intersection point, but we leave // the multiplicity of this point undefined. - std::pair ip_mult(p_r, 0); - *oi++ = make_object(ip_mult); + Intersection_point ip_mult(p_r, 0); + *oi++ = Intersection_result(ip_mult); + return oi; } - return (oi); + return oi; } }; - /*! Get an Intersect_2 functor object. */ + /*! Obtain an Intersect_2 functor object. */ Intersect_2 intersect_2_object() const { return Intersect_2(*this); } class Are_mergeable_2 { @@ -845,8 +803,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Check whether it is possible to merge two given x-monotone curves. + /*! Check whether it is possible to merge two given x-monotone curves. * \param cv1 The first curve. * \param cv2 The second curve. * \return (true) if the two curves are mergeable, that is, if they are @@ -856,20 +813,20 @@ public: bool operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2) const { - if (!m_traits.equal_2_object()(cv1.right(), cv2.left()) && - !m_traits.equal_2_object()(cv2.right(), cv1.left())) + const Kernel& kernel = m_traits; + typename Kernel::Equal_2 equal = kernel.equal_2_object(); + if (! equal(cv1.right(), cv2.left()) && + ! equal(cv2.right(), cv1.left())) return false; // Check whether the two curves have the same supporting line. - const Kernel& kernel = m_traits; - typename Kernel::Equal_2 equal = kernel.equal_2_object(); return (equal(cv1.line(), cv2.line()) || equal(cv1.line(), kernel.construct_opposite_line_2_object()(cv2.line()))); } }; - /*! Get an Are_mergeable_2 functor object. */ + /*! Obtain an Are_mergeable_2 functor object. */ Are_mergeable_2 are_mergeable_2_object() const { return Are_mergeable_2(*this); } @@ -891,8 +848,7 @@ public: friend class Arr_segment_traits_2; public: - /*! - * Merge two given x-monotone curves into a single curve (segment). + /*! Merge two given x-monotone curves into a single curve (segment). * \param cv1 The first curve. * \param cv2 The second curve. * \param c Output: The merged curve. @@ -904,25 +860,26 @@ public: { CGAL_precondition(m_traits.are_mergeable_2_object()(cv1, cv2)); - Equal_2 equal = m_traits.equal_2_object(); + const Kernel& kernel = m_traits; + auto equal = kernel.equal_2_object(); // Check which curve extends to the right of the other. if (equal(cv1.right(), cv2.left())) { // cv2 extends cv1 to the right. c = cv1; c.set_right(cv2.right()); + return; } - else { - CGAL_precondition(equal(cv2.right(), cv1.left())); - // cv1 extends cv2 to the right. - c = cv2; - c.set_right(cv1.right()); - } + CGAL_precondition(equal(cv2.right(), cv1.left())); + + // cv1 extends cv2 to the right. + c = cv2; + c.set_right(cv1.right()); } }; - /*! Get a Merge_2 functor object. */ + /*! Obtain a Merge_2 functor object. */ Merge_2 merge_2_object() const { return Merge_2(*this); } //@} @@ -932,8 +889,7 @@ public: class Approximate_2 { public: - /*! - * Return an approximation of a point coordinate. + /*! Obtain an approximation of a point coordinate. * \param p The exact point. * \param i The coordinate index (either 0 or 1). * \pre i is either 0 or 1. @@ -947,13 +903,12 @@ public: } }; - /*! Get an Approximate_2 functor object. */ + /*! Obtain an Approximate_2 functor object. */ Approximate_2 approximate_2_object() const { return Approximate_2(); } class Construct_x_monotone_curve_2 { public: - /*! - * Return an x-monotone curve connecting the two given endpoints. + /*! Obtain an x-monotone curve connecting the two given endpoints. * \param p The first point. * \param q The second point. * \pre p and q must not be the same. @@ -963,7 +918,7 @@ public: { return (X_monotone_curve_2(p, q)); } }; - /*! Get a Construct_x_monotone_curve_2 functor object. */ + /*! Obtain a Construct_x_monotone_curve_2 functor object. */ Construct_x_monotone_curve_2 construct_x_monotone_curve_2_object() const { return Construct_x_monotone_curve_2(); } //@} @@ -1011,41 +966,37 @@ public: // exchange src and tgt IF they do not conform with the direction X_monotone_curve_2 trimmed_segment; - if (xcv.is_directed_right() && compare_x_2(src, tgt) == LARGER) trimmed_segment = X_monotone_curve_2(tgt, src); - else if (!xcv.is_directed_right() && compare_x_2(src, tgt) == SMALLER ) + else if (! xcv.is_directed_right() && (compare_x_2(src, tgt) == SMALLER)) trimmed_segment = X_monotone_curve_2(tgt, src); else trimmed_segment = X_monotone_curve_2(src, tgt); - return (trimmed_segment); + return trimmed_segment; } }; - //get a Trim_2 functor object + /*! Obtain a Trim_2 functor object */ Trim_2 trim_2_object() const { return Trim_2(*this); } - class Compare_endpoints_xy_2 - { + class Compare_endpoints_xy_2 { public: - /*! - * Compare the endpoints of an $x$-monotone curve lexicographically. + /*! Compare the endpoints of an $x$-monotone curve lexicographically. * (assuming the curve has a designated source and target points). * \param cv The curve. * \return SMALLER if the curve is directed right; * LARGER if the curve is directed left. */ - Comparison_result operator() (const X_monotone_curve_2& cv) const + Comparison_result operator()(const X_monotone_curve_2& cv) const { return (cv.is_directed_right()) ? (SMALLER) : (LARGER); } }; - /*! Get a Compare_endpoints_xy_2 functor object. */ + /*! Obtain a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const { return Compare_endpoints_xy_2(); } class Construct_opposite_2 { public: - /*! - * Construct an opposite x-monotone (with swapped source and target). + /*! Construct an opposite x-monotone (with swapped source and target). * \param cv The curve. * \return The opposite curve. */ @@ -1053,17 +1004,16 @@ public: { return (cv.flip()); } }; - /*! Get a Construct_opposite_2 functor object. */ + /*! Obtain a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const { return Construct_opposite_2(); } //@} }; -/*! - * \class A representation of a segment, as used by the Arr_segment_traits_2 +/*! \class A representation of a segment, as used by the Arr_segment_traits_2 * traits-class. */ -template +template class Arr_segment_2 : public Arr_segment_traits_2::_Segment_cached_2 { @@ -1089,7 +1039,7 @@ public: * \pre The two points are not the same. */ Arr_segment_2(const Point_2& source, const Point_2& target) : - Base(source,target) + Base(source, target) {} /*! Construct a segment from a line and two end-points. @@ -1101,7 +1051,7 @@ public: */ Arr_segment_2(const Line_2& line, const Point_2& source, const Point_2& target) : - Base(line,source,target) + Base(line,source, target) {} /*! Cast to a segment. @@ -1109,8 +1059,8 @@ public: operator Segment_2() const { Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); - return (seg); + Segment_2 seg = kernel.construct_segment_2_object()(this->m_ps, this->m_pt); + return seg; } /*! Create a bounding box for the segment. @@ -1118,37 +1068,37 @@ public: Bbox_2 bbox() const { Kernel kernel; - Segment_2 seg = kernel.construct_segment_2_object()(this->ps, this->pt); - return (kernel.construct_bbox_2_object() (seg)); + Segment_2 seg = kernel.construct_segment_2_object()(this->m_ps, this->m_pt); + return (kernel.construct_bbox_2_object()(seg)); } /*! Obtain the segment source. */ - const Point_2& source() const { return (this->ps); } + const Point_2& source() const { return (this->m_ps); } /*! Obtain the segment target. */ - const Point_2& target() const { return (this->pt); } + const Point_2& target() const { return (this->m_pt); } /*! Flip the segment (swap its source and target). */ Arr_segment_2 flip() const { - Arr_segment_2 opp; - opp.l = this->l; - opp.ps = this->pt; - opp.pt = this->ps; - opp.is_pt_max = !(this->is_pt_max); - opp.is_vert = this->is_vert; - opp.is_degen = this->is_degen; + Arr_segment_2 opp; + opp.m_l = this->m_l; + opp.m_ps = this->m_pt; + opp.m_pt = this->m_ps; + opp.m_is_pt_max = !(this->m_is_pt_max); + opp.m_is_vert = this->m_is_vert; + opp.m_is_degen = this->m_is_degen; - return (opp); + return opp; } }; /*! Exporter for the segment class used by the traits-class. */ -template +template OutputStream& operator<<(OutputStream& os, const Arr_segment_2& seg) { os << static_cast(seg); @@ -1157,13 +1107,13 @@ OutputStream& operator<<(OutputStream& os, const Arr_segment_2& seg) /*! Importer for the segment class used by the traits-class. */ -template +template InputStream& operator>>(InputStream& is, Arr_segment_2& seg) { typename Kernel::Segment_2 kernel_seg; is >> kernel_seg; seg = kernel_seg; - return (is); + return is; } } //namespace CGAL 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 532b2bf4dbd..5847dd43e02 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 @@ -7,7 +7,7 @@ // $Id$ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // -// Author(s) : Efi Fogel +// Author(s): Efi Fogel #ifndef CGAL_ARR_TRACING_TRAITS_H #define CGAL_ARR_TRACING_TRAITS_H @@ -26,6 +26,8 @@ #include #include +#include + #include #include #include @@ -592,7 +594,7 @@ public: public: /*! Construct */ - Intersect_2(const Base * base, bool enabled = true) : + Intersect_2(const Base* base, bool enabled = true) : m_object(base->intersect_2_object()), m_enabled(enabled) {} /*! Operate @@ -604,37 +606,41 @@ public: * multiplicity * \return the output iterator */ - template + template OutputIterator operator()(const X_monotone_curve_2 & xcv1, const X_monotone_curve_2 & xcv2, OutputIterator oi) const { - if (!m_enabled) return m_object(xcv1, xcv2, oi); + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + if (! m_enabled) return m_object(xcv1, xcv2, oi); + std::cout << "intersect" << std::endl << " xcv1: " << xcv1 << std::endl << " xcv2: " << xcv2 << std::endl; - std::list container; + std::list container; m_object(xcv1, xcv2, 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; + for (const auto& item : container) { + const X_monotone_curve_2* xcv = boost::get(&item); + if (xcv != nullptr) { + std::cout << " result[" << i++ << "]: xcv: " << *xcv << std::endl; continue; } - std::pair point_pair; - if (assign (point_pair, *it)) { - std::cout << " result[" << i++ << "]: p: " << point_pair.first - << ", multiplicity: " << point_pair.second << std::endl; + const Intersection_point* ip = boost::get(&item); + if (ip != nullptr) { + std::cout << " result[" << i++ << "]: p: " << ip->first + << ", multiplicity: " << ip->second << std::endl; continue; } } - 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; } 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 aa0532cde12..b3d8c63f5b2 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 @@ -132,8 +132,8 @@ void Arrangement_zone_2::compute_zone() // In this case m_cv overlaps the curve associated with m_intersect_he. // Compute the overlapping subcurve. bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -148,8 +148,8 @@ void Arrangement_zone_2::compute_zone() m_intersect_he = m_arr.non_const_handle(*hh); bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -207,8 +207,8 @@ void Arrangement_zone_2::compute_zone() // In this case m_cv overlaps the curve associated with m_intersect_he. // Compute the overlapping subcurve to the right of curr_v. bool dummy; - m_obj = _compute_next_intersection(m_intersect_he, false, dummy); - m_overlap_cv = object_cast(m_obj); + auto obj = _compute_next_intersection(m_intersect_he, false, dummy); + m_overlap_cv = boost::get(*obj); // Remove the overlap from the map. _remove_next_intersection(m_intersect_he); @@ -800,7 +800,7 @@ _direct_intersecting_edge_to_left(const X_monotone_curve_2& cv_ins, // Get the next intersection of cv with the given halfedge. // template -CGAL::Object +typename Arrangement_zone_2::Optional_intersection Arrangement_zone_2:: _compute_next_intersection(Halfedge_handle he, bool skip_first_point, @@ -811,7 +811,7 @@ _compute_next_intersection(Halfedge_handle he, // Try to locate the intersections with this curve in the intersections map. Intersect_map_iterator iter = m_inter_map.find(p_curve); - const Intersect_point_2* ip; + const Intersection_point* ip; const X_monotone_curve_2* icv; bool valid_intersection; @@ -821,13 +821,13 @@ _compute_next_intersection(Halfedge_handle he, // Retrieve the intersections list from the map. Intersect_list& inter_list = iter->second; - if (inter_list.empty()) return CGAL::Object(); + if (inter_list.empty()) return Optional_intersection(); // Locate the first intersection that lies to the right of m_left_pt // (if the left point exists). while (! inter_list.empty()) { // Compare that current object with m_left_pt (if exists). - ip = object_cast(&(inter_list.front())); + ip = boost::get(&(inter_list.front())); if (m_left_on_boundary) { // The left end lie on the left boundary, so all intersections are @@ -851,7 +851,7 @@ _compute_next_intersection(Halfedge_handle he, } else { // We have an overlapping subcurve. - icv = object_cast(&(inter_list.front())); + icv = boost::get(&(inter_list.front())); CGAL_assertion(icv != nullptr); if (m_geom_traits->is_closed_2_object()(*icv, ARR_MIN_END)) { @@ -869,14 +869,14 @@ _compute_next_intersection(Halfedge_handle he, } // Found an intersection to m_left_pt's right. - if (valid_intersection) return (inter_list.front()); + if (valid_intersection) return Optional_intersection(inter_list.front()); // Discard the current intersection, which lies to m_left_pt's left. inter_list.pop_front(); } // If we reached here, the list of intersections is empty: - return CGAL::Object(); + return Optional_intersection(); } // The intersections with the curve have not been computed yet, so we @@ -894,7 +894,7 @@ _compute_next_intersection(Halfedge_handle he, // Discard all intersection lying to the left of m_left_pt (if exists). while (! inter_list.empty()) { // Compare that current object with m_left_pt (if exists). - ip = object_cast(&(inter_list.front())); + ip = boost::get(&(inter_list.front())); if (ip != nullptr) { // We have a simple intersection point - if we don't have to skip it, @@ -920,7 +920,7 @@ _compute_next_intersection(Halfedge_handle he, } else { // We have an overlapping subcurve. - icv = object_cast(&(inter_list.front())); + icv = boost::get(&(inter_list.front())); CGAL_assertion(icv != nullptr); if (m_geom_traits->is_closed_2_object()(*icv, ARR_MIN_END)) { @@ -947,8 +947,8 @@ _compute_next_intersection(Halfedge_handle he, m_inter_map[p_curve] = inter_list; // Return the first intersection object computed (may be empty). - if (inter_list.empty()) return CGAL::Object(); - else return (inter_list.front()); + if (inter_list.empty()) return Optional_intersection(); + else return Optional_intersection(inter_list.front()); } //----------------------------------------------------------------------------- @@ -1105,14 +1105,14 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary, // Compute the next intersection of m_cv and the current halfedge. bool intersection_on_right_boundary; - CGAL::Object iobj = + Optional_intersection iobj = _compute_next_intersection(he_curr, left_equals_curr_endpoint, intersection_on_right_boundary); - if (! iobj.is_empty()) { + if (iobj) { // We have found an intersection (either a simple point or an // overlapping x-monotone curve). - const Intersect_point_2* int_p = object_cast(&iobj); + const Intersection_point* int_p = boost::get(&*iobj); if (int_p != nullptr) { Point_2 ip = int_p->first; @@ -1134,7 +1134,7 @@ _leftmost_intersection(Ccb_halfedge_circulator he_curr, bool on_boundary, else { // We have located an overlapping curve. Assign ip as its left // endpoint. - const X_monotone_curve_2* icv = object_cast(&iobj); + const X_monotone_curve_2* icv = boost::get(&*iobj); CGAL_assertion(icv != nullptr); Point_2 ip = min_vertex(*icv); 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 b3d39acaf46..55616307cd0 100644 --- a/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Arrangement_zone_2.h @@ -93,22 +93,25 @@ protected: Right_side_category>::result Are_all_sides_oblivious_category; - 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::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::Ccb_halfedge_circulator Ccb_halfedge_circulator; // Types used for caching intersection points: - typedef std::pair Intersect_point_2; - typedef std::list Intersect_list; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::optional Optional_intersection; + typedef std::list Intersect_list; typedef std::map - Intersect_map; - typedef typename Intersect_map::iterator Intersect_map_iterator; + Intersect_map; + typedef typename Intersect_map::iterator Intersect_map_iterator; - typedef std::set Curves_set; - typedef typename Curves_set::iterator Curves_set_iterator; + typedef std::set Curves_set; + typedef typename Curves_set::iterator Curves_set_iterator; // Data members: Arrangement_2& m_arr; // The associated arrangement. @@ -378,14 +381,15 @@ private: * point coincides with the right * curve-end, which lies on the * surface boundary. - * \return An object representing the next intersection: Intersect_point_2 + * \return An object representing the next intersection: Intersection_point * in case of a simple intersection point, X_monotone_curve_2 in * case of an overlap, and an empty object if there is no * intersection. */ - CGAL::Object _compute_next_intersection(Halfedge_handle he, - bool skip_first_point, - bool& intersect_on_right_boundary); + Optional_intersection + _compute_next_intersection(Halfedge_handle he, + bool skip_first_point, + bool& intersect_on_right_boundary); /*! Remove the next intersection of m_cv with the given halfedge from the map. * \param he A handle to the halfedge. 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 adb833f663a..de6f2e14529 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 @@ -1459,29 +1459,24 @@ public: 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 << ""); // if arcs overlap, just store their common part, otherwise compute // point-wise intersections - std::vector< Arc_2 > common_arcs; - if (cv1._trim_if_overlapped(cv2, std::back_inserter(common_arcs))) { - typename std::vector< Arc_2 >::const_iterator it; - for(it = common_arcs.begin(); it < common_arcs.end(); it++) { - *oi++ = CGAL::make_object(*it); - } + std::vector arcs; + if (cv1._trim_if_overlapped(cv2, std::back_inserter(arcs))) { + for (const auto& item : arcs) *oi++ = Intersection_result(item); return oi; } // process non-ov erlapping case - typedef std::pair< Point_2, unsigned int > Point_and_mult; - typedef std::vector< Point_and_mult > Point_vector; - Point_vector vec; - typename Point_vector::const_iterator it; + std::vector vec; Arc_2::_intersection_points(cv1, cv2, std::back_inserter(vec)); - - for (it = vec.begin(); it != vec.end(); it++) { - *oi++ = CGAL::make_object(*it); - } + for (const auto& item : vec) *oi++ = Intersection_result(item); return oi; } diff --git a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h index ba2e709c6cf..73d7f3b0326 100644 --- a/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h +++ b/Arrangement_on_surface_2/include/CGAL/Surface_sweep_2/Arr_insertion_traits_2.h @@ -80,17 +80,13 @@ public: protected: //! The base operators. Base_intersect_2 m_base_intersect; - Halfedge_handle invalid_he; /*! Constructor. * The constructor is declared private to allow only the functor * obtaining function, which is a member of the nesting class, * constructing it. */ - Intersect_2(const Base_intersect_2& base) : - m_base_intersect (base), - invalid_he() - {} + Intersect_2(const Base_intersect_2& base) : m_base_intersect (base) {} //! Allow its functor obtaining function calling the private constructor. friend class Arr_insertion_traits_2; @@ -101,6 +97,14 @@ public: const X_monotone_curve_2& cv2, OutputIterator oi) { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef boost::variant + Intersection_base_result; + + Halfedge_handle invalid_he; + if ((cv1.halfedge_handle() != invalid_he) && (cv2.halfedge_handle() != invalid_he) && (cv1.halfedge_handle() != cv2.halfedge_handle())) @@ -110,40 +114,32 @@ public: return oi; } - OutputIterator oi_end = m_base_intersect(cv1.base(), cv2.base(), oi); - const Base_x_monotone_curve_2* base_overlap_cv; - const std::pair* intersect_p; - + std::vector xections; + m_base_intersect(cv1.base(), cv2.base(), std::back_inserter(xections)); // convert objects that are associated with Base_x_monotone_curve_2 to // X_monotone_curve_2 - for(; oi != oi_end; ++oi) { - base_overlap_cv = object_cast(&(*oi)); - if (base_overlap_cv != nullptr) { - // Add halfedge handles to the resulting curve. - Halfedge_handle he; - - if (cv1.halfedge_handle() != invalid_he) he = cv1.halfedge_handle(); - else if (cv2.halfedge_handle() != invalid_he) - he = cv2.halfedge_handle(); - - X_monotone_curve_2 overlap_cv (*base_overlap_cv, he); - - overlap_cv.set_overlapping(); - *oi = make_object (overlap_cv); + for (const auto& xection : xections) { + const Intersection_point* + p_p = boost::get(&xection); + if (p_p != nullptr) { + *oi++ = Intersection_result(xection); + continue; } - else { - intersect_p = - object_cast >(&(*oi)); + const Base_x_monotone_curve_2* base_cv_p = + boost::get(&xection); + CGAL_assertion(base_cv_p); - CGAL_assertion (intersect_p != nullptr); - - *oi = make_object(std::make_pair(Point_2(intersect_p->first), - intersect_p->second)); - } + // Add halfedge handles to the resulting curve. + Halfedge_handle he; + if (cv1.halfedge_handle() != invalid_he) he = cv1.halfedge_handle(); + else if (cv2.halfedge_handle() != invalid_he) + he = cv2.halfedge_handle(); + X_monotone_curve_2 cv(*base_cv_p, he); + cv.set_overlapping(); + *oi++ = Intersection_result(cv); } - - // Return a past-the-end iterator. - return oi_end; + xections.clear(); + return oi; } }; 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 8f6275e441d..c94ecf40913 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 @@ -345,24 +345,31 @@ public: class Intersect_2 { protected: //! The base traits. - const Arr_overlay_traits_2* m_traits; + const Arr_overlay_traits_2& m_traits; /*! Constructor. * The constructor is declared protected to allow only the functor * obtaining function, which is a member of the nesting class, * constructing it. */ - Intersect_2(const Arr_overlay_traits_2* traits) : m_traits(traits) {} + Intersect_2(const Arr_overlay_traits_2& traits) : m_traits(traits) {} //! Allow its functor obtaining function calling the protected constructor. friend class Arr_overlay_traits_2; public: - template + template OutputIterator operator()(const X_monotone_curve_2& xcv1, const X_monotone_curve_2& xcv2, OutputIterator oi) { + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef std::pair Intersection_base_point; + typedef boost::variant + Intersection_base_result; + // In case the curves originate from the same arrangement, they are // obviously interior-disjoint. if (xcv1.color() == xcv2.color()) return oi; @@ -396,19 +403,16 @@ public: // Note that we do not bother with curves whose left ends are open, // since such curved did not intersect before. - const std::pair* base_ipt; - const Base_x_monotone_curve_2* overlap_xcv; bool send_xcv1_first = true; - OutputIterator oi_end; - Parameter_space_in_x_2 ps_x_op = m_traits->parameter_space_in_x_2_object(); - Parameter_space_in_y_2 ps_y_op = m_traits->parameter_space_in_y_2_object(); - const Arr_parameter_space bx1 = ps_x_op(xcv1, ARR_MIN_END); - const Arr_parameter_space by1 = ps_y_op(xcv1, ARR_MIN_END); - const Arr_parameter_space bx2 = ps_x_op(xcv2, ARR_MIN_END); - const Arr_parameter_space by2 = ps_y_op(xcv2, ARR_MIN_END); + auto ps_x_op = m_traits.parameter_space_in_x_2_object(); + auto ps_y_op = m_traits.parameter_space_in_y_2_object(); + Arr_parameter_space bx1 = ps_x_op(xcv1, ARR_MIN_END); + Arr_parameter_space by1 = ps_y_op(xcv1, ARR_MIN_END); + Arr_parameter_space bx2 = ps_x_op(xcv2, ARR_MIN_END); + Arr_parameter_space by2 = ps_y_op(xcv2, ARR_MIN_END); - const Gt2* m_base_tr = m_traits->base_traits(); + const Gt2* m_base_tr = m_traits.base_traits(); if ((bx1 == ARR_INTERIOR) && (by1 == ARR_INTERIOR) && (bx2 == ARR_INTERIOR) && (by2 == ARR_INTERIOR)) @@ -419,15 +423,17 @@ public: m_base_tr->construct_min_vertex_2_object()(xcv2.base())) == LARGER); } - oi_end = (send_xcv1_first) ? - m_base_tr->intersect_2_object()(xcv1.base(), xcv2.base(), oi) : - m_base_tr->intersect_2_object()(xcv2.base(), xcv1.base(), oi); + auto intersector = m_base_tr->intersect_2_object(); + std::vector xections; + (send_xcv1_first) ? + intersector(xcv1.base(), xcv2.base(), std::back_inserter(xections)) : + intersector(xcv2.base(), xcv1.base(), std::back_inserter(xections)); // Convert objects that are associated with Base_x_monotone_curve_2 to // the exteneded X_monotone_curve_2. - while (oi != oi_end) { - base_ipt = object_cast >(&(*oi)); - + for (const auto& xection : xections) { + const Intersection_base_point* base_ipt = + boost::get(&xection); if (base_ipt != nullptr) { // We have a red-blue intersection point, so we attach the // intersecting red and blue halfedges to it. @@ -451,42 +457,44 @@ public: // Create the extended point and add the multiplicity. Point_2 ex_point(base_ipt->first, red_cell, blue_cell); - *oi++ = CGAL::make_object(std::make_pair(ex_point, base_ipt->second)); + *oi++ = + Intersection_result(std::make_pair(ex_point, base_ipt->second)); + continue; + } + + const Base_x_monotone_curve_2* overlap_xcv = + boost::get(&xection); + CGAL_assertion(overlap_xcv != nullptr); + + // We have a red-blue overlap, so we mark the curve accordingly. + Halfedge_handle_red red_he; + Halfedge_handle_blue blue_he; + + if (xcv1.color() == RED) { + red_he = xcv1.red_halfedge_handle(); + + // Overlap can occur only between curves from a different color. + CGAL_assertion(xcv2.color() == BLUE); + blue_he = xcv2.blue_halfedge_handle(); } else { - overlap_xcv = object_cast(&(*oi)); - CGAL_assertion(overlap_xcv != nullptr); + CGAL_assertion((xcv1.color() == BLUE) && (xcv2.color() == RED)); - // We have a red-blue overlap, so we mark the curve accordingly. - Halfedge_handle_red red_he; - Halfedge_handle_blue blue_he; - - if (xcv1.color() == RED) { - red_he = xcv1.red_halfedge_handle(); - - // Overlap can occur only between curves from a different color. - CGAL_assertion(xcv2.color() == BLUE); - blue_he = xcv2.blue_halfedge_handle(); - } - else { - CGAL_assertion((xcv1.color() == BLUE) && (xcv2.color() == RED)); - - red_he = xcv2.red_halfedge_handle(); - blue_he = xcv1.blue_halfedge_handle(); - } - - *oi++ = CGAL::make_object(X_monotone_curve_2(*overlap_xcv, - red_he, blue_he)); + red_he = xcv2.red_halfedge_handle(); + blue_he = xcv1.blue_halfedge_handle(); } + + X_monotone_curve_2 cv(*overlap_xcv, red_he, blue_he); + *oi++ = Intersection_result(cv); } // Return the past-the-end iterator. - return oi_end; + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const { return Intersect_2(this); } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } /*! A functor that splits an arc at a point. */ class Split_2 { 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 b69443c205d..a519c90b1e1 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 @@ -17,6 +17,7 @@ #include #include #include + #include "Traits_base_test.h" /*! Traits test */ @@ -989,18 +990,22 @@ intersect_wrapper(std::istringstream& str_stream) typedef typename Traits::X_monotone_curve_2 X_monotone_curve_2; typedef typename Traits::Multiplicity Multiplicity; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + unsigned int id1, id2; str_stream >> id1 >> id2; - std::vector object_vec; + std::vector xections; this->m_geom_traits.intersect_2_object()(this->m_xcurves[id1], this->m_xcurves[id2], - std::back_inserter(object_vec)); + std::back_inserter(xections)); std::cout << "Test: intersect( " << this->m_xcurves[id1] << "," << this->m_xcurves[id2] << " ) ? "; size_t num; str_stream >> num; - if (!this->compare(num, object_vec.size(), "size")) return false; + if (! this->compare(num, xections.size(), "size")) return false; for (size_t i = 0; i < num; ++i) { unsigned int type; // 0 - point, 1 - x-monotone curve @@ -1011,30 +1016,25 @@ intersect_wrapper(std::istringstream& str_stream) if (type == 0) str_stream >> multiplicity; unsigned int exp_type = 1; - const X_monotone_curve_2 * xcv_ptr = - CGAL::object_cast (&(object_vec[i])); + const X_monotone_curve_2* cv_p = + boost::get(&(xections[i])); - if (xcv_ptr != NULL) { - if (!this->compare(type, exp_type, "type")) return false; - - if (!this->compare_curves(this->m_xcurves[id], *xcv_ptr)) return false; + if (cv_p != nullptr) { + if (! this->compare(type, exp_type, "type")) return false; + if (! this->compare_curves(this->m_xcurves[id], *cv_p)) return false; continue; } exp_type = 0; - typedef std::pair Point_2_pair; - const Point_2_pair * pt_pair_ptr = - CGAL::object_cast (&(object_vec[i])); - assert(pt_pair_ptr != NULL); - if (!this->compare(type, exp_type, "type")) return false; - if (!this->compare_points(this->m_points[id], (*pt_pair_ptr).first)) - return false; - if (!this->compare(multiplicity, (*pt_pair_ptr).second, "multiplicity")) - return false; - } //forloop - - object_vec.clear(); + const Intersection_point* p_p = + boost::get(&(xections[i])); + assert(p_p != nullptr); + if (! this->compare(type, exp_type, "type")) return false; + if (! this->compare_points(this->m_points[id], p_p->first)) return false; + if (! this->compare(multiplicity, p_p->second, "multiplicity")) return false; + } + xections.clear(); return true; } diff --git a/BGL/include/CGAL/boost/graph/named_params_helper.h b/BGL/include/CGAL/boost/graph/named_params_helper.h index db7473882b9..d3cd5b68461 100644 --- a/BGL/include/CGAL/boost/graph/named_params_helper.h +++ b/BGL/include/CGAL/boost/graph/named_params_helper.h @@ -25,6 +25,8 @@ #include #include #include +#include + #include #include @@ -500,6 +502,18 @@ CGAL_DEF_GET_INITIALIZED_INDEX_MAP(face, typename boost::graph_traits::fa > ::type type; }; + template + class GetAdjacencies + { + public: + typedef Emptyset_iterator Empty; + typedef typename internal_np::Lookup_named_param_def < + internal_np::adjacencies_t, + NamedParameters, + Empty//default + > ::type type; + }; + } // namespace Point_set_processing_3 template diff --git a/BGL/include/CGAL/boost/graph/parameters_interface.h b/BGL/include/CGAL/boost/graph/parameters_interface.h index 17cf689d262..0ca726f6e31 100644 --- a/BGL/include/CGAL/boost/graph/parameters_interface.h +++ b/BGL/include/CGAL/boost/graph/parameters_interface.h @@ -98,6 +98,7 @@ CGAL_add_named_parameter(i_used_as_a_predicate_t, i_used_as_a_predicate, i_used_ CGAL_add_named_parameter(nesting_levels_t, nesting_levels, nesting_levels); CGAL_add_named_parameter(i_used_for_volume_orientation_t, i_used_for_volume_orientation, i_used_for_volume_orientation); CGAL_add_named_parameter(area_threshold_t, area_threshold, area_threshold) +CGAL_add_named_parameter(halfedges_keeper_t, halfedges_keeper, halfedges_keeper) CGAL_add_named_parameter(volume_threshold_t, volume_threshold, volume_threshold) CGAL_add_named_parameter(dry_run_t, dry_run, dry_run) @@ -147,6 +148,7 @@ CGAL_add_named_parameter(transformation_checkers_t, transformation_checkers, tra CGAL_add_named_parameter(inspector_t, inspector, inspector) CGAL_add_named_parameter(logger_t, logger, logger) CGAL_add_named_parameter(pointmatcher_config_t, pointmatcher_config, pointmatcher_config) +CGAL_add_named_parameter(adjacencies_t, adjacencies, adjacencies) // List of named parameters used in Surface_mesh_approximation package CGAL_add_named_parameter(verbose_level_t, verbose_level, verbose_level) @@ -165,6 +167,12 @@ CGAL_add_named_parameter(with_dihedral_angle_t, with_dihedral_angle, with_dihedr CGAL_add_named_parameter(optimize_anchor_location_t, optimize_anchor_location, optimize_anchor_location) CGAL_add_named_parameter(pca_plane_t, pca_plane, pca_plane) +// tetrahedral remeshing parameters +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) + // output parameters CGAL_add_named_parameter(face_proxy_map_t, face_proxy_map, face_proxy_map) CGAL_add_named_parameter(proxies_t, proxies, proxies) @@ -176,4 +184,3 @@ CGAL_add_named_parameter(accuracy_t, accuracy, accuracy) CGAL_add_named_parameter(maximum_running_time_t, maximum_running_time, maximum_running_time) CGAL_add_named_parameter(overlap_t, overlap, overlap) CGAL_add_named_parameter(maximum_normal_deviation_t, maximum_normal_deviation, maximum_normal_deviation) - diff --git a/BGL/test/BGL/test_cgal_bgl_named_params.cpp b/BGL/test/BGL/test_cgal_bgl_named_params.cpp index fd75c02888c..1d65c3cd1c2 100644 --- a/BGL/test/BGL/test_cgal_bgl_named_params.cpp +++ b/BGL/test/BGL/test_cgal_bgl_named_params.cpp @@ -95,8 +95,9 @@ void test(const NamedParameters& np) assert(get_parameter(np, CGAL::internal_np::snapping_tolerance).v == 59); assert(get_parameter(np, CGAL::internal_np::dry_run).v == 60); assert(get_parameter(np, CGAL::internal_np::do_lock_mesh).v == 61); + assert(get_parameter(np, CGAL::internal_np::halfedges_keeper).v == 62); + assert(get_parameter(np, CGAL::internal_np::do_simplify_border).v == 64); assert(get_parameter(np, CGAL::internal_np::maximum_number_of_faces).v == 78910); - assert(get_parameter(np, CGAL::internal_np::do_simplify_border).v == 62); // Named parameters that we use in the package 'Surface Mesh Simplification' assert(get_parameter(np, CGAL::internal_np::get_cost_policy).v == 34); @@ -201,7 +202,8 @@ void test(const NamedParameters& np) check_same_type<59>(get_parameter(np, CGAL::internal_np::snapping_tolerance)); check_same_type<60>(get_parameter(np, CGAL::internal_np::dry_run)); check_same_type<61>(get_parameter(np, CGAL::internal_np::do_lock_mesh)); - check_same_type<62>(get_parameter(np, CGAL::internal_np::do_simplify_border)); + check_same_type<62>(get_parameter(np, CGAL::internal_np::halfedges_keeper)); + check_same_type<64>(get_parameter(np, CGAL::internal_np::do_simplify_border)); check_same_type<78910>(get_parameter(np, CGAL::internal_np::maximum_number_of_faces)); // Named parameters that we use in the package 'Surface Mesh Simplification' @@ -348,8 +350,9 @@ int main() .snapping_tolerance(A<59>(59)) .dry_run(A<60>(60)) .do_lock_mesh(A<61>(61)) - .do_simplify_border(A<62>(62)) + .halfedges_keeper(A<62>(62)) .use_convex_hull(A<63>(63)) + .do_simplify_border(A<64>(64)) .point_map(A<9000>(9000)) .query_point_map(A<9001>(9001)) .normal_map(A<9002>(9002)) diff --git a/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h b/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h index 4d09d1f41e3..76efa0e5073 100644 --- a/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h +++ b/Boolean_set_operations_2/doc/Boolean_set_operations_2/Concepts/ArrDirectionalTraits--Intersect_2.h @@ -16,24 +16,23 @@ public: /// A model of this concept must provide: /// @{ -/*! -computes the intersections of `xc1` and `xc2` and -inserts them in an ascending lexicographic \f$ xy\f$-order into the -output iterator `oi`. The value-type of `Output_iterator` is -`CGAL::Object`, where each `Object` wraps either a -`pair` object, which -represents an intersection point with its multiplicity (in case the -multiplicity is undefined or unknown, it is set to \f$ 0\f$) or an -`ArrDirectionalTraits::X_monotone_curve_2` object, representing an -overlapping subcurve of `xc1` and `xc2`. In the latter case, -the overlapping subcurves are given the direction of `xc1` and -`xc2` if their directions are identical. Otherwise, the overlapping -subcurves are given an arbitrary direction. The operator returns a -past-the-end iterator for the output sequence. -*/ -Output_iterator operator()(ArrDirectionalTraits::X_monotone_curve_2 xc1, -ArrDirectionalTraits::X_monotone_curve_2 xc2, -Output_iterator& oi); +/*! computes the intersections of `xc1` and `xc2` and inserts them in an + * ascending lexicographic \f$ xy\f$-order into a range begining at + * `oi`. The type `OutputIterator` dereferences a `boost::variant` of either the + * type `pair` or the type + * `ArrDirectionalTraits::X_monotone_curve_2`. An object of the former type + * represents an intersection point with its multiplicity (in case the + * multiplicity is undefined or unknown, it is set to \f$ 0\f$). An object of + * the latter type representing an overlapping subcurve of `xc1` and `xc2`. The + * overlapping subcurves are given the direction of `xc1` and `xc2` if their + * directions are identical. Otherwise, the overlapping subcurves are given an + * arbitrary direction. The operator returns a past-the-end iterator of the + * destination range. + */ +OutputIterator operator()(ArrDirectionalTraits::X_monotone_curve_2 xc1, + ArrDirectionalTraits::X_monotone_curve_2 xc2, + Output_iterator& oi); /// @} diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h index 854f90f70c3..5d062639df6 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_agg_meta_traits.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Baruch Zukerman +// Author(s): Baruch Zukerman +// Efi Fogel #ifndef CGAL_BSO_2_GPS_AGG_META_TRAITS_H #define CGAL_BSO_2_GPS_AGG_META_TRAITS_H @@ -81,8 +82,8 @@ class Gps_agg_meta_traits : typedef typename Arr::Traits_adaptor_2 Traits; typedef Traits Gt2; - typedef typename Gt2::X_monotone_curve_2 Base_X_monotone_curve_2; - typedef typename Gt2::Point_2 Base_Point_2; + typedef typename Gt2::X_monotone_curve_2 Base_x_monotone_curve_2; + typedef typename Gt2::Point_2 Base_point_2; typedef typename Gt2::Construct_min_vertex_2 Base_Construct_min_vertex_2; typedef typename Gt2::Construct_max_vertex_2 Base_Construct_max_vertex_2; typedef typename Gt2::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2; @@ -106,8 +107,8 @@ public: typedef Point_with_vertex Point_data; private: - typedef Gps_traits_decorator - Base; + typedef Gps_agg_meta_traits Self; + typedef Gps_traits_decorator Base; public: typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; @@ -145,93 +146,88 @@ public: class Intersect_2 { private: - Base_Intersect_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - Base_Compare_xy_2 m_base_cmp_xy; - Base_Construct_min_vertex_2 m_base_ctr_min_v; + const Self& m_traits; + + /*! Constructor. */ + Intersect_2(const Self& traits) : m_traits(traits) {} + + friend Self; public: - /*! Construct. */ - Intersect_2(const Base_Intersect_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Base_Compare_xy_2& base_cmp_xy, - const Base_Construct_min_vertex_2& base_ctr_min_v) : - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_base_cmp_xy(base_cmp_xy), - m_base_ctr_min_v(base_ctr_min_v) - {} - template OutputIterator operator()(const X_monotone_curve_2& cv1, const X_monotone_curve_2& cv2, OutputIterator oi) const { - if (cv1.data().arr() == cv2.data().arr()) { - return oi; // the curves are disjoint-interior because they - // are already at the same arrangement. - } + // Check whether the curves are already in the same arrangement, and thus + // must be interior-disjoint + if (cv1.data().arr() == cv2.data().arr()) return oi; - const std::pair* base_pt; - const Base_X_monotone_curve_2* overlap_cv; - OutputIterator oi_end; - if(m_base_cmp_xy(m_base_ctr_min_v(cv1.base()), - m_base_ctr_min_v(cv2.base())) == LARGER) - oi_end = m_base(cv1.base(), cv2.base(), oi); + typedef const std::pair + Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef const std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); + auto base_intersect = base_traits->intersect_2_object(); + + std::vector xections; + if (base_cmp_xy(base_ctr_min_vertex(cv1.base()), + base_ctr_min_vertex(cv2.base())) == LARGER) + base_intersect(cv1.base(), cv2.base(), back_inserter(xections)); else - oi_end = m_base(cv2.base(), cv1.base(), oi); + base_intersect(cv2.base(), cv1.base(), back_inserter(xections)); - // convert objects that are associated with Base_X_monotone_curve_2 to + // convert objects that are associated with Base_x_monotone_curve_2 to // the extenede X_monotone_curve_2 - for (; oi != oi_end; ++oi) { - base_pt = object_cast >(&(*oi)); - + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); if (base_pt != nullptr) { Point_2 point_plus(base_pt->first); // the extended point - *oi = CGAL::make_object(std::make_pair(point_plus, - base_pt->second)); + *oi++ = + Intersection_result(std::make_pair(point_plus, base_pt->second)); + continue; + } + + const Base_x_monotone_curve_2* overlap_cv = + boost::get(&xection); + CGAL_assertion(overlap_cv != nullptr); + unsigned int ov_bc; + unsigned int ov_twin_bc; + if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) { + // cv1 and cv2 have the same directions + ov_bc = cv1.data().bc() + cv2.data().bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); } else { - overlap_cv = object_cast(&(*oi)); - - if (overlap_cv != nullptr) { - unsigned int ov_bc; - unsigned int ov_twin_bc; - if (m_base_cmp_endpoints(cv1) == m_base_cmp_endpoints(cv2)) { - // cv1 and cv2 have the same directions - ov_bc = cv1.data().bc() + cv2.data().bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); - } - else { - // cv1 and cv2 have opposite directions - ov_bc = cv1.data().bc() + cv2.data().twin_bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); - } - - if(m_base_cmp_endpoints(*overlap_cv) != m_base_cmp_endpoints(cv1)) { - // overlap_cv, cv1 have opposite directions - std::swap(ov_bc, ov_twin_bc); - } - - Curve_data cv_data(cv1.data().arr(), Halfedge_handle(), - ov_bc, ov_twin_bc); - *oi = CGAL::make_object(X_monotone_curve_2(*overlap_cv, cv_data)); - } + // cv1 and cv2 have opposite directions + ov_bc = cv1.data().bc() + cv2.data().twin_bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); } + + if (base_cmp_endpoints(*overlap_cv) != base_cmp_endpoints(cv1)) { + // overlap_cv, cv1 have opposite directions + std::swap(ov_bc, ov_twin_bc); + } + + Curve_data cv_data(cv1.data().arr(), Halfedge_handle(), + ov_bc, ov_twin_bc); + *oi++ = Intersection_result(X_monotone_curve_2(*overlap_cv, cv_data)); } - //return past-end iterator - return oi_end; + + return oi; } }; /*! Obtain an Intersect_2 functor object. */ - Intersect_2 intersect_2_object() const - { - return Intersect_2(this->m_base_tr->intersect_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this->m_base_tr->compare_xy_2_object(), - this->m_base_tr->construct_min_vertex_2_object()); - } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } class Split_2 { private: @@ -256,7 +252,7 @@ public: /*! Obtain a Split_2 functor object. */ Split_2 split_2_object() const - { return Split_2(this->m_base_tr->split_2_object()); } + { return Split_2(this->m_base_traits->split_2_object()); } class Construct_min_vertex_2 { private: @@ -286,7 +282,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object() const { - return Construct_min_vertex_2(this->m_base_tr-> + return Construct_min_vertex_2(this->m_base_traits-> construct_min_vertex_2_object()); } @@ -318,7 +314,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object() const { - return Construct_max_vertex_2(this->m_base_tr-> + return Construct_max_vertex_2(this->m_base_traits-> construct_max_vertex_2_object()); } @@ -348,7 +344,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_xy_2 compare_xy_2_object() const - { return Compare_xy_2(this->m_base_tr->compare_xy_2_object()); } + { return Compare_xy_2(this->m_base_traits->compare_xy_2_object()); } // left-right class Parameter_space_in_x_2 { @@ -380,7 +376,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Parameter_space_in_x_2 parameter_space_in_x_2_object() const { - return Parameter_space_in_x_2(this->m_base_tr-> + return Parameter_space_in_x_2(this->m_base_traits-> parameter_space_in_x_2_object()); } @@ -404,7 +400,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_y_near_boundary_2 compare_y_near_boundary_2_object() const { - return Compare_y_near_boundary_2(this->m_base_tr-> + return Compare_y_near_boundary_2(this->m_base_traits-> compare_y_near_boundary_2_object() ); } @@ -443,7 +439,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Parameter_space_in_y_2 parameter_space_in_y_2_object() const { - return Parameter_space_in_y_2(this->m_base_tr-> + return Parameter_space_in_y_2(this->m_base_traits-> parameter_space_in_y_2_object()); } @@ -476,7 +472,7 @@ public: /*! Obtain a Construct_min_vertex_2 functor object. */ Compare_x_near_boundary_2 compare_x_near_boundary_2_object() const { - return Compare_x_near_boundary_2(this->m_base_tr-> + return Compare_x_near_boundary_2(this->m_base_traits-> compare_x_near_boundary_2_object()); } diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h index 2c1557a2619..bbf2835fb68 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_insertion_meta_traits.h @@ -75,7 +75,7 @@ public: Construct_min_vertex_2 construct_min_vertex_2_object () const { return Construct_min_vertex_2 - (this->m_base_tr->construct_min_vertex_2_object()); + (this->m_base_traits->construct_min_vertex_2_object()); } @@ -100,7 +100,7 @@ public: Construct_max_vertex_2 construct_max_vertex_2_object () const { return Construct_max_vertex_2 - (this->m_base_tr->construct_max_vertex_2_object()); + (this->m_base_traits->construct_max_vertex_2_object()); } class Compare_xy_2 @@ -123,7 +123,7 @@ public: /*! Get a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object () const { - return Compare_xy_2(m_base_tr->compare_xy_2_object()); + return Compare_xy_2(m_base_traits->compare_xy_2_object()); } }; diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h index 48b969adea8..fdc111751de 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_simplifier_traits.h @@ -8,7 +8,8 @@ // SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial // // -// Author(s) : Baruch Zukerman +// Author(s): Baruch Zukerman +// Efi Fogel #ifndef CGAL_GPS_SIMPLIFIER_TRAITS_H #define CGAL_GPS_SIMPLIFIER_TRAITS_H @@ -20,103 +21,67 @@ namespace CGAL { -class Gps_simplifier_curve_data -{ +class Gps_simplifier_curve_data { protected: unsigned int m_bc; unsigned int m_twin_bc; unsigned int m_index; public: - Gps_simplifier_curve_data() - {} + Gps_simplifier_curve_data() {} - Gps_simplifier_curve_data(unsigned int bc, - unsigned int twin_bc, + Gps_simplifier_curve_data(unsigned int bc, unsigned int twin_bc, unsigned int index): m_bc(bc), m_twin_bc(twin_bc), m_index(index) {} - unsigned int bc() const - { - return m_bc; - } + unsigned int bc() const { return m_bc; } - unsigned int twin_bc() const - { - return m_twin_bc; - } + unsigned int twin_bc() const { return m_twin_bc; } - unsigned int index() const - { - return m_index; - } + unsigned int index() const { return m_index; } - unsigned int& index() - { - return m_index; - } + unsigned int& index() { return m_index; } - unsigned int& twin_bc() - { - return m_twin_bc; - } + unsigned int& twin_bc() { return m_twin_bc; } - void set_bc(unsigned int bc) - { - m_bc = bc; - } + void set_bc(unsigned int bc) { m_bc = bc; } - void set_twin_bc(unsigned int twin_bc) - { - m_twin_bc = twin_bc; - } + void set_twin_bc(unsigned int twin_bc) { m_twin_bc = twin_bc; } - void set_index(unsigned int index) - { - m_index = index; - } + void set_index(unsigned int index) { m_index = index; } }; -struct Gps_simplifier_point_data -{ +struct Gps_simplifier_point_data { protected: unsigned int m_index; public: - Gps_simplifier_point_data() - {} + Gps_simplifier_point_data() {} - Gps_simplifier_point_data(unsigned int index) : m_index(index) - {} + Gps_simplifier_point_data(unsigned int index) : m_index(index) {} - unsigned int index() const - { - return m_index; - } + unsigned int index() const { return m_index; } - void set_index(unsigned int index) - { - m_index = index; - } + void set_index(unsigned int index) { m_index = index; } }; -template +template class Gps_simplifier_traits : public Gps_traits_decorator { public: - typedef Traits_ Traits; + typedef Traits_ Traits; typedef Gps_traits_decorator Base; - typedef Gps_simplifier_traits Self; - typedef typename Traits::X_monotone_curve_2 Base_X_monotone_curve_2; - typedef typename Traits::Point_2 Base_Point_2; + Gps_simplifier_point_data> Base; + typedef Gps_simplifier_traits Self; + typedef typename Traits::X_monotone_curve_2 Base_x_monotone_curve_2; + typedef typename Traits::Point_2 Base_point_2; typedef typename Traits::Construct_min_vertex_2 Base_Construct_min_vertex_2; typedef typename Traits::Construct_max_vertex_2 Base_Construct_max_vertex_2; typedef typename Traits::Compare_endpoints_xy_2 Base_Compare_endpoints_xy_2; @@ -129,9 +94,7 @@ public: protected: mutable unsigned int m_pgn_size; - public: - typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; typedef typename Base::Point_2 Point_2; typedef typename Base::Multiplicity Multiplicity; @@ -139,333 +102,256 @@ public: typedef typename Base::Curve_data Curve_data; typedef typename Base::Point_data Point_data; - Gps_simplifier_traits() - {} + Gps_simplifier_traits() {} - Gps_simplifier_traits(const Traits & tr) : Base(tr) - {} + Gps_simplifier_traits(const Traits& tr) : Base(tr) {} - unsigned int polygon_size() const - { - return m_pgn_size; - } + unsigned int polygon_size() const { return m_pgn_size; } - void set_polygon_size(unsigned int pgn_size) const - { - m_pgn_size = pgn_size; - } + void set_polygon_size(unsigned int pgn_size) const { m_pgn_size = pgn_size; } bool is_valid_index(unsigned int index) const - { - return (index < m_pgn_size); - } + { return (index < m_pgn_size); } - unsigned int invalid_index() const - { - return (m_pgn_size); - } + unsigned int invalid_index() const { return (m_pgn_size); } - - class Intersect_2 - { + class Intersect_2 { private: - - Base_Intersect_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - Base_Compare_xy_2 m_base_cmp_xy; - Base_Construct_min_vertex_2 m_ctr_min_v; - const Self * m_self_tr; - - public: + /*! The traits (in case it has state) */ + const Self& m_traits; /*! Constructor. */ - Intersect_2 (const Base_Intersect_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Base_Compare_xy_2& base_cmp_xy, - const Base_Construct_min_vertex_2& , - const Self* tr) : - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_base_cmp_xy(base_cmp_xy), - m_self_tr(tr) - {} + Intersect_2(const Self& tr) : m_traits(tr) {} - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + friend Self; + + public: + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef const std::pair + Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef const std::pair Intersection_point; + typedef boost::variant + Intersection_result; + + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); + auto base_intersect = base_traits->intersect_2_object(); + //// if the two curves are incident, do not intersect them - //if(m_self_tr->is_valid_index(cv1.data().index()) && - // m_self_tr->is_valid_index(cv2.data().index())) + //if (m_traits.is_valid_index(cv1.data().index()) && + // m_traits.is_valid_index(cv2.data().index())) //{ // unsigned int index_diff = // (cv1.data().index() > cv2.data().index()) ? // (cv1.data().index() - cv2.data().index()): // (cv2.data().index() - cv1.data().index()); - // if(index_diff == 1 ||index_diff == m_self_tr->polygon_size() -1) + // if(index_diff == 1 ||index_diff == m_traits.polygon_size() -1) // { // return (oi); // } //} - const std::pair *base_pt; - const Base_X_monotone_curve_2 *overlap_cv; - OutputIterator oi_end; - if(m_base_cmp_xy(m_ctr_min_v(cv1.base()), - m_ctr_min_v(cv2.base())) == LARGER) - oi_end = m_base(cv1.base(), cv2.base(), oi); + std::vector xections; + if (base_cmp_xy(base_ctr_min_vertex(cv1.base()), + base_ctr_min_vertex(cv2.base())) == LARGER) + base_intersect(cv1.base(), cv2.base(), back_inserter(xections)); else - oi_end = m_base(cv2.base(), cv1.base(), oi); + base_intersect(cv2.base(), cv1.base(), back_inserter(xections)); - // convert objects that are associated with Base_X_monotone_curve_2 to + // convert objects that are associated with Base_x_monotone_curve_2 to // the extenede X_monotone_curve_2 - for(; oi != oi_end; ++oi) - { - base_pt = object_cast >(&(*oi)); - - if (base_pt != nullptr) - { - Point_data pt_data(m_self_tr->invalid_index()); - Point_2 point_plus (base_pt->first, pt_data); // the extended point - *oi = CGAL::make_object(std::make_pair(point_plus, - base_pt->second)); + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); + if (base_pt != nullptr) { + Point_data pt_data(m_traits.invalid_index()); + Point_2 point_plus(base_pt->first, pt_data); // the extended point + *oi++ = + Intersection_result(std::make_pair(point_plus, base_pt->second)); + continue; } - else - { - overlap_cv = object_cast (&(*oi)); - if (overlap_cv != nullptr) - { - unsigned int ov_bc; - unsigned int ov_twin_bc; - if(m_base_cmp_endpoints(cv1) == m_base_cmp_endpoints(cv2)) - { - // cv1 and cv2 have the same directions - ov_bc = cv1.data().bc() + cv2.data().bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); - } - else - { - // cv1 and cv2 have opposite directions - ov_bc = cv1.data().bc() + cv2.data().twin_bc(); - ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); - } + const Base_x_monotone_curve_2* overlap_cv = + boost::get(&xection); - if(m_base_cmp_endpoints(*overlap_cv) != m_base_cmp_endpoints(cv1)) - { - // overlap_cv, cv1 have opposite directions - std::swap(ov_bc, ov_twin_bc); - } - - Curve_data cv_data(ov_bc, ov_twin_bc, m_self_tr->invalid_index()); - *oi = CGAL::make_object (X_monotone_curve_2 (*overlap_cv, cv_data)); - } + CGAL_assertion(overlap_cv != nullptr); + unsigned int ov_bc; + unsigned int ov_twin_bc; + if (base_cmp_endpoints(cv1) == base_cmp_endpoints(cv2)) { + // cv1 and cv2 have the same directions + ov_bc = cv1.data().bc() + cv2.data().bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().twin_bc(); } + else { + // cv1 and cv2 have opposite directions + ov_bc = cv1.data().bc() + cv2.data().twin_bc(); + ov_twin_bc = cv1.data().twin_bc() + cv2.data().bc(); + } + + if (base_cmp_endpoints(*overlap_cv) != base_cmp_endpoints(cv1)) { + // overlap_cv, cv1 have opposite directions + std::swap(ov_bc, ov_twin_bc); + } + + Curve_data cv_data(ov_bc, ov_twin_bc, m_traits.invalid_index()); + *oi++ = Intersection_result(X_monotone_curve_2(*overlap_cv, cv_data)); } - //return past-end iterator - return oi_end; + + return oi; } }; - /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return Intersect_2(this->m_base_tr->intersect_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this->m_base_tr->compare_xy_2_object(), - this->m_base_tr->construct_min_vertex_2_object(), - this); - } + /*! Obtain an Intersect_2 functor object. */ + Intersect_2 intersect_2_object () const { return Intersect_2(*this); } - class Split_2 - { + class Split_2 { private: - Base_Split_2 m_base_split; - const Self * m_self_tr; - - public: + const Self& m_traits; /*! Constructor. */ - Split_2 (const Base_Split_2& base, const Self* tr) : - m_base_split(base), - m_self_tr(tr) - {} + Split_2(const Self& tr) : m_traits(tr) {} - void operator() (const X_monotone_curve_2& cv, const Point_2 & p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + friend Self; + + public: + void operator()(const X_monotone_curve_2& cv, const Point_2 & p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { - m_base_split(cv.base(), - p.base(), - c1.base(), - c2.base()); + const auto* base_traits = m_traits.m_base_traits; + auto base_split = base_traits->split_2_object(); + base_split(cv.base(), p.base(), c1.base(), c2.base()); const Curve_data& cv_data = cv.data(); - c1.set_data(Curve_data(cv_data.bc(), - cv_data.twin_bc(), - m_self_tr->invalid_index())); + c1.set_data(Curve_data(cv_data.bc(), cv_data.twin_bc(), + m_traits.invalid_index())); - c2.set_data(Curve_data(cv_data.bc(), - cv_data.twin_bc(), - m_self_tr->invalid_index())); + c2.set_data(Curve_data(cv_data.bc(), cv_data.twin_bc(), + m_traits.invalid_index())); } }; /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const - { - return Split_2(this->m_base_tr->split_2_object(), this); - } + Split_2 split_2_object () const { return Split_2(*this); } - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { private: - Base_Construct_min_vertex_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - const Self * m_self_tr; + const Self& m_traits; + + Construct_min_vertex_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - - Construct_min_vertex_2(const Base_Construct_min_vertex_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Self * tr): - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_self_tr(tr) - {} - - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ - Point_2 operator() (const X_monotone_curve_2 & cv) const + Point_2 operator()(const X_monotone_curve_2 & cv) const { - if(!m_self_tr->is_valid_index(cv.data().index())) - { - return Point_2 (m_base(cv.base()), m_self_tr->invalid_index()); - } + const auto* base_traits = m_traits.m_base_traits; + auto base_ctr_min_vertex = base_traits->construct_min_vertex_2_object(); - Comparison_result res = m_base_cmp_endpoints(cv); + if (! m_traits.is_valid_index(cv.data().index())) + return Point_2(base_ctr_min_vertex(cv.base()), m_traits.invalid_index()); + + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + Comparison_result res = base_cmp_endpoints(cv); Point_data pt_data; - if(res == SMALLER) - { + if (res == SMALLER) { // min vertex is the source pt_data.set_index(cv.data().index()); } - else - { + else { // min vertex is the target - pt_data.set_index((cv.data().index() + 1) % m_self_tr->polygon_size()); + pt_data.set_index((cv.data().index() + 1) % m_traits.polygon_size()); } - return Point_2 (m_base(cv.base()), pt_data); + return Point_2(base_ctr_min_vertex(cv.base()), pt_data); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return Construct_min_vertex_2 - (this->m_base_tr->construct_min_vertex_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this); - } + { return Construct_min_vertex_2(*this); } - - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { private: - Base_Construct_max_vertex_2 m_base; - Base_Compare_endpoints_xy_2 m_base_cmp_endpoints; - const Self * m_self_tr; + const Self& m_traits; + + Construct_max_vertex_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - - Construct_max_vertex_2(const Base_Construct_max_vertex_2& base, - const Base_Compare_endpoints_xy_2& base_cmp_endpoints, - const Self * tr): - m_base(base), - m_base_cmp_endpoints(base_cmp_endpoints), - m_self_tr(tr) - {} - - /*! - * Get the right endpoint of the x-monotone curve (segment). + /*! Obtain the right endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ Point_2 operator() (const X_monotone_curve_2 & cv) const { - if(!m_self_tr->is_valid_index(cv.data().index())) - { - return Point_2 (m_base(cv.base()), m_self_tr->invalid_index()); - } - Comparison_result res = m_base_cmp_endpoints(cv); + const auto* base_traits = m_traits.m_base_traits; + auto base_ctr_max_vertex = base_traits->construct_max_vertex_2_object(); + if (! m_traits.is_valid_index(cv.data().index())) + return Point_2(base_ctr_max_vertex(cv.base()), m_traits.invalid_index()); + + auto base_cmp_endpoints = base_traits->compare_endpoints_xy_2_object(); + Comparison_result res = base_cmp_endpoints(cv); Point_data pt_data; - if(res == SMALLER) - { + if (res == SMALLER) { // min vertex is the target - pt_data.set_index((cv.data().index() + 1) % m_self_tr->polygon_size()); + pt_data.set_index((cv.data().index() + 1) % m_traits.polygon_size()); } - else - { + else { // min vertex is the source pt_data.set_index(cv.data().index()); } - return Point_2 (m_base(cv.base()), pt_data); + return Point_2(base_ctr_max_vertex(cv.base()), pt_data); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return Construct_max_vertex_2 - (this->m_base_tr->construct_max_vertex_2_object(), - this->m_base_tr->compare_endpoints_xy_2_object(), - this); - } + { return Construct_max_vertex_2(*this); } - class Compare_xy_2 - { + class Compare_xy_2 { private: - Base_Compare_xy_2 m_base; - const Self * m_self_tr; + const Self& m_traits; + + Compare_xy_2(const Self& tr) : m_traits(tr) {} + + friend Self; public: - Compare_xy_2(const Base_Compare_xy_2& base, - const Self * tr): - m_base(base), - m_self_tr(tr) - {} - - - /*! - * Get the left endpoint of the x-monotone curve (segment). + /*! Obtain the left endpoint of the x-monotone curve (segment). * \param cv The curve. * \return The left endpoint. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { + const auto* base_traits = m_traits.m_base_traits; + auto base_cmp_xy = base_traits->compare_xy_2_object(); + //if one of the indexes is invalid, compare p1 and p2 - if(! m_self_tr->is_valid_index(p1.data().index()) || - ! m_self_tr->is_valid_index(p2.data().index())) - return (m_base(p1.base(), p2.base())); + if (! m_traits.is_valid_index(p1.data().index()) || + ! m_traits.is_valid_index(p2.data().index())) + return (base_cmp_xy(p1.base(), p2.base())); // if the two point has the same index, return EQUAL - if(p1.data().index() == p2.data().index()) - { - return EQUAL; - } + if (p1.data().index() == p2.data().index()) return EQUAL; - return (m_base(p1.base(), p2.base())); + return (base_cmp_xy(p1.base(), p2.base())); } }; /*! Get a Construct_min_vertex_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return Compare_xy_2(this->m_base_tr->compare_xy_2_object(), this); - } + Compare_xy_2 compare_xy_2_object () const { return Compare_xy_2(*this); } }; } //namespace CGAL diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h index 74b62b9d5f5..74664d72795 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Gps_traits_decorator.h @@ -202,25 +202,27 @@ public: protected: //Data members - const Base * m_base_tr; + const Base* m_base_traits; bool m_traits_owner; public: Gps_traits_decorator() : - m_base_tr(new Base()), + m_base_traits(new Base()), m_traits_owner(true) {} - Gps_traits_decorator(const Base & base_traits) : - m_base_tr(&base_traits), + Gps_traits_decorator(const Base& base_traits) : + m_base_traits(&base_traits), m_traits_owner(false) {} ~Gps_traits_decorator() { - if (m_traits_owner) - delete m_base_tr; + if (m_traits_owner) { + delete m_base_traits; + m_base_traits = nullptr; + } } class Compare_x_2 @@ -242,7 +244,7 @@ public: /*! Get a Compare_x_2 functor object. */ Compare_x_2 compare_x_2_object () const { - return Compare_x_2(m_base_tr->compare_x_2_object()); + return Compare_x_2(m_base_traits->compare_x_2_object()); } @@ -265,7 +267,7 @@ public: /*! Get a Compare_xy_2 functor object. */ Compare_xy_2 compare_xy_2_object () const { - return Compare_xy_2(m_base_tr->compare_xy_2_object()); + return Compare_xy_2(m_base_traits->compare_xy_2_object()); } class Construct_min_vertex_2 @@ -288,7 +290,7 @@ public: /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const { - return Construct_min_vertex_2(m_base_tr->construct_min_vertex_2_object()); + return Construct_min_vertex_2(m_base_traits->construct_min_vertex_2_object()); } class Construct_max_vertex_2 @@ -311,7 +313,7 @@ public: /*! Get a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const { - return Construct_max_vertex_2(m_base_tr->construct_max_vertex_2_object()); + return Construct_max_vertex_2(m_base_traits->construct_max_vertex_2_object()); } @@ -334,7 +336,7 @@ public: /*! Get a Is_vertical_2 functor object. */ Is_vertical_2 is_vertical_2_object() const { - return Is_vertical_2(m_base_tr->is_vertical_2_object()); + return Is_vertical_2(m_base_traits->is_vertical_2_object()); } @@ -358,7 +360,7 @@ public: /*! Get a compare_y_at_x_2_object functor object. */ Compare_y_at_x_2 compare_y_at_x_2_object() const { - return Compare_y_at_x_2(m_base_tr->compare_y_at_x_2_object()); + return Compare_y_at_x_2(m_base_traits->compare_y_at_x_2_object()); } @@ -384,7 +386,7 @@ public: /*! Get a Compare_y_at_x_right_2 functor object. */ Compare_y_at_x_right_2 compare_y_at_x_right_2_object() const { - return Compare_y_at_x_right_2(m_base_tr->compare_y_at_x_right_2_object()); + return Compare_y_at_x_right_2(m_base_traits->compare_y_at_x_right_2_object()); } @@ -407,7 +409,7 @@ public: /*! Get a Equal_2 functor object. */ Equal_2 equal_2_object() const { - return Equal_2(m_base_tr->equal_2_object()); + return Equal_2(m_base_traits->equal_2_object()); } @@ -432,7 +434,7 @@ public: /*! Get a Split_2 functor object. */ Split_2 split_2_object() const { - return Split_2(m_base_tr->split_2_object()); + return Split_2(m_base_traits->split_2_object()); } @@ -495,9 +497,9 @@ public: /*! Get a Intersect_2 functor object. */ Intersect_2 intersect_2_object() const { - return Intersect_2(m_base_tr->intersect_2_object(), - m_base_tr->compare_xy_2_object(), - m_base_tr->construct_min_vertex_2_object()); + return Intersect_2(m_base_traits->intersect_2_object(), + m_base_traits->compare_xy_2_object(), + m_base_traits->construct_min_vertex_2_object()); } @@ -522,7 +524,7 @@ public: /*! Get a Compare_endpoints_xy_2 functor object. */ Compare_endpoints_xy_2 compare_endpoints_xy_2_object() const { - return Compare_endpoints_xy_2(m_base_tr->compare_endpoints_xy_2_object()); + return Compare_endpoints_xy_2(m_base_traits->compare_endpoints_xy_2_object()); } @@ -545,7 +547,7 @@ public: /*! Get a Construct_opposite_2 functor object. */ Construct_opposite_2 construct_opposite_2_object() const { - return Construct_opposite_2(m_base_tr->construct_opposite_2_object()); + return Construct_opposite_2(m_base_traits->construct_opposite_2_object()); } }; diff --git a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h index 39a5e7dd34a..833f9afd571 100644 --- a/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h +++ b/Boolean_set_operations_2/include/CGAL/Boolean_set_operations_2/Polygon_2_curve_iterator.h @@ -60,9 +60,9 @@ public: Edge_const_iterator m_curr_edge; // points to the current edge iterator public: - Polygon_2_curve_iterator< X_monotone_curve_2_, Polygon_ >(){} + Polygon_2_curve_iterator(){} - Polygon_2_curve_iterator< X_monotone_curve_2_, Polygon_ > + Polygon_2_curve_iterator (const Polygon* pgn, Edge_const_iterator ci) : m_pgn(pgn), m_curr_edge(ci) {} diff --git a/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h b/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h index 1d29214e267..4b88536cf14 100644 --- a/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h +++ b/Boolean_set_operations_2/include/CGAL/Gps_circle_segment_traits_2.h @@ -27,7 +27,7 @@ class Gps_circle_segment_traits_2 : public Gps_traits_2 > { public: - Gps_circle_segment_traits_2(bool use_cache = false) : + Gps_circle_segment_traits_2(bool use_cache = false) : Gps_traits_2 >() { this->m_use_cache = use_cache; diff --git a/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h b/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h index 068e95c2169..3f916b7e71d 100644 --- a/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h +++ b/Boolean_set_operations_2/include/CGAL/Gps_traits_2.h @@ -35,6 +35,8 @@ public: typedef typename Base::Point_2 Point_2; typedef typename Base::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Base::Multiplicity Multiplicity; + //Polygon_2 type is required by GeneralPolygonSetTraits Concept typedef General_polygon_t Polygon_2; //Polygon_2 is a model of the GeneralPolygon2 concept diff --git a/CGALConfigVersion.cmake b/CGALConfigVersion.cmake new file mode 100644 index 00000000000..f1363d9a8f6 --- /dev/null +++ b/CGALConfigVersion.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/CMakeLists.txt b/CMakeLists.txt index acdc5817a06..9696ca95b3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,6 +10,7 @@ export(PACKAGE CGAL) set( CGAL_BRANCH_BUILD ON CACHE INTERNAL "Create CGAL from a Git branch" FORCE) +include(${CMAKE_SOURCE_DIR}/CGALConfigVersion.cmake) include(${CMAKE_SOURCE_DIR}/Installation/cmake/modules/CGAL_SCM.cmake) CGAL_detect_git(${CMAKE_SOURCE_DIR}) diff --git a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h index ec41f708100..7a04f837092 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_3.h @@ -169,6 +169,9 @@ public: Aff_transformation_3 operator*(const Aff_transformationC3 &t) const { return (*this->Ptr()) * (*t.Ptr()); } + std::ostream & + print(std::ostream &os) const; + bool operator==(const Aff_transformationC3 &t)const { for(int i=0; i<3; ++i) @@ -188,13 +191,21 @@ protected: }; +template < class R > +std::ostream& +Aff_transformationC3::print(std::ostream &os) const +{ + this->Ptr()->print(os); + return os; +} + #ifndef CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONC3 template < class R > -std::ostream &operator<<(std::ostream &os, - const Aff_transformationC3 &t) +std::ostream& +operator<<(std::ostream &os, const Aff_transformationC3 &t) { - t.print(os); - return os; + t.print(os); + return os; } #endif // CGAL_NO_OSTREAM_INSERT_AFF_TRANSFORMATIONC3 diff --git a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h index d1335a1096b..406cb7accca 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/Aff_transformation_rep_3.h @@ -183,8 +183,8 @@ public: virtual std::ostream &print(std::ostream &os) const { os <<"Aff_transformationC3("<(); } + { PTR = (Rep*) new _Tee_for_output_iterator_rep(); } Tee_for_output_iterator& operator=(const T& value) @@ -82,7 +82,7 @@ public: _Tee_for_output_iterator_rep* ptr() - { return (_Tee_for_output_iterator_rep*)(PTR.p); } + { return (_Tee_for_output_iterator_rep*)PTR; } protected: OutputIterator o_it; diff --git a/Convex_hull_d/include/CGAL/Regular_complex_d.h b/Convex_hull_d/include/CGAL/Regular_complex_d.h index 753637ec1e5..4a5a32b1213 100644 --- a/Convex_hull_d/include/CGAL/Regular_complex_d.h +++ b/Convex_hull_d/include/CGAL/Regular_complex_d.h @@ -87,7 +87,7 @@ public: void* pp; void* for_compact_container() const { return pp; } - void* & for_compact_container() { return pp; } + void for_compact_container(void *p) { pp = p; } #ifdef CGAL_USE_LEDA LEDA_MEMORY(RC_vertex_d) @@ -153,7 +153,7 @@ public: void* pp; void* for_compact_container() const { return pp; } - void* & for_compact_container() { return pp; } + void for_compact_container(void *p) { pp = p; } #if 0 struct Point_const_iterator { diff --git a/Documentation/doc/CMakeLists.txt b/Documentation/doc/CMakeLists.txt index 744b16f32e8..9c1695ca28e 100644 --- a/Documentation/doc/CMakeLists.txt +++ b/Documentation/doc/CMakeLists.txt @@ -252,9 +252,7 @@ endif() if (NOT CGAL_CREATED_VERSION_NUM) if (CGAL_BRANCH_BUILD) - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/MAJOR_NUMBER" CGAL_MAJOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/MINOR_NUMBER" CGAL_MINOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_ROOT}/Maintenance/release_building/BUGFIX_NUMBER" CGAL_BUGFIX_VERSION REGEX "[0-9]*") + include(${CGAL_ROOT}/CGALConfigVersion.cmake) if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") diff --git a/Documentation/doc/Documentation/packages.txt b/Documentation/doc/Documentation/packages.txt index 5fb6e1a5446..a18528a063d 100644 --- a/Documentation/doc/Documentation/packages.txt +++ b/Documentation/doc/Documentation/packages.txt @@ -90,6 +90,7 @@ \package_listing{Surface_mesher} \package_listing{Skin_surface_3} \package_listing{Mesh_3} +\package_listing{Tetrahedral_remeshing} \package_listing{Periodic_3_mesh_3} \cgalPackageSection{PartReconstruction,Shape Reconstruction} diff --git a/Documentation/doc/biblio/cgal_manual.bib b/Documentation/doc/biblio/cgal_manual.bib index e2a2fd57555..6dcd0e958c7 100644 --- a/Documentation/doc/biblio/cgal_manual.bib +++ b/Documentation/doc/biblio/cgal_manual.bib @@ -3127,6 +3127,14 @@ pages = "207--221" year={2012}, organization={Wiley Online Library} } + +@article{faraj2016mvr, + author = {Noura Faraj and Jean-Marc Thiery and Tamy Boubekeur}, + title = {Multi-Material Adaptive Volume Remesher}, + journal = {Compurer and Graphics Journal (proc. Shape Modeling International 2016)}, + year = {2016}, +} + % ---------------------------------------------------------------------------- % END OF BIBFILE % ---------------------------------------------------------------------------- diff --git a/Filtered_kernel/include/CGAL/Lazy.h b/Filtered_kernel/include/CGAL/Lazy.h index df94fc2de19..067fbe57463 100644 --- a/Filtered_kernel/include/CGAL/Lazy.h +++ b/Filtered_kernel/include/CGAL/Lazy.h @@ -718,17 +718,17 @@ public : Lazy(Self_rep *r) { - PTR.p = r; + PTR = r; } Lazy(const ET& e) { - PTR.p = new Lazy_rep_0(e); + PTR = new Lazy_rep_0(e); } Lazy(ET&& e) { - PTR.p = new Lazy_rep_0(std::move(e)); + PTR = new Lazy_rep_0(std::move(e)); } friend void swap(Lazy& a, Lazy& b) noexcept @@ -768,7 +768,7 @@ public : return z; } - Self_rep * ptr() const { return (Self_rep*) PTR.p; } + Self_rep * ptr() const { return (Self_rep*) PTR; } }; // The magic functor for Construct_bbox_[2,3], as there is no Lazy diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h index 982c8a2a750..3a42574fa9d 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/Aff_transformationH2.h @@ -771,6 +771,17 @@ operator*(const Aff_transformationH2& right_argument) const right_argument.Ptr()->general_form() ); } +template +std::ostream& +operator<<(std::ostream& out, const Aff_transformationH2& t) +{ + typename R::RT RT0(0); + Aff_transformation_repH2 r = t.Ptr()->general_form(); + return out << "| "<< r.a << ' ' << r.b << ' ' << r.c << " |\n" + << "| "<< r.d << ' ' << r.e << ' ' << r.f << " |\n" + << "| "<< RT0 << ' ' << RT0 << ' ' << r.g << " |\n"; +} + template Aff_transformationH2 _general_transformation_composition( Aff_transformation_repH2 l, diff --git a/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h b/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h index 601f4d3e9d6..382c80e2c0b 100644 --- a/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h +++ b/Inscribed_areas/include/CGAL/Largest_empty_iso_rectangle_2.h @@ -233,12 +233,11 @@ public: ~Largest_empty_iso_rectangle_2(); //! An operator= - Largest_empty_iso_rectangle_2& - operator =(const Largest_empty_iso_rectangle_2& ler); + Largest_empty_iso_rectangle_2& + operator =(const Largest_empty_iso_rectangle_2& ler); //! A copy constructor - Largest_empty_iso_rectangle_2( - const Largest_empty_iso_rectangle_2& ler); + Largest_empty_iso_rectangle_2(const Largest_empty_iso_rectangle_2& ler); struct Internal_point { Point_2 x_part;// the x coordinate of the point diff --git a/Installation/CGALConfigVersion.cmake b/Installation/CGALConfigVersion.cmake new file mode 100644 index 00000000000..9b0b10600b1 --- /dev/null +++ b/Installation/CGALConfigVersion.cmake @@ -0,0 +1 @@ +include(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/Installation/CHANGES.md b/Installation/CHANGES.md index dbc8910ac48..dd77b957e8f 100644 --- a/Installation/CHANGES.md +++ b/Installation/CHANGES.md @@ -21,6 +21,15 @@ Release History the signed distance of two points to a line, or the line passing through two given points. Corresponding functors in the model (`Compare_signed_distance_to_line_2`) are also added. +### Point Set Processing + - Add a function `CGAL::cluster_point_set()` that segments a point + cloud into connected components based on a distance threshold. + - **Breaking change:** `CGAL::remove_outliers()` has been + parallelized and thus has a new template parameter + `ConcurrencyTag`. To update your code simply add as first template + parameter `CGAL::Sequential_tag` or `CGAL::Parallel_tag` when + calling this function. + ### 2D Triangulations - Add function `split_subconstraint_graph_into_constraints()` to `Constrained_triangulation_plus_2` to initialize the constraints @@ -37,11 +46,31 @@ Release History is given an optional template parameter `ConcurrencyTag` (default value remains `CGAL::Sequential_tag` for backward compatibility). +### Surface Mesh + + - **Breaking change**: The function `CGAL::Surface_mesh::clear()` now removes all non-default properties instead of just emptying them. + Release 5.0 ----------- Release date: June 2020 +### 2D Arrangement on Surface + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant` in all traits concepts and models. + As there is an implicit conversion from `boost::variant` to `CGAL::Object`, the + new code is backward compatible. However, it is recommended that all calls + to the intersection functions are fixed to use the new return type. + +### 2D Regularized Boolean Operations + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant` in the concept `ArrDirectionalTraits::Intersect_2` and + its models.. + +### 2D Minkowski sums + - Changed intersection return type from legacy `CGAL::Object` to modern + `boost::variant` in the (internally used) model `Arr_labeled_traits_2`. + ### Surface Mesh Topology (new package) - This package allows to compute some topological invariants of diff --git a/Installation/CMakeLists.txt b/Installation/CMakeLists.txt index ad6e3b6e3cd..42dfeb8190a 100644 --- a/Installation/CMakeLists.txt +++ b/Installation/CMakeLists.txt @@ -20,7 +20,7 @@ if(POLICY CMP0056) cmake_policy(SET CMP0056 NEW) endif() -# Use GNUInstallDirst to get canonical paths +# Use GNUInstallDirs to get canonical paths include(GNUInstallDirs) #-------------------------------------------------------------------------------------------------- @@ -135,10 +135,6 @@ if ( CGAL_BRANCH_BUILD ) # Create version files # - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/MAJOR_NUMBER" CGAL_MAJOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/MINOR_NUMBER" CGAL_MINOR_VERSION REGEX "[0-9]*") - file(STRINGS "${CGAL_MAINTENANCE_PACKAGE_DIR}/release_building/BUGFIX_NUMBER" CGAL_BUGFIX_VERSION REGEX "[0-9]*") - file(REMOVE ${CMAKE_BINARY_DIR}/VERSION) if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") @@ -765,11 +761,11 @@ set ( CGAL_INSTALL_CMAKE_DIR "${CGAL_INSTALL_LIB_DIR}/cmake/CGAL" CACHE STRING "The folder where CGAL CMake modules will be installed, relative to CMAKE_INSTALL_PREFIX" ) -set ( CGAL_INSTALL_DOC_DIR "${CMAKE_INSTALL_DATAROOTDIR}/doc/${CGAL_VERSION_DIR}" +set ( CGAL_INSTALL_DOC_DIR "${CMAKE_INSTALL_DOCDIR}" CACHE STRING "The folder where CGAL documentation and license files will be installed, relative to CMAKE_INSTALL_PREFIX" ) -set ( CGAL_INSTALL_MAN_DIR "${CMAKE_INSTALL_DATAROOTDIR}/man/man1" +set ( CGAL_INSTALL_MAN_DIR "${CMAKE_INSTALL_MANDIR}/man1" CACHE STRING "The folder where manual pages for CGAL scripts will be installed, relative to CMAKE_INSTALL_PREFIX" ) @@ -863,6 +859,8 @@ if(NOT CGAL_HEADER_ONLY) else() configure_file("${CGAL_MODULES_DIR}/CGALConfig_binary_header_only.cmake.in" "${CMAKE_BINARY_DIR}/CGALConfig.cmake" @ONLY) + configure_file("${CGAL_MODULES_DIR}/CGALConfigVersion_binary_header_only.cmake.in" + "${CMAKE_BINARY_DIR}/CGALConfigVersion.cmake" @ONLY) endif() #-------------------------------------------------------------------------------------------------- @@ -916,12 +914,17 @@ if(NOT CGAL_HEADER_ONLY) ${CMAKE_BINARY_DIR}/config/CGALConfig.cmake DESTINATION ${CGAL_INSTALL_CMAKE_DIR} ) else() - configure_file(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig-installation-dirs.cmake.in - ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake) install(FILES - ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake ${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig.cmake - DESTINATION ${CGAL_INSTALL_CMAKE_DIR} ) + ${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfigVersion.cmake + DESTINATION ${CGAL_INSTALL_CMAKE_DIR}) + if(NOT CGAL_INSTALL_CMAKE_DIR STREQUAL "${CGAL_INSTALL_LIB_DIR}/cmake/CGAL") + configure_file(${CMAKE_CURRENT_LIST_DIR}/lib/cmake/CGAL/CGALConfig-installation-dirs.cmake.in + ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake) + install(FILES + ${CMAKE_BINARY_DIR}/config/CGALConfig-installation-dirs.cmake + DESTINATION ${CGAL_INSTALL_CMAKE_DIR}) + endif() endif() if(CGAL_INSTALL_MAN_DIR) @@ -1369,4 +1372,3 @@ if(NOT CGAL_BRANCH_BUILD AND EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/doc") # in a non-branch build this is the top-level CMakeLists.txt add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/doc") endif() - diff --git a/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in b/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in new file mode 100644 index 00000000000..9b30fbcad5f --- /dev/null +++ b/Installation/cmake/modules/CGALConfigVersion_binary_header_only.cmake.in @@ -0,0 +1,5 @@ +# +# This file points to the CGALConfigVersion.cmake for header-only CGAL. +# + +include(@CGAL_INSTALLATION_PACKAGE_DIR@/lib/cmake/CGAL/CGALConfigVersion.cmake) diff --git a/Installation/cmake/modules/CGAL_Macros.cmake b/Installation/cmake/modules/CGAL_Macros.cmake index 4d501fa5ce5..cbd17669609 100644 --- a/Installation/cmake/modules/CGAL_Macros.cmake +++ b/Installation/cmake/modules/CGAL_Macros.cmake @@ -397,7 +397,7 @@ if( NOT CGAL_MACROS_FILE_INCLUDED ) # CGALConfig.cmake is platform specific so it is generated and stored in the binary folder. configure_file("${CGAL_MODULES_DIR}/CGALConfig_binary.cmake.in" "${CMAKE_BINARY_DIR}/CGALConfig.cmake" @ONLY) write_basic_package_version_file("${CMAKE_BINARY_DIR}/CGALConfigVersion.cmake" - VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUILD_VERSION}" + VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}" COMPATIBILITY SameMajorVersion) # There is also a version of CGALConfig.cmake that is prepared in case CGAL in installed in CMAKE_INSTALL_PREFIX. diff --git a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake index 9125a477c93..6590e31f940 100644 --- a/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake +++ b/Installation/cmake/modules/CGAL_SetupCGALDependencies.cmake @@ -85,7 +85,7 @@ function(CGAL_setup_CGAL_dependencies target) set(keyword PUBLIC) endif() if(CGAL_DISABLE_GMP) - target_compile_definitions(${target} ${keyword} CGAL_DISABLE_GMP=1) + target_compile_definitions(${target} ${keyword} CGAL_DISABLE_GMP=1) else() use_CGAL_GMP_support(${target} ${keyword}) set(CGAL_USE_GMP TRUE CACHE INTERNAL "CGAL library is configured to use GMP") @@ -95,7 +95,7 @@ function(CGAL_setup_CGAL_dependencies target) if(WITH_LEDA) use_CGAL_LEDA_support(${target} ${keyword}) endif() - + if (NOT CGAL_HEADER_ONLY) target_compile_definitions(${target} ${keyword} CGAL_NOT_HEADER_ONLY=1) endif() @@ -136,6 +136,12 @@ function(CGAL_setup_CGAL_dependencies target) $<$:/bigobj> # Use /bigobj by default ) endif() + elseif ("${CMAKE_CXX_COMPILER_ID}" MATCHES "AppleClang") + if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 11.0.3) + message(STATUS "Apple Clang version ${CMAKE_CXX_COMPILER_VERSION} compiler detected") + message(STATUS "Boost MP is turned off for all Apple Clang versions below 11.0.3!") + target_compile_options(${target} ${keyword} "-DCGAL_DO_NOT_USE_BOOST_MP") + endif() elseif(CMAKE_CXX_COMPILER_ID MATCHES "Intel") message( STATUS "Using Intel Compiler. Adding -fp-model strict" ) if(WIN32) @@ -166,7 +172,7 @@ function(CGAL_setup_CGAL_dependencies target) endif() if ( "${CMAKE_SYSTEM_PROCESSOR}" MATCHES "alpha" ) message( STATUS "Using gcc on alpha. Adding -mieee -mfp-rounding-mode=d" ) - target_compile_options(${target} ${keyword} "-mieee -mfp-rounding-mode=d" ) + target_compile_options(${target} ${keyword} "-mieee" "-mfp-rounding-mode=d" ) endif() endif() endfunction() diff --git a/Installation/cmake/modules/CGAL_add_test.cmake b/Installation/cmake/modules/CGAL_add_test.cmake index 5579413e177..ea86b4d64f1 100644 --- a/Installation/cmake/modules/CGAL_add_test.cmake +++ b/Installation/cmake/modules/CGAL_add_test.cmake @@ -104,12 +104,10 @@ function(cgal_add_compilation_test exe_name) if(NOT TARGET cgal_check_build_system) add_custom_target(cgal_check_build_system) add_dependencies( ALL_CGAL_TARGETS cgal_check_build_system ) - endif() - if(NOT TEST check_build_system) add_test(NAME "check_build_system" COMMAND "${CMAKE_COMMAND}" --build "${CMAKE_BINARY_DIR}" --target "cgal_check_build_system" --config "$") set_property(TEST "check_build_system" - APPEND PROPERTY LABELS "Installation") + APPEND PROPERTY LABELS "${PROJECT_NAME}") if(POLICY CMP0066) # cmake 3.7 or later set_property(TEST "check_build_system" PROPERTY FIXTURES_SETUP "check_build_system_SetupFixture") diff --git a/Installation/cmake/modules/CGAL_parse_version_h.cmake b/Installation/cmake/modules/CGAL_parse_version_h.cmake index c7b134d4229..fa0b22cd316 100644 --- a/Installation/cmake/modules/CGAL_parse_version_h.cmake +++ b/Installation/cmake/modules/CGAL_parse_version_h.cmake @@ -11,7 +11,8 @@ function(cgal_parse_version_h version_h_file name) # CMAKE_MATCH_3 and CMAKE_MATCH_4 corresponds to the two sub-expressions # of the alternative, and cannot be non-empty at the same time. set(${ARGV2} "${CMAKE_MATCH_3}${CMAKE_MATCH_4}" PARENT_SCOPE) # major version - set(${ARGV3} "${CMAKE_MATCH_5}" PARENT_SCOPE) # minor version + MATH(EXPR ${ARGV3} "${CMAKE_MATCH_5}") # minor version without leading 0 + set(${ARGV3} "${${ARGV3}}" PARENT_SCOPE) set(${ARGV4} "${CMAKE_MATCH_6}" PARENT_SCOPE) # patch number set(${ARGV5} "${CMAKE_MATCH_7}" PARENT_SCOPE) # build number endfunction() diff --git a/Installation/include/CGAL/config.h b/Installation/include/CGAL/config.h index a215cbbf4e5..181ba462b31 100644 --- a/Installation/include/CGAL/config.h +++ b/Installation/include/CGAL/config.h @@ -36,6 +36,10 @@ # define WIN64 #endif +#ifdef BOOST_MSVC +#define _SILENCE_CXX17_ALLOCATOR_VOID_DEPRECATION_WARNING 1 +#endif + #ifdef CGAL_INCLUDE_WINDOWS_DOT_H // Mimic users including this file which defines min max macros // and other names leading to name clashes @@ -546,13 +550,9 @@ using std::max; #endif // Macro to specify a 'noreturn' attribute. -#if defined(__GNUG__) || __has_attribute(__noreturn__) -# define CGAL_NORETURN __attribute__ ((__noreturn__)) -#elif defined (_MSC_VER) -# define CGAL_NORETURN __declspec(noreturn) -#else -# define CGAL_NORETURN -#endif +// (This macro existed in CGAL before we switched to C++11. Let's keep +// the macro defined for backward-compatibility. That cannot harm.) +#define CGAL_NORETURN [[noreturn]] // Macro to specify [[no_unique_address]] if supported #if __has_cpp_attribute(no_unique_address) @@ -740,5 +740,4 @@ typedef const void * Nullptr_t; // Anticipate C++0x's std::nullptr_t /// @} #include - #endif // CGAL_CONFIG_H diff --git a/Installation/include/CGAL/license/Tetrahedral_remeshing.h b/Installation/include/CGAL/license/Tetrahedral_remeshing.h new file mode 100644 index 00000000000..10c8d9e138d --- /dev/null +++ b/Installation/include/CGAL/license/Tetrahedral_remeshing.h @@ -0,0 +1,54 @@ +// Copyright (c) 2016 GeometryFactory SARL (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) : Andreas Fabri +// +// Warning: this file is generated, see include/CGAL/licence/README.md + +#ifndef CGAL_LICENSE_TETRAHEDRAL_REMESHING_H +#define CGAL_LICENSE_TETRAHEDRAL_REMESHING_H + +#include +#include + +#ifdef CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +# if CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +# if defined(CGAL_LICENSE_WARNING) + + CGAL_pragma_warning("Your commercial license for CGAL does not cover " + "this release of the Tetrahedral Remeshing package.") +# endif + +# ifdef CGAL_LICENSE_ERROR +# error "Your commercial license for CGAL does not cover this release \ + of the Tetrahedral Remeshing package. \ + You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +# endif // CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE < CGAL_RELEASE_DATE + +#else // no CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +# if defined(CGAL_LICENSE_WARNING) + CGAL_pragma_warning("\nThe macro CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE is not defined." + "\nYou use the CGAL Tetrahedral Remeshing package under " + "the terms of the GPLv3+.") +# endif // CGAL_LICENSE_WARNING + +# ifdef CGAL_LICENSE_ERROR +# error "The macro CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE is not defined.\ + You use the CGAL Tetrahedral Remeshing package under the terms of \ + the GPLv3+. You get this error, as you defined CGAL_LICENSE_ERROR." +# endif // CGAL_LICENSE_ERROR + +#endif // no CGAL_TETRAHEDRAL_REMESHING_COMMERCIAL_LICENSE + +#endif // CGAL_LICENSE_TETRAHEDRAL_REMESHING_H diff --git a/Installation/include/CGAL/license/gpl_package_list.txt b/Installation/include/CGAL/license/gpl_package_list.txt index 57a8ac6662c..f249f09b1ac 100644 --- a/Installation/include/CGAL/license/gpl_package_list.txt +++ b/Installation/include/CGAL/license/gpl_package_list.txt @@ -93,3 +93,4 @@ Triangulation_3 3D Triangulations Triangulation dD Triangulations Visibility_2 2D Visibility Computation Voronoi_diagram_2 2D Voronoi Diagram Adaptor +Tetrahedral_remeshing Tetrahedral Remeshing diff --git a/Installation/lib/cmake/CGAL/CGALConfig.cmake b/Installation/lib/cmake/CGAL/CGALConfig.cmake index 50f2ed24e1c..de6a495a1bc 100644 --- a/Installation/lib/cmake/CGAL/CGALConfig.cmake +++ b/Installation/lib/cmake/CGAL/CGALConfig.cmake @@ -1,4 +1,4 @@ -# +# # This file is the CGALConfig.cmake for a header-only CGAL installation # @@ -53,6 +53,9 @@ else() if(NOT EXISTS ${CGAL_ROOT}/include/CGAL/config.h) get_filename_component(CGAL_ROOT "${CGAL_ROOT}" DIRECTORY) endif() + if(NOT EXISTS ${CGAL_ROOT}/include/CGAL/config.h) + get_filename_component(CGAL_ROOT "${CGAL_ROOT}" DIRECTORY) + endif() endif() # not BRANCH_BUILD: it can be an installed CGAL, or the tarball layout if(EXISTS ${CGAL_CONFIG_DIR}/CGAL_add_test.cmake) @@ -156,7 +159,17 @@ endforeach() cgal_setup_module_path() set(CGAL_USE_FILE ${CGAL_MODULES_DIR}/UseCGAL.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_IOStreams.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Boost_Serialization.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_Eigen.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_GLPK.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_LASLIB.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenCV.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_OpenGR.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_SCIP.cmake) include(${CGAL_MODULES_DIR}/CGAL_target_use_TBB.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_TensorFlow.cmake) +include(${CGAL_MODULES_DIR}/CGAL_target_use_pointmatcher.cmake) include("${CGAL_MODULES_DIR}/CGAL_parse_version_h.cmake") cgal_parse_version_h( "${CGAL_INSTALLATION_PACKAGE_DIR}/include/CGAL/version.h" diff --git a/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake new file mode 100644 index 00000000000..bfc6a1fa17d --- /dev/null +++ b/Installation/lib/cmake/CGAL/CGALConfigVersion.cmake @@ -0,0 +1,26 @@ +set(CGAL_MAJOR_VERSION 5) +set(CGAL_MINOR_VERSION 1) +set(CGAL_BUGFIX_VERSION 0) +set(CGAL_VERSION_PUBLIC_RELEASE_VERSION "5.1-dev") +set(CGAL_VERSION_PUBLIC_RELEASE_NAME "CGAL-${CGAL_VERSION_PUBLIC_RELEASE_VERSION}") + +if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) + set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") +else() + set(CGAL_CREATED_VERSION_NUM "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}") +endif() + +set(PACKAGE_VERSION ${CGAL_CREATED_VERSION_NUM}) + +if(PACKAGE_VERSION VERSION_LESS PACKAGE_FIND_VERSION) + set(PACKAGE_VERSION_COMPATIBLE FALSE) +else() + if(PACKAGE_FIND_VERSION_MAJOR STREQUAL CGAL_MAJOR_VERSION) + set(PACKAGE_VERSION_COMPATIBLE TRUE) + else() + set(PACKAGE_VERSION_COMPATIBLE FALSE) + endif() + if(PACKAGE_FIND_VERSION STREQUAL PACKAGE_VERSION) + set(PACKAGE_VERSION_EXACT TRUE) + endif() +endif() diff --git a/Installation/test/Installation/CMakeLists.txt b/Installation/test/Installation/CMakeLists.txt index cba75d0bb15..47debb2ff63 100644 --- a/Installation/test/Installation/CMakeLists.txt +++ b/Installation/test/Installation/CMakeLists.txt @@ -99,3 +99,43 @@ else() message(STATUS "NOTICE: This program requires the CGAL library, and will not be compiled.") endif() + +function(CGAL_installation_test_find_package_version mode) + set(EXACT) + if(mode STREQUAL "less") + set(CGAL_MINOR_VERSION 0) + endif() + if(mode STREQUAL "less_major") + set(CGAL_MAJOR_VERSION 0) + endif() + if(mode STREQUAL "greater" OR mode STREQUAL "fail-exact") + MATH(EXPR CGAL_MINOR_VERSION "${CGAL_MINOR_VERSION} + 1") + endif() + if(mode STREQUAL "exact" OR mode STREQUAL "fail-exact") + set(EXACT "EXACT ") + endif() + if (CGAL_BUGFIX_VERSION AND CGAL_BUGFIX_VERSION GREATER 0) + set(VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}.${CGAL_BUGFIX_VERSION}") + else() + set(VERSION "${CGAL_MAJOR_VERSION}.${CGAL_MINOR_VERSION}") + endif() + 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) + cgal_setup_test_properties(test_find_package_version_${mode}) +endfunction() + +CGAL_installation_test_find_package_version(less) +CGAL_installation_test_find_package_version(less_major) +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) diff --git a/Installation/test/Installation/test_find_package.cmake.in b/Installation/test/Installation/test_find_package.cmake.in new file mode 100644 index 00000000000..fc7152ef4d4 --- /dev/null +++ b/Installation/test/Installation/test_find_package.cmake.in @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION ${CMAKE_VERSION}) +project( test_find_package_${mode} ) +find_package(CGAL ${VERSION} ${EXACT}REQUIRED + PATHS ${CGAL_DIR} + NO_DEFAULT_PATH + NO_PACKAGE_ROOT_PATH + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_PACKAGE_REGISTRY + NO_CMAKE_BUILDS_PATH + NO_CMAKE_SYSTEM_PATH + NO_CMAKE_SYSTEM_PACKAGE_REGISTRY + ) diff --git a/Interpolation/include/CGAL/interpolation_functions.h b/Interpolation/include/CGAL/interpolation_functions.h index 58780776458..0c672580504 100644 --- a/Interpolation/include/CGAL/interpolation_functions.h +++ b/Interpolation/include/CGAL/interpolation_functions.h @@ -34,7 +34,7 @@ struct Data_access typedef typename Map::mapped_type Data_type; typedef typename Map::key_type Key_type; - Data_access(const Map& m): map(m){} + Data_access(const Map& m): map(m){} std::pair< Data_type, bool> operator()(const Key_type& p) const diff --git a/Interval_skip_list/include/CGAL/Interval_skip_list.h b/Interval_skip_list/include/CGAL/Interval_skip_list.h index 33a2ad9f195..a445981a3f2 100644 --- a/Interval_skip_list/include/CGAL/Interval_skip_list.h +++ b/Interval_skip_list/include/CGAL/Interval_skip_list.h @@ -115,7 +115,7 @@ class Interval_for_container : public Interval_ {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } }; @@ -457,7 +457,7 @@ class Interval_for_container : public Interval_ public: #ifdef CGAL_ISL_USE_CCC void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } #endif bool operator==(const IntervalListElt& e) diff --git a/Kernel_23/include/CGAL/determinant.h b/Kernel_23/include/CGAL/determinant.h index fe14a2d1974..f470720d560 100644 --- a/Kernel_23/include/CGAL/determinant.h +++ b/Kernel_23/include/CGAL/determinant.h @@ -202,6 +202,204 @@ determinant( return m012345; } +template +RT +determinant( + const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, const RT& a65, const RT& a66) +{ +// First compute the det2x2 + const RT m01 = a00*a11 - a10*a01; + const RT m02 = a00*a21 - a20*a01; + const RT m03 = a00*a31 - a30*a01; + const RT m04 = a00*a41 - a40*a01; + const RT m05 = a00*a51 - a50*a01; + const RT m06 = a00*a61 - a60*a01; + + const RT m12 = a10*a21 - a20*a11; + const RT m13 = a10*a31 - a30*a11; + const RT m14 = a10*a41 - a40*a11; + const RT m15 = a10*a51 - a50*a11; + const RT m16 = a10*a61 - a60*a11; + + const RT m23 = a20*a31 - a30*a21; + const RT m24 = a20*a41 - a40*a21; + const RT m25 = a20*a51 - a50*a21; + const RT m26 = a20*a61 - a60*a21; + + const RT m34 = a30*a41 - a40*a31; + const RT m35 = a30*a51 - a50*a31; + const RT m36 = a30*a61 - a60*a31; + + const RT m45 = a40*a51 - a50*a41; + const RT m46 = a40*a61 - a60*a41; + + const RT m56 = a50*a61 - a60*a51; + +// Now compute the minors of rank 3 + const RT m012 = m01*a22 - m02*a12 + m12*a02; + const RT m013 = m01*a32 - m03*a12 + m13*a02; + const RT m014 = m01*a42 - m04*a12 + m14*a02; + const RT m015 = m01*a52 - m05*a12 + m15*a02; + const RT m016 = m01*a62 - m06*a12 + m16*a02; + + const RT m023 = m02*a32 - m03*a22 + m23*a02; + const RT m024 = m02*a42 - m04*a22 + m24*a02; + const RT m025 = m02*a52 - m05*a22 + m25*a02; + const RT m026 = m02*a62 - m06*a22 + m26*a02; + const RT m034 = m03*a42 - m04*a32 + m34*a02; + const RT m035 = m03*a52 - m05*a32 + m35*a02; + const RT m036 = m03*a62 - m06*a32 + m36*a02; + + const RT m045 = m04*a52 - m05*a42 + m45*a02; + const RT m046 = m04*a62 - m06*a42 + m46*a02; + + const RT m056 = m05*a62 - m06*a52 + m56*a02; + + + const RT m123 = m12*a32 - m13*a22 + m23*a12; + const RT m124 = m12*a42 - m14*a22 + m24*a12; + const RT m125 = m12*a52 - m15*a22 + m25*a12; + const RT m126 = m12*a62 - m16*a22 + m26*a12; + + const RT m134 = m13*a42 - m14*a32 + m34*a12; + const RT m135 = m13*a52 - m15*a32 + m35*a12; + const RT m136 = m13*a62 - m16*a32 + m36*a12; + + const RT m145 = m14*a52 - m15*a42 + m45*a12; + const RT m146 = m14*a62 - m16*a42 + m46*a12; + + const RT m156 = m15*a62 - m16*a52 + m56*a12; + + const RT m234 = m23*a42 - m24*a32 + m34*a22; + const RT m235 = m23*a52 - m25*a32 + m35*a22; + const RT m236 = m23*a62 - m26*a32 + m36*a22; + + const RT m245 = m24*a52 - m25*a42 + m45*a22; + const RT m246 = m24*a62 - m26*a42 + m46*a22; + + const RT m256 = m25*a62 - m26*a52 + m56*a22; + + const RT m345 = m34*a52 - m35*a42 + m45*a32; + const RT m346 = m34*a62 - m36*a42 + m46*a32; + + const RT m356 = m35*a62 - m36*a52 + m56*a32; + + const RT m456 = m45*a62 - m46*a52 + m56*a42; + +// Now compute the minors of rank 4 + const RT m0123 = m012*a33 - m013*a23 + m023*a13 - m123*a03; + + const RT m0124 = m012*a43 - m014*a23 + m024*a13 - m124*a03; + const RT m0125 = m012*a53 - m015*a23 + m025*a13 - m125*a03; + const RT m0126 = m012*a63 - m016*a23 + m026*a13 - m126*a03; + + const RT m0134 = m013*a43 - m014*a33 + m034*a13 - m134*a03; + const RT m0135 = m013*a53 - m015*a33 + m035*a13 - m135*a03; + const RT m0136 = m013*a63 - m016*a33 + m036*a13 - m136*a03; + + const RT m0145 = m014*a53 - m015*a43 + m045*a13 - m145*a03; + const RT m0146 = m014*a63 - m016*a43 + m046*a13 - m146*a03; + + const RT m0156 = m015*a63 - m016*a53 + m056*a13 - m156*a03; + + const RT m0234 = m023*a43 - m024*a33 + m034*a23 - m234*a03; + const RT m0235 = m023*a53 - m025*a33 + m035*a23 - m235*a03; + const RT m0236 = m023*a63 - m026*a33 + m036*a23 - m236*a03; + + const RT m0245 = m024*a53 - m025*a43 + m045*a23 - m245*a03; + const RT m0246 = m024*a63 - m026*a43 + m046*a23 - m246*a03; + + const RT m0256 = m025*a63 - m026*a53 + m056*a23 - m256*a03; + + const RT m0345 = m034*a53 - m035*a43 + m045*a33 - m345*a03; + const RT m0346 = m034*a63 - m036*a43 + m046*a33 - m346*a03; + + const RT m0356 = m035*a63 - m036*a53 + m056*a33 - m356*a03; + + const RT m0456 = m045*a63 - m046*a53 + m056*a43 - m456*a03; + + const RT m1234 = m123*a43 - m124*a33 + m134*a23 - m234*a13; + const RT m1235 = m123*a53 - m125*a33 + m135*a23 - m235*a13; + const RT m1236 = m123*a63 - m126*a33 + m136*a23 - m236*a13; + + const RT m1245 = m124*a53 - m125*a43 + m145*a23 - m245*a13; + const RT m1246 = m124*a63 - m126*a43 + m146*a23 - m246*a13; + + const RT m1256 = m125*a63 - m126*a53 + m156*a23 - m256*a13; + + const RT m1345 = m134*a53 - m135*a43 + m145*a33 - m345*a13; + const RT m1346 = m134*a63 - m136*a43 + m146*a33 - m346*a13; + + const RT m1356 = m135*a63 - m136*a53 + m156*a33 - m356*a13; + const RT m1456 = m145*a63 - m146*a53 + m156*a43 - m456*a13; + + const RT m2345 = m234*a53 - m235*a43 + m245*a33 - m345*a23; + const RT m2346 = m234*a63 - m236*a43 + m246*a33 - m346*a23; + + const RT m2356 = m235*a63 - m236*a53 + m256*a33 - m356*a23; + const RT m2456 = m245*a63 - m246*a53 + m256*a43 - m456*a23; + + const RT m3456 = m345*a63 - m346*a53 + m356*a43 - m456*a33; + + + // Now compute the minors of rank 5 + const RT m01234 = m0123*a44 - m0124*a34 + m0134*a24 - m0234*a14 + m1234*a04; + + const RT m01235 = m0123*a54 - m0125*a34 + m0135*a24 - m0235*a14 + m1235*a04; + + const RT m01236 = m0123*a64 - m0126*a34 + m0136*a24 - m0236*a14 + m1236*a04; + + const RT m01245 = m0124*a54 - m0125*a44 + m0145*a24 - m0245*a14 + m1245*a04; + const RT m01246 = m0124*a64 - m0126*a44 + m0146*a24 - m0246*a14 + m1246*a04; + + const RT m01256 = m0125*a64 - m0126*a54 + m0156*a24 - m0256*a14 + m1256*a04; + + const RT m01345 = m0134*a54 - m0135*a44 + m0145*a34 - m0345*a14 + m1345*a04; + const RT m01346 = m0134*a64 - m0136*a44 + m0146*a34 - m0346*a14 + m1346*a04; + + const RT m01356 = m0135*a64 - m0136*a54 + m0156*a34 - m0356*a14 + m1356*a04; + const RT m01456 = m0145*a64 - m0146*a54 + m0156*a44 - m0456*a14 + m1456*a04; + + const RT m02345 = m0234*a54 - m0235*a44 + m0245*a34 - m0345*a24 + m2345*a04; + const RT m02346 = m0234*a64 - m0236*a44 + m0246*a34 - m0346*a24 + m2346*a04; + + const RT m02356 = m0235*a64 - m0236*a54 + m0256*a34 - m0356*a24 + m2356*a04; + const RT m02456 = m0245*a64 - m0246*a54 + m0256*a44 - m0456*a24 + m2456*a04; + const RT m03456 = m0345*a64 - m0346*a54 + m0356*a44 - m0456*a34 + m3456*a04; + + const RT m12345 = m1234*a54 - m1235*a44 + m1245*a34 - m1345*a24 + m2345*a14; + const RT m12346 = m1234*a64 - m1236*a44 + m1246*a34 - m1346*a24 + m2346*a14; + + + const RT m12356 = m1235*a64 - m1236*a54 + m1256*a34 - m1356*a24 + m2356*a14; + const RT m12456 = m1245*a64 - m1246*a54 + m1256*a44 - m1456*a24 + m2456*a14; + const RT m13456 = m1345*a64 - m1346*a54 + m1356*a44 - m1456*a34 + m3456*a14; + + const RT m23456 = m2345*a64 - m2346*a54 + m2356*a44 - m2456*a34 + m3456*a24; + +// Now compute the minors of rank 6 + const RT m012345 = m01234*a55 - m01235*a45 + m01245*a35 - m01345*a25 + m02345*a15 - m12345*a05; + const RT m012346 = m01234*a65 - m01236*a45 + m01246*a35 - m01346*a25 + m02346*a15 - m12346*a05; + const RT m012356 = m01235*a65 - m01236*a55 + m01256*a35 - m01356*a25 + m02356*a15 - m12356*a05; + const RT m012456 = m01245*a65 - m01246*a55 + m01256*a45 - m01456*a25 + m02456*a15 - m12456*a05; + const RT m013456 = m01345*a65 - m01346*a55 + m01356*a45 - m01456*a35 + m03456*a15 - m13456*a05; + const RT m023456 = m02345*a65 - m02346*a55 + m02356*a45 - m02456*a35 + m03456*a25 - m23456*a05; + const RT m123456 = m12345*a65 - m12346*a55 + m12356*a45 - m12456*a35 + m13456*a25 - m23456*a15; + + + // Now compute the minors of rank 7 + const RT m0123456 = m012345 * a66 - m012346 * a56 + m012356 * a46 - m012456 * a36 + m013456 * a26 - m023456 * a16 + m123456 * a06; + + return m0123456; +} + + } //namespace CGAL #endif // CGAL_DETERMINANT_H diff --git a/Kernel_23/test/Kernel_23/determinant_77.cpp b/Kernel_23/test/Kernel_23/determinant_77.cpp new file mode 100644 index 00000000000..c48be9908d8 --- /dev/null +++ b/Kernel_23/test/Kernel_23/determinant_77.cpp @@ -0,0 +1,121 @@ +#include +#include + +#include + +#include + +using CGAL::determinant; + +template +RT det_77_alt(const RT& a00, const RT& a01, const RT& a02, const RT& a03, const RT& a04, const RT& a05, const RT& a06, + const RT& a10, const RT& a11, const RT& a12, const RT& a13, const RT& a14, const RT& a15, const RT& a16, + const RT& a20, const RT& a21, const RT& a22, const RT& a23, const RT& a24, const RT& a25, const RT& a26, + const RT& a30, const RT& a31, const RT& a32, const RT& a33, const RT& a34, const RT& a35, const RT& a36, + const RT& a40, const RT& a41, const RT& a42, const RT& a43, const RT& a44, const RT& a45, const RT& a46, + const RT& a50, const RT& a51, const RT& a52, const RT& a53, const RT& a54, const RT& a55, const RT& a56, + const RT& a60, const RT& a61, const RT& a62, const RT& a63, const RT& a64, const RT& a65, const RT& a66) +{ + const RT r1 = a06 * determinant( + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r2 = - a16 * determinant(a00, a01, a02, a03, a04, a05, + + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r3 = a26 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r4 = - a36 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r5 = a46 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + + a50, a51, a52, a53, a54, a55, + a60, a61, a62, a63, a64, a65); + + const RT r6 = - a56 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + + a60, a61, a62, a63, a64, a65); + + const RT r7 = a66 * determinant(a00, a01, a02, a03, a04, a05, + a10, a11, a12, a13, a14, a15, + a20, a21, a22, a23, a24, a25, + a30, a31, a32, a33, a34, a35, + a40, a41, a42, a43, a44, a45, + a50, a51, a52, a53, a54, a55 + + ); + + return r1 + r2 + r3 + r4 + r5 + r6 + r7; +} + +int main(int, char**) +{ + assert(determinant(4, 5, 1, 4, 6, 3, 1, + 4, 3, 6, 4, 2, 7, 3, + 6, 3, 3, 6, 2, 4, 5, + 1, 4, 3, 5, 5, 6 ,1, + 1, 3, 2, 7, 9, 6, 1, + 7, 6, 5, 4, 6, 2, 2, + 2, 3, 5, 7, 4, 3, 3) == 763); + + CGAL::Random rnd; + std::cout << "Seed: " << rnd.get_seed() << std::endl; + + for(int k=0; k<100; ++k) + { + std::array, 7> mat; + for(int i=0; i<7; ++i) + for(int j=0; j<7; ++j) + mat[i][j] = rnd.get_int(-18, 18); + + const int det_1 = determinant(mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4], mat[0][5], mat[0][6], + mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4], mat[1][5], mat[1][6], + mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4], mat[2][5], mat[2][6], + mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4], mat[3][5], mat[3][6], + mat[4][0], mat[4][1], mat[4][2], mat[4][3], mat[4][4], mat[4][5], mat[4][6], + mat[0][0], mat[5][1], mat[5][2], mat[5][3], mat[5][4], mat[5][5], mat[5][6], + mat[6][0], mat[6][1], mat[6][2], mat[6][3], mat[6][4], mat[6][5], mat[6][6]); + + const int det_2 = det_77_alt(mat[0][0], mat[0][1], mat[0][2], mat[0][3], mat[0][4], mat[0][5], mat[0][6], + mat[1][0], mat[1][1], mat[1][2], mat[1][3], mat[1][4], mat[1][5], mat[1][6], + mat[2][0], mat[2][1], mat[2][2], mat[2][3], mat[2][4], mat[2][5], mat[2][6], + mat[3][0], mat[3][1], mat[3][2], mat[3][3], mat[3][4], mat[3][5], mat[3][6], + mat[4][0], mat[4][1], mat[4][2], mat[4][3], mat[4][4], mat[4][5], mat[4][6], + mat[0][0], mat[5][1], mat[5][2], mat[5][3], mat[5][4], mat[5][5], mat[5][6], + mat[6][0], mat[6][1], mat[6][2], mat[6][3], mat[6][4], mat[6][5], mat[6][6]); + + std::cout << "dets: " << det_1 << " " << det_2 << std::endl; + assert(det_1 == det_2); + } + + std::cout << "Done!" << std::endl; + return EXIT_SUCCESS; +} diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt deleted file mode 100644 index d21e9b70bb9..00000000000 --- a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/CMakeCache.txt +++ /dev/null @@ -1,761 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: c:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits -# It was generated by CMake: C:/dev/CMake/bin/cmake.exe -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Build shared libraries -BUILD_SHARED_LIBS:BOOL=ON - -//Build the testing tree. -BUILD_TESTING:BOOL=OFF - -//Activate the debug messages of the script FindBoost -Boost_DEBUG:BOOL=OFF - -//Path to a file. -Boost_INCLUDE_DIR:PATH=C:/3rdPartyLibs/boost/boost_1_67_0 - -//Value Computed by CMake -CGAL_BINARY_DIR:STATIC=C:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits - -//Link with static Boost libraries -CGAL_Boost_USE_STATIC_LIBS:BOOL=OFF - -//User-defined flags -CGAL_CXX_FLAGS:STRING= -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS /fp:strict /fp:except- /wd4503 /bigobj - -//Dependencies for the target -CGAL_Core_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;CGAL; - -//Set this to TRUE if you want to define or modify any of CMAKE_*_FLAGS. -// When this is FALSE, all the CMAKE_*_FLAGS flags are overriden -// with the values used when building the CGAL libs. For CGAL_*_flags -// (used for ADDITIONAL flags) , there is no need to set this to -// TRUE. -CGAL_DONT_OVERRIDE_CMAKE_FLAGS:BOOL=TRUE - -//Select to allow to preconfiguration of external libraries -CGAL_ENABLE_PRECONFIG:BOOL=ON - -//Enable the header only version of CGAL -CGAL_HEADER_ONLY:BOOL=OFF - -//The folder where CGAL user-side scripts will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_BIN_DIR:STRING=bin - -//The folder where CGAL CMake modules will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_CMAKE_DIR:STRING=lib/CGAL - -//The folder where CGAL documentation and license files will be -// installed, relative to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_DOC_DIR:STRING=C:/Program Files (x86)/CGAL/share/doc/CGAL-4.9 - -//The folder where CGAL header files will be installed, relative -// to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_INC_DIR:STRING=include - -//The folder where CGAL libraries will be installed, relative to -// CMAKE_INSTALL_PREFIX -CGAL_INSTALL_LIB_DIR:STRING=lib - -//The folder where manual pages for CGAL scripts will be installed, -// relative to CMAKE_INSTALL_PREFIX -CGAL_INSTALL_MAN_DIR:STRING=C:/Program Files (x86)/CGAL/share/man/man1 - -//Dependencies for the target -CGAL_ImageIO_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;CGAL;general;C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib; - -//Dependencies for the target -CGAL_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib; - -//Dependencies for the target -CGAL_Qt5_LIB_DEPENDS:STATIC=general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib;general;C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib;general;Qt5::OpenGL;general;Qt5::Svg;general;CGAL;general;glu32;general;opengl32; - -//Value Computed by CMake -CGAL_SOURCE_DIR:STATIC=C:/CGAL/CGAL-4.9 - -//Path to a program. -CMAKE_AR:FILEPATH=CMAKE_AR-NOTFOUND - -//Build type: Release or Debug -CMAKE_BUILD_TYPE:STRING=Debug - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//Semicolon separated list of supported configuration types, only -// supports Debug, Release, MinSizeRel, and RelWithDebInfo, anything -// else will be ignored. -CMAKE_CONFIGURATION_TYPES:STRING=Debug;Release;MinSizeRel;RelWithDebInfo - -//User-defined flags -CMAKE_CXX_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 /GR /EHsc -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS /fp:strict /fp:except- /wd4503 /bigobj /permissive- /std:c++latest - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Ob0 /Od /RTC1 - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_CXX_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DCGAL_NDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=/MD /O2 /Ob1 /DNDEBUG - -//Libraries linked by default with all C++ applications. -CMAKE_CXX_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING=/DWIN32 /D_WINDOWS /W3 - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=/D_DEBUG /MDd /Ob0 /Od /RTC1 - -//Flags used by the compiler during release builds for minimum -// size. -CMAKE_C_FLAGS_MINSIZEREL:STRING=/MD /O1 /Ob1 /DNDEBUG - -//Flags used by the compiler during release builds. -CMAKE_C_FLAGS_RELEASE:STRING=/MD /O2 /Ob2 /DCGAL_NDEBUG - -//Flags used by the compiler during release builds with debug info. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=/MD /O2 /Ob1 /DNDEBUG - -//Libraries linked by default with all C applications. -CMAKE_C_STANDARD_LIBRARIES:STRING=kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=/machine:x64 /INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING=/INCREMENTAL:NO /DEBUG:NONE - -//user executables (bin) -CMAKE_INSTALL_BINDIR:PATH=bin - -//read-only architecture-independent data (DATAROOTDIR) -CMAKE_INSTALL_DATADIR:PATH= - -//read-only architecture-independent data root (share) -CMAKE_INSTALL_DATAROOTDIR:PATH=share - -//documentation root (DATAROOTDIR/doc/PROJECT_NAME) -CMAKE_INSTALL_DOCDIR:PATH= - -//C header files (include) -CMAKE_INSTALL_INCLUDEDIR:PATH=include - -//info documentation (DATAROOTDIR/info) -CMAKE_INSTALL_INFODIR:PATH= - -//object code libraries (lib) -CMAKE_INSTALL_LIBDIR:PATH=lib - -//program executables (libexec) -CMAKE_INSTALL_LIBEXECDIR:PATH=libexec - -//locale-dependent data (DATAROOTDIR/locale) -CMAKE_INSTALL_LOCALEDIR:PATH= - -//modifiable single-machine data (var) -CMAKE_INSTALL_LOCALSTATEDIR:PATH=var - -//man documentation (DATAROOTDIR/man) -CMAKE_INSTALL_MANDIR:PATH= - -//C header files for non-gcc (/usr/include) -CMAKE_INSTALL_OLDINCLUDEDIR:PATH=/usr/include - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=C:/Program Files (x86)/CGAL - -//Run-time variable data (LOCALSTATEDIR/run) -CMAKE_INSTALL_RUNSTATEDIR:PATH= - -//system admin executables (sbin) -CMAKE_INSTALL_SBINDIR:PATH=sbin - -//modifiable architecture-independent data (com) -CMAKE_INSTALL_SHAREDSTATEDIR:PATH=com - -//read-only single-machine data (etc) -CMAKE_INSTALL_SYSCONFDIR:PATH=etc - -//Path to a program. -CMAKE_LINKER:FILEPATH=C:/Program Files (x86)/Microsoft Visual Studio/2017/Professional/VC/Tools/MSVC/14.11.25503/bin/HostX86/x64/link.exe - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=/machine:x64 /DEBUG:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=CGAL - -//RC compiler -CMAKE_RC_COMPILER:FILEPATH=rc - -//Flags for Windows Resource Compiler. -CMAKE_RC_FLAGS:STRING=/DWIN32 - -//Flags for Windows Resource Compiler during debug builds. -CMAKE_RC_FLAGS_DEBUG:STRING=/D_DEBUG - -//Flags for Windows Resource Compiler during release builds for -// minimum size. -CMAKE_RC_FLAGS_MINSIZEREL:STRING= - -//Flags for Windows Resource Compiler during release builds. -CMAKE_RC_FLAGS_RELEASE:STRING= - -//Flags for Windows Resource Compiler during release builds with -// debug info. -CMAKE_RC_FLAGS_RELWITHDEBINFO:STRING= - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=/machine:x64 /debug:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=OFF - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=OFF - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING=/machine:x64 /debug:NONE /INCREMENTAL:NO - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=OFF - -//The directory containing the ESBTL header files WITHOUT the ESBTL -// prefix -ESBTL_INCLUDE_DIR:PATH=C:/3rdPartyLibs/esbtl/include - -//The directory containing the GMP header files -GMP_INCLUDE_DIR:PATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include - -//Path to the GMP library -GMP_LIBRARIES:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib - -GMP_LIBRARIES_DIR:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib - -//The directory containing the MPFR header files -MPFR_INCLUDE_DIR:PATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include - -//Path to the MPFR library -MPFR_LIBRARIES:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib - -MPFR_LIBRARIES_DIR:FILEPATH=C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib - -//OpenGL library for win32 -OPENGL_gl_LIBRARY:STRING=opengl32 - -//GLU library for win32 -OPENGL_glu_LIBRARY:STRING=glu32 - -//The directory containing a CMake configuration file for Qt5Core. -Qt5Core_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Core - -//The directory containing a CMake configuration file for Qt5Gui. -Qt5Gui_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Gui - -//The directory containing a CMake configuration file for Qt5OpenGL. -Qt5OpenGL_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5OpenGL - -//The directory containing a CMake configuration file for Qt5Svg. -Qt5Svg_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Svg - -//The directory containing a CMake configuration file for Qt5Widgets. -Qt5Widgets_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5Widgets - -//The directory containing a CMake configuration file for Qt5. -Qt5_DIR:PATH=C:/3rdPartyLibs/Qt/5.9.1/msvc2017_64/lib/cmake/Qt5 - -//Select external library BLAS -WITH_BLAS:BOOL=OFF - -//Enable CGAL component CGAL_Core -WITH_CGAL_Core:BOOL=ON - -//Enable CGAL component CGAL_ImageIO -WITH_CGAL_ImageIO:BOOL=ON - -//Enable CGAL component CGAL_Qt5 -WITH_CGAL_Qt5:BOOL=ON - -//Select external library Coin3D -WITH_Coin3D:BOOL=OFF - -//Select external library ESBTL -WITH_ESBTL:BOOL=ON - -//Select external library Eigen3 -WITH_Eigen3:BOOL=OFF - -//Select external library GMP -WITH_GMP:BOOL=ON - -//Select external library IPE -WITH_IPE:BOOL=OFF - -//Select external library LAPACK -WITH_LAPACK:BOOL=OFF - -//Select external library LEDA -WITH_LEDA:BOOL=OFF - -//Select external library MPFI -WITH_MPFI:BOOL=OFF - -//Select external library MPFR -WITH_MPFR:BOOL=ON - -//Select external library NTL -WITH_NTL:BOOL=OFF - -//Select external library OpenGL -WITH_OpenGL:BOOL=OFF - -//Select external library OpenNL -WITH_OpenNL:BOOL=OFF - -//Select external library QGLViewer -WITH_QGLViewer:BOOL=OFF - -//Select external library RS -WITH_RS:BOOL=OFF - -//Select external library RS3 -WITH_RS3:BOOL=OFF - -//Select external library ZLIB -WITH_ZLIB:BOOL=ON - -//Select demos -WITH_demos:BOOL=OFF - -//Select examples -WITH_examples:BOOL=OFF - -//Path to a file. -ZLIB_INCLUDE_DIR:PATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include - -//Path to a library. -ZLIB_LIBRARY_DEBUG:FILEPATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib - -//Path to a library. -ZLIB_LIBRARY_RELEASE:FILEPATH=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: Boost_DEBUG -Boost_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: Boost_INCLUDE_DIR -Boost_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//Avoid future search of boost-cmake -Boost_NO_BOOST_CMAKE:INTERNAL=TRUE -CGAL_3RD_PARTY_DEFINITIONS:INTERNAL=-DBOOST_ALL_DYN_LINK -CGAL_3RD_PARTY_INCLUDE_DIRS:INTERNAL=C:/3rdPartyLibs/boost/boost_1_67_0 -CGAL_3RD_PARTY_LIBRARIES:INTERNAL= -CGAL_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_3RD_PARTY_PRECONFIGURED:INTERNAL= -//ADVANCED property for variable: CGAL_Boost_USE_STATIC_LIBS -CGAL_Boost_USE_STATIC_LIBS-ADVANCED:INTERNAL=1 -//Test CGAL_CFG_DENORMALS_COMPILE_BUG -CGAL_CFG_DENORMALS_COMPILE_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_DENORMALS_COMPILE_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG -CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG:INTERNAL= -//Result of TRY_COMPILE -CGAL_CFG_FPU_ROUNDING_MODE_UNWINDING_VC_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_IEEE_754_BUG -CGAL_CFG_IEEE_754_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_IEEE_754_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_ISTREAM_INT_BUG -CGAL_CFG_ISTREAM_INT_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_ISTREAM_INT_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_5 -CGAL_CFG_MATCHING_BUG_5:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_5_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_6 -CGAL_CFG_MATCHING_BUG_6:INTERNAL= -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_6_COMPILED:INTERNAL=FALSE -//Test CGAL_CFG_MATCHING_BUG_7 -CGAL_CFG_MATCHING_BUG_7:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_7_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_MATCHING_BUG_8 -CGAL_CFG_MATCHING_BUG_8:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_MATCHING_BUG_8_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG -CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NESTED_CLASS_FRIEND_DECLARATION_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_LIMITS -CGAL_CFG_NO_LIMITS:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_LIMITS_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_NEXTAFTER -CGAL_CFG_NO_NEXTAFTER:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_NEXTAFTER_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NO_STL -CGAL_CFG_NO_STL:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NO_STL_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_NUMERIC_LIMITS_BUG -CGAL_CFG_NUMERIC_LIMITS_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_NUMERIC_LIMITS_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG -CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_OUTOFLINE_MEMBER_DEFINITION_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG -CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_TEMPLATE_IN_DEFAULT_PARAMETER_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG -CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_TYPENAME_BEFORE_DEFAULT_ARGUMENT_BUG_COMPILED:INTERNAL=TRUE -//Test CGAL_CFG_USING_BASE_MEMBER_BUG_2 -CGAL_CFG_USING_BASE_MEMBER_BUG_2:INTERNAL=1 -//Result of TRY_COMPILE -CGAL_CFG_USING_BASE_MEMBER_BUG_2_COMPILED:INTERNAL=TRUE -CGAL_CONFIGURED_LIBRARIES:INTERNAL=CGAL_Core;CGAL_ImageIO;CGAL_Qt5 -//Directory containing the Core package -CGAL_CORE_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_Core_3RD_PARTY_DEFINITIONS:INTERNAL= -CGAL_Core_3RD_PARTY_INCLUDE_DIRS:INTERNAL= -CGAL_Core_3RD_PARTY_LIBRARIES:INTERNAL= -CGAL_Core_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_Core_LIBRARY:INTERNAL= -//Variable hidden from user -CGAL_ESSENTIAL_3RD_PARTY_LIBRARIES:INTERNAL=GMP;MPFR -CGAL_EXECUTABLE_TARGETS:INTERNAL= -//Variable hidden from user -CGAL_EXT_LIB_BLAS_PREFIX:INTERNAL=BLAS -//Variable hidden from user -CGAL_EXT_LIB_Coin3D_PREFIX:INTERNAL=COIN3D -//Variable hidden from user -CGAL_EXT_LIB_ESBTL_PREFIX:INTERNAL=ESBTL -//Variable hidden from user -CGAL_EXT_LIB_Eigen3_PREFIX:INTERNAL=EIGEN3 -//Variable hidden from user -CGAL_EXT_LIB_GMP_PREFIX:INTERNAL=GMP -//Variable hidden from user -CGAL_EXT_LIB_IPE_PREFIX:INTERNAL=IPE -//Variable hidden from user -CGAL_EXT_LIB_LAPACK_PREFIX:INTERNAL=LAPACK -//Variable hidden from user -CGAL_EXT_LIB_LEDA_PREFIX:INTERNAL=LEDA -//Variable hidden from user -CGAL_EXT_LIB_MPFI_PREFIX:INTERNAL=MPFI -//Variable hidden from user -CGAL_EXT_LIB_MPFR_PREFIX:INTERNAL=MPFR -//Variable hidden from user -CGAL_EXT_LIB_NTL_PREFIX:INTERNAL=NTL -//Variable hidden from user -CGAL_EXT_LIB_OpenGL_PREFIX:INTERNAL=OpenGL -//Variable hidden from user -CGAL_EXT_LIB_OpenNL_PREFIX:INTERNAL=OpenNL -//Variable hidden from user -CGAL_EXT_LIB_QGLViewer_PREFIX:INTERNAL=QGLVIEWER -//Variable hidden from user -CGAL_EXT_LIB_RS3_PREFIX:INTERNAL=RS3 -//Variable hidden from user -CGAL_EXT_LIB_RS_PREFIX:INTERNAL=RS -//Variable hidden from user -CGAL_EXT_LIB_ZLIB_PREFIX:INTERNAL=ZLIB -//Directory containing the GraphicsView package -CGAL_GRAPHICSVIEW_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -//Directory containing the Installation package -CGAL_INSTALLATION_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_ImageIO_3RD_PARTY_DEFINITIONS:INTERNAL=-DCGAL_USE_ZLIB -CGAL_ImageIO_3RD_PARTY_INCLUDE_DIRS:INTERNAL=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include -CGAL_ImageIO_3RD_PARTY_LIBRARIES:INTERNAL=C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib -CGAL_ImageIO_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_ImageIO_LIBRARY:INTERNAL= -CGAL_ImageIO_USE_ZLIB:INTERNAL=ON -//Directory containing the Maintenance package -CGAL_MAINTENANCE_PACKAGE_DIR:INTERNAL=C:/CGAL/CGAL-4.9 -CGAL_Qt5_3RD_PARTY_DEFINITIONS:INTERNAL= -CGAL_Qt5_3RD_PARTY_INCLUDE_DIRS:INTERNAL= -CGAL_Qt5_3RD_PARTY_LIBRARIES:INTERNAL=glu32;opengl32 -CGAL_Qt5_3RD_PARTY_LIBRARIES_DIRS:INTERNAL= -CGAL_Qt5_LIBRARY:INTERNAL= -//Variable hidden from user -CGAL_SUPPORTING_3RD_PARTY_LIBRARIES:INTERNAL=GMP;MPFR;ZLIB;OpenGL;LEDA;MPFI;RS;RS3;OpenNL;Eigen3;BLAS;LAPACK;QGLViewer;ESBTL;Coin3D;NTL;IPE -//This is the cygwin platform. -CGAL_WIN32_CMAKE_ON_CYGWIN:INTERNAL=TRUE -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=c:/CGAL/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=3 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=9 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=3 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=C:/dev/CMake/bin/cmake.exe -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=C:/dev/CMake/bin/cpack.exe -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=C:/dev/CMake/bin/ctest.exe -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_STANDARD_LIBRARIES -CMAKE_CXX_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_STANDARD_LIBRARIES -CMAKE_C_STANDARD_LIBRARIES-ADVANCED:INTERNAL=1 -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=Unknown -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Name of external makefile project generator. -CMAKE_EXTRA_GENERATOR:INTERNAL= -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Visual Studio 15 2017 Win64 -//Name of generator platform. -CMAKE_GENERATOR_PLATFORM:INTERNAL= -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Source directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=C:/CGAL/CGAL-4.9 -//ADVANCED property for variable: CMAKE_INSTALL_BINDIR -CMAKE_INSTALL_BINDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DATADIR -CMAKE_INSTALL_DATADIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DATAROOTDIR -CMAKE_INSTALL_DATAROOTDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_DOCDIR -CMAKE_INSTALL_DOCDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_INCLUDEDIR -CMAKE_INSTALL_INCLUDEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_INFODIR -CMAKE_INSTALL_INFODIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LIBDIR -CMAKE_INSTALL_LIBDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LIBEXECDIR -CMAKE_INSTALL_LIBEXECDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LOCALEDIR -CMAKE_INSTALL_LOCALEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_LOCALSTATEDIR -CMAKE_INSTALL_LOCALSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_MANDIR -CMAKE_INSTALL_MANDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_OLDINCLUDEDIR -CMAKE_INSTALL_OLDINCLUDEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_RUNSTATEDIR -CMAKE_INSTALL_RUNSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SBINDIR -CMAKE_INSTALL_SBINDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SHAREDSTATEDIR -CMAKE_INSTALL_SHAREDSTATEDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_INSTALL_SYSCONFDIR -CMAKE_INSTALL_SYSCONFDIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_MAKEFILES:INTERNAL=6 -//Platform information initialized -CMAKE_PLATFORM_INFO_INITIALIZED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_COMPILER -CMAKE_RC_COMPILER-ADVANCED:INTERNAL=1 -CMAKE_RC_COMPILER_WORKS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS -CMAKE_RC_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_DEBUG -CMAKE_RC_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_MINSIZEREL -CMAKE_RC_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_RELEASE -CMAKE_RC_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RC_FLAGS_RELWITHDEBINFO -CMAKE_RC_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=C:/dev/CMake/share/cmake-3.9 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Variable hidden from user -CMAKE_UNAME:INTERNAL=C:/cygwin/bin/uname.exe -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 -//Details about finding GMP -FIND_PACKAGE_MESSAGE_DETAILS_GMP:INTERNAL=[C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libgmp-10.lib][C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include][v()] -//Details about finding MPFR -FIND_PACKAGE_MESSAGE_DETAILS_MPFR:INTERNAL=[C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/lib/libmpfr-4.lib][C:/3rdPartyLibs/VC-64/gmp-5.0.1_and_mpfr-3.0.0/include][v()] -//Details about finding ZLIB -FIND_PACKAGE_MESSAGE_DETAILS_ZLIB:INTERNAL=[C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/lib/zlib.lib][C:/3rdPartyLibs/zlib-1.2.11/build_msvc2013/include][v1.2.11()] -//Result of TRY_COMPILE -GMP_COMPILE_RES:INTERNAL=TRUE -GMP_IN_CGAL_AUXILIARY:INTERNAL=TRUE -//Result of TRY_RUN -GMP_RUN_RES:INTERNAL=0 -//Generator uses intermediate configuration directory -HAS_CFG_INTDIR:INTERNAL=TRUE -//Result of TRY_COMPILE -MPFR_COMPILE_RES:INTERNAL=TRUE -MPFR_IN_CGAL_AUXILIARY:INTERNAL=TRUE -//Result of TRY_RUN -MPFR_RUN_RES:INTERNAL=0 -//ADVANCED property for variable: OPENGL_gl_LIBRARY -OPENGL_gl_LIBRARY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: OPENGL_glu_LIBRARY -OPENGL_glu_LIBRARY-ADVANCED:INTERNAL=1 -//Result of TRY_COMPILE -ZLIB_COMPILE_RES:INTERNAL=TRUE -//ADVANCED property for variable: ZLIB_INCLUDE_DIR -ZLIB_INCLUDE_DIR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_DEBUG -ZLIB_LIBRARY_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: ZLIB_LIBRARY_RELEASE -ZLIB_LIBRARY_RELEASE-ADVANCED:INTERNAL=1 -//Result of TRY_RUN -ZLIB_RUN_RES:INTERNAL=0 -//Last used Boost_ADDITIONAL_VERSIONS value. -_Boost_ADDITIONAL_VERSIONS_LAST:INTERNAL=1.69.1;1.69.0;1.69;1.68.1;1.68.0;1.68;1.67.1;1.67.0;1.67;1.66.1;1.66.0;1.66;1.65.1;1.65.0;1.65;1.64.1;1.64.0;1.64;1.63.1;1.63.0;1.63;1.62.1;1.62.0;1.62;1.61.1;1.61.0;1.61;1.60.1;1.60.0;1.60;1.59.1;1.59.0;1.59;1.58.1;1.58.0;1.58;1.57.1;1.57.0;1.57;1.56.1;1.56.0;1.56;1.55.1;1.55.0;1.55;1.54.1;1.54.0;1.54;1.53.1;1.53.0;1.53;1.52.1;1.52.0;1.52;1.51.1;1.51.0;1.51;1.50.1;1.50.0;1.50;1.49.1;1.49.0;1.49;1.48.1;1.48.0;1.48;1.47.1;1.47.0;1.47;1.46.1;1.46.0;1.46;1.45.1;1.45.0;1.45;1.44.1;1.44.0;1.44;1.43.1;1.43.0;1.43;1.42.1;1.42.0;1.42;1.41.1;1.41.0;1.41;1.40.1;1.40.0;1.40;1.39.1;1.39.0;1.39;1.38.1;1.38.0;1.38;1.37.1;1.37.0;1.37 -//Components requested for this build tree. -_Boost_COMPONENTS_SEARCHED:INTERNAL= -//Last used Boost_INCLUDE_DIR value. -_Boost_INCLUDE_DIR_LAST:INTERNAL=C:/3rdPartyLibs/boost/boost_1_67_0 -//Last used Boost_NAMESPACE value. -_Boost_NAMESPACE_LAST:INTERNAL=boost -//Last used Boost_USE_MULTITHREADED value. -_Boost_USE_MULTITHREADED_LAST:INTERNAL=TRUE -//Last used Boost_USE_STATIC_LIBS value. -_Boost_USE_STATIC_LIBS_LAST:INTERNAL=OFF -//CMAKE_INSTALL_PREFIX during last run -_GNUInstallDirs_LAST_CMAKE_INSTALL_PREFIX:INTERNAL=C:/Program Files (x86)/CGAL - diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake new file mode 100644 index 00000000000..14386bd1103 --- /dev/null +++ b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/init.cmake @@ -0,0 +1,27 @@ +#SET( Ceres_DIR "C:\\3rdPartyLibs\\ceres-solver\\install-dir\\CMake" CACHE STRING "") + +SET(CMAKE_BUILD_TYPE "Debug" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS "/DWIN32 /D_WINDOWS /W3 /GR /EHsc -D_CRT_SECURE_NO_DEPRECATE -D_SCL_SECURE_NO_DEPRECATE -D_CRT_SECURE_NO_WARNINGS -D_SCL_SECURE_NO_WARNINGS -D_SILENCE_CXX17_ADAPTOR_TYPEDEFS_DEPRECATION_WARNING /fp:strict /fp:except- /wd4503 /bigobj /permissive- /std:c++17" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob0 /Od /RTC1" CACHE STRING "") + +SET(CMAKE_CXX_FLAGS_RELEASE "/MD /O2 /Ob2 /DCGAL_NDEBUG" CACHE STRING "") + +SET(TBBROOT "C:/3rdPartyLibs/tbb2018_20170919oss" CACHE STRING "") + +SET(WITH_GMP ON CACHE BOOL "") + +SET(WITH_GMPXX OFF CACHE BOOL "") + +SET(WITH_MPFR ON CACHE BOOL "") + +SET(WITH_NTL OFF CACHE BOOL "") + +SET(WITH_demos ON CACHE BOOL "") + +SET(CGAL_HEADER_ONLY ON CACHE BOOL "") + +SET(Boost_DIR "C:\\3rdPartyLibs\\boost_master\\install_dir\\lib\\cmake\\Boost-1.71.0" CACHE PATH "") + +SET(CGAL_Boost_USE_STATIC_LIBS ON CACHE BOOL "") \ No newline at end of file diff --git a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup index 9b4c6c4e4ec..c365c26798c 100644 --- a/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup +++ b/Maintenance/infrastructure/gauguin.geometryfactory.com/reference_platforms/x64_Cygwin-Windows10_MSVC2017-Debug-64bits/setup @@ -3,9 +3,11 @@ export VC_VERSION="14.1" export VC_VERSION_YEAR="2017" export ARCH="64" export QT_VERSION="5.9.1" +BOOST_VERSION="1.71" export PLATFORM_REFERENCE="/cygdrive/c/CGAL/reference_platforms" -export BOOST_VERSION=1_67_0 export TBB_ARCH="intel64" export EIGEN3_DIR="C:/3rdPartyLibs/eigen-master" +export INIT_FILE="C:\\CGAL\\reference_platforms\\x64_Cygwin-Windows10_MSVC2017-Debug-64bits\\init.cmake" export OPENMESH_DIR="C:\3rdPartyLibs\OpenMesh_7_1" source "${PLATFORM_REFERENCE}/setup_common" +export PATH="/cygdrive/c/3rdPartyLibs/boost_master/install_dir/lib:${PATH}" diff --git a/Maintenance/release_building/BUGFIX_NUMBER b/Maintenance/release_building/BUGFIX_NUMBER deleted file mode 100644 index 573541ac970..00000000000 --- a/Maintenance/release_building/BUGFIX_NUMBER +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/Maintenance/release_building/MAJOR_NUMBER b/Maintenance/release_building/MAJOR_NUMBER deleted file mode 100644 index 7ed6ff82de6..00000000000 --- a/Maintenance/release_building/MAJOR_NUMBER +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/Maintenance/release_building/MINOR_NUMBER b/Maintenance/release_building/MINOR_NUMBER deleted file mode 100644 index d00491fd7e5..00000000000 --- a/Maintenance/release_building/MINOR_NUMBER +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/Maintenance/release_building/public_release_name b/Maintenance/release_building/public_release_name deleted file mode 100644 index 0c48f1e0ed2..00000000000 --- a/Maintenance/release_building/public_release_name +++ /dev/null @@ -1 +0,0 @@ -CGAL-5.1-dev diff --git a/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h b/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h index 696edc53ba8..b706db459d6 100644 --- a/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h +++ b/Mesh_2/include/CGAL/Delaunay_mesh_face_base_2.h @@ -17,6 +17,7 @@ #include +#include namespace CGAL { @@ -67,6 +68,14 @@ public: /** compatibility with CGAL-3.2 */ inline void set_marked(const bool b) { in_domain=b; } + + typedef Tag_true Has_timestamp; + + std::size_t time_stamp() const { return time_stamp_; } + + void set_time_stamp(const std::size_t& ts) { time_stamp_ = ts; } + + std::size_t time_stamp_; }; } // namespace CGAL diff --git a/Mesh_2/test/Mesh_2/reproductibility.cpp b/Mesh_2/test/Mesh_2/reproductibility.cpp new file mode 100644 index 00000000000..bb470c98b67 --- /dev/null +++ b/Mesh_2/test/Mesh_2/reproductibility.cpp @@ -0,0 +1,90 @@ +//#define CGAL_MESH_2_DEBUG_BAD_FACES +//#define CGAL_MESH_2_DEBUG_CLUSTERS + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +using K = CGAL::Exact_predicates_inexact_constructions_kernel; +using Vb = CGAL::Triangulation_vertex_base_2; +using Fb = CGAL::Delaunay_mesh_face_base_2; +using Tds = CGAL::Triangulation_data_structure_2; +using CDT = CGAL::Constrained_Delaunay_triangulation_2; +using Criteria = CGAL::Delaunay_mesh_size_criteria_2; +using Mesher = CGAL::Delaunay_mesher_2; + +using Vertex_handle = CDT::Vertex_handle; +using Point = CDT::Point; + +int main(int, char**) +{ + auto triangulate = [](int index) + { + CDT cdt; + + Vertex_handle va = cdt.insert(Point(-0.74397572, -0.54545455)); + Vertex_handle vb = cdt.insert(Point(-0.13526831, -1)); + Vertex_handle vc = cdt.insert(Point(0.067634156, -1)); + Vertex_handle vd = cdt.insert(Point(0.33817078, -0.54545455)); + Vertex_handle ve = cdt.insert(Point(0.74397572, 0.27272727)); + Vertex_handle vf = cdt.insert(Point(0.74397572, 0.54545455)); + Vertex_handle vg = cdt.insert(Point(0.067634156, 1)); + Vertex_handle vh = cdt.insert(Point(-0.13526831, 1)); + Vertex_handle vi = cdt.insert(Point(-0.74397572, -0.18181818)); + + cdt.insert_constraint(va, vb); + cdt.insert_constraint(vb, vc); + cdt.insert_constraint(vc, vd); + cdt.insert_constraint(vd, ve); + cdt.insert_constraint(ve, vf); + cdt.insert_constraint(vf, vg); + cdt.insert_constraint(vg, vh); + cdt.insert_constraint(vh, vi); + cdt.insert_constraint(vi, va); + + const std::vector points{ + Point(0.65605132, 0.43821259), + Point(0.23073753, -0.4476739), + Point(-0.037496007, -0.93636364), + Point(-0.00095596601, 0.88181818), + Point(-0.62452925, -0.30720903), + Point(-0.69663181, -0.45045525), + }; + + cdt.insert(points.cbegin(), points.cend()); + + std::cout << "Meshing: " << index << std::endl; + + std::cout << "Number of vertices before: " << cdt.number_of_vertices() << std::endl; + + Mesher mesher(cdt); + mesher.set_criteria(Criteria(0.125, 0.05*std::sqrt(2))); + + mesher.refine_mesh(); + + std::cout << "Number of vertices after: " << cdt.number_of_vertices() << std::endl; + + std::stringstream ss; + ss << cdt; + + return ss.str(); + }; + + const std::string ref_cdts = triangulate(0); + + for (int i = 1; i < 20; ++i) + { + const std::string cdts = triangulate(i); + if (ref_cdts != cdts) + return 1; + } + + return 0; +} 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 e412edfe31b..f1414264ca1 100644 --- a/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Compact_mesh_cell_base_3.h @@ -458,7 +458,7 @@ public: void set_neighbor(int i, Cell_handle n) { CGAL_triangulation_precondition( i >= 0 && i <= 3); - CGAL_triangulation_precondition( this != &*n ); + CGAL_triangulation_precondition( this != n.operator->() ); N[i] = n; } @@ -471,10 +471,10 @@ public: void set_neighbors(Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3) { - CGAL_triangulation_precondition( this != &*n0 ); - CGAL_triangulation_precondition( this != &*n1 ); - CGAL_triangulation_precondition( this != &*n2 ); - CGAL_triangulation_precondition( this != &*n3 ); + CGAL_triangulation_precondition( this != n0.operator->() ); + CGAL_triangulation_precondition( this != n1.operator->() ); + CGAL_triangulation_precondition( this != n2.operator->() ); + CGAL_triangulation_precondition( this != n3.operator->() ); N[0] = n0; N[1] = n1; N[2] = n2; @@ -491,7 +491,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void *p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h index b4ef55cc46b..52ac49d057b 100644 --- a/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h +++ b/Mesh_3/include/CGAL/IO/File_binary_mesh_3.h @@ -13,7 +13,7 @@ #ifndef CGAL_IO_FILE_BINARY_MESH_3_H #define CGAL_IO_FILE_BINARY_MESH_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/IO/File_maya.h b/Mesh_3/include/CGAL/IO/File_maya.h index 15a38ee55ad..b9e67d978ee 100644 --- a/Mesh_3/include/CGAL/IO/File_maya.h +++ b/Mesh_3/include/CGAL/IO/File_maya.h @@ -12,7 +12,7 @@ #ifndef CGAL_IO_FILE_MAYA_H #define CGAL_IO_FILE_MAYA_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/IO/File_medit.h b/Mesh_3/include/CGAL/IO/File_medit.h index 72573e89d31..42501a7fd63 100644 --- a/Mesh_3/include/CGAL/IO/File_medit.h +++ b/Mesh_3/include/CGAL/IO/File_medit.h @@ -14,7 +14,7 @@ #ifndef CGAL_IO_FILE_MEDIT_H #define CGAL_IO_FILE_MEDIT_H -#include +#include #include @@ -754,7 +754,7 @@ output_to_medit(std::ostream& os, typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; typedef typename Tr::Vertex_handle Vertex_handle; - typedef typename Tr::Weighted_point Weighted_point; + typedef typename Tr::Point Point; //can be weighted or not const Tr& tr = c3t3.triangulation(); @@ -783,7 +783,7 @@ output_to_medit(std::ostream& os, ++vit) { V[vit] = inum++; - Weighted_point p = tr.point(vit); + Point p = tr.point(vit); os << CGAL::to_double(p.x()) << ' ' << CGAL::to_double(p.y()) << ' ' << CGAL::to_double(p.z()) << ' ' diff --git a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h b/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h index 132df01c693..d69f445716f 100644 --- a/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h +++ b/Mesh_3/include/CGAL/IO/facets_in_complex_3_to_triangle_mesh.h @@ -14,7 +14,7 @@ #ifndef CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H #define CGAL_FACETS_IN_COMPLEX_3_TO_TRIANGLE_MESH_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Has_features.h b/Mesh_3/include/CGAL/Mesh_3/Has_features.h index 2eb7f6844fa..94d9b02de4b 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Has_features.h +++ b/Mesh_3/include/CGAL/Mesh_3/Has_features.h @@ -13,7 +13,7 @@ #ifndef CGAL_MESH_3_HAS_FEATURES_H #define CGAL_MESH_3_HAS_FEATURES_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h index 02b31a987b9..af999cd1bc9 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_complex_3_in_triangulation_3_base.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_BASE_H #define CGAL_MESH_3_MESH_COMPLEX_3_IN_TRIANGULATION_3_BASE_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h index 4bd39365f22..f4b279a0fdc 100644 --- a/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_3/Mesh_surface_cell_base_3.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_3_MESH_SURFACE_CELL_BASE_3_H #define CGAL_MESH_3_MESH_SURFACE_CELL_BASE_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/config.h b/Mesh_3/include/CGAL/Mesh_3/config.h index 07e7c765993..ccb05647ef5 100644 --- a/Mesh_3/include/CGAL/Mesh_3/config.h +++ b/Mesh_3/include/CGAL/Mesh_3/config.h @@ -12,7 +12,7 @@ #ifndef CGAL_MESH_3_CONFIG_H #define CGAL_MESH_3_CONFIG_H 1 -#include +#include #include diff --git a/Mesh_3/include/CGAL/Mesh_3/io_signature.h b/Mesh_3/include/CGAL/Mesh_3/io_signature.h index 286d5e5e3ac..d871b8ffe7d 100644 --- a/Mesh_3/include/CGAL/Mesh_3/io_signature.h +++ b/Mesh_3/include/CGAL/Mesh_3/io_signature.h @@ -13,7 +13,7 @@ #ifndef CGAL_MESH_3_IO_SIGNATURE_H #define CGAL_MESH_3_IO_SIGNATURE_H -#include +#include #define CGAL_MESH_3_IO_H // the old include macro, tested by other files diff --git a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h index c5cd5256df3..632d87a83d8 100644 --- a/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h +++ b/Mesh_3/include/CGAL/Mesh_3/tet_soup_to_c3t3.h @@ -17,18 +17,32 @@ #ifndef CGAL_MESH_3_TET_SOUP_TO_C3T3_H #define CGAL_MESH_3_TET_SOUP_TO_C3T3_H -#include +#include #include #include #include -#include +#include +#include +#include +#include #include namespace CGAL { + +template +std::array make_ordered_vertex_array(const Vh vh0, const Vh vh1, const Vh vh2) +{ + std::array ft = { {vh0, vh1, vh2} }; + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + if (ft[2] < ft[1]) std::swap(ft[1], ft[2]); + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + return ft; +} + template void build_vertices(Tr& tr, const std::vector& points, @@ -49,22 +63,22 @@ void build_vertices(Tr& tr, } template -void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, - boost::unordered_map, - std::vector > >& incident_cells_map) +bool add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; // the opposite vertex of f in c is i - Facet f; - f.insert(c->vertex((i + 1) % 4)); - f.insert(c->vertex((i + 2) % 4)); - f.insert(c->vertex((i + 3) % 4)); - CGAL_precondition(f.size() == 3); + Facet_vvv f = make_ordered_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + CGAL_precondition(f[0] != f[1] && f[1] != f[2]); Incident_cell e = std::make_pair(c, i); std::vector vec; @@ -74,20 +88,27 @@ void add_facet_to_incident_cells_map(const typename Tr::Cell_handle c, int i, if(!is_insert_successful.second) // the entry already exists in the map { // a facet must have exactly two incident cells - CGAL_assertion(is_insert_successful.first->second.size() == 1); + if (is_insert_successful.first->second.size() != 1) + { + if(verbose) + std::cout << "Error in add_facet_to_incident_cells_map" << std::endl; + return false; + } is_insert_successful.first->second.push_back(e); } + return true; } template -void build_finite_cells(Tr& tr, - const std::vector >& finite_cells, - const std::vector& vertex_handle_vector, - boost::unordered_map, +bool build_finite_cells(Tr& tr, + const std::vector >& finite_cells, + const std::vector& vertex_handle_vector, + boost::unordered_map, std::vector > >& incident_cells_map, - const std::map, int>& border_facets) + const std::map, int>& border_facets, + const bool verbose) { - typedef boost::array Tet_with_ref; // 4 ids + 1 reference + typedef std::array Tet_with_ref; // 4 ids + 1 reference typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; @@ -101,7 +122,7 @@ void build_finite_cells(Tr& tr, for(std::size_t i=0; i vs; + std::array vs; for(int j=0; j<4; ++j) { @@ -118,9 +139,8 @@ void build_finite_cells(Tr& tr, == POSITIVE); Cell_handle c = tr.tds().create_cell(vs[0], vs[1], vs[2], vs[3]); - c->info() = tet[4]; // the cell's info keeps the reference of the tetrahedron + c->set_subdomain_index(tet[4]); // the cell's info keeps the reference of the tetrahedron - CGAL_precondition(tet[4] > 0); // assign cells to vertices for(int j=0; j<4; ++j) { @@ -131,17 +151,18 @@ void build_finite_cells(Tr& tr, // build the map used for adjacency later for(int j=0; j<4; ++j) { - add_facet_to_incident_cells_map(c, j, incident_cells_map); + if(!add_facet_to_incident_cells_map(c, j, incident_cells_map, verbose)) + return false; if(border_facets.size() != 0) { - boost::array facet; + std::array facet; facet[0]=tet[(j+1) % 4]; facet[1]=tet[(j+2) % 4]; facet[2]=tet[(j+3) % 4]; //find the circular permutation that puts the smallest index in the first place. int n0 = (std::min)((std::min)(facet[0], facet[1]), facet[2]); int k=0; - boost::array f; + std::array f; do { f[0]=facet[(0+k)%3]; @@ -150,7 +171,7 @@ void build_finite_cells(Tr& tr, ++k; } while(f[0] != n0); - typename std::map, int>::const_iterator it = border_facets.find(f); + typename std::map, int>::const_iterator it = border_facets.find(f); if(it != border_facets.end()) { c->set_surface_patch_index(j, it->second); @@ -170,34 +191,38 @@ void build_finite_cells(Tr& tr, } } } + return true; } template -void add_infinite_facets_to_incident_cells_map(typename Tr::Cell_handle c, - int inf_vert_pos, - std::map, - std::vector > >& incident_cells_map) +bool add_infinite_facets_to_incident_cells_map(typename Tr::Cell_handle c, + int inf_vert_pos, + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { int l = (inf_vert_pos + 1) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b1 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); l = (inf_vert_pos + 2) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b2 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); l = (inf_vert_pos + 3) % 4; - add_facet_to_incident_cells_map(c, l, incident_cells_map); + bool b3 = add_facet_to_incident_cells_map(c, l, incident_cells_map, verbose); + return b1 && b2 && b3; } template -void build_infinite_cells(Tr& tr, - boost::unordered_map, - std::vector > >& incident_cells_map) +bool build_infinite_cells(Tr& tr, + boost::unordered_map, + std::vector > >& incident_cells_map, + const bool verbose) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; + + std::vector infinite_cells; // check the incident cells map for facets who only have one incident cell // and build the infinite cell on the opposite side @@ -214,41 +239,67 @@ void build_infinite_cells(Tr& tr, Cell_handle opp_c; // the infinite cell that we are creating needs to be well oriented... - int inf_vert_position_in_opp_c = 0; if(i == 0 || i == 2) opp_c = tr.tds().create_cell(tr.infinite_vertex(), - c->vertex((i+1)%4), - c->vertex((i+2)%4), - c->vertex((i+3)%4)); + c->vertex((i + 2) % 4), + c->vertex((i + 1) % 4), + c->vertex((i + 3) % 4)); else opp_c = tr.tds().create_cell(tr.infinite_vertex(), - c->vertex((i+1)%4), - c->vertex((i+3)%4), - c->vertex((i+2)%4)); + c->vertex((i + 3) % 4), + c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4)); + + infinite_cells.push_back(opp_c); // set the infinite_vertex's incident cell if(tr.infinite_vertex()->cell() == Cell_handle()) tr.infinite_vertex()->set_cell(opp_c); - // add the facets to the incident cells map - // the only finite facet - it->second.push_back(std::make_pair(opp_c, inf_vert_position_in_opp_c)); + it->second.push_back(std::make_pair(opp_c, 0)); CGAL_assertion(it->second.size() == 2); } + +#ifdef CGAL_TET_SOUP_TO_C3T3_DEBUG + for (auto icit : incident_cells_map) + CGAL_assertion(icit.second.size() == 2); + + std::map facets; + for (const Cell_handle c : infinite_cells) + { + for (int i = 1; i < 4; ++i) + { + std::array vs = make_ordered_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + if (facets.find(vs) == facets.end()) + facets.insert(std::make_pair(vs, 1)); + else + facets[vs]++; + } + } + for (auto fp : facets) + CGAL_assertion(fp.second == 2); +#endif + + // add the facets to the incident cells map + for (const Cell_handle c : infinite_cells) + if(!add_infinite_facets_to_incident_cells_map(c, 0, incident_cells_map, verbose)) + return false; + + return true; } template bool assign_neighbors(Tr& tr, - const boost::unordered_map, - std::vector > >& incident_cells_map) + const boost::unordered_map, + std::vector > >& incident_cells_map) { - typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map, + std::vector > Incident_cells_map; typename Incident_cells_map::const_iterator icit = incident_cells_map.begin(); for(; icit!=incident_cells_map.end(); ++icit) @@ -270,19 +321,23 @@ bool assign_neighbors(Tr& tr, template bool build_triangulation(Tr& tr, const std::vector& points, - const std::vector >& finite_cells, - const std::map, int>& border_facets) + const std::vector >& finite_cells, + const std::map, int>& border_facets, + std::vector& vertex_handle_vector, + const bool verbose = false) { typedef typename Tr::Vertex_handle Vertex_handle; typedef typename Tr::Cell_handle Cell_handle; - typedef std::set Facet; + typedef std::array Facet_vvv; // associate to a face the two (at most) incident tets and the id of the face in the cell typedef std::pair Incident_cell; - typedef boost::unordered_map > Incident_cells_map; + typedef boost::unordered_map > Incident_cells_map; Incident_cells_map incident_cells_map; - std::vector vertex_handle_vector(points.size() + 1); // id to vertex_handle + vertex_handle_vector.resize(points.size() + 1); // id to vertex_handle + //index 0 is for infinite vertex + // 1 to n for points in `points` CGAL_precondition(!points.empty()); @@ -298,22 +353,29 @@ bool build_triangulation(Tr& tr, { vh->set_dimension(-1); } - if(!finite_cells.empty()) + if (!finite_cells.empty()) { - build_finite_cells(tr, finite_cells, vertex_handle_vector, incident_cells_map, border_facets); - build_infinite_cells(tr, incident_cells_map); - tr.tds().set_dimension(3); - if(!assign_neighbors(tr, incident_cells_map)) + if(!build_finite_cells(tr, finite_cells, vertex_handle_vector, incident_cells_map, + border_facets, verbose)) return false; - std::cout << "built triangulation : " << std::endl; - std::cout << tr.number_of_cells() << " cells" << std::endl; + if(!build_infinite_cells(tr, incident_cells_map, verbose)) + return false; + tr.tds().set_dimension(3); + if (!assign_neighbors(tr, incident_cells_map)) + return false; + if (verbose) + { + std::cout << "built triangulation : " << std::endl; + std::cout << tr.number_of_cells() << " cells" << std::endl; + } } - std::cout << tr.number_of_vertices() << " vertices" << std::endl; + if(verbose) + std::cout << tr.number_of_vertices() << " vertices" << std::endl; if(c3t3_loader_failed) return true; else - return tr.is_valid(true); + return tr.tds().is_valid(); } template @@ -322,8 +384,8 @@ bool build_triangulation_from_file(std::istream& is, { typedef typename Tr::Point Point_3; - typedef boost::array Facet; // 3 = id - typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference std::vector finite_cells; std::vector points; @@ -404,7 +466,9 @@ bool build_triangulation_from_file(std::istream& is, if(finite_cells.empty()) return false; - bool is_well_built = build_triangulation(tr, points, finite_cells, border_facets); + std::vector vertices(points.size() + 1); + bool is_well_built = build_triangulation(tr, + points, finite_cells, border_facets, vertices); return is_well_built; } diff --git a/Mesh_3/include/CGAL/Mesh_3/utilities.h b/Mesh_3/include/CGAL/Mesh_3/utilities.h index 4d73f43de53..5e49f7a617e 100644 --- a/Mesh_3/include/CGAL/Mesh_3/utilities.h +++ b/Mesh_3/include/CGAL/Mesh_3/utilities.h @@ -17,7 +17,7 @@ #ifndef CGAL_MESH_3_UTILITIES_H #define CGAL_MESH_3_UTILITIES_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_cell_base_3.h b/Mesh_3/include/CGAL/Mesh_cell_base_3.h index 5c719d22fe6..2babd0cc5db 100644 --- a/Mesh_3/include/CGAL/Mesh_cell_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_cell_base_3.h @@ -15,7 +15,7 @@ #ifndef CGAL_MESH_CELL_BASE_3_H #define CGAL_MESH_CELL_BASE_3_H -#include +#include // #define CGAL_DEPRECATED_HEADER "" diff --git a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h index 954478ccee7..8fb53524d81 100644 --- a/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h +++ b/Mesh_3/include/CGAL/Mesh_complex_3_in_triangulation_3.h @@ -18,7 +18,7 @@ #ifndef CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H #define CGAL_MESH_COMPLEX_3_IN_TRIANGULATION_3_H -#include +#include #include #include diff --git a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h index 9ad67147d1b..aeb3411a1e1 100644 --- a/Mesh_3/include/CGAL/Mesh_vertex_base_3.h +++ b/Mesh_3/include/CGAL/Mesh_vertex_base_3.h @@ -20,7 +20,7 @@ #ifndef CGAL_COMPACT_MESH_VERTEX_BASE_3_H #define CGAL_COMPACT_MESH_VERTEX_BASE_3_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h b/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h index 08ecbdb070a..b08974e545e 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/Boundary_of_subdomain_of_complex_3_in_triangulation_3_to_off.h @@ -12,7 +12,7 @@ #ifndef CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H #define CGAL_INTERNAL_MESH_3_BOUNDARY_OF_SUDDOMAIN_OF_COMPLEX_3_IN_TRIANGULATION_3_TO_OFF_H -#include +#include #include diff --git a/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h b/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h index b84f4639b51..1bbf2f971aa 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/get_index.h @@ -17,7 +17,7 @@ #ifndef CGAL_INTERNAL_MESH_3_GET_INDEX_3_H #define CGAL_INTERNAL_MESH_3_GET_INDEX_3_H -#include +#include #include 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 6f637bebb48..62bde6e2135 100644 --- a/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h +++ b/Mesh_3/include/CGAL/internal/Mesh_3/indices_management.h @@ -18,7 +18,7 @@ #ifndef CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H #define CGAL_INTERNAL_MESH_3_INDICES_MANAGEMENT_H -#include +#include #include diff --git a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp b/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp index 124cb0f75aa..6df89caf971 100644 --- a/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp +++ b/Mesh_3/test/Mesh_3/test_c3t3_into_facegraph.cpp @@ -49,8 +49,8 @@ int main (int argc, char** argv){ cit != c3t3.triangulation().finite_cells_end(); ++cit) { - CGAL_assertion(cit->info() >= 0); - c3t3.add_to_complex(cit, cit->info()); + CGAL_assertion(cit->subdomain_index() >= 0); + c3t3.add_to_complex(cit, cit->subdomain_index()); for(int i=0; i < 4; ++i) { if(cit->surface_patch_index(i)>0) diff --git a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h index 256769ff2bf..f8e614a3142 100644 --- a/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_2.h +++ b/Minkowski_sum_2/include/CGAL/Minkowski_sum_2/Arr_labeled_traits_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_LABELED_TRAITS_2_H #define CGAL_ARR_LABELED_TRAITS_2_H @@ -25,95 +25,79 @@ namespace CGAL { * such that the comparison of two points, as well as the computation of the * intersections between two segments can be easily filtered. */ -template -class Arr_labeled_traits_2 : public Traits_ -{ +template +class Arr_labeled_traits_2 : public Traits_ { private: + typedef Traits_ Base_traits_2; + typedef Arr_labeled_traits_2 Traits; - typedef Traits_ Base_traits_2; - typedef typename Base_traits_2::Point_2 Base_point_2; - 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::X_monotone_curve_2 Base_x_monotone_curve_2; public: + typedef typename Base_traits_2::Multiplicity Multiplicity; /*! \class * A point extended by a label. */ - class Point_2 : public Base_point_2 - { + class Point_2 : public Base_point_2 { private: - - Point_label _label; + Point_label m_label; public: - /*! Default constructor. */ - Point_2 () - {} + Point_2() {} /*! Constructor from a base point. */ - Point_2 (const Base_point_2& p) : - Base_point_2 (p), - _label() + Point_2(const Base_point_2& p) : + Base_point_2(p), + m_label() {} /*! Constructor from a point an a label. */ - Point_2 (const Base_point_2& p, const Point_label& label) : - Base_point_2 (p), - _label (label) + Point_2(const Base_point_2& p, const Point_label& label) : + Base_point_2(p), + m_label(label) {} /*! Get the label. */ - const Point_label& label () const - { - return (_label); - } + const Point_label& label() const { return (m_label); } }; /*! \class * An x-monotone curve extended by a label. */ - class X_monotone_curve_2 : public Base_x_monotone_curve_2 - { + class X_monotone_curve_2 : public Base_x_monotone_curve_2 { private: - - X_curve_label _label; + X_curve_label m_label; public: - /*! Default constructor. */ - X_monotone_curve_2 () - {} + X_monotone_curve_2() {} /*! Constructor from a base x-monotone curve. */ - X_monotone_curve_2 (const Base_x_monotone_curve_2& p) : - Base_x_monotone_curve_2 (p), - _label() + X_monotone_curve_2(const Base_x_monotone_curve_2& p) : + Base_x_monotone_curve_2(p), + m_label() {} /*! Constructor from an x-monotone curve an a label. */ - X_monotone_curve_2 (const Base_x_monotone_curve_2& p, - const X_curve_label& label) : - Base_x_monotone_curve_2 (p), - _label (label) + X_monotone_curve_2(const Base_x_monotone_curve_2& p, + const X_curve_label& label) : + Base_x_monotone_curve_2(p), + m_label(label) {} /*! Get the label (const version). */ - const X_curve_label& label () const - { - return (_label); - } + const X_curve_label& label() const { return m_label; } /*! Get the label (non-const version). */ - X_curve_label& label () - { - return (_label); - } + X_curve_label& label() { return m_label; } /*! Set the label. */ - void set_label (const X_curve_label& label) + void set_label(const X_curve_label& label) { - _label = label; + m_label = label; return; } }; @@ -122,8 +106,7 @@ public: typedef Tag_false Has_merge_category; /*! Default constructor. */ - Arr_labeled_traits_2 () - {} + Arr_labeled_traits_2() {} // Inherited functors: typedef typename Base_traits_2::Is_vertical_2 Is_vertical_2; @@ -134,280 +117,232 @@ public: /// \name Overriden functors. //@{ - class Compare_x_2 - { + class Compare_x_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Compare_x_2 (const Base_traits_2 * _base) : - base (_base) - {} + Compare_x_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Compare the x-coordinates of two points. + friend Traits; + + public: + /*! Compare the x-coordinates of two points. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { // If two points have the same label, they are equal. - if (p1.label() == p2.label()) - return (EQUAL); + if (p1.label() == p2.label()) return (EQUAL); - return (base->compare_x_2_object()(p1, p2)); + return (m_base_traits.compare_x_2_object()(p1, p2)); } }; /*! Get a Compare_x_2 functor object. */ - Compare_x_2 compare_x_2_object () const - { - return (Compare_x_2 (this)); - } + Compare_x_2 compare_x_2_object() const { return (Compare_x_2(*this)); } - - class Compare_xy_2 - { + class Compare_xy_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Compare_xy_2 (const Base_traits_2 *_base) : - base (_base) - {} + Compare_xy_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Compare two points lexigoraphically: by x, then by y. + friend Traits; + + public: + /*! Compare two points lexigoraphically: by x, then by y. */ - Comparison_result operator() (const Point_2& p1, const Point_2& p2) const + Comparison_result operator()(const Point_2& p1, const Point_2& p2) const { // If two points have the same label, they are equal. - if (p1.label() == p2.label()) - return (EQUAL); + if (p1.label() == p2.label()) return (EQUAL); - return (base->compare_xy_2_object()(p1, p2)); + return (m_base_traits.compare_xy_2_object()(p1, p2)); } }; - /*! Get a Compare_xy_2 functor object. */ - Compare_xy_2 compare_xy_2_object () const - { - return (Compare_xy_2 (this)); - } + /*! Obtain a Compare_xy_2 functor object. */ + Compare_xy_2 compare_xy_2_object() const { return Compare_xy_2(*this); } - - class Construct_min_vertex_2 - { + class Construct_min_vertex_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Construct_min_vertex_2 (const Base_traits_2 *_base) : - base (_base) + Construct_min_vertex_2(const Base_traits_2& base_tr) : + m_base_traits(base_tr) {} - /*! - * Get the left endpoint of the x-monotone curve. - */ - Point_2 operator() (const X_monotone_curve_2& cv) const - { - const Base_point_2& pt = base->construct_min_vertex_2_object() (cv); + friend Traits; - if (cv.label().right_count() == 1 && cv.label().left_count() == 0) - { + public: + /*! Obtain the left endpoint of the x-monotone curve. + */ + Point_2 operator()(const X_monotone_curve_2& cv) const + { + auto base_ctr_min_vertex = m_base_traits.construct_min_vertex_2_object(); + const Base_point_2& pt = base_ctr_min_vertex(cv); + + if ((cv.label().right_count() == 1) && (cv.label().left_count() == 0)) { // A curve directed from left to right: - Point_label label (cv.label().component(), cv.label().index()); + Point_label label(cv.label().component(), cv.label().index()); return (Point_2 (pt, label)); } - else if (cv.label().right_count() == 0 && cv.label().left_count() == 1) + else if ((cv.label().right_count() == 0) && + (cv.label().left_count() == 1)) { // A curve directed from right to left: - Point_label label (cv.label().component(), - cv.label().is_last() ? 0 : cv.label().index()+1); + Point_label label(cv.label().component(), + cv.label().is_last() ? 0 : cv.label().index()+1); - return (Point_2 (pt, label)); + return (Point_2(pt, label)); } // Assign an invalid label to the point. - return (Point_2 (pt)); + return Point_2(pt); } }; /*! Get a Construct_min_vertex_2 functor object. */ Construct_min_vertex_2 construct_min_vertex_2_object () const - { - return (Construct_min_vertex_2 (this)); - } + { return Construct_min_vertex_2(*this); } - - class Construct_max_vertex_2 - { + class Construct_max_vertex_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Construct_max_vertex_2 (const Base_traits_2 *_base) : - base (_base) + Construct_max_vertex_2(const Base_traits_2& base_tr) : + m_base_traits(base_tr) {} - /*! - * Get the right endpoint of the x-monotone curve. + friend Traits; + + public: + /*! Obtain the right endpoint of the x-monotone curve. */ - Point_2 operator() (const X_monotone_curve_2& cv) const + Point_2 operator()(const X_monotone_curve_2& cv) const { - const Base_point_2& pt = base->construct_max_vertex_2_object() (cv); + auto base_ctr_max_vertex = m_base_traits.construct_max_vertex_2_object(); + const Base_point_2& pt = base_ctr_max_vertex(cv); - if (cv.label().right_count() == 1 && cv.label().left_count() == 0) - { + if ((cv.label().right_count() == 1) && (cv.label().left_count() == 0)) { // A curve directed from left to right: - Point_label label (cv.label().component(), - cv.label().is_last() ? 0 : cv.label().index()+1); + Point_label label(cv.label().component(), + cv.label().is_last() ? 0 : cv.label().index()+1); - return (Point_2 (pt, label)); + return Point_2(pt, label); } - else if (cv.label().right_count() == 0 && cv.label().left_count() == 1) + else if ((cv.label().right_count() == 0) && + (cv.label().left_count() == 1)) { // A curve directed from right to left: - Point_label label (cv.label().component(), cv.label().index()); + Point_label label(cv.label().component(), cv.label().index()); - return (Point_2 (pt, label)); + return Point_2(pt, label); } // Assign an invalid label to the point. - return (Point_2 (pt)); + return Point_2(pt); } }; /*! Get a Construct_max_vertex_2 functor object. */ Construct_max_vertex_2 construct_max_vertex_2_object () const - { - return (Construct_max_vertex_2 (this)); - } + { return Construct_max_vertex_2(*this); } - - class Split_2 - { + class Split_2 { private: - - const Base_traits_2 * base; - - public: + const Base_traits_2& m_base_traits; /*! Constructor. */ - Split_2 (const Base_traits_2 * _base) : - base (_base) - {} + Split_2(const Base_traits_2& base_tr) : m_base_traits(base_tr) {} - /*! - * Split a given x-monotone curve at a given point into two sub-curves. + friend Traits; + + public: + /*! Split a given x-monotone curve at a given point into two sub-curves. */ - void operator() (const X_monotone_curve_2& cv, const Point_2& p, - X_monotone_curve_2& c1, X_monotone_curve_2& c2) const + void operator()(const X_monotone_curve_2& cv, const Point_2& p, + X_monotone_curve_2& c1, X_monotone_curve_2& c2) const { // Split the base curve into two. - base->split_2_object() (cv, p, c1, c2); + m_base_traits.split_2_object()(cv, p, c1, c2); // Duplicate the label to both subcurves. - c1.set_label (cv.label()); - c2.set_label (cv.label()); - - return; + c1.set_label(cv.label()); + c2.set_label(cv.label()); } }; /*! Get a Split_2 functor object. */ - Split_2 split_2_object () const - { - return (Split_2 (this)); - } + Split_2 split_2_object() const { return Split_2(*this); } - - class Intersect_2 - { + class Intersect_2 { private: - - const Base_traits_2 * base; + const Base_traits_2& m_base_traits; public: - /*! Constructor. */ - Intersect_2 (const Base_traits_2 * _base) : - base (_base) - {} + Intersect_2(const Base_traits_2& traits) : m_base_traits(traits) {} - /*! - * Find the intersections of the two given curves and insert them to the + /*! Find the intersections of the two given curves and insert them to the * given output iterator. */ - template - OutputIterator operator() (const X_monotone_curve_2& cv1, - const X_monotone_curve_2& cv2, - OutputIterator oi) const + template + OutputIterator operator()(const X_monotone_curve_2& cv1, + const X_monotone_curve_2& cv2, + OutputIterator oi) const { + typedef std::pair Intersection_base_point; + typedef boost::variant + Intersection_base_result; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + // In case the curves are adjacent in their curve sequence, we do // not have to compute their intersection (we already know that they // have just one common endpoint). - if (cv1.label().is_adjacent (cv2.label())) - return (oi); + if (cv1.label().is_adjacent(cv2.label())) return oi; // Compute the intersection. - std::list base_objs; + std::list xections; + m_base_traits.intersect_2_object()(cv1, cv2, std::back_inserter(xections)); - base->intersect_2_object() (cv1, cv2, std::back_inserter (base_objs)); - - if (base_objs.empty()) - return (oi); + if (xections.empty()) return oi; // Attach labels to the intersection objects. - std::list::iterator obj_it; - const std::pair *base_pt; - const Base_x_monotone_curve_2 *base_xcv; + for (const auto& xection : xections) { + const Intersection_base_point* base_pt = + boost::get(&xection); - for (obj_it = base_objs.begin(); obj_it != base_objs.end(); ++obj_it) - { - base_pt = - object_cast > (&(*obj_it)); - - if (base_pt != nullptr) - { + if (base_pt != nullptr) { // Attach an invalid label to an itersection point. - *oi = CGAL::make_object - (std::make_pair (Point_2 (base_pt->first), base_pt->second)); - ++oi; + *oi++ = Intersection_result(std::make_pair(Point_2(base_pt->first), + base_pt->second)); + continue; } - else - { - base_xcv = object_cast (&(*obj_it)); - CGAL_assertion (base_xcv != nullptr); - // Attach a merged label to the overlapping curve. - *oi = CGAL::make_object - (X_monotone_curve_2 (*base_xcv, - X_curve_label (cv1.label(), cv2.label()))); - ++oi; - } + const Base_x_monotone_curve_2* base_xcv = + boost::get(&xection); + CGAL_assertion(base_xcv != nullptr); + + // Attach a merged label to the overlapping curve. + *oi++ = + Intersection_result(X_monotone_curve_2(*base_xcv, + X_curve_label(cv1.label(), + cv2.label()))); } - return (oi); + return oi; } }; /*! Get an Intersect_2 functor object. */ - Intersect_2 intersect_2_object () const - { - return (Intersect_2 (this)); - } + Intersect_2 intersect_2_object() const { return Intersect_2(*this); } //@} }; diff --git a/NewKernel_d/include/CGAL/Epick_d.h b/NewKernel_d/include/CGAL/Epick_d.h index 54b6633ebec..39575dd034a 100644 --- a/NewKernel_d/include/CGAL/Epick_d.h +++ b/NewKernel_d/include/CGAL/Epick_d.h @@ -40,7 +40,12 @@ struct Epick_d_help1 }; #undef CGAL_BASE #define CGAL_BASE \ - Cartesian_static_filters,Epick_d_help2 > + Cartesian_filter_K< \ + Epick_d_help1, \ + Cartesian_base_d, \ + Cartesian_base_d::Type, Dim>, \ + typename Functors_without_division::type \ + > template struct Epick_d_help2 : CGAL_BASE @@ -49,10 +54,21 @@ struct Epick_d_help2 constexpr Epick_d_help2(int d):CGAL_BASE(d){} }; #undef CGAL_BASE +#define CGAL_BASE \ + Cartesian_static_filters,Epick_d_help3 > + +template +struct Epick_d_help3 +: CGAL_BASE +{ + constexpr Epick_d_help3(){} + constexpr Epick_d_help3(int d):CGAL_BASE(d){} +}; +#undef CGAL_BASE #define CGAL_BASE \ Kernel_d_interface< \ Cartesian_wrap< \ - Epick_d_help2, \ + Epick_d_help3, \ Epick_d > > template struct Epick_d diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h index 1bfc92a88c8..a379cee7ed9 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_LA_functors.h @@ -58,7 +58,7 @@ template struct Construct_LA_vector } template typename std::enable_if::value && - std::is_same, Dimension>::value, + std::is_same, Dimension>::value, result_type>::type operator()(U&&...u)const{ return typename Constructor::Values()(std::forward(u)...); @@ -66,7 +66,7 @@ template struct Construct_LA_vector //template::value>::type,class=typename std::enable_if<(sizeof...(U)==static_dim+1)>::type,class=void> template typename std::enable_if::value && - std::is_same, Dimension>::value, + std::is_same, Dimension>::value, result_type>::type operator()(U&&...u)const{ return Apply_to_last_then_rest()(typename Constructor::Values_divide(),std::forward(u)...); diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h index 3496330a7ac..ed164e844da 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Cartesian_filter_K.h @@ -20,23 +20,49 @@ namespace CGAL { -template < typename Base_, typename AK_, typename EK_ > -struct Cartesian_filter_K : public Base_, - private Store_kernel, private Store_kernel2 + // It would be nicer to write the table in the other direction: Orientation_of_points_tag is good up to 6, Side_of_oriented_sphere_tag up to 5, etc. +template struct Functors_without_division { typedef typeset<> type; }; +template<> struct Functors_without_division > { + typedef typeset type; +}; +template<> struct Functors_without_division > { + typedef typeset type; +}; +template<> struct Functors_without_division > { + typedef typeset type; +}; +template<> struct Functors_without_division > { + typedef typeset type; +}; +template<> struct Functors_without_division > { + typedef typeset type; +}; +template<> struct Functors_without_division > { + typedef typeset type; +}; + +// FIXME: +// - Is_exact (which should be renamed to Uses_no_arithmetic) predicates should not be filtered +// - Functors_without_division should be defined near/in the actual functors + +template < typename Base_, typename AK_, typename EK_, typename Pred_list = typeset_all > +struct Cartesian_filter_K : public Base_ { + CGAL_NO_UNIQUE_ADDRESS Store_kernel sak; + CGAL_NO_UNIQUE_ADDRESS Store_kernel sek; constexpr Cartesian_filter_K(){} constexpr Cartesian_filter_K(int d):Base_(d){} //FIXME: or do we want an instance of AK and EK belonging to this kernel, //instead of a reference to external ones? - constexpr Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),Store_kernel(a),Store_kernel2(b){} - constexpr Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),Store_kernel(a),Store_kernel2(b){} + constexpr Cartesian_filter_K(AK_ const&a,EK_ const&b):Base_(),sak(a),sek(b){} + constexpr Cartesian_filter_K(int d,AK_ const&a,EK_ const&b):Base_(d),sak(a),sek(b){} typedef Base_ Kernel_base; typedef AK_ AK; typedef EK_ EK; typedef typename Store_kernel::reference_type AK_rt; - AK_rt approximate_kernel()const{return this->kernel();} - typedef typename Store_kernel2::reference2_type EK_rt; - EK_rt exact_kernel()const{return this->kernel2();} + AK_rt approximate_kernel()const{return sak.kernel();} + typedef typename Store_kernel::reference_type EK_rt; + EK_rt exact_kernel()const{return sek.kernel();} // MSVC is too dumb to perform the empty base optimization. typedef boost::mpl::and_< @@ -52,12 +78,12 @@ struct Cartesian_filter_K : public Base_, // TODO: only fix some types, based on some criterion? template struct Type : Get_type {}; - template::type> struct Functor : + template::type, bool=Pred_list::template contains::value> struct Functor : Inherit_functor {}; - template struct Functor { + template struct Functor { typedef typename Get_functor::type AP; typedef typename Get_functor::type EP; - typedef Filtered_predicate2 type; + typedef Filtered_predicate2 type; }; // TODO: // template struct Functor : diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h index a6190e42b5a..c3d2281ad96 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Filtered_predicate2.h @@ -40,7 +40,7 @@ namespace CGAL { // - Some caching could be done at the Point_2 level. -template +template class Filtered_predicate2 { //TODO: pack (at least use a tuple) @@ -65,7 +65,6 @@ public: Filtered_predicate2() {} - template Filtered_predicate2(const K& k) : ep(k.exact_kernel()), ap(k.approximate_kernel()), c2e(k,k.exact_kernel()), c2a(k,k.approximate_kernel()) {} diff --git a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h index 4dd8b5ca845..3d4afd905e5 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/LA_eigen/LA.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include namespace CGAL { @@ -100,15 +102,72 @@ template struct LA_eigen { return (int)v.cols(); } - template static NT determinant(Mat_ const&m,bool=false){ + template static NT determinant_aux [[noreturn]] (Mat_ const&, Tag_true) { + CGAL_error(); + } + template static NT determinant_aux(Mat_ const& m, Tag_false) { return m.determinant(); } + // TODO: https://gitlab.com/libeigen/eigen/-/issues/1782 + // Implement a version of (sign_of_)determinant that works + // without (inexact) division in any dimension + template static NT determinant(Mat_ const&m,bool=false){ + switch(m.rows()){ + //case 0: + // return 1; + case 1: + return m(0,0); + case 2: + return CGAL::determinant( + m(0,0),m(0,1), + m(1,0),m(1,1)); + case 3: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2), + m(1,0),m(1,1),m(1,2), + m(2,0),m(2,1),m(2,2)); + case 4: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3), + m(1,0),m(1,1),m(1,2),m(1,3), + m(2,0),m(2,1),m(2,2),m(2,3), + m(3,0),m(3,1),m(3,2),m(3,3)); + case 5: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4)); + case 6: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5)); + case 7: + return CGAL::determinant( + m(0,0),m(0,1),m(0,2),m(0,3),m(0,4),m(0,5),m(0,6), + m(1,0),m(1,1),m(1,2),m(1,3),m(1,4),m(1,5),m(1,6), + m(2,0),m(2,1),m(2,2),m(2,3),m(2,4),m(2,5),m(2,6), + m(3,0),m(3,1),m(3,2),m(3,3),m(3,4),m(3,5),m(3,6), + m(4,0),m(4,1),m(4,2),m(4,3),m(4,4),m(4,5),m(4,6), + m(5,0),m(5,1),m(5,2),m(5,3),m(5,4),m(5,5),m(5,6), + m(6,0),m(6,1),m(6,2),m(6,3),m(6,4),m(6,5),m(6,6)); + default: + return determinant_aux(m, Boolean_tag<(Mat_::MaxRowsAtCompileTime >= 1 && Mat_::MaxRowsAtCompileTime <= 7)>()); + + } + } + template static typename Same_uncertainty_nt::type sign_of_determinant(Mat_ const&m,bool=false) { - return CGAL::sign(m.determinant()); + return CGAL::sign(LA_eigen::determinant(m)); } template static int rank(Mat_ const&m){ diff --git a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h index d9f4112cf68..56ecd5df953 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/Lazy_cartesian.h @@ -56,10 +56,10 @@ namespace internal { // Whenever a construction takes iterator pairs as input, whether they point to double of Lazy objects, copy the ranges inside the lazy result so they are available for update_exact(). We analyze the input to try and guess where iterator pairs are. I would prefer if each functor had a specific signature (no overload in this layer) so we wouldn't have to guess. namespace Lazy_internal { templatestruct typelist{}; -templatestruct arg_i{}; -templatestruct arg_i_begin{}; -templatestruct arg_i_end{}; -templatestruct arg_i_ip1_range{}; +templatestruct arg_i{}; +templatestruct arg_i_begin{}; +templatestruct arg_i_end{}; +templatestruct arg_i_ip1_range{}; templatestruct analyze_args; templatestruct analyze_args> { typedef T creator; @@ -73,24 +73,24 @@ struct analyze_args,typelist,typelist,std::enab analyze_args>,typelist,arg_i_end>,typelist> {}; template using analyze_args_for_lazy = analyze_args,typelist<>,typelist>; templatestruct extract1; -templatestruct extract1,T>:std::tuple_element{}; -templatestruct extract1,T>{ +templatestruct extract1,T>:std::tuple_element{}; +templatestruct extract1,T>{ typedef std::tuple_element_t E; typedef std::remove_cv_t> It; typedef typename std::iterator_traits::value_type element_type; // TODO: find a way to use an array of the right size, at least for the most frequent constructions typedef std::vector type; }; -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i,std::tupleconst&t) {return std::get(t);} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_begin,std::tupleconst&t) {return std::begin(std::get(t));} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_end,std::tupleconst&t) {return std::end(std::get(t));} -templatedecltype(auto) +templatedecltype(auto) do_extract(arg_i_ip1_range,std::tupleconst&t) { typedef std::tuple L; @@ -294,7 +294,7 @@ struct Lazy_cartesian : template struct Functor { typedef typename Get_functor::type FA; typedef typename Get_functor::type FE; - typedef Filtered_predicate2 type; + typedef Filtered_predicate2 type; }; template struct Functor { typedef Lazy_construction2 type; diff --git a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h index b9bfe61749f..5249dff2fcb 100644 --- a/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h +++ b/NewKernel_d/include/CGAL/NewKernel_d/store_kernel.h @@ -13,12 +13,12 @@ #define CGAL_STORE_KERNEL_H #include -#include +#include namespace CGAL { namespace internal { BOOST_MPL_HAS_XXX_TRAIT_DEF(Do_not_store_kernel) -template::value,bool=has_Do_not_store_kernel::value> struct Do_not_store_kernel { +template::value,bool=has_Do_not_store_kernel::value> struct Do_not_store_kernel { enum { value=false }; typedef Tag_false type; }; diff --git a/NewKernel_d/include/CGAL/argument_swaps.h b/NewKernel_d/include/CGAL/argument_swaps.h index 85915098e26..a6f2cd8d794 100644 --- a/NewKernel_d/include/CGAL/argument_swaps.h +++ b/NewKernel_d/include/CGAL/argument_swaps.h @@ -18,9 +18,9 @@ namespace CGAL { namespace internal { -template struct Apply_to_last_then_rest_; +template struct Apply_to_last_then_rest_; -template +template struct Apply_to_last_then_rest_ { typedef typename Apply_to_last_then_rest_::result_type result_type; inline result_type operator()(F&&f,T&&t,U&&...u)const{ diff --git a/NewKernel_d/include/CGAL/typeset.h b/NewKernel_d/include/CGAL/typeset.h index 9c494a412a9..77c37c89c39 100644 --- a/NewKernel_d/include/CGAL/typeset.h +++ b/NewKernel_d/include/CGAL/typeset.h @@ -41,11 +41,17 @@ namespace CGAL { template using contains = std::false_type; template using add = typeset; }; + struct typeset_all { + typedef typeset_all type; + template using contains = std::true_type; + template using add = typeset_all; + }; template struct typeset_union_ : typeset_union_::type, typename T2::tail> {}; template struct typeset_union_ > : T {}; + template struct typeset_union_ : typeset_all {}; template struct typeset_intersection_ { @@ -55,8 +61,8 @@ namespace CGAL { std::conditional::value, typename U::template add::type, U>::type type; }; - template - struct typeset_intersection_,T> : typeset<> {}; + template struct typeset_intersection_, T> : typeset<> {}; + template struct typeset_intersection_ : T {}; template using typeset_union = typename typeset_union_::type; diff --git a/Number_types/include/CGAL/GMP/Gmpq_type.h b/Number_types/include/CGAL/GMP/Gmpq_type.h index 54776eb5b78..451d2b00cdd 100644 --- a/Number_types/include/CGAL/GMP/Gmpq_type.h +++ b/Number_types/include/CGAL/GMP/Gmpq_type.h @@ -223,7 +223,7 @@ public: Gmpq& operator/=(const Gmpq &q); bool operator==(const Gmpq &q) const noexcept { return mpq_equal(this->mpq(), q.mpq()) != 0;} - bool operator< (const Gmpq &q) const noexcept { return mpq_cmp(this->mpq(), q.mpq()) < 0; } + bool operator< (const Gmpq &q) const { return mpq_cmp(this->mpq(), q.mpq()) < 0; } double to_double() const noexcept; Sign sign() const noexcept; diff --git a/Number_types/include/CGAL/Lazy_exact_nt.h b/Number_types/include/CGAL/Lazy_exact_nt.h index b0c401a3797..1a511325de9 100644 --- a/Number_types/include/CGAL/Lazy_exact_nt.h +++ b/Number_types/include/CGAL/Lazy_exact_nt.h @@ -438,6 +438,69 @@ public : return *this = new Lazy_exact_Div(*this, b); } + // Mixed comparisons with int. + friend bool operator<(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = a.approx() < b; + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return a.exact() < b; + } + + friend bool operator>(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b < a.approx(); + if (is_certain(res)) + return get_certain(res); + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b < a.exact(); + } + + friend bool operator==(const Lazy_exact_nt& a, int b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b == a.approx(); + if (is_certain(res)) + return get_certain(res); + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b == a.exact(); + } + + + // Mixed comparisons with double. + friend bool operator<(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = a.approx() < b; + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return a.exact() < b; + } + + friend bool operator>(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b < a.approx(); + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b < a.exact(); + } + + friend bool operator==(const Lazy_exact_nt& a, double b) + { + CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); + Uncertain res = b == a.approx(); + if (is_certain(res)) + return res; + CGAL_BRANCH_PROFILER_BRANCH(tmp); + return b == a.exact(); + } + // % kills filtering Self & operator%=(const Self& b) { @@ -562,84 +625,6 @@ operator%(const Lazy_exact_nt& a, const Lazy_exact_nt& b) } - -// Mixed operators with int. -template -bool -operator<(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = a.approx() < b; - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return a.exact() < b; -} - -template -bool -operator>(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b < a.approx(); - if (is_certain(res)) - return get_certain(res); - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b < a.exact(); -} - -template -bool -operator==(const Lazy_exact_nt& a, int b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b == a.approx(); - if (is_certain(res)) - return get_certain(res); - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b == a.exact(); -} - - -// Mixed operators with double. -template -bool -operator<(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = a.approx() < b; - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return a.exact() < b; -} - -template -bool -operator>(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b < a.approx(); - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b < a.exact(); -} - -template -bool -operator==(const Lazy_exact_nt& a, double b) -{ - CGAL_BRANCH_PROFILER(std::string(" failures/calls to : ") + std::string(CGAL_PRETTY_FUNCTION), tmp); - Uncertain res = b == a.approx(); - if (is_certain(res)) - return res; - CGAL_BRANCH_PROFILER_BRANCH(tmp); - return b == a.exact(); -} - - - template Lazy_exact_nt< typename Coercion_traits::Type > operator+(const Lazy_exact_nt& a, const Lazy_exact_nt& b) diff --git a/Number_types/include/CGAL/MP_Float.h b/Number_types/include/CGAL/MP_Float.h index 56e22b7e39b..68cfdecde44 100644 --- a/Number_types/include/CGAL/MP_Float.h +++ b/Number_types/include/CGAL/MP_Float.h @@ -27,6 +27,7 @@ #include #include #include +#include // MP_Float : multiprecision scaled integers. @@ -106,7 +107,13 @@ MP_Float operator*(const MP_Float &a, const MP_Float &b); MP_Float operator%(const MP_Float &a, const MP_Float &b); -class MP_Float +class MP_Float : boost::totally_ordered1 > +#endif + > { public: typedef short limb; @@ -223,6 +230,22 @@ public: MP_Float& operator*=(const MP_Float &a) { return *this = *this * a; } MP_Float& operator%=(const MP_Float &a) { return *this = *this % a; } + friend bool operator<(const MP_Float &a, const MP_Float &b) + { return INTERN_MP_FLOAT::compare(a, b) == SMALLER; } + + friend bool operator==(const MP_Float &a, const MP_Float &b) + { return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); } + +#ifdef _MSC_VER + // Needed because without /permissive-, it makes hidden friends visible (from Quotient) + friend bool operator==(const MP_Float &a, int b) { return a == MP_Float(b); } + friend bool operator==(const MP_Float &a, double b) { return a == MP_Float(b); } + friend bool operator< (const MP_Float &a, int b) { return a < MP_Float(b); } + friend bool operator< (const MP_Float &a, double b) { return a < MP_Float(b); } + friend bool operator> (const MP_Float &a, int b) { return a > MP_Float(b); } + friend bool operator> (const MP_Float &a, double b) { return a > MP_Float(b); } +#endif + exponent_type max_exp() const { return exponent_type(v.size()) + exp; @@ -365,30 +388,6 @@ inline void swap(MP_Float &m, MP_Float &n) { m.swap(n); } -inline -bool operator<(const MP_Float &a, const MP_Float &b) -{ return INTERN_MP_FLOAT::compare(a, b) == SMALLER; } - -inline -bool operator>(const MP_Float &a, const MP_Float &b) -{ return b < a; } - -inline -bool operator>=(const MP_Float &a, const MP_Float &b) -{ return ! (a < b); } - -inline -bool operator<=(const MP_Float &a, const MP_Float &b) -{ return ! (a > b); } - -inline -bool operator==(const MP_Float &a, const MP_Float &b) -{ return (a.v == b.v) && (a.v.empty() || (a.exp == b.exp)); } - -inline -bool operator!=(const MP_Float &a, const MP_Float &b) -{ return ! (a == b); } - MP_Float approximate_sqrt(const MP_Float &d); diff --git a/Number_types/include/CGAL/Mpzf.h b/Number_types/include/CGAL/Mpzf.h index d775431ebcf..2612e29b3a0 100644 --- a/Number_types/include/CGAL/Mpzf.h +++ b/Number_types/include/CGAL/Mpzf.h @@ -340,18 +340,62 @@ struct Mpzf { exp=x.exp; if(size!=0) mpn_copyi(data(),x.data(),asize); } -#if !defined(CGAL_MPZF_USE_CACHE) +#if defined(CGAL_MPZF_USE_CACHE) + Mpzf(Mpzf&& x)noexcept:size(x.size),exp(x.exp){ + auto xd = x.data(); + while(*--xd==0); + if (xd != x.cache) { + data() = x.data(); + x.init(); + } else { + init(); + if(size!=0) mpn_copyi(data(),x.data(),std::abs(size)); + } + x.size = 0; + } + Mpzf& operator=(Mpzf&& x)noexcept{ + if (this == &x) return *this; // is this needed? + size = x.size; + exp = x.exp; + auto xd = x.data(); + auto td = data(); + while(*--xd==0); + while(*--td==0); + if (xd != x.cache) { + data() = x.data(); + if (td != cache) { + pool::push(td+1); + // should we instead give it to x in case x is reused? + // x.data() = td + 1; + } + x.init(); + } else { + // In some cases data points in the middle of the buffer, reset it + data() = td + 1; + if(size!=0) mpn_copyi(data(),x.data(),std::abs(size)); + } + x.size = 0; + return *this; + } +#else Mpzf(Mpzf&& x):data_(x.data()),size(x.size),exp(x.exp){ x.init(); // yes, that's a shame... x.size = 0; x.exp = 0; } - Mpzf& operator=(Mpzf&& x){ - std::swap(size,x.size); + Mpzf& operator=(Mpzf&& x)noexcept{ + size = x.size; + // In case something tries to read it, size needs to be smaller than data + x.size = 0; exp = x.exp; std::swap(data(),x.data()); return *this; } + friend void swap(Mpzf&a, Mpzf&b)noexcept{ + std::swap(a.size, b.size); + std::swap(a.exp, b.exp); + std::swap(a.data(), b.data()); + } friend Mpzf operator-(Mpzf&& x){ Mpzf ret = std::move(x); ret.size = -ret.size; @@ -534,6 +578,12 @@ struct Mpzf { friend bool operator!=(Mpzf const&a, Mpzf const&b){ return !(a==b); } + friend Mpzf const& min BOOST_PREVENT_MACRO_SUBSTITUTION (Mpzf const&a, Mpzf const&b){ + return (b& operator*= (const CGAL_double(NT)& r); Quotient& operator/= (const CGAL_double(NT)& r); + friend bool operator==(const Quotient& x, const Quotient& y) + { return x.num * y.den == x.den * y.num; } + friend bool operator==(const Quotient& x, const NT& y) + { return x.den * y == x.num; } + friend inline bool operator==(const Quotient& x, const CGAL_int(NT) & y) + { return x.den * y == x.num; } + friend inline bool operator==(const Quotient& x, const CGAL_double(NT) & y) + { return x.den * y == x.num; } // Uh? + Quotient& normalize(); const NT& numerator() const { return num; } @@ -438,31 +447,6 @@ quotient_truncation(const Quotient& r) -template -CGAL_MEDIUM_INLINE -bool -operator==(const Quotient& x, const Quotient& y) -{ return x.num * y.den == x.den * y.num; } - -template -CGAL_MEDIUM_INLINE -bool -operator==(const Quotient& x, const NT& y) -{ return x.den * y == x.num; } - -template -inline -bool -operator==(const Quotient& x, const CGAL_int(NT) & y) -{ return x.den * y == x.num; } - -template -inline -bool -operator==(const Quotient& x, const CGAL_double(NT) & y) -{ return x.den * y == x.num; } - - template CGAL_MEDIUM_INLINE diff --git a/Number_types/test/Number_types/Mpzf_new.cpp b/Number_types/test/Number_types/Mpzf_new.cpp new file mode 100644 index 00000000000..414f1f2534b --- /dev/null +++ b/Number_types/test/Number_types/Mpzf_new.cpp @@ -0,0 +1,40 @@ +#include + +#ifdef CGAL_USE_GMP +# include +#endif +#ifdef CGAL_HAS_MPZF + +#include +#include +#include +#include + +int main() { + { + typedef CGAL::Mpzf NT; + typedef CGAL::Integral_domain_without_division_tag Tag; + typedef CGAL::Tag_true Is_exact; + + CGAL::test_algebraic_structure(); + CGAL::test_algebraic_structure(NT(4),NT(6),NT(15)); + CGAL::test_algebraic_structure(NT(-4),NT(6),NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(-6),NT(15)); + CGAL::test_algebraic_structure(NT(-4),NT(-6),NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(6),NT(-15)); + CGAL::test_algebraic_structure(NT(-4),NT(6), NT(15)); + CGAL::test_algebraic_structure(NT(4),NT(-6),NT(-15)); + CGAL::test_algebraic_structure(NT(-4),NT(-6),NT(-15)); + + CGAL::test_real_embeddable(); + } + + return 0; +} + +#else +int main() +{ + return 0; +} +#endif //CGAL_HAS_MPZF diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h index 477c1294fa1..4680993e372 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/evolution.h @@ -76,7 +76,7 @@ public: std::generate(group4.begin(), group4.end(), [&]{ return m_rng.get_int(0, im); }); // crossover I, pick A or B - constexpr FT lweight = 0.4, uweight = 0.6; + const FT lweight = 0.4, uweight = 0.6; std::vector new_simplices(m); @@ -160,8 +160,6 @@ public: std::cout << std::endl; #endif - // optimize the current best rotation by using the exact OBB 2D algorithm - // along the axes of the current best OBB m_best_v = &(m_population.get_best_vertex()); Matrix& best_m = m_best_v->matrix(); @@ -170,7 +168,10 @@ public: std::cout << "fitness: " << m_best_v->fitness() << std::endl; #endif - optimize_along_OBB_axes(best_m, m_points, m_traits); + // optimize the current best rotation by using the exact OBB 2D algorithm + // along the axes of the current best OBB + Optimizer_along_axes optimizer_2D; + optimizer_2D(best_m, m_points, m_traits); m_best_v->fitness() = compute_fitness(best_m, m_points, m_traits); // stopping criteria diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h index 7bd6b4be3e6..d8497ba486a 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/internal/optimize_2.h @@ -214,6 +214,25 @@ void optimize_along_OBB_axes(typename Traits::Matrix& rot, } } +// This operation makes no sense if an exact number type is used, so skip it, if so +template ::Is_exact> +struct Optimizer_along_axes +{ + template + void operator()(typename Traits::Matrix& rot, const PointRange& points, const Traits& traits) + { + return optimize_along_OBB_axes(rot, points, traits); + } +}; + +template +struct Optimizer_along_axes +{ + template + void operator()(typename Traits::Matrix&, const PointRange&, const Traits&) { } +}; + } // namespace internal } // namespace Optimal_bounding_box } // namespace CGAL diff --git a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h index 49e4b2974f7..99f8be9cc7e 100644 --- a/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h +++ b/Optimal_bounding_box/include/CGAL/Optimal_bounding_box/oriented_bounding_box.h @@ -23,7 +23,6 @@ #include #include -#include #include #include #include @@ -64,25 +63,42 @@ void construct_oriented_bounding_box(const PointRange& points, std::array& obb_points, const Traits& traits) { + typedef typename Traits::FT FT; typedef typename Traits::Point_3 Point; + CGAL_precondition(!points.empty()); + // Construct the bbox of the transformed point set - CGAL::Bbox_3 bbox; - for(const Point& pt : points) + typename PointRange::const_iterator pit = std::begin(points); + const Point& first_pt = *pit++; + const Point first_rot_pt = transformation.transform(first_pt); + FT xmin = first_rot_pt.x(), xmax = first_rot_pt.x(); + FT ymin = first_rot_pt.y(), ymax = first_rot_pt.y(); + FT zmin = first_rot_pt.z(), zmax = first_rot_pt.z(); + + for(typename PointRange::const_iterator end=std::end(points); pit!=end; ++pit) { - const Point rotated_pt = transformation.transform(pt); - bbox += traits.construct_bbox_3_object()(rotated_pt); + const Point rot_pt = transformation.transform(*pit); + + xmin = (std::min)(rot_pt.x(), xmin); + ymin = (std::min)(rot_pt.y(), ymin); + zmin = (std::min)(rot_pt.z(), zmin); + xmax = (std::max)(rot_pt.x(), xmax); + ymax = (std::max)(rot_pt.y(), ymax); + zmax = (std::max)(rot_pt.z(), zmax); } - obb_points[0] = Point(bbox.xmin(), bbox.ymin(), bbox.zmin()); - obb_points[1] = Point(bbox.xmax(), bbox.ymin(), bbox.zmin()); - obb_points[2] = Point(bbox.xmax(), bbox.ymax(), bbox.zmin()); - obb_points[3] = Point(bbox.xmin(), bbox.ymax(), bbox.zmin()); + typename Traits::Construct_point_3 cp = traits.construct_point_3_object(); - obb_points[4] = Point(bbox.xmin(), bbox.ymax(), bbox.zmax()); // see order in make_hexahedron()... - obb_points[5] = Point(bbox.xmin(), bbox.ymin(), bbox.zmax()); - obb_points[6] = Point(bbox.xmax(), bbox.ymin(), bbox.zmax()); - obb_points[7] = Point(bbox.xmax(), bbox.ymax(), bbox.zmax()); + obb_points[0] = cp(xmin, ymin, zmin); + obb_points[1] = cp(xmax, ymin, zmin); + obb_points[2] = cp(xmax, ymax, zmin); + obb_points[3] = cp(xmin, ymax, zmin); + + obb_points[4] = cp(xmin, ymax, zmax); // see order in make_hexahedron()... + obb_points[5] = cp(xmin, ymin, zmax); + obb_points[6] = cp(xmax, ymin, zmax); + obb_points[7] = cp(xmax, ymax, zmax); // Apply the inverse rotation to the rotated axis aligned bounding box for(std::size_t i=0; i<8; ++i) diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h index 1109c4a0181..7b475e9a11e 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_cell_base_3.h @@ -233,7 +233,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void *p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h index 539c3278bf3..e264e523063 100644 --- a/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h +++ b/Periodic_3_triangulation_3/include/CGAL/Periodic_3_triangulation_ds_vertex_base_3.h @@ -80,8 +80,8 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _c.for_compact_container(); } - void * & for_compact_container() - { return _c.for_compact_container(); } + void for_compact_container(void *p) + { _c.for_compact_container(p); } private: Cell_handle _c; diff --git a/Point_set_3/package_info/Point_set_3/dependencies b/Point_set_3/package_info/Point_set_3/dependencies index cab851ef527..6f0ec394588 100644 --- a/Point_set_3/package_info/Point_set_3/dependencies +++ b/Point_set_3/package_info/Point_set_3/dependencies @@ -1,5 +1,6 @@ Algebraic_foundations BGL +Circulator GraphicsView Installation Interval_support diff --git a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt index 78e0ba58613..3d482fdc4f2 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/PackageDescription.txt @@ -56,6 +56,7 @@ format. - `CGAL::pointmatcher::compute_registration_transformation()` - `CGAL::pointmatcher::register_point_sets()` - `CGAL::remove_outliers()` +- `CGAL::cluster_point_set()` - `CGAL::grid_simplify_point_set()` - `CGAL::random_simplify_point_set()` - `CGAL::hierarchy_simplify_point_set()` diff --git a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt index 24f0ee8e87e..514afa2b06c 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/Point_set_processing_3.txt @@ -610,15 +610,43 @@ individually. \cgalFigureCaptionEnd +\section Point_set_processing_3Clustering Clustering +If an input point set represents several objects which are spatially +separated, a clustering algorithm can be applied to identify connected +components on a nearest neighbor graph built using a query sphere of +fixed radius centered on each point. + +The clustering is stored in a cluster map which associates each input +point with the index of the cluster it belongs to: users can then use +this map however they find it relevant to their use case, for example +segmenting the input point set into one point set per +cluster. \cgalFigureRef{Point_set_processing_3figclustering} shows +different clustering outputs. + +\cgalFigureBegin{Point_set_processing_3figclustering,clustering.png} +Point Set Clustering outputs (one color per cluster). Top: input point +set and clustering using a neighbor radius of 1.5 (147 clusters +extracted). Bottom: clustering with neighbor radius 3.0 (37 clusters +extracted), and with neighbor radius 6.0 (5 clusters extracted). +\cgalFigureEnd + + +\subsection Point_set_processing_3Example_clustering Example + +In the following example, clusters (and adjacencies between them) are +computed and stored as colors in a PLY file: + +\cgalExample{Point_set_processing_3/clustering_example.cpp} \section Point_set_processing_3OutlierRemoval Outlier Removal -Function `remove_outliers()` deletes a user-specified fraction -of outliers from an input point set. More specifically, it sorts the -input points in increasing order of average squared distances to their -nearest neighbors and deletes the points with largest value. The user -can either specify a fixed number of nearest neighbors or a fixed +Function `remove_outliers()` deletes a user-specified fraction of +outliers from an input point set. More specifically, it partitions the +input points with respect to the average squared distances to their +nearest neighbors and deletes the points with largest value, either +partitionning with a threshold or removing a fixed percentage. The +user can either specify a fixed number of nearest neighbors or a fixed spherical neighborhood radius. \subsection Point_set_processing_3Example_outlier_removal Example @@ -966,4 +994,3 @@ libraries that perform registration on two point sets. */ } /* namespace CGAL */ - diff --git a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt index 3cdfe3727b9..2374e1ea02f 100644 --- a/Point_set_processing_3/doc/Point_set_processing_3/examples.txt +++ b/Point_set_processing_3/doc/Point_set_processing_3/examples.txt @@ -9,6 +9,7 @@ \example Point_set_processing_3/registration_with_OpenGR.cpp \example Point_set_processing_3/registration_with_pointmatcher.cpp \example Point_set_processing_3/registration_with_opengr_pointmatcher_pipeline.cpp +\example Point_set_processing_3/clustering_example.cpp \example Point_set_processing_3/remove_outliers_example.cpp \example Point_set_processing_3/grid_simplification_example.cpp \example Point_set_processing_3/grid_simplify_indices.cpp diff --git a/Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png b/Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png new file mode 100644 index 00000000000..e50b92a0059 Binary files /dev/null and b/Point_set_processing_3/doc/Point_set_processing_3/fig/clustering.png differ diff --git a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt index 36412ac7b68..85f5f79eed8 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt +++ b/Point_set_processing_3/examples/Point_set_processing_3/CMakeLists.txt @@ -69,7 +69,11 @@ if ( CGAL_FOUND ) create_single_source_cgal_program( "normal_estimation.cpp" ) CGAL_target_use_Eigen(normal_estimation) + create_single_source_cgal_program( "clustering_example.cpp" ) + CGAL_target_use_Eigen(clustering_example) + create_single_source_cgal_program( "edges_example.cpp" ) + CGAL_target_use_Eigen(edges_example) # Executables that require libpointmatcher find_package(libpointmatcher QUIET) @@ -101,8 +105,6 @@ if ( CGAL_FOUND ) message(STATUS "NOTICE : registration_with_opengr_pointmatcher_pipeline requires libpointmatcher and OpenGR, and will not be compiled.") endif() - CGAL_target_use_Eigen(edges_example) - create_single_source_cgal_program( "callback_example.cpp" ) CGAL_target_use_Eigen(callback_example) @@ -132,7 +134,8 @@ if ( CGAL_FOUND ) normals_example jet_smoothing_example normal_estimation - callback_example) + callback_example + clustering_example) if(TARGET ${target}) CGAL_target_use_TBB(${target}) endif() diff --git a/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp new file mode 100644 index 00000000000..934609dd152 --- /dev/null +++ b/Point_set_processing_3/examples/Point_set_processing_3/clustering_example.cpp @@ -0,0 +1,62 @@ +#include +#include +#include +#include +#include + +#include +#include + +#include + +using Kernel = CGAL::Exact_predicates_inexact_constructions_kernel; +using Point_3 = Kernel::Point_3; +using Point_set = CGAL::Point_set_3; + +int main (int argc, char** argv) +{ + // Read input file + std::ifstream ifile ((argc > 1) ? argv[1] : "data/hippo1.ply", std::ios_base::binary); + Point_set points; + ifile >> points; + + // Add a cluster map + Point_set::Property_map cluster_map = points.add_property_map ("cluster", -1).first; + + // Compute average spacing + double spacing = CGAL::compute_average_spacing (points, 12); + std::cerr << "Spacing = " << spacing << std::endl; + + // Adjacencies stored in vector + std::vector > adjacencies; + + // Compute clusters + CGAL::Real_timer t; + t.start(); + std::size_t nb_clusters + = CGAL::cluster_point_set (points, cluster_map, + points.parameters().neighbor_radius(spacing). + adjacencies (std::back_inserter (adjacencies))); + t.stop(); + std::cerr << "Found " << nb_clusters << " clusters with " << adjacencies.size() + << " adjacencies in " << t.time() << " seconds" << std::endl; + + // Output a colored PLY file + Point_set::Property_map red = points.add_property_map("red", 0).first; + Point_set::Property_map green = points.add_property_map("green", 0).first; + Point_set::Property_map blue = points.add_property_map("blue", 0).first; + for (Point_set::Index idx : points) + { + // One color per cluster + CGAL::Random rand (cluster_map[idx]); + red[idx] = rand.get_int(64, 192); + green[idx] = rand.get_int(64, 192); + blue[idx] = rand.get_int(64, 192); + } + + std::ofstream ofile ("out.ply", std::ios_base::binary); + CGAL::set_binary_mode (ofile); + ofile << points; + + return EXIT_SUCCESS; +} diff --git a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp index 89dd118252b..579829b2b4c 100644 --- a/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp +++ b/Point_set_processing_3/examples/Point_set_processing_3/remove_outliers_example.cpp @@ -39,7 +39,7 @@ int main(int argc, char*argv[]) // FIRST OPTION // // I don't know the ratio of outliers present in the point set std::vector::iterator first_to_remove - = CGAL::remove_outliers + = CGAL::remove_outliers (points, nb_neighbors, CGAL::parameters::threshold_percent (100.). // No limit on the number of outliers to remove @@ -55,7 +55,7 @@ int main(int argc, char*argv[]) // I know the ratio of outliers present in the point set const double removed_percentage = 5.0; // percentage of points to remove - points.erase(CGAL::remove_outliers + points.erase(CGAL::remove_outliers (points, nb_neighbors, CGAL::parameters::threshold_percent(removed_percentage). // Minimum percentage to remove diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h index 5e8996db035..bdd9291c559 100644 --- a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/Neighbor_query.h @@ -14,6 +14,7 @@ #include +#include #include #include #include @@ -39,8 +40,13 @@ public: typedef PointMap Point_map; typedef typename Kernel::FT FT; + typedef typename boost::property_traits::value_type Point; + + typedef typename Kernel::Point_2 Point_2; typedef typename Kernel::Point_3 Point_3; + typedef std::is_same Is_2d; + typedef typename Range_iterator_type::type input_iterator; typedef typename input_iterator::value_type value_type; @@ -64,7 +70,10 @@ public: } }; - typedef CGAL::Search_traits_3 Tree_traits_base; + typedef typename std::conditional, + CGAL::Search_traits_3 >::type Tree_traits_base; + typedef CGAL::Search_traits_adapter Tree_traits; typedef CGAL::Sliding_midpoint Splitter; typedef CGAL::Distance_adapter > Distance; @@ -102,8 +111,8 @@ public: PointMap point_map() const { return m_point_map; } template - void get_iterators (const Point_3& query, unsigned int k, FT neighbor_radius, - OutputIterator output) const + void get_iterators (const Point& query, unsigned int k, FT neighbor_radius, + OutputIterator output, bool fallback_k_if_sphere_empty = true) const { if (neighbor_radius != FT(0)) { @@ -135,7 +144,7 @@ public: // Fallback, if less than 3 points are return, search for the 3 // first points - if (nb < 3) + if (fallback_k_if_sphere_empty && nb < 3) k = 3; // Else, no need to search for K nearest neighbors else @@ -163,7 +172,7 @@ public: } template - void get_points (const Point_3& query, unsigned int k, FT neighbor_radius, + void get_points (const Point& query, unsigned int k, FT neighbor_radius, OutputIterator output) const { return get_iterators(query, k, neighbor_radius, diff --git a/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h new file mode 100644 index 00000000000..84976b8f23c --- /dev/null +++ b/Point_set_processing_3/include/CGAL/Point_set_processing_3/internal/bbox_diagonal.h @@ -0,0 +1,59 @@ +// Copyright (c) 2020 GeometryFactory (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H +#define CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H + +#include + +namespace CGAL +{ +namespace Point_set_processing_3 +{ +namespace internal +{ + +template +double bbox_diagonal (const PointRange& points, PointMap point_map, const typename Kernel::Point_2&) +{ + CGAL::Bbox_2 bbox = CGAL::bbox_2 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), + CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); + + return CGAL::approximate_sqrt + ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin())); +} + +template +double bbox_diagonal (const PointRange& points, PointMap point_map, const typename Kernel::Point_3&) +{ + CGAL::Bbox_3 bbox = CGAL::bbox_3 (CGAL::make_transform_iterator_from_property_map (points.begin(), point_map), + CGAL::make_transform_iterator_from_property_map (points.end(), point_map)); + + return CGAL::approximate_sqrt + ((bbox.xmax() - bbox.xmin()) * (bbox.xmax() - bbox.xmin()) + + (bbox.ymax() - bbox.ymin()) * (bbox.ymax() - bbox.ymin()) + + (bbox.zmax() - bbox.zmin()) * (bbox.zmax() - bbox.zmin())); +} + +template +double bbox_diagonal (const PointRange& points, PointMap point_map) +{ + typedef typename boost::property_traits::value_type Point; + return bbox_diagonal::Kernel> (points, point_map, Point()); +} + +} // namespace internal +} // namespace Point_set_processing_3 +} // namespace CGAL + + +#endif // CGAL_PSP_INTERNAL_BBOX_DIAGONAL_H diff --git a/Point_set_processing_3/include/CGAL/cluster_point_set.h b/Point_set_processing_3/include/CGAL/cluster_point_set.h new file mode 100644 index 00000000000..3098db06c97 --- /dev/null +++ b/Point_set_processing_3/include/CGAL/cluster_point_set.h @@ -0,0 +1,251 @@ +// Copyright (c) 2020 GeometryFactory Sarl (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org). +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// Author(s) : Simon Giraudot + +#ifndef CGAL_CLUSTER_POINT_SET_H +#define CGAL_CLUSTER_POINT_SET_H + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#include + +namespace CGAL +{ + + +/// \cond SKIP_IN_MANUAL +namespace Point_set_processing_3 +{ + +namespace internal +{ + +// Trick to both compile version with Emptyset_iterator and with +// user-provided OutputIterator. Many output iterators (such as +// `std::back_insert_iterator`) cannot be default constructed, which +// makes the mechanism `choose_param(get_param(...),Default())` fails. +template +OutputIterator get_adjacencies (const NamedParameters& np, OutputIterator*) +{ + return CGAL::parameters::get_parameter(np, internal_np::adjacencies); +} + +template +CGAL::Emptyset_iterator get_adjacencies (const NamedParameters&, CGAL::Emptyset_iterator*) +{ + return CGAL::Emptyset_iterator(); +} + +} // namespace internal + +} // namespace Point_set_processing_3 +/// \endcond + +// ---------------------------------------------------------------------------- +// Public section +// ---------------------------------------------------------------------------- + +/** + \ingroup PkgPointSetProcessing3Algorithms + Identifies connected components on a nearest neighbor graph built + using a query sphere of fixed radius centered on each point. + + \tparam PointRange is a model of `Range`. The value type of its + iterator is the key type of the named parameter `point_map`. + \tparam ClusterMap is a model of `ReadWritePropertyMap` with value + type `std::size_t`. + + \param points input point range. + \param cluster_map maps each point to the index of the cluster it belongs to. + \param np optional sequence of \ref psp_namedparameters "Named Parameters" among the ones listed below. + + \cgalNamedParamsBegin + \cgalParamBegin{point_map} a model of `ReadablePropertyMap` with value type `geom_traits::Point_3`. + If this parameter is omitted, `CGAL::Identity_property_map` is used.\cgalParamEnd + \cgalParamBegin{callback} an instance of + `std::function`. It is called regularly when the + algorithm is running: the current advancement (between 0. and + 1.) is passed as parameter. If it returns `true`, then the + algorithm continues its execution normally; if it returns + `false`, the algorithm is stopped and the number of already + computed clusters is returned.\cgalParamEnd + \cgalParamBegin{neighbor_radius} spherical neighborhood + radius. If no value is provided, the default value is 1% of the + bounding box diagonal.\cgalParamEnd + \cgalParamBegin{attraction_factor} used to compute adjacencies + between clusters. Adjacencies are computed using a nearest + neighbor graph built similarly to the one used for clustering, + using `attraction_factor * neighbor_radius` as + parameter. %Default value is `2`.\cgalParamEnd + \cgalParamBegin{adjacencies} model of `OutputIterator` that + accepts objects of type `std::pair`. Each pair contains the indices of two adjacent + clusters. If this parameter is not used, adjacencies are not + computed at all.\cgalParamEnd + \cgalParamBegin{geom_traits} an instance of a geometric traits class, model of `Kernel`\cgalParamEnd + \cgalNamedParamsEnd + + \return the number of clusters identified. +*/ +template +std::size_t cluster_point_set (PointRange& points, + ClusterMap cluster_map, + const NamedParameters& np) +{ + using parameters::choose_parameter; + using parameters::get_parameter; + + // basic geometric types + typedef typename PointRange::iterator iterator; + typedef typename iterator::value_type value_type; + typedef typename CGAL::GetPointMap::type PointMap; + typedef typename Point_set_processing_3::GetK::Kernel Kernel; + typedef typename Point_set_processing_3::GetAdjacencies::type Adjacencies; + + CGAL_static_assertion_msg(!(boost::is_same::type, + typename GetSvdTraits::NoTraits>::value), + "Error: no SVD traits"); + + PointMap point_map = choose_parameter(get_parameter(np, internal_np::point_map), PointMap()); + typename Kernel::FT neighbor_radius = choose_parameter(get_parameter(np, internal_np::neighbor_radius), + typename Kernel::FT(-1)); + typename Kernel::FT factor = choose_parameter(get_parameter(np, internal_np::attraction_factor), + typename Kernel::FT(2)); + + const std::function& callback = choose_parameter(get_parameter(np, internal_np::callback), + std::function()); + + double callback_factor = 1.; + if (!std::is_same::Empty>::value) + callback_factor = 0.5; + + // types for K nearest neighbors search structure + typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; + + // precondition: at least one element in the container. + // to fix: should have at least three distinct points + // but this is costly to check + CGAL_point_set_processing_precondition(points.begin() != points.end()); + + // If no radius is given, init with 1% of bbox diagonal + if (neighbor_radius < 0) + neighbor_radius = 0.01 * Point_set_processing_3::internal::bbox_diagonal (points, point_map); + + // Init cluster map with -1 + for (const value_type& p : points) + put (cluster_map, p, -1); + + Neighbor_query neighbor_query (points, point_map); + + std::queue todo; + std::size_t nb_clusters = 0; + + // Flooding algorithm from each point + std::size_t done = 0; + std::size_t size = points.size(); + + for (iterator it = points.begin(); it != points.end(); ++ it) + { + const value_type& p = *it; + + if (int(get (cluster_map, p)) != -1) + continue; + + todo.push (it); + + while (!todo.empty()) + { + iterator current = todo.front(); + todo.pop(); + + if (int(get (cluster_map, *current)) != -1) + continue; + + put (cluster_map, *current, nb_clusters); + ++ done; + + if (callback && !callback (callback_factor * (done + 1) / double(size))) + return (nb_clusters + 1); + + neighbor_query.get_iterators (get (point_map, *current), 0, neighbor_radius, + boost::make_function_output_iterator + ([&](const iterator& it) { todo.push(it); }), true); + + } + + ++ nb_clusters; + } + + if (!std::is_same::Empty>::value) + { + Adjacencies adjacencies = Point_set_processing_3::internal::get_adjacencies(np, (Adjacencies*)(nullptr)); + neighbor_radius *= factor; + + std::vector neighbors; + std::vector > adj; + + done = 0; + for (const value_type& p : points) + { + std::size_t c0 = get (cluster_map, p); + + neighbors.clear(); + neighbor_query.get_iterators (get (point_map, p), 0, neighbor_radius, + std::back_inserter (neighbors), false); + + for (const iterator& it : neighbors) + { + std::size_t c1 = get (cluster_map, *it); + if (c0 < c1) + adj.push_back (std::make_pair (c0, c1)); + else if (c0 > c1) + adj.push_back (std::make_pair (c1, c0)); + // else c0 == c1, ignore + } + + ++ done; + if (callback && !callback (callback_factor + callback_factor * (done + 1) / double(size))) + return nb_clusters; + } + std::sort (adj.begin(), adj.end()); + auto last = std::unique (adj.begin(), adj.end()); + std::copy (adj.begin(), last, adjacencies); + } + + return nb_clusters; +} + +/// \cond SKIP_IN_MANUAL +// overload with default NP +template +std::size_t cluster_point_set (PointRange& points, + ClusterMap cluster_map, + unsigned int k) +{ + return cluster_point_set (points, cluster_map, k, + CGAL::Point_set_processing_3::parameters::all_default(points)); +} +/// \endcond + +} // namespace CGAL + + +#endif // CGAL_CLUSTER_POINT_SET_H diff --git a/Point_set_processing_3/include/CGAL/remove_outliers.h b/Point_set_processing_3/include/CGAL/remove_outliers.h index a0403d9bed1..e4beaf9a6b2 100644 --- a/Point_set_processing_3/include/CGAL/remove_outliers.h +++ b/Point_set_processing_3/include/CGAL/remove_outliers.h @@ -17,6 +17,8 @@ #include #include +#include +#include #include #include #include @@ -24,6 +26,8 @@ #include #include +#include + #include #include #include @@ -84,7 +88,9 @@ compute_avg_knn_sq_distance_3( \ingroup PkgPointSetProcessing3Algorithms Removes outliers: - computes average squared distance to the nearest neighbors, - - and sorts the points in increasing order of average distance. + - and partitions the points either using a threshold on the of + average distance or selecting a fixed percentage of points with + the highest average distances This method modifies the order of input points so as to pack all remaining points first, and returns an iterator over the first point to remove (see erase-remove idiom). @@ -92,6 +98,8 @@ compute_avg_knn_sq_distance_3( \pre `k >= 2` + \tparam ConcurrencyTag enables sequential versus parallel algorithm. Possible values are `Sequential_tag`, + `Parallel_tag`, and `Parallel_if_available_tag`. \tparam PointRange is a model of `Range`. The value type of its iterator is the key type of the named parameter `point_map`. @@ -160,7 +168,8 @@ compute_avg_knn_sq_distance_3( account; if `threshold_distance=0` only `threshold_percent` is taken into account. */ -template typename PointRange::iterator @@ -190,9 +199,6 @@ remove_outliers( typedef typename PointRange::iterator iterator; typedef typename iterator::value_type value_type; - // actual type of input points - typedef typename std::iterator_traits::value_type Enriched_point; - // types for K nearest neighbors search structure typedef Point_set_processing_3::internal::Neighbor_query Neighbor_query; @@ -211,48 +217,76 @@ remove_outliers( std::size_t nb_points = points.size(); // iterate over input points and add them to multimap sorted by distance to k - std::multimap sorted_points; - std::size_t nb = 0; - for(const value_type& vt : points) + std::vector > sorted_points; + sorted_points.reserve (nb_points); + for (const value_type& p : points) + sorted_points.push_back(std::make_pair (FT(0), p)); + + Point_set_processing_3::internal::Callback_wrapper + callback_wrapper (callback, nb_points); + + CGAL::for_each + (sorted_points, + [&](std::pair& p) -> bool + { + if (callback_wrapper.interrupted()) + return false; + + p.first = internal::compute_avg_knn_sq_distance_3( + get(point_map, p.second), + neighbor_query, k, neighbor_radius); + + ++ callback_wrapper.advancement(); + return true; + }); + + std::size_t first_index_to_remove = std::size_t(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); + + typename std::vector >::iterator f2r + = sorted_points.begin(); + + if (threshold_distance != FT(0)) + f2r = std::partition (sorted_points.begin(), sorted_points.end(), + [&threshold_distance](const std::pair& p) -> bool + { + return p.first < threshold_distance * threshold_distance; + }); + + if (static_cast(std::distance (sorted_points.begin(), f2r)) < first_index_to_remove) { - FT sq_distance = internal::compute_avg_knn_sq_distance_3( - get(point_map, vt), - neighbor_query, k, neighbor_radius); - sorted_points.insert( std::make_pair(sq_distance, vt) ); - if (callback && !callback ((nb+1) / double(nb_points))) - return points.end(); - ++ nb; + std::nth_element (f2r, + sorted_points.begin() + first_index_to_remove, + sorted_points.end()); + f2r = sorted_points.begin() + first_index_to_remove; } - // Replaces [points.begin(), points.end()) range by the multimap content. - // Returns the iterator after the (100-threshold_percent) % best points. - typename PointRange::iterator first_point_to_remove = points.begin(); - typename PointRange::iterator dst = points.begin(); - int first_index_to_remove = int(double(sorted_points.size()) * ((100.0-threshold_percent)/100.0)); - typename std::multimap::iterator src; - int index; - for (src = sorted_points.begin(), index = 0; - src != sorted_points.end(); - ++src, ++index) + // Replaces [points.begin(), points.end()) range by the sorted content. + iterator pit = points.begin(); + iterator out = points.begin(); + + for (auto sit = sorted_points.begin(); sit != sorted_points.end(); ++ sit) { - *dst++ = src->second; - if (index <= first_index_to_remove || - src->first < threshold_distance * threshold_distance) - first_point_to_remove = dst; + *pit = sit->second; + if (sit == f2r) + out = pit; + ++ pit; } - return first_point_to_remove; + callback_wrapper.join(); + + // Returns the iterator on the first point to remove + return out; } /// \cond SKIP_IN_MANUAL // variant with default NP -template +template typename PointRange::iterator remove_outliers( PointRange& points, unsigned int k) ///< number of neighbors. { - return remove_outliers (points, k, CGAL::Point_set_processing_3::parameters::all_default(points)); + return remove_outliers (points, k, CGAL::Point_set_processing_3::parameters::all_default(points)); } /// \endcond diff --git a/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp b/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp index 474d2aa23ac..aa8e5be878a 100644 --- a/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp +++ b/Point_set_processing_3/test/Point_set_processing_3/remove_outliers_test.cpp @@ -50,8 +50,9 @@ void test_avg_knn_sq_distance(std::deque& points, // input point set << nb_neighbors_remove_outliers << ")...\n"; // Removes outliers using erase-remove idiom - points.erase(CGAL::remove_outliers(points, nb_neighbors_remove_outliers, - CGAL::parameters::threshold_percent(removed_percentage)), + points.erase(CGAL::remove_outliers + (points, nb_neighbors_remove_outliers, + CGAL::parameters::threshold_percent(removed_percentage)), points.end()); // Optional: after erase(), use Scott Meyer's "swap trick" to trim excess capacity @@ -139,4 +140,3 @@ int main(int argc, char * argv[]) std::cerr << "Tool returned " << accumulated_fatal_err << std::endl; return accumulated_fatal_err; } - diff --git a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp index ff58e34ed31..594961714d4 100644 --- a/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp +++ b/Poisson_surface_reconstruction_3/examples/Poisson_surface_reconstruction_3/tutorial_example.cpp @@ -63,9 +63,10 @@ int main(int argc, char*argv[]) /////////////////////////////////////////////////////////////////// //! [Outlier removal] - CGAL::remove_outliers (points, - 24, // Number of neighbors considered for evaluation - points.parameters().threshold_percent (5.0)); // Percentage of points to remove + CGAL::remove_outliers + (points, + 24, // Number of neighbors considered for evaluation + points.parameters().threshold_percent (5.0)); // Percentage of points to remove std::cout << points.number_of_removed_points() << " point(s) are outliers." << std::endl; 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 bbe55ca4cbc..7b13f109a6d 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 @@ -16,7 +16,7 @@ typedef Mesh::Property_map Exact_point_computed; namespace PMP = CGAL::Polygon_mesh_processing; namespace params = PMP::parameters; -struct Coref_point_map +struct Exact_vertex_point_map { // typedef for the property map typedef boost::property_traits::value_type value_type; @@ -25,64 +25,39 @@ struct Coref_point_map typedef boost::property_traits::key_type key_type; // exterior references - Exact_point_computed* exact_point_computed_ptr; - Exact_point_map* exact_point_ptr; - Mesh* mesh_ptr; - - Exact_point_computed& exact_point_computed() const - { - CGAL_assertion(exact_point_computed_ptr!=NULL); - return *exact_point_computed_ptr; - } - - Exact_point_map& exact_point() const - { - CGAL_assertion(exact_point_ptr!=NULL); - return *exact_point_ptr; - } - - Mesh& mesh() const - { - CGAL_assertion(mesh_ptr!=NULL); - return *mesh_ptr; - } + Exact_point_map exact_point_map; + Mesh* tm_ptr; // Converters CGAL::Cartesian_converter to_exact; CGAL::Cartesian_converter to_input; - Coref_point_map() - : exact_point_computed_ptr(NULL) - , exact_point_ptr(NULL) - , mesh_ptr(NULL) + Exact_vertex_point_map() + : tm_ptr(nullptr) {} - Coref_point_map(Exact_point_map& ep, - Exact_point_computed& epc, - Mesh& m) - : exact_point_computed_ptr(&epc) - , exact_point_ptr(&ep) - , mesh_ptr(&m) - {} - - friend - reference get(const Coref_point_map& map, key_type k) + Exact_vertex_point_map(const Exact_point_map& ep, Mesh& tm) + : exact_point_map(ep) + , tm_ptr(&tm) { - // create exact point if it does not exist - if (!map.exact_point_computed()[k]){ - map.exact_point()[k]=map.to_exact(map.mesh().point(k)); - map.exact_point_computed()[k]=true; - } - return map.exact_point()[k]; + for (Mesh::Vertex_index v : vertices(tm)) + exact_point_map[v]=to_exact(tm.point(v)); } friend - void put(const Coref_point_map& map, key_type k, const EK::Point_3& p) + reference get(const Exact_vertex_point_map& map, key_type k) { - map.exact_point_computed()[k]=true; - map.exact_point()[k]=p; + CGAL_precondition(map.tm_ptr!=nullptr); + return map.exact_point_map[k]; + } + + friend + void put(const Exact_vertex_point_map& map, key_type k, const EK::Point_3& p) + { + CGAL_precondition(map.tm_ptr!=nullptr); + map.exact_point_map[k]=p; // create the input point from the exact one - map.mesh().point(k)=map.to_input(p); + map.tm_ptr->point(k)=map.to_input(p); } }; @@ -109,30 +84,26 @@ int main(int argc, char* argv[]) Exact_point_map mesh1_exact_points = mesh1.add_property_map("e:exact_point").first; - Exact_point_computed mesh1_exact_points_computed = - mesh1.add_property_map("e:exact_points_computed").first; Exact_point_map mesh2_exact_points = mesh2.add_property_map("e:exact_point").first; - Exact_point_computed mesh2_exact_points_computed = - mesh2.add_property_map("e:exact_points_computed").first; - Coref_point_map mesh1_pm(mesh1_exact_points, mesh1_exact_points_computed, mesh1); - Coref_point_map mesh2_pm(mesh2_exact_points, mesh2_exact_points_computed, mesh2); + Exact_vertex_point_map mesh1_vpm(mesh1_exact_points, mesh1); + Exact_vertex_point_map mesh2_vpm(mesh2_exact_points, mesh2); if ( PMP::corefine_and_compute_intersection(mesh1, mesh2, mesh1, - params::vertex_point_map(mesh1_pm), - params::vertex_point_map(mesh2_pm), - params::vertex_point_map(mesh1_pm) ) ) + params::vertex_point_map(mesh1_vpm), + params::vertex_point_map(mesh2_vpm), + params::vertex_point_map(mesh1_vpm) ) ) { if ( PMP::corefine_and_compute_union(mesh1, mesh2, mesh2, - params::vertex_point_map(mesh1_pm), - params::vertex_point_map(mesh2_pm), - params::vertex_point_map(mesh2_pm) ) ) + params::vertex_point_map(mesh1_vpm), + params::vertex_point_map(mesh2_vpm), + params::vertex_point_map(mesh2_vpm) ) ) { std::cout << "Intersection and union were successfully computed\n"; std::ofstream output("inter_union.off"); diff --git a/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp b/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp index e44be56106e..4d9003f0d6a 100644 --- a/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp +++ b/Polygon_mesh_processing/examples/Polygon_mesh_processing/repair_polygon_soup_example.cpp @@ -11,7 +11,7 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel K; typedef K::Point_3 Point_3; -typedef std::vector Polygon; +typedef std::vector CGAL_Polygon; typedef CGAL::Surface_mesh Mesh; namespace PMP = CGAL::Polygon_mesh_processing; @@ -20,7 +20,7 @@ int main(int, char**) { // First, construct a polygon soup with some problems std::vector points; - std::vector polygons; + std::vector polygons; points.push_back(Point_3(0,0,0)); points.push_back(Point_3(1,0,0)); @@ -30,7 +30,7 @@ int main(int, char**) points.push_back(Point_3(0,1,0)); // duplicate point points.push_back(Point_3(0,-2,0)); // unused point - Polygon p; + CGAL_Polygon p; p.push_back(0); p.push_back(1); p.push_back(2); polygons.push_back(p); diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h index 0afbd777fc6..ee729742aee 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/Weights.h @@ -141,9 +141,9 @@ public: Vector a = get(ppmap(), v0) - get(ppmap(), v1); Vector b = get(ppmap(), v2) - get(ppmap(), v1); - double dot_ab = a*b; - double dot_aa = a.squared_length(); - double dot_bb = b.squared_length(); + double dot_ab = CGAL::to_double(a * b); + double dot_aa = CGAL::to_double(a.squared_length()); + double dot_bb = CGAL::to_double(b.squared_length()); double lb = -0.999, ub = 0.999; double cosine = dot_ab / CGAL::sqrt(dot_aa) / CGAL::sqrt(dot_bb); cosine = (cosine < lb) ? lb : cosine; @@ -853,6 +853,45 @@ public: } }; +// Cotangent_value_Meyer has been changed to the version: +// Cotangent_value_Meyer_secure to avoid imprecisions from +// the issue #4706 - https://github.com/CGAL/cgal/issues/4706. +template< +class PolygonMesh, class VertexPointMap = typename boost::property_map::type> +class Cotangent_weight_with_voronoi_area_fairing_secure { + + typedef PolygonMesh PM; + typedef VertexPointMap VPMap; + Voronoi_area voronoi_functor; + Cotangent_weight > cotangent_functor; + +public: + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_) : + voronoi_functor(pmesh_, get(CGAL::vertex_point, pmesh_)), + cotangent_functor(pmesh_, get(CGAL::vertex_point, pmesh_)) + { } + + Cotangent_weight_with_voronoi_area_fairing_secure(PM& pmesh_, VPMap vpmap_) : + voronoi_functor(pmesh_, vpmap_), + cotangent_functor(pmesh_, vpmap_) + { } + + PM& pmesh() { + return voronoi_functor.pmesh(); + } + + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + + double w_i(vertex_descriptor v_i) { + return 0.5 / voronoi_functor(v_i); + } + + double w_ij(halfedge_descriptor he) { + return cotangent_functor(he) * 2.0; + } +}; + template class Uniform_weight_fairing { diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h index 18f5a0f3ecc..9a33c892e80 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/distance.h @@ -29,7 +29,7 @@ #include #ifdef CGAL_LINKED_WITH_TBB -#include +#include "tbb/parallel_reduce.h" #include #include #endif // CGAL_LINKED_WITH_TBB @@ -81,21 +81,27 @@ struct Distance_computation{ const AABB_tree& tree; const PointRange& sample_points; Point_3 initial_hint; - std::atomic* distance; - + double distance; + //constro Distance_computation( const AABB_tree& tree, const Point_3& p, - const PointRange& sample_points, - std::atomic* d) + const PointRange& sample_points) : tree(tree) , sample_points(sample_points) , initial_hint(p) - , distance(d) + , distance(-1) + {} + //split constro + Distance_computation(Distance_computation& s, tbb::split ) + : tree(s.tree) + , sample_points(s.sample_points) + , initial_hint(s.initial_hint) + , distance(-1) {} void - operator()(const tbb::blocked_range& range) const + operator()(const tbb::blocked_range& range) { Point_3 hint = initial_hint; double hdist = 0; @@ -107,15 +113,11 @@ struct Distance_computation{ if(d > hdist) hdist=d; } - - // update max value stored in distance - double current_value = *distance; - while( current_value < hdist ) - { - if(distance->compare_exchange_weak(current_value, hdist)) - current_value = hdist; - } + if(hdist > distance) + distance = hdist; } + + void join( Distance_computation& rhs ) {distance = std::max(rhs.distance, distance); } }; #endif @@ -136,9 +138,9 @@ double approximate_Hausdorff_distance_impl( { std::atomic distance; distance=0; - Distance_computation f(tree, hint, sample_points, &distance); - tbb::parallel_for(tbb::blocked_range(0, sample_points.size()), f); - return distance; + Distance_computation f(tree, hint, sample_points); + tbb::parallel_reduce(tbb::blocked_range(0, sample_points.size()), f); + return f.distance; } else #endif diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h index 204ea2e9d6e..727e007995a 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/fair.h @@ -158,7 +158,11 @@ namespace internal { #endif typedef typename GetVertexPointMap < TriangleMesh, NamedParameters>::type VPMap; - typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing + + // Cotangent_weight_with_voronoi_area_fairing has been changed to the version: + // Cotangent_weight_with_voronoi_area_fairing_secure to avoid imprecisions from + // the issue #4706 - https://github.com/CGAL/cgal/issues/4706. + typedef CGAL::internal::Cotangent_weight_with_voronoi_area_fairing_secure Default_Weight_calculator; VPMap vpmap_ = choose_parameter(get_parameter(np, internal_np::vertex_point), 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 325a3693d5b..c3929c5c3cc 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 @@ -682,6 +682,10 @@ public: halfedge_descriptor h1 = it->second.first[&tm1]; halfedge_descriptor h2 = it->second.first[&tm2]; +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << "Looking at triangles around edge " << tm1.point(source(h1, tm1)) << " " << tm1.point(target(h1, tm1)) << "\n"; +#endif + CGAL_assertion(ids.first==vertex_to_node_id1[source(h1,tm1)]); CGAL_assertion(ids.second==vertex_to_node_id1[target(h1,tm1)]); CGAL_assertion(ids.first==vertex_to_node_id2[source(h2,tm2)]); @@ -713,6 +717,9 @@ public: //Nothing allowed if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 1\n"; +#endif impossible_operation.set(); return; } @@ -723,6 +730,9 @@ public: //Ambiguous, we can do nothing if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 2\n"; +#endif impossible_operation.set(); return; } @@ -776,6 +786,9 @@ public: { CGAL_assertion(!used_to_clip_a_surface); //Ambiguous, we do nothing +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 3\n"; +#endif impossible_operation.set(); return; } @@ -971,6 +984,9 @@ public: // poly_second - poly_first = {0} // poly_first \cap poly_second = q1q2 // opposite( poly_first U poly_second ) = p2p1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 4\n"; +#endif impossible_operation.set(TM1_MINUS_TM2); // tm1-tm2 is non-manifold } else{ @@ -982,7 +998,12 @@ public: is_patch_inside_tm2.set(patch_id_p1); is_patch_inside_tm2.set(patch_id_p2); if (!used_to_clip_a_surface) + { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 5\n"; +#endif impossible_operation.set(INTERSECTION); // tm1 n tm2 is non-manifold + } } } else @@ -997,6 +1018,9 @@ public: { if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 6\n"; +#endif impossible_operation.set(); return; } @@ -1018,6 +1042,9 @@ public: { if (!used_to_clip_a_surface) { +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 7\n"; +#endif impossible_operation.set(); return; } @@ -1039,6 +1066,9 @@ public: // poly_second - poly_first = q1q2 // poly_first \cap poly_second = {0} // opposite( poly_first U poly_second ) = p2q1 U q2p1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 8\n"; +#endif impossible_operation.set(UNION); // tm1 U tm2 is non-manifold } else{ @@ -1049,6 +1079,9 @@ public: // poly_second - poly_first = q1p1 U p2q2 // poly_first \cap poly_second = p1p2 // opposite( poly_first U poly_second ) = q2q1 +#ifdef CGAL_COREFINEMENT_DEBUG + std::cout << " Non-manifold edge case 9\n"; +#endif impossible_operation.set(TM2_MINUS_TM1); // tm2 - tm1 is non-manifold } } 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 b67ac5dc5d6..def4359d132 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 @@ -1161,8 +1161,9 @@ bool fill_hole_with_constraints(std::vector(patch)) { +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG std::cout << "Unhealthy patch, use base fill_hole" << std::endl; +#endif return fill_hole(cc_border_hedges, cc_faces, working_face_range, tmesh, vpm, gt); } @@ -1796,9 +1799,9 @@ bool remove_self_intersections(const FaceRange& face_range, // TODO : possible optimization to reduce the range to check with the bbox // of the previous patches or something. self_intersections(working_face_range, tmesh, std::back_inserter(self_inter)); - +#ifdef CGAL_PMP_REMOVE_SELF_INTERSECTION_DEBUG std::cout << self_inter.size() << " intersecting pairs" << std::endl; - +#endif for(const Face_pair& fp : self_inter) { faces_to_remove.insert(fp.first); 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 c901065a1da..8f16d4d7bdb 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 @@ -53,39 +53,32 @@ #endif namespace CGAL{ - namespace Polygon_mesh_processing{ - namespace internal{ -template +template struct Less_for_halfedge { - typedef typename boost::graph_traits::halfedge_descriptor - halfedge_descriptor; - typedef typename boost::property_traits::reference Point; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename boost::property_traits::reference Point; - Less_for_halfedge(const PM& pmesh_, - const VertexPointMap& vpmap_) - : pmesh(pmesh_), - vpmap(vpmap_) + Less_for_halfedge(const PolygonMesh& pmesh_, const VertexPointMap& vpm_) + : pmesh(pmesh_), vpm(vpm_) {} - bool operator()(halfedge_descriptor h1, - halfedge_descriptor h2) const + bool operator()(halfedge_descriptor h1, halfedge_descriptor h2) const { - Point s1 = get(vpmap,target(opposite(h1, pmesh), pmesh)); - Point t1 = get(vpmap,target(h1, pmesh)); - Point s2 = get(vpmap,target(opposite(h2, pmesh), pmesh)); - Point t2 = get(vpmap,target(h2, pmesh)); - return - ( s1 < t1? std::make_pair(s1,t1) : std::make_pair(t1, s1) ) - < - ( s2 < t2? std::make_pair(s2,t2) : std::make_pair(t2, s2) ); + Point s1 = get(vpm,target(opposite(h1, pmesh), pmesh)); + Point t1 = get(vpm,target(h1, pmesh)); + Point s2 = get(vpm,target(opposite(h2, pmesh), pmesh)); + Point t2 = get(vpm,target(h2, pmesh)); + + return (s1 < t1 ? std::make_pair(s1,t1) : std::make_pair(t1, s1)) + < (s2 < t2 ? std::make_pair(s2,t2) : std::make_pair(t2, s2)); } - const PM& pmesh; - const VertexPointMap& vpmap; + const PolygonMesh& pmesh; + const VertexPointMap& vpm; }; //add a pair of border halfedges to be stitched. @@ -94,140 +87,181 @@ template void fill_pairs(const Halfedge& he, Border_halfedge_map& border_halfedge_map, Halfedge_pair& halfedge_pairs, Manifold_halfedge_pair& manifold_halfedge_pairs, - VPMAP vpmap, + VPM vpm, const Mesh& pmesh) { typename Border_halfedge_map::iterator set_it; bool insertion_ok; - std::tie(set_it, insertion_ok) - = border_halfedge_map.insert(std::make_pair(he,std::make_pair(1,0))); + std::tie(set_it, insertion_ok) = border_halfedge_map.insert(std::make_pair(he,std::make_pair(1,0))); - if ( !insertion_ok ){ // we found already a halfedge with the points + if(!insertion_ok) // we found already a halfedge with the points + { ++set_it->second.first; // increase the multiplicity if(set_it->second.first == 2) { set_it->second.second = halfedge_pairs.size(); // set the id of the pair in the vector - halfedge_pairs.push_back( std::make_pair(set_it->first, he) ); - if ( get(vpmap, source(he,pmesh))==get(vpmap, target(set_it->first,pmesh)) && - get(vpmap, target(he,pmesh))==get(vpmap, source(set_it->first,pmesh)) ) + halfedge_pairs.push_back( std::make_pair(set_it->first, he)); + if(get(vpm, source(he,pmesh)) == get(vpm, target(set_it->first, pmesh)) && + get(vpm, target(he,pmesh)) == get(vpm, source(set_it->first, pmesh))) { manifold_halfedge_pairs.push_back(true); } else - manifold_halfedge_pairs.push_back(false); - } - else - if ( set_it->second.first > 2 ) { - manifold_halfedge_pairs[ set_it->second.second ] = false; + manifold_halfedge_pairs.push_back(false); } + } + else if(set_it->second.first > 2) + { + manifold_halfedge_pairs[ set_it->second.second ] = false; + } } } -template -std::size_t num_component_wrapper(const Mesh& pmesh, - CCMap cc, - FIMap fim) +template +struct Default_halfedges_keeper { - return CGAL::Polygon_mesh_processing::connected_components(pmesh, cc, - CGAL::Polygon_mesh_processing::parameters::face_index_map(fim)); -} + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; -//specialization if there is no default FIMap, create one -template -std::size_t num_component_wrapper(Mesh& pmesh, - CCMap cc, - boost::cgal_no_property::type) + Default_halfedges_keeper() { } + + halfedge_descriptor operator()(const halfedge_descriptor h1, const halfedge_descriptor h2) const + { + return (h1 < h2) ? h1 : h2; // Arbitrary preference + } +}; + +// Provided for convenience. If passed to stitch_borders(), this ensures that if any of the two +// edges is marked, then the preserver edge is also marked. +template +struct Halfedges_keeper_with_marked_edge_priority { + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - boost::unordered_map::face_descriptor, std::size_t> fim; + Halfedges_keeper_with_marked_edge_priority(const EMM& emm, const PolygonMesh& pmesh) + : emm(emm), pmesh(pmesh) + { } - //init the map - std::size_t i=-1; - for(typename boost::graph_traits::face_descriptor f : faces(pmesh)) - fim[f]=++i; + halfedge_descriptor operator()(const halfedge_descriptor h1, const halfedge_descriptor h2) const + { + // If h2 is marked, then whether h1 is marked or not, we can just return h2 + if(get(emm, edge(h2, pmesh))) + return h2; - return CGAL::Polygon_mesh_processing::connected_components(pmesh, - cc, - parameters::face_index_map(boost::make_assoc_property_map(fim))); -} + // If only h1 is marked, return h1; + // If both or none are marked, it does not matter which we are keeping, so also return h1 + return h1; + } -template +private: + const EMM& emm; + const PolygonMesh& pmesh; +}; + +template OutputIterator -collect_duplicated_stitchable_boundary_edges -(PM& pmesh, OutputIterator out, LessHedge less_hedge, - const VertexPointMap& vpmap, const CGAL_PMP_NP_CLASS& np) +collect_duplicated_stitchable_boundary_edges(PolygonMesh& pmesh, + OutputIterator out, + const CGAL_PMP_NP_CLASS& np) { - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef std::map, LessHedge> Border_halfedge_map; - Border_halfedge_map border_halfedge_map(less_hedge); - std::vector< std::pair > halfedge_pairs; - std::vector< bool > manifold_halfedge_pairs; + using parameters::choose_parameter; + using parameters::get_parameter; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + + typedef typename GetVertexPointMap::const_type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pmesh)); + + typedef CGAL::dynamic_face_property_t Face_property_tag; + typedef typename boost::property_map::type Face_cc_map; - typedef CGAL::dynamic_face_property_t Face_property_tag; - typedef typename boost::property_map::type Face_cc_map; Face_cc_map cc; - std::size_t num_component = 0; + std::size_t num_cc = 0; std::vector > border_edges_per_cc; - bool per_cc = parameters::choose_parameter(parameters::get_parameter(np, internal_np::apply_per_connected_component), - false); + + typedef typename internal_np::Lookup_named_param_def >::type Halfedge_keeper; + const Halfedge_keeper hd_kpr = choose_parameter(get_parameter(np, internal_np::halfedges_keeper), + Default_halfedges_keeper()); + + bool per_cc = choose_parameter(get_parameter(np, internal_np::apply_per_connected_component), false); + + typedef Less_for_halfedge Less_hedge; + typedef std::map, Less_hedge> Border_halfedge_map; + + Less_hedge less_hedge(pmesh, vpm); + Border_halfedge_map border_halfedge_map(less_hedge); + + std::vector > halfedge_pairs; + std::vector manifold_halfedge_pairs; + if(per_cc) { cc = get(Face_property_tag(), pmesh); - - num_component = num_component_wrapper(pmesh, cc, CGAL::get_initialized_face_index_map(pmesh, np)); - border_edges_per_cc.resize(num_component); + num_cc = connected_components(pmesh, cc, np); + border_edges_per_cc.resize(num_cc); } for(halfedge_descriptor he : halfedges(pmesh)) { - if ( !CGAL::is_border(he, pmesh) ) + if(!CGAL::is_border(he, pmesh)) continue; + if(per_cc) - { border_edges_per_cc[get(cc, face(opposite(he, pmesh), pmesh))].push_back(he); - } else - { - fill_pairs(he, border_halfedge_map, halfedge_pairs, - manifold_halfedge_pairs, vpmap, pmesh); - } + fill_pairs(he, border_halfedge_map, halfedge_pairs, manifold_halfedge_pairs, vpm, pmesh); } + if(per_cc) { - for(std::size_t i = 0; i < num_component; ++i) + for(std::size_t i=0; i(border_edges_per_cc[i].size()); ++j) + + Border_halfedge_map border_halfedge_map_in_cc(less_hedge); + for(std::size_t j=0; j -void update_target_vertex(typename boost::graph_traits::halfedge_descriptor h, - typename boost::graph_traits::vertex_descriptor v_kept, - PM& pmesh) +template +void update_target_vertex(typename boost::graph_traits::halfedge_descriptor h, + typename boost::graph_traits::vertex_descriptor v_kept, + PolygonMesh& pmesh) { - typename boost::graph_traits::halfedge_descriptor start = h; - do{ + typename boost::graph_traits::halfedge_descriptor start = h; + do + { set_target(h, v_kept, pmesh); h = opposite(next(h, pmesh), pmesh); - } while( h != start ); + } + while(h != start); } template @@ -268,11 +318,10 @@ uf_get_handle(vertex_descriptor v, Handle_map& handles) { std::pair insert_res = - handles.insert( std::make_pair(v, typename Union_find::handle()) ); - if( insert_res.second ) - { - insert_res.first->second=uf_vertices.make_set(v); - } + handles.insert(std::make_pair(v, typename Union_find::handle())); + if(insert_res.second) + insert_res.first->second = uf_vertices.make_set(v); + return insert_res.first->second; } @@ -287,20 +336,18 @@ void uf_join_vertices(vertex_descriptor v1, vertex_descriptor v2, uf_vertices.unify_sets(h1, h2); } - - // main functions (vertices to keep selected and halfedge pairs filtered) -template -void run_stitch_borders(PM& pmesh, +void run_stitch_borders(PolygonMesh& pmesh, const HalfedgePairsRange& to_stitch, const VertexPointMap& vpm, Uf_vertices& uf_vertices, Uf_handles& uf_handles) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename std::pair halfedges_pair; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename std::pair halfedges_pair; CGAL_USE(vpm); @@ -325,13 +372,13 @@ void run_stitch_borders(PM& pmesh, vertex_descriptor v_to_keep = *uf_vertices.find(uf_get_handle(h1_tgt, uf_vertices, uf_handles)); - if (v_to_keep!=h1_tgt) + if(v_to_keep!=h1_tgt) { vertices_to_delete.push_back(h1_tgt); update_target_vertex(h1, v_to_keep, pmesh); } - if (v_to_keep != h2_src && h1_tgt!=h2_src) + if(v_to_keep != h2_src && h1_tgt!=h2_src) { vertices_to_delete.push_back( h2_src ); update_target_vertex(opposite(h2, pmesh), v_to_keep, pmesh); @@ -343,19 +390,19 @@ void run_stitch_borders(PM& pmesh, //update vertex pointers: target of h1 vs source of h2 v_to_keep = *uf_vertices.find(uf_get_handle(h2_tgt, uf_vertices, uf_handles)); - if (v_to_keep!=h2_tgt) + if(v_to_keep!=h2_tgt) { vertices_to_delete.push_back( h2_tgt ); update_target_vertex(h2, v_to_keep, pmesh); } - if (v_to_keep!=h1_src && h1_src!=h2_tgt) + if(v_to_keep!=h1_src && h1_src!=h2_tgt) { vertices_to_delete.push_back( h1_src ); update_target_vertex(opposite(h1, pmesh), v_to_keep, pmesh); } - set_halfedge(v_to_keep, opposite(h1,pmesh), pmesh); + set_halfedge(v_to_keep, opposite(h1, pmesh), pmesh); } /// Update next/prev of neighbor halfedges (that are not set for stiching) @@ -412,14 +459,14 @@ void run_stitch_borders(PM& pmesh, } } -template -std::size_t stitch_borders_impl(PM& pmesh, +template +std::size_t stitch_borders_impl(PolygonMesh& pmesh, const HalfedgePairsRange& to_stitch, const VertexPointMap& vpm) { - typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; - typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename std::pair halfedges_pair; + typedef typename boost::graph_traits::vertex_descriptor vertex_descriptor; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + typedef typename std::pair halfedges_pair; // The first step of the algorithm is to filter halfedges to be stitched so that // after stitching no edges will be present more than once. @@ -479,9 +526,9 @@ std::size_t stitch_borders_impl(PM& pmesh, typename Uf_handles::iterator it_res = uf_handles.find(other_vd); - if (it_res!=uf_handles.end()) // if the other vertex is also involved in a merge + if(it_res!=uf_handles.end()) // if the other vertex is also involved in a merge { - if (other_vd < vd) + if(other_vd < vd) continue; // avoid reporting twice the same edge typename Uf_vertices::handle src_handle=uf_vertices.find(it_res->second); @@ -505,7 +552,7 @@ std::size_t stitch_borders_impl(PM& pmesh, break; // nothing to do case 2: { - if (is_border_edge(it->second.front(), pmesh) && + if(is_border_edge(it->second.front(), pmesh) && is_border_edge(it->second.back(), pmesh)) break; // these are edges that are most possibly scheduled for stitching or will create a two halfedge loop CGAL_FALLTHROUGH; @@ -524,7 +571,7 @@ std::size_t stitch_borders_impl(PM& pmesh, } // filter halfedges to stitch - if (!unstitchable_vertices.empty()) + if(!unstitchable_vertices.empty()) { std::vector to_stitch_filtered; to_stitch_filtered.reserve( to_stitch.size()); @@ -532,7 +579,7 @@ std::size_t stitch_borders_impl(PM& pmesh, { // We test both halfedges because the previous test // might involve only one of the two halfedges - if ( unstitchable_vertices.count( source(hk.first, pmesh) )== 0 && + if(unstitchable_vertices.count( source(hk.first, pmesh) )== 0 && unstitchable_vertices.count( target(hk.first, pmesh) )== 0 && unstitchable_vertices.count( source(hk.second, pmesh) )== 0 && unstitchable_vertices.count( target(hk.second, pmesh) )== 0 ) @@ -607,9 +654,16 @@ std::size_t stitch_boundary_cycle(const typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef typename GetVertexPointMap::const_type VPMap; - VPMap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(vertex_point, pm)); + typedef typename GetVertexPointMap::const_type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pm)); + + typedef internal::Default_halfedges_keeper Default_halfedges_keeper; + typedef typename internal_np::Lookup_named_param_def::type Halfedge_keeper; + const Halfedge_keeper hd_kpr = choose_parameter(get_parameter(np, internal_np::halfedges_keeper), + Default_halfedges_keeper()); std::size_t stitched_boundary_cycles_n = 0; @@ -674,12 +728,14 @@ std::size_t stitch_boundary_cycle(const typename boost::graph_traits::const_type VPMap; - VPMap vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(vertex_point, pmesh)); + typedef typename GetVertexPointMap::const_type VPM; + VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), + get_const_property_map(vertex_point, pmesh)); return internal::stitch_borders_impl(pmesh, hedge_pairs_to_stitch, vpm); } @@ -902,16 +964,7 @@ template std::size_t stitch_borders(PolygonMesh& pmesh, const CGAL_PMP_NP_CLASS& np) { - using parameters::choose_parameter; - using parameters::get_parameter; - - typedef typename boost::graph_traits::halfedge_descriptor - halfedge_descriptor; - std::vector< std::pair > hedge_pairs_to_stitch; - - typedef typename GetVertexPointMap::const_type VPM; - VPM vpm = choose_parameter(get_parameter(np, internal_np::vertex_point), - get_const_property_map(vertex_point, pmesh)); + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; #ifdef CGAL_PMP_STITCHING_DEBUG std::cout << "------- Stitch cycles..." << std::endl; @@ -924,10 +977,8 @@ std::size_t stitch_borders(PolygonMesh& pmesh, std::cout << "------- Stitch all..." << std::endl; #endif - internal::collect_duplicated_stitchable_boundary_edges(pmesh, - std::back_inserter(hedge_pairs_to_stitch), - internal::Less_for_halfedge(pmesh, vpm), - vpm, np); + std::vector< std::pair > hedge_pairs_to_stitch; + internal::collect_duplicated_stitchable_boundary_edges(pmesh, std::back_inserter(hedge_pairs_to_stitch), np); res += stitch_borders(pmesh, hedge_pairs_to_stitch, np); diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp index cdf0f5eab8c..a4782d4f0dd 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/test_stitching.cpp @@ -1,29 +1,33 @@ +// #define CGAL_PMP_STITCHING_DEBUG_PP + #include #include - #include #include +#include +#include +#include #include #include -#include - #include +#include #include +#include namespace PMP = CGAL::Polygon_mesh_processing; namespace params = CGAL::parameters; -typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; -typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; +//////////////////////////////////////////////////////////////////////////////////////////////////// +template void test_stitch_boundary_cycles(const char* fname, const std::size_t expected_n) { - std::cout << "Testing boundary cycles " << fname << "..." << std::flush; + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; - typedef CGAL::Surface_mesh Mesh; + std::cout << "Testing stitch_boundary_cycles(); file: " << fname << "..." << std::flush; std::ifstream input(fname); Mesh mesh; @@ -32,160 +36,149 @@ void test_stitch_boundary_cycles(const char* fname, return; } + // stitching a single cycle should work from any border halfedge + for(halfedge_descriptor h : halfedges(mesh)) + { + if(!is_border(h, mesh)) + continue; + + std::unordered_map h2h; + + Mesh mesh_cpy; + CGAL::copy_face_graph(mesh, mesh_cpy, + CGAL::parameters::halfedge_to_halfedge_output_iterator(std::inserter(h2h, h2h.end()))); + + assert(is_border(h2h.at(h), mesh_cpy)); + + PMP::stitch_boundary_cycle(h2h.at(h), mesh_cpy); + assert(is_valid_polygon_mesh(mesh_cpy)); + } + std::size_t res = PMP::stitch_boundary_cycles(mesh); std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; assert(res == expected_n); - assert(is_valid(mesh)); + assert(is_valid_polygon_mesh(mesh)); } -template -void test_polyhedron(const char* fname, - const std::size_t expected_n) +template +void test_stitch_boundary_cycles() { - std::cout << "Testing Polyhedron_3 " << fname << "..." << std::flush; - - typedef CGAL::Polyhedron_3 Polyhedron; - - std::ifstream input(fname); - Polyhedron poly; - if (!input || !(input >> poly)){ - std::cerr << "Error: can not read file."; - return; - } - - assert(poly.size_of_vertices() > 0); - - std::size_t res = PMP::stitch_borders(poly); - poly.normalize_border(); - - std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; - assert(poly.is_valid(false, 5)); - assert(res == expected_n); - - std::cout << "OK\n"; + test_stitch_boundary_cycles("data_stitching/boundary_cycle.off", 4); + test_stitch_boundary_cycles("data_stitching/boundary_cycle_2.off", 2); } -template -void test_polyhedron_cc(const char* fname, - const std::size_t expected_n) +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void test_stitch_borders(const char* fname, + const std::size_t expected_n, + const bool per_cc = false, + std::set unconstrained_edges = { }) { - std::cout << "Testing Polyhedron_3 " << fname << "..." << std::flush; - - typedef CGAL::Polyhedron_3 Polyhedron; - - std::ifstream input(fname); - Polyhedron poly; - if (!input || !(input >> poly)){ - std::cerr << "Error: can not read file."; - return; - } - - assert(poly.size_of_vertices() > 0); - - std::size_t res = PMP::stitch_borders(poly, params::apply_per_connected_component(true)); - poly.normalize_border(); - - std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; - assert(poly.is_valid(false, 5)); - assert(res == expected_n); - - std::cout << "OK\n"; -} - -void test_surface_mesh(const char* fname, - const std::size_t expected_n) -{ - std::cout << "Testing Surface_mesh " << fname << "..." << std::flush; - - typedef CGAL::Surface_mesh Mesh; + std::cout << "Testing stitch_borders(); file: " << fname << "..." << std::flush; std::ifstream input(fname); Mesh mesh; - if (!input || !(input >> mesh)){ + if (!input || !(input >> mesh)) + { std::cerr << "Error: can not read file."; return; } - std::size_t res = PMP::stitch_borders(mesh); + // Mark some edges as UNCONSTRAINED, the stitched mesh must not contain these edges + typedef typename boost::graph_traits::edge_descriptor edge_descriptor; + typedef CGAL::dynamic_edge_property_t Edge_property_tag; + typedef typename boost::property_map::type Marked_edges; + typedef PMP::internal::Halfedges_keeper_with_marked_edge_priority Keeper; + + Marked_edges marks = get(Edge_property_tag(), mesh); + int id = 0; + for(edge_descriptor e : edges(mesh)) + put(marks, e, (unconstrained_edges.count(id++) == 0)); + + Keeper kpr(marks, mesh); + + std::size_t res = PMP::stitch_borders(mesh, params::apply_per_connected_component(per_cc) + .halfedges_keeper(kpr)); std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; + for(edge_descriptor e : edges(mesh)) { + assert(get(marks, e)); // must not be marked as unconstrained + } + assert(res == expected_n); assert(is_valid_polygon_mesh(mesh)); - - std::cout << "OK\n"; } -void test_surface_mesh_cc(const char* fname, - const std::size_t expected_n) +template +void test_stitch_borders() { - std::cout << "Testing Surface_mesh " << fname << "..." << std::flush; - - typedef CGAL::Surface_mesh Mesh; - - std::ifstream input(fname); - Mesh mesh; - if (!input || !(input >> mesh)){ - std::cerr << "Error: can not read file."; - return; - } - - std::size_t res = PMP::stitch_borders(mesh, params::apply_per_connected_component(true)); - std::cout << "res: " << res << " (expected: " << expected_n << ")" << std::endl; - - assert(res == expected_n); - assert(is_valid(mesh)); - - std::cout << "OK\n"; + test_stitch_borders("data_stitching/deg_border.off", 2, false /*per_cc*/, {9, 12} /*unconstrained edges*/); + test_stitch_borders("data_stitching/full_border.off", 4); + test_stitch_borders("data_stitching/full_border_quads.off", 4); + test_stitch_borders("data_stitching/half_border.off", 2, false, {23, 15}); + test_stitch_borders("data_stitching/incidence_3.off", 3); + test_stitch_borders("data_stitching/incoherent_patch_orientation.off", 1); + test_stitch_borders("data_stitching/mid_border.off", 2); + test_stitch_borders("data_stitching/multiple_incidence.off", 10, false, {3, 5, 16, 24, 31, 45, 53, 65}); + test_stitch_borders("data_stitching/non_stitchable.off", 0); + test_stitch_borders("data_stitching/non_manifold.off", 0); + test_stitch_borders("data_stitching/non_manifold2.off", 0); + test_stitch_borders("data_stitching/two_patches.off", 3); + test_stitch_borders("data_stitching/nm_cubes.off", 4, true /*per cc*/); } -void bug_test() -{ - typedef CGAL::Simple_cartesian K; - typedef K::Point_3 Point_3; - CGAL::Surface_mesh tm; +//////////////////////////////////////////////////////////////////////////////////////////////////// - CGAL::make_triangle(Point_3(0,0,0), Point_3(1,0,0), Point_3(0,1,0), tm); - CGAL::make_triangle(Point_3(0,0,0), Point_3(1,0,0), Point_3(0,1,0), tm); - CGAL::make_triangle(Point_3(0,0,0), Point_3(1,0,0), Point_3(0,1,0), tm); - CGAL::make_triangle(Point_3(0,0,0), Point_3(1,0,0), Point_3(0,1,0), tm); +template +void test_degenerate() +{ + std::cout << "Testing degenerate cases" << std::endl; + + typedef typename boost::property_traits< + typename CGAL::GetVertexPointMap::const_type>::value_type Point; + + Mesh tm; + + CGAL::make_triangle(Point(0,0,0), Point(1,0,0), Point(0,1,0), tm); + CGAL::make_triangle(Point(0,0,0), Point(1,0,0), Point(0,1,0), tm); + CGAL::make_triangle(Point(0,0,0), Point(1,0,0), Point(0,1,0), tm); + CGAL::make_triangle(Point(0,0,0), Point(1,0,0), Point(0,1,0), tm); CGAL::Polygon_mesh_processing::stitch_borders(tm); } +//////////////////////////////////////////////////////////////////////////////////////////////////// + +template +void test() +{ + test_stitch_boundary_cycles(); + test_stitch_borders(); + test_degenerate(); +} + int main() { - test_stitch_boundary_cycles("data_stitching/boundary_cycle.off", 4); - test_stitch_boundary_cycles("data_stitching/boundary_cycle_2.off", 2); + typedef CGAL::Exact_predicates_inexact_constructions_kernel EPICK; - test_polyhedron("data_stitching/deg_border.off", 2); - test_polyhedron("data_stitching/full_border.off", 4); - test_polyhedron("data_stitching/full_border.off", 4); - test_polyhedron("data_stitching/full_border_quads.off", 4); - test_polyhedron("data_stitching/half_border.off", 2); - test_polyhedron("data_stitching/incidence_3.off", 3); - test_polyhedron("data_stitching/incoherent_patch_orientation.off", 1); - test_polyhedron("data_stitching/mid_border.off", 2); - test_polyhedron("data_stitching/multiple_incidence.off", 10); - test_polyhedron("data_stitching/non_stitchable.off", 0); - test_polyhedron("data_stitching/non_manifold.off", 0); - test_polyhedron("data_stitching/non_manifold2.off", 0); - test_polyhedron("data_stitching/two_patches.off", 3); - test_polyhedron_cc("data_stitching/nm_cubes.off", 4); + std::cout << "--- Test EPICK SM" << std::endl; + test >(); - test_surface_mesh("data_stitching/deg_border.off", 2); - test_surface_mesh("data_stitching/full_border.off", 4); - test_surface_mesh("data_stitching/full_border_quads.off", 4); - test_surface_mesh("data_stitching/half_border.off", 2); - test_surface_mesh("data_stitching/incidence_3.off", 3); - test_surface_mesh("data_stitching/incoherent_patch_orientation.off", 1); - test_surface_mesh("data_stitching/mid_border.off", 2); - test_surface_mesh("data_stitching/multiple_incidence.off", 10); - test_surface_mesh("data_stitching/non_stitchable.off", 0); - test_surface_mesh("data_stitching/non_manifold.off", 0); - test_surface_mesh_cc("data_stitching/nm_cubes.off", 4); + std::cout << "--- Test EPICK Polyhedron" << std::endl; + test >(); - bug_test(); + // Disabled because it takes too long for some test plateforms +// typedef CGAL::Exact_predicates_exact_constructions_kernel EPECK; + +// std::cout << "--- Test EPECK SM" << std::endl; +// test >(); + +// std::cout << "--- Test EPECK Polyhedron" << std::endl; +// test >(); + + std::cout << "Done!" << std::endl; return EXIT_SUCCESS; } diff --git a/Polyhedron/demo/Polyhedron/CMakeLists.txt b/Polyhedron/demo/Polyhedron/CMakeLists.txt index 9e00808a516..32da38d5618 100644 --- a/Polyhedron/demo/Polyhedron/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/CMakeLists.txt @@ -402,6 +402,13 @@ add_executable ( CGAL_PMP PMP.cpp ) add_dependencies(CGAL_PMP PMP) target_link_libraries( CGAL_PMP PRIVATE polyhedron_demo ) add_to_cached_list( CGAL_EXECUTABLE_TARGETS CGAL_PMP ) + +#WS Server +if(TARGET Qt5::WebSockets) + add_executable (WS_server Server_ws.cpp) + target_link_libraries(WS_server PUBLIC Qt5::WebSockets) + message(STATUS "Qt5WebSockets was found. Using WebSockets is therefore possible.") +endif() # # Exporting # diff --git a/Polyhedron/demo/Polyhedron/MainWindow.cpp b/Polyhedron/demo/Polyhedron/MainWindow.cpp index bd370cd7827..ee2274122fe 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.cpp +++ b/Polyhedron/demo/Polyhedron/MainWindow.cpp @@ -77,12 +77,6 @@ #include "Color_map.h" -#ifdef CGAL_USE_WEBSOCKETS -#include -#include -#include -#endif - using namespace CGAL::Three; QScriptValue myScene_itemToScriptValue(QScriptEngine *engine, @@ -2940,25 +2934,12 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() bool do_upload = false; #ifdef CGAL_USE_SSH QString user = settings.value("ssh_user", QString()).toString(); - QString pass; if(!user.isEmpty()) { QMessageBox::StandardButton doyou = QMessageBox::question(this, tr("Upload ?"), tr("Do you wish to upload the scene" " using the SSH preferences ?")); - bool ok; do_upload = (doyou == QMessageBox::Yes); - if(do_upload) - { - pass = QInputDialog::getText(this, "SSH Password", - "Enter ssh key password:", - QLineEdit::Password, - tr(""), - &ok); - if(!ok) - return; - pass = pass.trimmed(); - } } #endif @@ -3109,12 +3090,31 @@ void MainWindow::on_actionSa_ve_Scene_as_Script_triggered() path.prepend("Polyhedron_demo_"); try{ ssh_session session; - bool res = establish_ssh_session(session, - user.toStdString().c_str(), - server.toStdString().c_str(), - pk.toStdString().c_str(), - privK.toStdString().c_str(), - pass.toStdString().c_str()); + bool res = establish_ssh_session_from_agent(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str()); + + if(!res) + { + bool ok; + QString pass; + pass = QInputDialog::getText(this, "SSH Password", + "Enter ssh key password:", + QLineEdit::Password, + tr(""), + &ok); + if(!ok) + return; + pass = pass.trimmed(); + res = establish_ssh_session(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str(), + privK.toStdString().c_str(), + pass.toStdString().c_str()); + } + if(!res) { QMessageBox::warning(this, @@ -3590,25 +3590,13 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() #ifdef CGAL_USE_SSH QString user = settings.value("ssh_user", QString()).toString(); - QString pass; + if(!user.isEmpty()) { QMessageBox::StandardButton doyou = QMessageBox::question(this, tr("Download ?"), tr("Do you wish to download the scene" " using the SSH preferences ?")); - bool ok; do_download= (doyou == QMessageBox::Yes); - if(do_download) - { - pass = QInputDialog::getText(this, "SSH Password", - "Enter ssh key password:", - QLineEdit::Password, - tr(""), - &ok); - if(!ok) - return; - pass = pass.trimmed(); - } } #endif @@ -3623,22 +3611,30 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() server = server.trimmed(); pk = pk.trimmed(); privK=privK.trimmed(); - QString path; - path = QInputDialog::getText(this, - "", - tr("Enter the name of the scene file.")); - if(path.isEmpty()) - return; - if(!path.contains("Polyhedron_demo_")) - path.prepend("Polyhedron_demo_"); + try{ ssh_session session; - bool res = establish_ssh_session(session, - user.toStdString().c_str(), - server.toStdString().c_str(), - pk.toStdString().c_str(), - privK.toStdString().c_str(), - pass.toStdString().c_str()); + bool res = establish_ssh_session_from_agent(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str()); + if(!res){ + bool ok; + QString pass= QInputDialog::getText(this, "SSH Password", + "Enter ssh key password:", + QLineEdit::Password, + tr(""), + &ok); + if(!ok) + return; + pass = pass.trimmed(); + res = establish_ssh_session(session, + user.toStdString().c_str(), + server.toStdString().c_str(), + pk.toStdString().c_str(), + privK.toStdString().c_str(), + pass.toStdString().c_str()); + } if(!res) { QMessageBox::warning(this, @@ -3646,7 +3642,22 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() "The SSH session could not be started."); return; } + QStringList names; + if(!CGAL::ssh_internal::explore_the_galaxy(session, names)) + { + QMessageBox::warning(this, + "Error", + "Could not find remote directory."); + } + QString path; + path = QInputDialog::getItem(this, + "Choose a file", + tr("Choose the scene file."), + names); filename = QString("%1/load_scene.js").arg(QDir::tempPath()); + if(path.isEmpty()) + return; + path.prepend("Polyhedron_demo_"); path = tr("/tmp/%2").arg(path); res = pull_file(session,path.toStdString().c_str(), filename.toStdString().c_str()); if(!res) @@ -3681,90 +3692,3 @@ void MainWindow::on_actionLoad_a_Scene_from_a_Script_File_triggered() tmp_file.remove(); } } - -#ifdef CGAL_USE_WEBSOCKETS -void MainWindow::on_action_Start_a_Session_triggered() -{ - QAction * action= findChild("action_Start_a_Session"); - static EchoServer *server =nullptr; - if(action->isChecked()){ - server = new EchoServer(1234); - QObject::connect(server, &EchoServer::closed, server,&EchoServer::deleteLater); - } - else - { - server->deleteLater(); - } -} - -EchoServer::EchoServer(quint16 port) : - QObject(CGAL::Three::Three::mainWindow()), - m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"), - QWebSocketServer::NonSecureMode, this)) -{ - if (m_pWebSocketServer->listen(QHostAddress::Any, port)) { - connect(m_pWebSocketServer, &QWebSocketServer::newConnection, - this, &EchoServer::onNewConnection); - connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed); - } - QHostAddress local_host("0.0.0.0"); - - //to avoid printing 127.0.0.1. Not realy sure it won't ever print the external ipv4 though. - const QHostAddress &localhost = QHostAddress(QHostAddress::LocalHost); - for (const QHostAddress &address: QNetworkInterface::allAddresses()) { - if (address.protocol() == QAbstractSocket::IPv4Protocol && address != localhost) - { - local_host= address; - break; - } - } - QMessageBox mb(QMessageBox::NoIcon, "WS Server", - tr("WebSockets Server started.\nEnter the following address in\nyour Network Preferences to be able to join it :\n" - "ws://%1:%2").arg(local_host.toString()).arg(port), QMessageBox::Ok, CGAL::Three::Three::mainWindow()); - mb.setTextInteractionFlags(Qt::TextSelectableByMouse); - mb.exec(); -} - -EchoServer::~EchoServer() -{ - m_pWebSocketServer->close(); - qDeleteAll(m_clients.begin(), m_clients.end()); -} - -void EchoServer::onNewConnection() -{ - QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); - - connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage); - connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage); - connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected); - - m_clients << pSocket; -} - -void EchoServer::processTextMessage(QString message) -{ - QWebSocket *pClient = qobject_cast(sender()); - for(auto *client : m_clients) { - if(client != pClient) - client->sendTextMessage(message); - } -} - -void EchoServer::processBinaryMessage(QByteArray message) -{ - QWebSocket *pClient = qobject_cast(sender()); - if (pClient) { - pClient->sendBinaryMessage(message); - } -} - -void EchoServer::socketDisconnected() -{ - QWebSocket *pClient = qobject_cast(sender()); - if (pClient) { - m_clients.removeAll(pClient); - pClient->deleteLater(); - } -} -#endif diff --git a/Polyhedron/demo/Polyhedron/MainWindow.h b/Polyhedron/demo/Polyhedron/MainWindow.h index 4e544c08378..8f681a3b3c8 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.h +++ b/Polyhedron/demo/Polyhedron/MainWindow.h @@ -354,10 +354,6 @@ protected Q_SLOTS: void save(QString filename, QList& to_save); //!Calls the function saveSnapShot of the viewer. void on_actionSaveSnapshot_triggered(); -#ifdef CGAL_USE_WEBSOCKETS - //!Starts a new WS server if none is already exist. Else, does nothing. - void on_action_Start_a_Session_triggered(); -#endif //!Opens a Dialog to choose a color and make it the background color. void setBackgroundColor(); //!Opens a Dialog to change the lighting settings @@ -501,30 +497,5 @@ protected: private: bool is_main; }; -#ifdef CGAL_USE_WEBSOCKETS -QT_FORWARD_DECLARE_CLASS(QWebSocketServer) -QT_FORWARD_DECLARE_CLASS(QWebSocket) -class EchoServer : public QObject -{ - Q_OBJECT -public: - explicit EchoServer(quint16 port); - ~EchoServer(); - - -Q_SIGNALS: - void closed(); - -private Q_SLOTS: - void onNewConnection(); - void processTextMessage(QString message); - void processBinaryMessage(QByteArray message); - void socketDisconnected(); - -private: - QWebSocketServer *m_pWebSocketServer; - QList m_clients; -}; -#endif #endif // ifndef MAINWINDOW_H diff --git a/Polyhedron/demo/Polyhedron/MainWindow.ui b/Polyhedron/demo/Polyhedron/MainWindow.ui index 6273a37bd16..a56c2c1afe8 100644 --- a/Polyhedron/demo/Polyhedron/MainWindow.ui +++ b/Polyhedron/demo/Polyhedron/MainWindow.ui @@ -97,7 +97,6 @@ - @@ -470,17 +469,6 @@ Load a Scene &from a Script File... - - - true - - - &Start a Session - - - Start a WebSocket Server to Share your Camera with Others on your Network. - - diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp index ee43207e134..9958f257dec 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Cluster_classification.cpp @@ -527,7 +527,7 @@ void Cluster_classification::change_color (int index, float* vmin, float* vmax) int cid = m_cluster_id[*it]; if (cid != -1) { - float v = std::max (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][cid])); + float v = (std::max) (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][cid])); m_points->point_set()->set_color(*it, ramp.r(v) * 255, ramp.g(v) * 255, ramp.b(v) * 255); } else diff --git a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp index 5f567487cff..3e8478e0a71 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Classification/Surface_mesh_item_classification.cpp @@ -151,7 +151,7 @@ void Surface_mesh_item_classification::change_color (int index, float* vmin, flo { for(face_descriptor fd : faces(*(m_mesh->polyhedron()))) { - float v = std::max (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][fd])); + float v = (std::max) (0.f, (std::min)(1.f, m_label_probabilities[corrected_index][fd])); m_color[fd] = CGAL::Color((unsigned char)(ramp.r(v) * 255), (unsigned char)(ramp.g(v) * 255), (unsigned char)(ramp.b(v) * 255)); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp index bad79971d59..ea5138c22ed 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/Surf_io_plugin.cpp @@ -27,7 +27,7 @@ class Surf_io_plugin: public: QString name() const { return "surf_io_plugin"; } - QString nameFilters() const { return "Amira files (*.surf)"; } + QString nameFilters() const { return "Amira files (*.surf);;Amira binary files (*.surf.am)"; } bool canLoad(QFileInfo) const{ return true; } template CGAL::Three::Scene_item* actual_load(QFileInfo fileinfo); diff --git a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp index 85df5328597..e1e9044f0b6 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/IO/VTK_io_plugin.cpp @@ -503,8 +503,8 @@ public: if (is_c3t3) { - typedef boost::array Facet; // 3 = id - typedef boost::array Tet_with_ref; // first 4 = id, fifth = reference + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference Scene_c3t3_item* c3t3_item = new Scene_c3t3_item(); c3t3_item->set_valid(false); //build a triangulation from data: @@ -547,7 +547,9 @@ public: std::swap(finite_cells[i][1], finite_cells[i][3]); } } - CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), points, finite_cells, border_facets); + std::vector new_vertices; + CGAL::build_triangulation(c3t3_item->c3t3().triangulation(), + points, finite_cells, border_facets, new_vertices); for( C3t3::Triangulation::Finite_cells_iterator cit = c3t3_item->c3t3().triangulation().finite_cells_begin(); diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp index d2232c11dd4..8b708c059f2 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/C3t3_io_plugin.cpp @@ -135,7 +135,8 @@ Polyhedron_demo_c3t3_binary_io_plugin::load( ++cit) { CGAL_assertion(cit->info() >= 0); - item->c3t3().add_to_complex(cit, cit->info()); + if(cit->info() != 0) + item->c3t3().add_to_complex(cit, cit->info()); for(int i=0; i < 4; ++i) { if(cit->surface_patch_index(i)>0) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt index 8f1468406ac..274464901df 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Mesh_3/CMakeLists.txt @@ -34,13 +34,13 @@ else() message(STATUS "NOTICE : the DICOM files (.dcm) need VTK libraries to be open and will not be able to.") endif() -find_package(Boost QUIET OPTIONAL_COMPONENTS filesystem) +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) target_link_libraries(io_image_plugin PUBLIC scene_image_item ${VTK_LIBRARIES} CGAL::CGAL_ImageIO) if(TARGET Boost::filesystem) - target_link_libraries(io_image_plugin PUBLIC Boost::filesystem) + target_link_libraries(io_image_plugin PUBLIC Boost::filesystem Boost::system) else() target_link_libraries(io_image_plugin PUBLIC ${Boost_LIBRARIES}) endif() diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp index 0eebfb574ab..4a99a1101c0 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Affine_transform_plugin.cpp @@ -143,11 +143,11 @@ public: { bbox = bbox + ps.point(*it).bbox(); } - CGAL::qglviewer::Vec min(bbox.xmin(),bbox.ymin(),bbox.zmin()); - CGAL::qglviewer::Vec max(bbox.xmax(),bbox.ymax(),bbox.zmax()); + CGAL::qglviewer::Vec v_min(bbox.xmin(),bbox.ymin(),bbox.zmin()); + CGAL::qglviewer::Vec v_max(bbox.xmax(),bbox.ymax(),bbox.zmax()); - setBbox(Bbox(min.x,min.y,min.z, - max.x,max.y,max.z)); + setBbox(Bbox(v_min.x,v_min.y,v_min.z, + v_max.x,v_max.y,v_max.z)); } bool isEmpty() const{return false;} Q_SIGNALS: diff --git a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp index 184770f685b..4215c75421b 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PCA/Basic_generator_plugin.cpp @@ -59,7 +59,7 @@ public : QMenu* menu = menuFile->findChild("menuGenerateObject"); if(!menu){ QAction* actionLoad = mw->findChild("actionLoadPlugin"); - menu = new QMenu(tr("Generate &Objet"), menuFile); + menu = new QMenu(tr("Generate &Object"), menuFile); menu->setObjectName("menuGenerateObject"); menuFile->insertMenu(actionLoad, menu); } diff --git a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp index 587e34051c9..031ac458e76 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/PMP/Distance_plugin.cpp @@ -34,6 +34,7 @@ typedef Scene_surface_mesh_item Scene_face_graph_item; typedef Scene_face_graph_item::Face_graph Face_graph; #if defined(CGAL_LINKED_WITH_TBB) +#include template struct Distance_computation{ const AABB_tree& tree; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt index f1f2c7e4d0f..b5a7c159731 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/CMakeLists.txt @@ -59,7 +59,7 @@ if(EIGEN3_FOUND) CGAL_target_use_pointmatcher(register_point_sets_plugin) endif() else() - message(STATUS "NOTICE: OpenGR and libpointmatcher were not found. Registrationp plugin will not be available.") + message(STATUS "NOTICE: OpenGR and libpointmatcher were not found. Registration plugin will not be available.") endif() else(EIGEN3_FOUND) @@ -94,6 +94,9 @@ endif() polyhedron_demo_plugin(point_set_wlop_plugin Point_set_wlop_plugin ${point_set_wlopFILES} KEYWORDS PointSetProcessing) target_link_libraries(point_set_wlop_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) + polyhedron_demo_plugin(point_set_clustering_plugin Point_set_clustering_plugin KEYWORDS PointSetProcessing) + target_link_libraries(point_set_clustering_plugin PUBLIC scene_points_with_normal_item scene_callback_signaler) + polyhedron_demo_plugin(merge_point_sets_plugin Merge_point_sets_plugin KEYWORDS PointSetProcessing Classification) target_link_libraries(merge_point_sets_plugin PUBLIC scene_points_with_normal_item) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp new file mode 100644 index 00000000000..951ca806115 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_clustering_plugin.cpp @@ -0,0 +1,241 @@ +#include "config.h" +#include "Scene_points_with_normal_item.h" +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "run_with_qprogressdialog.h" + +struct Clustering_functor + : public Functor_with_signal_callback +{ + Point_set* points; + Point_set::Property_map cluster_map; + const double neighbor_radius; + boost::shared_ptr result; + + Clustering_functor (Point_set* points, + const double neighbor_radius, + Point_set::Property_map cluster_map) + : points (points), cluster_map (cluster_map), + neighbor_radius (neighbor_radius), + result (new std::size_t(0)) { } + + void operator()() + { + *result = CGAL::cluster_point_set (*points, cluster_map, + points->parameters().neighbor_radius(neighbor_radius). + callback(*(this->callback()))); + } +}; + +using namespace CGAL::Three; + +class Polyhedron_demo_point_set_clustering_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") + + QAction* actionCluster; + +public: + void init(QMainWindow* mainWindow, CGAL::Three::Scene_interface* scene_interface, Messages_interface*) { + + scene = scene_interface; + mw = mainWindow; + actionCluster = new QAction(tr("Cluster Point Set"), mainWindow); + actionCluster->setObjectName("actionCluster"); + actionCluster->setProperty("subMenuName","Point Set Processing"); + autoConnectActions(); + } + + QList actions() const { + return QList() << actionCluster; + } + + bool applicable(QAction*) const { + Scene_points_with_normal_item* item = qobject_cast(scene->item(scene->mainSelectionIndex())); + return item; + } + +public Q_SLOTS: + void on_actionCluster_triggered(); + +}; // end + +void Polyhedron_demo_point_set_clustering_plugin::on_actionCluster_triggered() +{ + const CGAL::Three::Scene_interface::Item_id index = scene->mainSelectionIndex(); + + Scene_points_with_normal_item* item = + qobject_cast(scene->item(index)); + + if(item) + { + // Gets point set + Point_set* points = item->point_set(); + if(points == NULL) + return; + + QMultipleInputDialog dialog ("Clustering", mw); + QDoubleSpinBox* neighbor_radius = dialog.add ("Neighbor radius (0 = automatic):"); + neighbor_radius->setRange (0, 10000000); + neighbor_radius->setValue (0); + QSpinBox* min_nb = dialog.add ("Minimum number of points per cluster:"); + min_nb->setRange (1, 10000000); + min_nb->setValue (1); + + QCheckBox* add_property = dialog.add ("Add a \"cluster\" property to the input item"); + add_property->setChecked (true); + + QCheckBox* gen_color = dialog.add ("Generate one colored point set"); + gen_color->setChecked (true); + + QCheckBox* gen_sub = dialog.add ("Generate N point subsets"); + gen_sub->setChecked (false); + + if (!dialog.exec()) + return; + + QApplication::setOverrideCursor(Qt::BusyCursor); + QApplication::processEvents(); + CGAL::Real_timer task_timer; task_timer.start(); + + Point_set::Property_map cluster_map; + + if (add_property->isChecked()) + cluster_map = points->add_property_map ("cluster_map").first; + else + // Use long name to avoid overwriting potentially existing map + cluster_map = points->add_property_map ("cluster_point_set_property_map").first; + + // Default value + if (neighbor_radius->value() == 0) + { + neighbor_radius->setRange (-1, 10000000); + neighbor_radius->setValue(-1); + } + + // Computes average spacing + Clustering_functor functor (points, neighbor_radius->value(), cluster_map); + run_with_qprogressdialog (functor, "Clustering...", mw); + + std::size_t nb_clusters = *functor.result; + + Scene_group_item* group = nullptr; + std::vector new_items; + + if (gen_sub->isChecked()) + { + group = new Scene_group_item(QString("%1 (clusters)").arg(item->name())); + scene->addItem(group); + new_items.reserve (nb_clusters); + for (std::size_t i = 0; i < nb_clusters; ++ i) + { + Scene_points_with_normal_item* new_item = new Scene_points_with_normal_item; + new_item->point_set()->copy_properties (*points); + CGAL::Random rand((unsigned int)(i)); + unsigned char r, g, b; + r = static_cast(64 + rand.get_int(0, 192)); + g = static_cast(64 + rand.get_int(0, 192)); + b = static_cast(64 + rand.get_int(0, 192)); + new_item->setRgbColor(r, g, b); + new_item->setName (QString("Cluster %1 of %2").arg(i).arg(item->name())); + new_items.push_back (new_item); + } + } + + std::vector cluster_size (nb_clusters, 0); + for (Point_set::Index idx : *points) + { + if (gen_sub->isChecked()) + new_items[cluster_map[idx]]->point_set()->insert (*points, idx); + cluster_size[cluster_map[idx]] ++; + } + + if (gen_color->isChecked()) + { + Scene_points_with_normal_item* colored; + Point_set::Property_map red, green, blue; + + colored = new Scene_points_with_normal_item; + colored->setName (QString("%1 (clustering)").arg(item->name())); + + red = colored->point_set()->add_property_map("red", 0).first; + green = colored->point_set()->add_property_map("green", 0).first; + blue = colored->point_set()->add_property_map("blue", 0).first; + colored->point_set()->check_colors(); + + colored->point_set()->reserve (points->size()); + + for (Point_set::Index idx : *points) + { + Point_set::Index iidx = *(colored->point_set()->insert (points->point(idx))); + if (cluster_size[cluster_map[idx]] >= std::size_t(min_nb->value())) + { + CGAL::Random rand((unsigned int)(cluster_map[idx] + 1)); + unsigned char r, g, b; + r = static_cast(64 + rand.get_int(0, 192)); + g = static_cast(64 + rand.get_int(0, 192)); + b = static_cast(64 + rand.get_int(0, 192)); + red[iidx] = r; + green[iidx] = g; + blue[iidx] = b; + } + } + scene->addItem(colored); + } + + if (gen_sub->isChecked()) + { + for (Scene_points_with_normal_item* new_item : new_items) + { + if (new_item->point_set()->size() >= std::size_t(min_nb->value())) + { + scene->addItem(new_item); + scene->changeGroup (new_item, group); + } + else + delete new_item; + } + } + + if (!add_property->isChecked()) + points->remove_property_map (cluster_map); + + std::size_t memory = CGAL::Memory_sizer().virtual_size(); + std::cerr << "Number of clusters = " << nb_clusters << " (" + << task_timer.time() << " seconds, " + << (memory>>20) << " Mb allocated)" + << std::endl; + QApplication::restoreOverrideCursor(); + + item->setVisible (false); + item->invalidateOpenGLBuffers(); + scene->itemChanged(item); + } +} + + + +#include "Point_set_clustering_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp index f5a217a91c9..c79b878dd32 100644 --- a/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp +++ b/Polyhedron/demo/Polyhedron/Plugins/Point_set/Point_set_outliers_removal_plugin.cpp @@ -40,12 +40,13 @@ struct Outlier_removal_functor { // Computes outliers *result = - CGAL::remove_outliers(*points, - nb_neighbors, - points->parameters(). - threshold_percent(removed_percentage). - threshold_distance(distance_threshold). - callback (*(this->callback()))); + CGAL::remove_outliers + (*points, + nb_neighbors, + points->parameters(). + threshold_percent(removed_percentage). + threshold_distance(distance_threshold). + callback (*(this->callback()))); } }; diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..6b018456711 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,12 @@ +include( polyhedron_demo_macros ) + +remove_definitions(-DQT_STATICPLUGIN) + +qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_thread.h ) +qt5_wrap_cpp( VOLUME_MOC_OUTFILES ${CMAKE_CURRENT_SOURCE_DIR}/Volume_plane_interface.h ) + +qt5_wrap_ui( tetRemeshingUI_FILES Tetrahedral_remeshing_dialog.ui) +polyhedron_demo_plugin(tetrahedral_remeshing_plugin Tetrahedral_remeshing_plugin ${tetRemeshingUI_FILES} + KEYWORDS Tetrahedral_remeshing) +target_link_libraries(tetrahedral_remeshing_plugin + PUBLIC scene_c3t3_item ${OPENGL_gl_LIBRARY}) diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui new file mode 100644 index 00000000000..351de08c508 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_dialog.ui @@ -0,0 +1,210 @@ + + + Tetrahedral_remeshing_dialog + + + true + + + + 0 + 0 + 376 + 259 + + + + Isotropic remeshing criteria + + + + + + + 15 + 75 + true + + + + NO OBJECT + + + + + + + No size + + + + + + + Tetrahedral remeshing + + + + + + Protect boundaries + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 110 + 0 + + + + 1 + + + + + + + + + + false + + + + + + + Qt::Vertical + + + QSizePolicy::Maximum + + + + 20 + 40 + + + + + + + + Number of Main iterations + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + nbIterations_spinbox + + + + + + + Target edge length + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + edgeLength_dspinbox + + + + + + + + 110 + 0 + + + + 1000.000000000000000 + + + 0.100000000000000 + + + + + + + + + + Qt::Vertical + + + QSizePolicy::MinimumExpanding + + + + 0 + 0 + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + edgeLength_dspinbox + nbIterations_spinbox + protect_checkbox + buttonBox + + + + + buttonBox + accepted() + Tetrahedral_remeshing_dialog + accept() + + + 397 + 333 + + + 157 + 195 + + + + + buttonBox + rejected() + Tetrahedral_remeshing_dialog + reject() + + + 397 + 333 + + + 286 + 195 + + + + + diff --git a/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp new file mode 100644 index 00000000000..bbf5dc24de6 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Plugins/Tetrahedral_remeshing/Tetrahedral_remeshing_plugin.cpp @@ -0,0 +1,217 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +//#define CGAL_DUMP_REMESHING_STEPS +//#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +//#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS +//#define CGAL_TETRAHEDRAL_REMESHING_PROFILE +//#define CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES + +#include + +#include + +#include "Scene_c3t3_item.h" +#include "C3t3_type.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ui_Tetrahedral_remeshing_dialog.h" + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN +std::size_t nb_topology_test = 0; +std::size_t nb_impossible = 0; +std::size_t nb_valid_collapse = 0; +std::size_t nb_invalid_collapse = 0; +std::size_t nb_invalid_lengths = 0; +std::size_t nb_invalid_collapse_short = 0; +std::size_t nb_orientation_v0 = 0; +std::size_t nb_orientation_v1 = 0; +std::size_t nb_orientation_midpoint = 0; +std::size_t nb_test_v0 = 0; +std::size_t nb_test_v1 = 0; +std::size_t nb_test_midpoint = 0; +#endif + +using namespace CGAL::Three; +class Polyhedron_demo_tetrahedral_remeshing_plugin : + public QObject, + public Polyhedron_demo_plugin_interface +{ + Q_OBJECT + Q_INTERFACES(CGAL::Three::Polyhedron_demo_plugin_interface) + Q_PLUGIN_METADATA(IID "com.geometryfactory.PolyhedronDemo.PluginInterface/1.0" FILE "tetrahedral_remeshing_plugin.json") + +public: + void init(QMainWindow* mainWindow, Scene_interface* scene_interface, Messages_interface*) + { + this->scene = scene_interface; + this->mw = mainWindow; + + actionTetrahedralRemeshing_ = new QAction("Tetrahedral Remeshing", mw); + if (actionTetrahedralRemeshing_) { + connect(actionTetrahedralRemeshing_, SIGNAL(triggered()), + this, SLOT(tetrahedral_remeshing())); + } + } + + QList actions() const { + return QList() << actionTetrahedralRemeshing_; + } + + bool applicable(QAction*) const + { + return qobject_cast(scene->item(scene->mainSelectionIndex())); + } + +public Q_SLOTS: + void tetrahedral_remeshing() + { + const Scene_interface::Item_id index = scene->mainSelectionIndex(); + + Scene_c3t3_item* c3t3_item = + qobject_cast(scene->item(index)); + + if (c3t3_item) + { + // Create dialog box + QDialog dialog(mw); + Ui::Tetrahedral_remeshing_dialog ui + = tet_remeshing_dialog(&dialog, c3t3_item); + + // Get values + int i = dialog.exec(); + if (i == QDialog::Rejected) + { + std::cout << "Remeshing aborted" << std::endl; + return; + } + double target_length = ui.edgeLength_dspinbox->value(); + unsigned int nb_iter = ui.nbIterations_spinbox->value(); + bool protect = ui.protect_checkbox->isChecked(); + + // wait cursor + QApplication::setOverrideCursor(Qt::WaitCursor); + + QElapsedTimer time; + time.start(); + + CGAL::tetrahedral_isotropic_remeshing( + c3t3_item->c3t3(), + target_length, + CGAL::parameters::remesh_boundaries(!protect) + .number_of_iterations(nb_iter)); + + std::cout << "Remeshing done (" << time.elapsed() << " ms)" << std::endl; + + c3t3_item->invalidateOpenGLBuffers(); + c3t3_item->c3t3_changed(); + this->scene->itemChanged(index); + + // default cursor + QApplication::restoreOverrideCursor(); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + std::cout << "nb_topology_test = " << nb_topology_test << std::endl; + std::cout << "nb_impossible = " << nb_impossible << std::endl; + + std::cout << "nb_invalid_collapse_short = " << nb_invalid_collapse_short << std::endl; + + std::cout << "nb_orientation_fail_v0 = " << nb_orientation_v0 << std::endl; + std::cout << "nb_orientation_fail_v1 = " << nb_orientation_v1 << std::endl; + std::cout << "nb_orientation_fail_midpoint = " << nb_orientation_midpoint << std::endl; + + std::cout << "nb_test_v0 = " << nb_test_v0 << std::endl; + std::cout << "nb_test_v1 = " << nb_test_v1 << std::endl; + std::cout << "nb_test_midpoint = " << nb_test_midpoint << std::endl; + std::cout << std::endl; + + if (nb_test_v0 > 0) + std::cout << "nb_orientation_v0 / nb_test_v0 = " + << ((float)nb_orientation_v0 / (float)nb_test_v0) << std::endl; + if (nb_test_v1 > 1) + std::cout << "nb_orientation_v1 / nb_test_v1 = " + << ((float)nb_orientation_v1 / (float)nb_test_v1) << std::endl; + if (nb_test_midpoint > 0) + std::cout << "nb_orientation_midpoint / nb_test_midpoint = " + << ((float)nb_orientation_midpoint / (float)nb_test_midpoint) << std::endl; + + std::cout << std::endl; + std::cout << "nb_valid_collapse = " << nb_valid_collapse << std::endl; + std::cout << "nb_invalid_collapse = " << nb_invalid_collapse << std::endl; + std::cout << "nb_invalid_lengths = " << nb_invalid_lengths << std::endl; +#endif + } + else + { + std::cout << "Can't remesh that type of thing" << std::endl; + } + } + +private: + Scene_interface *scene; + QMainWindow* mw; + + Ui::Tetrahedral_remeshing_dialog + tet_remeshing_dialog(QDialog* dialog, + Scene_c3t3_item* c3t3_item) + { + Ui::Tetrahedral_remeshing_dialog ui; + ui.setupUi(dialog); + connect(ui.buttonBox, SIGNAL(accepted()), dialog, SLOT(accept())); + connect(ui.buttonBox, SIGNAL(rejected()), dialog, SLOT(reject())); + + //Set default parameters + Scene_interface::Bbox bbox = c3t3_item->bbox(); + ui.objectName->setText(c3t3_item->name()); + + ui.objectNameSize->setText( + tr("Object bbox size (w,h,d): %1, %2, %3") + .arg(bbox.xmax()-bbox.xmin(), 0, 'g', 3) + .arg(bbox.ymax()-bbox.ymin(), 0, 'g', 3) + .arg(bbox.zmax()-bbox.zmin(), 0, 'g', 3)); + + double diago_length = CGAL::sqrt((bbox.xmax()-bbox.xmin())*(bbox.xmax()-bbox.xmin()) + + (bbox.ymax()-bbox.ymin())*(bbox.ymax()-bbox.ymin()) + + (bbox.zmax()-bbox.zmin())*(bbox.zmax()-bbox.zmin())); + double log = std::log10(diago_length); + unsigned int nb_decimals = (log > 0) ? 5 : (std::ceil(-log)+3); + + ui.edgeLength_dspinbox->setDecimals(nb_decimals); + ui.edgeLength_dspinbox->setSingleStep(1e-3); + ui.edgeLength_dspinbox->setRange(1e-6 * diago_length, //min + 2. * diago_length);//max + ui.edgeLength_dspinbox->setValue(0.05 * diago_length); + + std::ostringstream oss; + oss << "Diagonal length of the Bbox of the triangulation to remesh is "; + oss << diago_length << "." << std::endl; + oss << "Default is 5% of it" << std::endl; + ui.edgeLength_dspinbox->setToolTip(QString::fromStdString(oss.str())); + + ui.nbIterations_spinbox->setSingleStep(1); + ui.nbIterations_spinbox->setRange(1/*min*/, 1000/*max*/); + ui.nbIterations_spinbox->setValue(1); + + ui.protect_checkbox->setChecked(false); + + return ui; + } + + +private: + QAction* actionTetrahedralRemeshing_; + +}; // end Polyhedron_demo_tetrahedral_remeshing_plugin + +#include "Tetrahedral_remeshing_plugin.moc" diff --git a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp index 01c192db153..085d63abf76 100644 --- a/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp +++ b/Polyhedron/demo/Polyhedron/Scene_c3t3_item.cpp @@ -1428,6 +1428,7 @@ void Scene_c3t3_item_priv::computeElements() //The grid { + positions_grid.resize(0); float x = (2 * (float)complex_diag()) / 10.0f; float y = (2 * (float)complex_diag()) / 10.0f; diff --git a/Polyhedron/demo/Polyhedron/Server_ws.cpp b/Polyhedron/demo/Polyhedron/Server_ws.cpp new file mode 100644 index 00000000000..82bea309a37 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Server_ws.cpp @@ -0,0 +1,100 @@ +#include +#include +#include +#include +#include +#include +#include "Server_ws.h" + +#include + + +EchoServer::EchoServer(quint16 port) : + QObject(), + m_pWebSocketServer(new QWebSocketServer(QStringLiteral("Echo Server"), + QWebSocketServer::NonSecureMode, this)) +{ + if (m_pWebSocketServer->listen(QHostAddress::Any, port)) { + connect(m_pWebSocketServer, &QWebSocketServer::newConnection, + this, &EchoServer::onNewConnection); + connect(m_pWebSocketServer, &QWebSocketServer::closed, this, &EchoServer::closed); + } + QHostAddress local_host("0.0.0.0"); + + //to avoid printing 127.0.0.1. Not realy sure it won't ever print the external ipv4 though. + const QHostAddress &localhost = QHostAddress(QHostAddress::LocalHost); + for (const QHostAddress &address: QNetworkInterface::allAddresses()) { + if (address.protocol() == QAbstractSocket::IPv4Protocol && address != localhost) + { + local_host= address; + break; + } + } + QMessageBox mb(QMessageBox::NoIcon, "WS Server", + tr("WebSockets Server started.\nEnter the following address in\nyour Network Preferences to be able to join it :\n" + "ws://%1:%2").arg(local_host.toString()).arg(port), QMessageBox::Ok); + mb.setTextInteractionFlags(Qt::TextSelectableByMouse); + mb.exec(); +} + +EchoServer::~EchoServer() +{ + m_pWebSocketServer->close(); + qDeleteAll(m_clients.begin(), m_clients.end()); +} + +void EchoServer::onNewConnection() +{ + QWebSocket *pSocket = m_pWebSocketServer->nextPendingConnection(); + + connect(pSocket, &QWebSocket::textMessageReceived, this, &EchoServer::processTextMessage); + connect(pSocket, &QWebSocket::binaryMessageReceived, this, &EchoServer::processBinaryMessage); + connect(pSocket, &QWebSocket::disconnected, this, &EchoServer::socketDisconnected); + + m_clients << pSocket; +} + +void EchoServer::processTextMessage(QString message) +{ + QWebSocket *pClient = qobject_cast(sender()); + for(auto *client : m_clients) { + if(client != pClient) + client->sendTextMessage(message); + } +} + +void EchoServer::processBinaryMessage(QByteArray message) +{ + QWebSocket *pClient = qobject_cast(sender()); + if (pClient) { + pClient->sendBinaryMessage(message); + } +} + +void EchoServer::socketDisconnected() +{ + QWebSocket *pClient = qobject_cast(sender()); + if (pClient) { + m_clients.removeAll(pClient); + pClient->deleteLater(); + } +} + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + QCommandLineParser parser; + parser.setApplicationDescription("WS Server"); + parser.addHelpOption(); + QCommandLineOption portOption(QStringList() << "p" << "port", + QCoreApplication::translate("main", "Port for echoserver [default: 1234]."), + QCoreApplication::translate("main", "port"), QLatin1Literal("1234")); + parser.addOption(portOption); + parser.process(a); + int port = parser.value(portOption).toInt(); + EchoServer *server = new EchoServer(port); + QObject::connect(server, &EchoServer::closed, &a, &QCoreApplication::quit); + + return a.exec(); +} + diff --git a/Polyhedron/demo/Polyhedron/Server_ws.h b/Polyhedron/demo/Polyhedron/Server_ws.h new file mode 100644 index 00000000000..fe94f6b2d08 --- /dev/null +++ b/Polyhedron/demo/Polyhedron/Server_ws.h @@ -0,0 +1,30 @@ +#ifndef SERVER_WS_H +#define SERVER_WS_H + +#include +#include +#include + +class EchoServer : public QObject +{ + Q_OBJECT +public: + explicit EchoServer(quint16 port); + ~EchoServer(); + + +Q_SIGNALS: + void closed(); + +private Q_SLOTS: + void onNewConnection(); + void processTextMessage(QString message); + void processBinaryMessage(QByteArray message); + void socketDisconnected(); + +private: + QWebSocketServer *m_pWebSocketServer; + QList m_clients; +}; + +#endif // SERVER_WS_H diff --git a/Polyhedron/demo/Polyhedron/Use_ssh.cpp b/Polyhedron/demo/Polyhedron/Use_ssh.cpp index 8acc1801b8e..028909251c2 100644 --- a/Polyhedron/demo/Polyhedron/Use_ssh.cpp +++ b/Polyhedron/demo/Polyhedron/Use_ssh.cpp @@ -20,8 +20,10 @@ #include #include #include +#include #include +#include bool test_result(int res) { @@ -135,6 +137,79 @@ bool establish_ssh_session(ssh_session &session, return true; } + +bool establish_ssh_session_from_agent(ssh_session& session, + const char *user, + const char *server, + const char *pub_key_path) +{ + int port = 22; + + //Can use SSH_LOG_PROTOCOL here for verbose output + int verbosity = SSH_LOG_NOLOG; + int res; + //retry 4 times max each time the connection asks to be retried. + for(int k = 0; k < 4; ++k) + { + session = ssh_new(); + ssh_options_set( session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity ); + ssh_options_set( session, SSH_OPTIONS_PORT, &port ); + ssh_options_set( session, SSH_OPTIONS_USER, user ); + ssh_options_set( session, SSH_OPTIONS_HOST, server); + + ssh_connect(session); +#if LIBSSH_VERSION_MAJOR <1 && LIBSSH_VERSION_MINOR < 8 + if( ssh_is_server_known(session) != SSH_SERVER_KNOWN_OK ) +#else + if( ssh_session_is_known_server(session) != SSH_KNOWN_HOSTS_OK ) +#endif + { + if(QMessageBox::warning(CGAL::Three::Three::mainWindow(), QString("Unknown Server"), + QString ("The server you are trying to join is not known.\n" + "Do you wish to add it to the known servers list and continue?"), + QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes) + { + return false; + } +#if LIBSSH_VERSION_MAJOR <1 && LIBSSH_VERSION_MINOR < 8 + if( ssh_write_knownhost(session) != SSH_OK ) +#else + if( ssh_session_update_known_hosts(session) != SSH_OK ) +#endif + { + std::cerr << "writeKnownHost failed" << std::endl; + return false; + } + else + { + ssh_connect(session); + } + } + ssh_key pubkey = ssh_key_new(); + ssh_pki_import_pubkey_file(pub_key_path, &pubkey); + res = ssh_userauth_try_publickey(session, NULL, pubkey); + if(res == SSH_AUTH_AGAIN) + ssh_disconnect(session); + else + break; + } + + + if(!test_result(res)) + { + ssh_disconnect(session); + return false; + } + + res = ssh_userauth_agent(session, user); + if(!test_result(res)) + { + ssh_disconnect(session); + return false; + } + return true; +} + void close_connection(ssh_session &session) { ssh_disconnect(session); @@ -282,5 +357,62 @@ bool pull_file(ssh_session &session, return true; } -}} +bool explore_the_galaxy(ssh_session &session, + QStringList& files) +{ + ssh_channel channel; + int rc; + channel = ssh_channel_new(session); + if (channel == NULL) return false; + rc = ssh_channel_open_session(channel); + if (rc != SSH_OK) + { + ssh_channel_free(channel); + return rc; + } + rc = ssh_channel_request_exec(channel, "ls /tmp"); + if (rc != SSH_OK) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return rc; + } + + char buffer[256]; + int nbytes; + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + while (nbytes > 0) + { + + std::string sbuf(buffer, nbytes); + if(sbuf.find("Polyhedron_demo_") != std::string::npos) + { + std::istringstream iss(sbuf); + std::string file; + while(iss >> file) + { + if(file.find("Polyhedron_demo_") != std::string::npos) + { + QString name(file.c_str()); + files.push_back(name.remove("Polyhedron_demo_")); + } + } + } + + nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0); + } + if (nbytes < 0) + { + ssh_channel_close(channel); + ssh_channel_free(channel); + return false; + } + ssh_channel_send_eof(channel); + ssh_channel_close(channel); + ssh_channel_free(channel); + return true; +} + +}// end of ssh_internal +}// end of CGAL #endif diff --git a/Polyhedron/demo/Polyhedron/Viewer.cpp b/Polyhedron/demo/Polyhedron/Viewer.cpp index ecadeba815a..57ed3f9d84f 100644 --- a/Polyhedron/demo/Polyhedron/Viewer.cpp +++ b/Polyhedron/demo/Polyhedron/Viewer.cpp @@ -1690,6 +1690,12 @@ void Viewer::setTotalPass(int p) void Viewer::messageLogged(QOpenGLDebugMessage msg) { + //filter out useless warning + // From those two links, we decided we didn't care for this warning: + // https://community.khronos.org/t/vertex-shader-in-program-2-is-being-recompiled-based-on-gl-state/76019 + // https://stackoverflow.com/questions/12004396/opengl-debug-context-performance-warning + if(msg.message().contains("is being recompiled")) + return; QString error; // Format based on severity @@ -2017,7 +2023,15 @@ void Viewer::onTextMessageSocketReceived(QString message) if(session != d->session){ return; } - moveCameraToCoordinates(position, 0.05f); + QStringList sl = position.split(" "); + if(sl.size() != 7) + return; + + CGAL::qglviewer::Vec pos(sl[0].toDouble(),sl[1].toDouble(),sl[2].toDouble()); + CGAL::qglviewer::Quaternion q(sl[3].toDouble(),sl[4].toDouble(), + sl[5].toDouble(),sl[6].toDouble()); + camera()->frame()->setPositionAndOrientation(pos, q); + update(); } #endif #include "Viewer.moc" diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h b/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h index 5d6b1fe41ae..9548ee658b9 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/IO/read_surf_trianglemesh.h @@ -168,6 +168,8 @@ void treat_surf_inner_region(std::istream& input, iss.str(input_line); std::string dump; iss >> dump >> name; + name.erase(std::remove(name.begin(), name.end(), '"'), name.end()); + name.erase(std::remove(name.begin(), name.end(), ','), name.end()); for(std::size_t j=0; j +bool fill_binary_vertices(std::istream& is, std::vector& points, const std::size_t& nb_points) +{ + float f[3]; + std::size_t pos = 0; + while(pos < nb_points) + { + is.read(reinterpret_cast(&f[0]), sizeof(f[0])); + if(!is.good()) + return false; + is.read(reinterpret_cast(&f[1]), sizeof(f[1])); + if(!is.good()) + return false; + is.read(reinterpret_cast(&f[2]), sizeof(f[2])); + if(!is.good()) + return false; + points.push_back(Point(f[0], f[1], f[2])); + ++pos; + } + return true; +} + +bool fill_binary_triangles(std::istream& is, std::vector >& triangles, const std::size_t& nb_trs) +{ + int tr[7]; + std::size_t pos = 0; + while(pos < nb_trs) + { + for(int i = 0; i < 7; ++i) + { + is.read(reinterpret_cast(&tr[i]), sizeof(tr[i])); + if(!is.good()) + return false; + } + std::array tri; + for(int i = 0; i < 3; ++i) + tri[i] = tr[i]; + triangles.push_back(tri); + ++pos; + } + return true; +} + +bool fill_binary_patch(std::istream& is, std::vector& patch, std::size_t size) +{ + int id = 0; + std::size_t pos = 0; + while(pos < size) + { + is.read(reinterpret_cast(&id), sizeof(int)); + if(!is.good()) + return false; + patch.push_back(id); + ++pos; + } + return true; +} + +template +bool build_binary_surf_patch(DuplicatedPointsOutIterator& out, + std::vector& output, + std::vector& points, + const std::vector >& polygons, + const std::vector& patch, + const std::size_t i) +{ + namespace PMP = CGAL::Polygon_mesh_processing; + typedef std::array Triangle_ind; + std::vector triangles; + triangles.reserve(patch.size()); + for(const std::size_t& id : patch) + { + triangles.push_back(polygons[id]); + } + if (!PMP::is_polygon_soup_a_polygon_mesh(triangles)) + { + std::cout << "Orientation of patch #" << (i + 1) << "..."; + std::cout.flush(); + + const std::size_t nbp_init = points.size(); + bool no_duplicates = + PMP::orient_polygon_soup(points, triangles);//returns false if some points + //were duplicated + + std::cout << "\rOrientation of patch #" << (i + 1) << " done"; + + if(!no_duplicates) //collect duplicates + { + for (std::size_t i = nbp_init; i < points.size(); ++i) + *out++ = points[i]; + std::cout << " (non manifold -> " + << (points.size() - nbp_init) << " duplicated vertices)"; + } + std::cout << "." << std::endl; + } + + Mesh& mesh = output[i]; + + PMP::internal::PS_to_PM_converter, std::vector > converter(points, triangles); + converter(mesh, false/*insert_isolated_vertices*/); + + CGAL_assertion(PMP::remove_isolated_vertices(mesh) == 0); + CGAL_assertion(is_valid_polygon_mesh(mesh)); + return true; +} }//end internal }//end IO @@ -292,72 +399,174 @@ bool read_surf(std::istream& input, std::vector& output, std::vector points; std::string line; - std::istringstream iss; std::size_t nb_vertices(0); std::vector materials; //ignore header int material_id = 0; int nb_patches = 0; - while(std::getline(input, line)) + if(!std::getline(input, line)) + return false; + bool binary = (line.find("BINARY") != std::string::npos); + if(!binary) { - if (line_starts_with(line, "Materials")) - { - if(!IO::internal::treat_surf_materials(input, materials, material_id)) - return false; - } - - //get grid box - if (line_starts_with(line, "GridBox")) - { - IO::internal::treat_surf_grid_box(line, grid_box); - } - - //get grid size - if (line_starts_with(line, "GridSize")) - { - IO::internal::treat_surf_grid_size(line, grid_size); - } - - //get number of vertices - if (line_starts_with(line, "Vertices")) - { - IO::internal::treat_surf_vertices(input, line, nb_vertices, points); - } - - //get number of patches - if (line_starts_with(line, "Patches")) - { - IO::internal::get_surf_patches(line, nb_patches, metadata, output); - break; - } - } - - for(int i=0; i < nb_patches; ++i) - { - std::size_t nb_triangles(0); - //get metada while(std::getline(input, line)) { - if (line_starts_with(line, "InnerRegion")) + if (line_starts_with(line, "Materials")) { - IO::internal::treat_surf_inner_region(input, line, materials, metadata, i); + if(!IO::internal::treat_surf_materials(input, materials, material_id)) + return false; } - if (line_starts_with(line, "Triangles")) + + //get grid box + if (line_starts_with(line, "GridBox")) { - IO::internal::treat_surf_triangles(line, nb_triangles); + IO::internal::treat_surf_grid_box(line, grid_box); + } + + //get grid size + if (line_starts_with(line, "GridSize")) + { + IO::internal::treat_surf_grid_size(line, grid_size); + } + + //get number of vertices + if (line_starts_with(line, "Vertices")) + { + IO::internal::treat_surf_vertices(input, line, nb_vertices, points); + } + + //get number of patches + if (line_starts_with(line, "Patches")) + { + IO::internal::get_surf_patches(line, nb_patches, metadata, output); break; } } - //connect triangles + for(int i=0; i < nb_patches; ++i) + { + std::size_t nb_triangles(0); + //get metada + while(std::getline(input, line)) + { + if (line_starts_with(line, "InnerRegion")) + { + IO::internal::treat_surf_inner_region(input, line, materials, metadata, i); + } + if (line_starts_with(line, "Triangles")) + { + IO::internal::treat_surf_triangles(line, nb_triangles); + break; + } + } + //connect triangles + typedef std::array Triangle_ind; + std::vector polygons; + IO::internal::connect_surf_triangles(input, nb_triangles, polygons); + + //build patch + IO::internal::build_surf_patch(out, output, points, polygons, i); + } // end loop on patches + } + else + { + int nTriangles = 0; typedef std::array Triangle_ind; - std::vector polygons; - IO::internal::connect_surf_triangles(input, nb_triangles, polygons); + std::vector triangles; + std::vector tr_per_patches; + int patch_counter = -1; + while(std::getline(input, line)) + { + //get nb vertices + if (line_starts_with(line, "nVertices")) + { + std::istringstream iss; + iss.str(line); + std::string dump; + if(!(iss >> dump >> nb_vertices)) + return false; + } + //get nb triangles + if (line_starts_with(line, "nTriangles")) + { + std::istringstream iss; + iss.str(line); + std::string dump; + if(!(iss >> dump >> nTriangles)) + return false; + std::cout<> dump >> dump >> nb_patches)) + return false; + std::cout<> dump >> dump >> nb_tr)) + return false; + tr_per_patches.push_back(nb_tr); + ++patch_counter; + } + else + { + std::cerr<<"Error in input file. Incoherent number of materials."< patch; + IO::internal::fill_binary_patch(input, patch, tr_per_patches[patch_counter]); + IO::internal::build_binary_surf_patch(out, output, points, triangles, patch, patch_counter++); + } + } + } return true; } diff --git a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h index 2cdca27452b..5d24a129302 100644 --- a/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h +++ b/Polyhedron/demo/Polyhedron/include/CGAL/Use_ssh.h @@ -1,6 +1,10 @@ #ifndef USE_SSH_H #define USE_SSH_H #include +#include + +class QStringList; + namespace CGAL{ namespace ssh_internal{ //should be used inside a try/catch(ssh::SshException e) @@ -12,6 +16,12 @@ bool establish_ssh_session(ssh_session& session, const char *pub_key_path, const char *priv_key_path, const char *priv_key_password); + +bool establish_ssh_session_from_agent(ssh_session& session, + const char *user, + const char *server, + const char *pub_key_path); + void close_connection(ssh_session& session); bool push_file(ssh_session& session, @@ -21,5 +31,8 @@ bool pull_file(ssh_session &session, const char *from_path, const char *to_path); +bool explore_the_galaxy(ssh_session &session, + QStringList &files); + }} #endif diff --git a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h index b30cf524458..540f17bd203 100644 --- a/Polynomial/include/CGAL/Polynomial/Polynomial_type.h +++ b/Polynomial/include/CGAL/Polynomial/Polynomial_type.h @@ -957,6 +957,52 @@ public: } friend Polynomial operator - <> (const Polynomial&); + + // + // Comparison Operators + // + + // polynomials only + friend bool operator == (const Polynomial& p1, const Polynomial& p2) { + CGAL_precondition(p1.degree() >= 0); + CGAL_precondition(p2.degree() >= 0); + if (p1.is_identical(p2)) return true; + if (p1.degree() != p2.degree()) return false; + for (int i = p1.degree(); i >= 0; i--) if (p1[i] != p2[i]) return false; + return true; + } + friend bool operator < (const Polynomial& p1, const Polynomial& p2) + { return ( p1.compare(p2) < 0 ); } + + // operators NT + friend bool operator == (const Polynomial& p, const NT& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == num; + } + friend bool operator < (const Polynomial& p,const NT& num) + { return ( p.compare(num) < 0 );} + friend bool operator > (const Polynomial& p,const NT& num) + { return ( p.compare(num) > 0 );} + + // compare int ################################# + friend bool operator == (const Polynomial& p, const CGAL_int(NT)& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == NT(num); + } + friend bool operator < (const Polynomial& p, const CGAL_int(NT)& num) + { return ( p.compare(NT(num)) < 0 );} + friend bool operator > (const Polynomial& p, const CGAL_int(NT)& num) + { return ( p.compare(NT(num)) > 0 );} + + // compare icoeff ################################### + friend bool operator == (const Polynomial& p, const CGAL_icoeff(NT)& num) { + CGAL_precondition(p.degree() >= 0); + return p.degree() == 0 && p[0] == NT(num); + } + friend bool operator < (const Polynomial& p, const CGAL_icoeff(NT)& num) + { return ( p.compare(NT(num)) < 0 );} + friend bool operator > (const Polynomial& p, const CGAL_icoeff(NT)& num) + { return ( p.compare(NT(num)) > 0 );} }; // class Polynomial // Arithmetic Operators, Part III: @@ -999,102 +1045,6 @@ Polynomial operator * (const Polynomial& p1, } -// -// Comparison Operators -// - -// polynomials only -template inline -bool operator == (const Polynomial& p1, const Polynomial& p2) { - CGAL_precondition(p1.degree() >= 0); - CGAL_precondition(p2.degree() >= 0); - if (p1.is_identical(p2)) return true; - if (p1.degree() != p2.degree()) return false; - for (int i = p1.degree(); i >= 0; i--) if (p1[i] != p2[i]) return false; - return true; -} -template inline -bool operator < (const Polynomial& p1, const Polynomial& p2) -{ return ( p1.compare(p2) < 0 ); } -template inline -bool operator > (const Polynomial& p1, const Polynomial& p2) -{ return ( p1.compare(p2) > 0 ); } - -// operators NT -template inline -bool operator == (const NT& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == num; -} -template inline -bool operator == (const Polynomial& p, const NT& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == num; -} -template inline -bool operator < (const NT& num, const Polynomial& p) -{ return ( p.compare(num) > 0 );} -template inline -bool operator < (const Polynomial& p,const NT& num) -{ return ( p.compare(num) < 0 );} -template inline -bool operator > (const NT& num, const Polynomial& p) -{ return ( p.compare(num) < 0 );} -template inline -bool operator > (const Polynomial& p,const NT& num) -{ return ( p.compare(num) > 0 );} - - -// compare int ################################# -template inline -bool operator == (const CGAL_int(NT)& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator == (const Polynomial& p, const CGAL_int(NT)& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator < (const CGAL_int(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) > 0 );} -template inline -bool operator < (const Polynomial& p, const CGAL_int(NT)& num) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const CGAL_int(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const Polynomial& p, const CGAL_int(NT)& num) -{ return ( p.compare(NT(num)) > 0 );} - -// compare icoeff ################################### -template inline -bool operator == (const CGAL_icoeff(NT)& num, const Polynomial& p) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator == (const Polynomial& p, const CGAL_icoeff(NT)& num) { - CGAL_precondition(p.degree() >= 0); - return p.degree() == 0 && p[0] == NT(num); -} -template inline -bool operator < (const CGAL_icoeff(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) > 0 );} -template inline -bool operator < (const Polynomial& p, const CGAL_icoeff(NT)& num) -{ return ( p.compare(NT(num)) < 0 );} - - -template inline -bool operator > (const CGAL_icoeff(NT)& num, const Polynomial& p) -{ return ( p.compare(NT(num)) < 0 );} -template inline -bool operator > (const Polynomial& p, const CGAL_icoeff(NT)& num) -{ return ( p.compare(NT(num)) > 0 );} - // // Algebraically non-trivial operations // diff --git a/Property_map/include/CGAL/property_map.h b/Property_map/include/CGAL/property_map.h index f58413b9755..988c7ab6583 100644 --- a/Property_map/include/CGAL/property_map.h +++ b/Property_map/include/CGAL/property_map.h @@ -27,6 +27,8 @@ #include // defines std::pair +#include +#include #include #include #include @@ -576,6 +578,38 @@ make_cartesian_converter_property_map(Vpm vpm) return Cartesian_converter_property_map(vpm); } +/// \cond SKIP_IN_MANUAL +// Syntaxic sugar for transform_iterator+pmap_to_unary_function +template +typename boost::transform_iterator, Iterator> +make_transform_iterator_from_property_map (Iterator it, Pmap pmap) +{ + return boost::make_transform_iterator (it, CGAL::Property_map_to_unary_function(pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::const_iterator> > +make_transform_range_from_property_map (const Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} + +// Syntaxic sugar for make_range+transform_iterator+pmap_to_unary_function +template +CGAL::Iterator_range, + typename Range::iterator> > +make_transform_range_from_property_map (Range& range, Pmap pmap) +{ + return CGAL::make_range + (make_transform_iterator_from_property_map (range.begin(), pmap), + make_transform_iterator_from_property_map (range.end(), pmap)); +} +/// \endcond + } // namespace CGAL diff --git a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp index 8fa4ac28fd7..4186c723d3e 100644 --- a/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp +++ b/STL_Extension/benchmark/compact_container_benchmark/cc_benchmark.cpp @@ -26,7 +26,7 @@ struct Truc { Truc(int v = 0) : value(v), /*value2(v), */p(NULL) {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void *ptr) { p = ptr; } int value; int value2; diff --git a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h index 41c30aea6c7..98a1af5ceb6 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Compact_container.h @@ -30,10 +30,9 @@ Returns the pointer necessary for `Compact_container_traits`. void * for_compact_container() const; /*! -Returns a reference to the pointer necessary for -`Compact_container_traits`. +Sets the pointer necessary for `Compact_container_traits` to `p`. */ -void * & for_compact_container(); +void for_compact_container(void* p); /// @} @@ -796,7 +795,7 @@ types `T` to make them usable with the default `Compact_container_traits`. `void * t.for_compact_container() const;` -`void *& t.for_compact_container();`. +`void t.for_compact_container(void *);`. */ @@ -820,11 +819,11 @@ static void * pointer(const T &t); /// \name Operations /// @{ /*! -Returns a reference to the pointer held by `t`. -The template version defines this function as: `return t.for_compact_container();` +Sets the pointer held by `t` to `p`. +The template version defines this function as: `t.for_compact_container(p);` */ -static void * & pointer(T &t); + static void set_pointer(T &t, void* p); diff --git a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h index 49d8826ba9c..65e853f489a 100644 --- a/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/doc/STL_Extension/CGAL/Concurrent_compact_container.h @@ -22,7 +22,7 @@ types `T` to make them usable with the default `Concurrent_compact_container`. `T` is any type providing the following member functions: `void * t.for_compact_container() const;` -`void *& t.for_compact_container();`. +`void t.for_compact_container(void *);`. */ template< typename T > struct Concurrent_compact_container_traits { @@ -40,11 +40,11 @@ struct Concurrent_compact_container_traits { /// \name Operations /// @{ /*! - Returns a reference to the pointer held by `t`. - The template version defines this function as: `return t.for_compact_container();` + Sets the pointer held by `t` to `p`. + The template version defines this function as: `t.for_compact_container(p);` */ - static void * & pointer(T &t); + static void set_pointer(T &t, void* p); /// @} diff --git a/STL_Extension/include/CGAL/Compact_container.h b/STL_Extension/include/CGAL/Compact_container.h index e416832c3a3..62751003b5a 100644 --- a/STL_Extension/include/CGAL/Compact_container.h +++ b/STL_Extension/include/CGAL/Compact_container.h @@ -25,6 +25,7 @@ #include #include #include +#include #include #include @@ -148,15 +149,15 @@ public: Compact_container_base() : p(nullptr) {} void * for_compact_container() const { return p; } - void * & for_compact_container() { return p; } + void for_compact_container(void* ptr) { p = ptr; } }; // The traits class describes the way to access the pointer. // It can be specialized. template < class T > struct Compact_container_traits { - static void * pointer(const T &t) { return t.for_compact_container(); } - static void * & pointer(T &t) { return t.for_compact_container(); } + static void * pointer(const T &t) { return t.for_compact_container(); } + static void set_pointer(T &t, void* p) { t.for_compact_container(p); } }; namespace internal { @@ -223,7 +224,8 @@ class Compact_container public: typedef typename Default::Get< TimeStamper_, CGAL::Time_stamper_impl >::type - Time_stamper_impl; + Time_stamper; + typedef Time_stamper Time_stamper_impl; // backward-compatibility typedef T value_type; typedef Allocator allocator_type; @@ -250,16 +252,14 @@ public: explicit Compact_container(const Allocator &a = Allocator()) : alloc(a) - , time_stamper(new Time_stamper_impl()) { - init (); + init(); } template < class InputIterator > Compact_container(InputIterator first, InputIterator last, const Allocator & a = Allocator()) : alloc(a) - , time_stamper(new Time_stamper_impl()) { init(); std::copy(first, last, CGAL::inserter(*this)); @@ -268,14 +268,19 @@ public: // The copy constructor and assignment operator preserve the iterator order Compact_container(const Compact_container &c) : alloc(c.get_allocator()) - , time_stamper(new Time_stamper_impl()) { init(); block_size = c.block_size; - *time_stamper = *c.time_stamper; + time_stamp = c.time_stamp.load(); std::copy(c.begin(), c.end(), CGAL::inserter(*this)); } + Compact_container(Compact_container&& c) noexcept + : alloc(c.get_allocator()) + { + c.swap(*this); + } + Compact_container & operator=(const Compact_container &c) { if (&c != this) { @@ -285,10 +290,16 @@ public: return *this; } + Compact_container & operator=(Compact_container&& c) noexcept + { + Self tmp(std::move(c)); + tmp.swap(*this); + return *this; + } + ~Compact_container() { clear(); - delete time_stamper; } bool is_used(const_iterator ptr) const @@ -328,17 +339,8 @@ public: return all_items[block_number].first[index_in_block]; } - void swap(Self &c) - { - std::swap(alloc, c.alloc); - std::swap(capacity_, c.capacity_); - std::swap(size_, c.size_); - std::swap(block_size, c.block_size); - std::swap(first_item, c.first_item); - std::swap(last_item, c.last_item); - std::swap(free_list, c.free_list); - all_items.swap(c.all_items); - std::swap(time_stamper, c.time_stamper); + friend void swap(Compact_container& a, Compact_container b) { + a.swap(b); } iterator begin() { return iterator(first_item, 0, 0); } @@ -383,7 +385,7 @@ public: new (ret) value_type(args...); CGAL_assertion(type(ret) == USED); ++size_; - time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -397,7 +399,7 @@ public: std::allocator_traits::construct(alloc, ret, t); CGAL_assertion(type(ret) == USED); ++size_; - time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, time_stamp); return iterator(ret, 0); } @@ -643,8 +645,8 @@ private: // This out of range compare is always true and causes lots of // unnecessary warnings. // CGAL_precondition(0 <= t && t < 4); - Traits::pointer(*ptr) = reinterpret_cast - (reinterpret_cast(clean_pointer((char *) p)) + (int) t); + Traits::set_pointer(*ptr, reinterpret_cast + (reinterpret_cast(clean_pointer((char *) p)) + (int) t)); } public: @@ -652,7 +654,21 @@ public: static bool is_begin_or_end(const_pointer ptr) { return type(ptr)==START_END; } + void swap(Self &c) + { + std::swap(alloc, c.alloc); + std::swap(capacity_, c.capacity_); + std::swap(size_, c.size_); + std::swap(block_size, c.block_size); + std::swap(first_item, c.first_item); + std::swap(last_item, c.last_item); + std::swap(free_list, c.free_list); + all_items.swap(c.all_items); + // non-atomic swap of time_stamp: + c.time_stamp = time_stamp.exchange(c.time_stamp.load()); + } +private: // We store a vector of pointers to all allocated blocks and their sizes. // Knowing all pointers, we don't have to walk to the end of a block to reach // the pointer to the next block. @@ -660,7 +676,9 @@ public: // by walking through the block till its end. // This opens up the possibility for the compiler to optimize the clear() // function considerably when has_trivial_destructor. - typedef std::vector > All_items; + using All_items = std::vector >; + + using time_stamp_t = std::atomic; void init() { @@ -671,21 +689,18 @@ public: first_item = nullptr; last_item = nullptr; all_items = All_items(); - time_stamper->reset(); + time_stamp = 0; } allocator_type alloc; - size_type capacity_; - size_type size_; - size_type block_size; - pointer free_list; - pointer first_item; - pointer last_item; - All_items all_items; - - // This is a pointer, so that the definition of Compact_container does - // not require a complete type `T`. - Time_stamper_impl* time_stamper; + size_type capacity_ = 0; + size_type size_ = 0; + size_type block_size = Increment_policy::first_block_size; + pointer free_list = nullptr; + pointer first_item = nullptr; + pointer last_item = nullptr; + All_items all_items = {}; + time_stamp_t time_stamp = {}; }; template < class T, class Allocator, class Increment_policy, class TimeStamper > @@ -759,7 +774,7 @@ void Compact_container::allocate_ne for (size_type i = block_size; i >= 1; --i) { EraseCounterStrategy::set_erase_counter(*(new_block + i), 0); - time_stamper->initialize_time_stamp(new_block + i); + Time_stamper::initialize_time_stamp(new_block + i); put_on_free_list(new_block + i); } // We insert this new block at the end. @@ -839,7 +854,6 @@ namespace internal { template < class DSC, bool Const > class CC_iterator { - typedef typename DSC::iterator iterator; typedef CC_iterator Self; public: typedef DSC CC; @@ -858,49 +872,51 @@ namespace internal { : ts(0) #endif { - m_ptr.p = nullptr; + m_ptr = nullptr; } - // Either a harmless copy-ctor, - // or a conversion from iterator to const_iterator. - CC_iterator (const iterator &it) + // Converting constructor from mutable to constant iterator + template + CC_iterator(const CC_iterator< + typename std::enable_if<(!OtherConst && Const), DSC>::type, + OtherConst> &const_it) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - : ts(Time_stamper_impl::time_stamp(it.operator->())) + : ts(Time_stamper::time_stamp(const_it.operator->())) #endif { - m_ptr.p = it.operator->(); + m_ptr = const_it.operator->(); } - // Same for assignment operator (otherwise MipsPro warns) - CC_iterator & operator= (const iterator &it) + // Assignment operator from mutable to constant iterator + template + CC_iterator & operator= (const CC_iterator< + typename std::enable_if<(!OtherConst && Const), DSC>::type, + OtherConst> &const_it) { - m_ptr.p = it.operator->(); + m_ptr = const_it.operator->(); #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(it.operator->()); + ts = Time_stamper::time_stamp(const_it.operator->()); #endif return *this; } // Construction from nullptr - CC_iterator (std::nullptr_t CGAL_assertion_code(n)) + CC_iterator (std::nullptr_t /*CGAL_assertion_code(n)*/) #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP : ts(0) #endif { - CGAL_assertion (n == nullptr); - m_ptr.p = nullptr; + //CGAL_assertion (n == nullptr); + m_ptr = nullptr; } private: - typedef typename DSC::Time_stamper_impl Time_stamper_impl; + typedef typename DSC::Time_stamper Time_stamper; #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP std::size_t ts; #endif - union { - pointer p; - void *vp; - } m_ptr; + pointer m_ptr; // Only Compact_container and Concurrent_compact_container should // access these constructors. @@ -916,16 +932,16 @@ namespace internal { : ts(0) #endif { - m_ptr.p = ptr; - if (m_ptr.p == nullptr) // empty container. + m_ptr = ptr; + if (m_ptr == nullptr) // empty container. return; - ++(m_ptr.p); // if not empty, p = start - if (DSC::type(m_ptr.p) == DSC::FREE) + ++(m_ptr); // if not empty, p = start + if (DSC::type(m_ptr) == DSC::FREE) increment(); #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP else - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -935,10 +951,10 @@ namespace internal { : ts(0) #endif { - m_ptr.p = ptr; + m_ptr = ptr; #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP if(ptr != nullptr){ - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); } #endif // end CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP } @@ -947,49 +963,49 @@ namespace internal { void increment() { // It's either pointing to end(), or valid. - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Incrementing a singular iterator or an empty container iterator ?"); - CGAL_assertion_msg(DSC::type(m_ptr.p) != DSC::START_END, + CGAL_assertion_msg(DSC::type(m_ptr) != DSC::START_END, "Incrementing end() ?"); // If it's not end(), then it's valid, we can do ++. do { - ++(m_ptr.p); - if (DSC::type(m_ptr.p) == DSC::USED || - DSC::type(m_ptr.p) == DSC::START_END) + ++(m_ptr); + if (DSC::type(m_ptr) == DSC::USED || + DSC::type(m_ptr) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif return; } - if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY) - m_ptr.p = DSC::clean_pointee(m_ptr.p); + if (DSC::type(m_ptr) == DSC::BLOCK_BOUNDARY) + m_ptr = DSC::clean_pointee(m_ptr); } while (true); } void decrement() { // It's either pointing to end(), or valid. - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Decrementing a singular iterator or an empty container iterator ?"); - CGAL_assertion_msg(DSC::type(m_ptr.p - 1) != DSC::START_END, + CGAL_assertion_msg(DSC::type(m_ptr - 1) != DSC::START_END, "Decrementing begin() ?"); // If it's not begin(), then it's valid, we can do --. do { - --m_ptr.p; - if (DSC::type(m_ptr.p) == DSC::USED || - DSC::type(m_ptr.p) == DSC::START_END) + --m_ptr; + if (DSC::type(m_ptr) == DSC::USED || + DSC::type(m_ptr) == DSC::START_END) { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - ts = Time_stamper_impl::time_stamp(m_ptr.p); + ts = Time_stamper::time_stamp(m_ptr); #endif return; } - if (DSC::type(m_ptr.p) == DSC::BLOCK_BOUNDARY) - m_ptr.p = DSC::clean_pointee(m_ptr.p); + if (DSC::type(m_ptr) == DSC::BLOCK_BOUNDARY) + m_ptr = DSC::clean_pointee(m_ptr); } while (true); } @@ -997,9 +1013,9 @@ namespace internal { Self & operator++() { - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Incrementing a singular iterator or an empty container iterator ?"); - /* CGAL_assertion_msg(DSC::type(m_ptr.p) == DSC::USED, + /* CGAL_assertion_msg(DSC::type(m_ptr) == DSC::USED, "Incrementing an invalid iterator."); */ increment(); return *this; @@ -1007,10 +1023,10 @@ namespace internal { Self & operator--() { - CGAL_assertion_msg(m_ptr.p != nullptr, + CGAL_assertion_msg(m_ptr != nullptr, "Decrementing a singular iterator or an empty container iterator ?"); - /*CGAL_assertion_msg(DSC::type(m_ptr.p) == DSC::USED - || DSC::type(m_ptr.p) == DSC::START_END, + /*CGAL_assertion_msg(DSC::type(m_ptr) == DSC::USED + || DSC::type(m_ptr) == DSC::START_END, "Decrementing an invalid iterator.");*/ decrement(); return *this; @@ -1022,13 +1038,13 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP bool is_time_stamp_valid() const { - return (ts == 0) || (ts == Time_stamper_impl::time_stamp(m_ptr.p)); + return (ts == 0) || (ts == Time_stamper::time_stamp(m_ptr)); } #endif // CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP - reference operator*() const { return *(m_ptr.p); } + reference operator*() const { return *(m_ptr); } - pointer operator->() const { return (m_ptr.p); } + pointer operator->() const { return (m_ptr); } // For std::less... bool operator<(const CC_iterator& other) const @@ -1036,7 +1052,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p); + return Time_stamper::less(m_ptr, other.m_ptr); } bool operator>(const CC_iterator& other) const @@ -1044,7 +1060,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p); + return Time_stamper::less(other.m_ptr, m_ptr); } bool operator<=(const CC_iterator& other) const @@ -1052,7 +1068,7 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(m_ptr.p, other.m_ptr.p) + return Time_stamper::less(m_ptr, other.m_ptr) || (*this == other); } @@ -1061,13 +1077,13 @@ namespace internal { #ifdef CGAL_COMPACT_CONTAINER_DEBUG_TIME_STAMP assert( is_time_stamp_valid() ); #endif - return Time_stamper_impl::less(other.m_ptr.p, m_ptr.p) + return Time_stamper::less(other.m_ptr, m_ptr) || (*this == other); } // Can itself be used for bit-squatting. - void * for_compact_container() const { return (m_ptr.vp); } - void * & for_compact_container() { return (m_ptr.vp); } + void * for_compact_container() const { return m_ptr; } + void for_compact_container(void* p) { m_ptr = static_cast(p); } }; template < class DSC, bool Const1, bool Const2 > @@ -1090,18 +1106,18 @@ namespace internal { template < class DSC, bool Const > inline bool operator==(const CC_iterator &rhs, - std::nullptr_t CGAL_assertion_code(n)) + std::nullptr_t /*CGAL_assertion_code(n)*/) { - CGAL_assertion( n == nullptr); + //CGAL_assertion( n == nullptr); return rhs.operator->() == nullptr; } template < class DSC, bool Const > inline bool operator!=(const CC_iterator &rhs, - std::nullptr_t CGAL_assertion_code(n)) + std::nullptr_t /*CGAL_assertion_code(n)*/) { - CGAL_assertion( n == nullptr); + //CGAL_assertion( n == nullptr); return rhs.operator->() != nullptr; } @@ -1119,7 +1135,7 @@ namespace handle { template struct Hash_functor; template - struct Hash_functor>{ + struct Hash_functor >{ std::size_t operator()(const CC_iterator& i) { diff --git a/STL_Extension/include/CGAL/Concurrent_compact_container.h b/STL_Extension/include/CGAL/Concurrent_compact_container.h index 5ab9eca6790..31250293142 100644 --- a/STL_Extension/include/CGAL/Concurrent_compact_container.h +++ b/STL_Extension/include/CGAL/Concurrent_compact_container.h @@ -66,7 +66,7 @@ template class has_##X { \ template < class T > struct Concurrent_compact_container_traits { static void * pointer(const T &t) { return t.for_compact_container(); } - static void * & pointer(T &t) { return t.for_compact_container(); } + static void set_pointer(T &t, void* p) { t.for_compact_container(p); } }; namespace CCC_internal { @@ -114,6 +114,8 @@ namespace CCC_internal { // Free list (head and size) template< typename pointer, typename size_type, typename CCC > class Free_list { + // Not that the implicitly-defined member functions copy the + // pointer, and not the pointed data. public: Free_list() : m_head(nullptr), m_size(0) { #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE @@ -150,13 +152,6 @@ public: #endif // CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE } bool empty() { return size() == 0; } - // Warning: copy the pointer, not the data! - Free_list& operator= (const Free_list& other) - { - m_head = other.m_head; - m_size = other.m_size; - return *this; - } void merge(Free_list &other) { @@ -210,7 +205,8 @@ class Concurrent_compact_container typedef Concurrent_compact_container_traits Traits; public: - typedef CGAL::Time_stamper_impl Time_stamper_impl; + typedef CGAL::Time_stamper_impl Time_stamper; + typedef Time_stamper Time_stamper_impl; // backward compatibility typedef T value_type; typedef Allocator allocator_type; @@ -241,7 +237,6 @@ public: explicit Concurrent_compact_container(const Allocator &a = Allocator()) : m_alloc(a) - , m_time_stamper(new Time_stamper_impl()) { init (); } @@ -250,7 +245,6 @@ public: Concurrent_compact_container(InputIterator first, InputIterator last, const Allocator & a = Allocator()) : m_alloc(a) - , m_time_stamper(new Time_stamper_impl()) { init(); std::copy(first, last, CGAL::inserter(*this)); @@ -259,13 +253,18 @@ public: // The copy constructor and assignment operator preserve the iterator order Concurrent_compact_container(const Concurrent_compact_container &c) : m_alloc(c.get_allocator()) - , m_time_stamper(new Time_stamper_impl()) { init(); m_block_size = c.m_block_size; std::copy(c.begin(), c.end(), CGAL::inserter(*this)); } + Concurrent_compact_container(Concurrent_compact_container&& c) noexcept + : m_alloc(c.get_allocator()) + { + c.swap(*this); + } + Concurrent_compact_container & operator=(const Concurrent_compact_container &c) { if (&c != this) { @@ -275,10 +274,16 @@ public: return *this; } + Concurrent_compact_container & operator=(Concurrent_compact_container&& c) noexcept + { + Self tmp(std::move(c)); + tmp.swap(*this); + return *this; + } + ~Concurrent_compact_container() { clear(); - delete m_time_stamper; } bool is_used(const_iterator ptr) const @@ -290,11 +295,8 @@ public: { std::swap(m_alloc, c.m_alloc); #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - { // non-atomic swap - size_type other_capacity = c.m_capacity; - c.m_capacity = size_type(m_capacity); - m_capacity = other_capacity; - } + // non-atomic swap of m_capacity + c.m_capacity = m_capacity.exchange(c.m_capacity.load()); #else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE std::swap(m_capacity, c.m_capacity); #endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE @@ -304,7 +306,12 @@ public: std::swap(m_last_item, c.m_last_item); std::swap(m_free_lists, c.m_free_lists); m_all_items.swap(c.m_all_items); - std::swap(m_time_stamper, c.m_time_stamper); + // non-atomic swap of m_time_stamp + c.m_time_stamp = m_time_stamp.exchange(c.m_time_stamp.load()); + } + + friend void swap(Concurrent_compact_container& a, Concurrent_compact_container& b) { + a.swap(b); } iterator begin() { return iterator(m_first_item, 0, 0); } @@ -544,7 +551,7 @@ private: { CGAL_assertion(type(ret) == USED); fl->dec_size(); - m_time_stamper->set_time_stamp(ret); + Time_stamper::set_time_stamp(ret, m_time_stamp); return iterator(ret, 0); } @@ -606,8 +613,8 @@ private: // This out of range compare is always true and causes lots of // unnecessary warnings. // CGAL_precondition(0 <= t && t < 4); - Traits::pointer(*ptr) = reinterpret_cast - (reinterpret_cast(clean_pointer((char *) p)) + (int) t); + Traits::set_pointer(*ptr, reinterpret_cast + (reinterpret_cast(clean_pointer((char *) p)) + (int) t)); } typedef tbb::queuing_mutex Mutex; @@ -619,8 +626,9 @@ private: // by walking through the block till its end. // This opens up the possibility for the compiler to optimize the clear() // function considerably when has_trivial_destructor. - typedef std::vector > All_items; + using All_items = std::vector >; + using time_stamp_t = std::atomic; void init() { @@ -636,25 +644,23 @@ private: m_first_item = nullptr; m_last_item = nullptr; m_all_items = All_items(); - m_time_stamper->reset(); + m_time_stamp = 0; } allocator_type m_alloc; #if CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - std::atomic m_capacity; + std::atomic m_capacity = {}; #else // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - size_type m_capacity; + size_type m_capacity = {}; #endif // not CGAL_CONCURRENT_COMPACT_CONTAINER_APPROXIMATE_SIZE - size_type m_block_size; + size_type m_block_size = CGAL_INIT_CONCURRENT_COMPACT_CONTAINER_BLOCK_SIZE; Free_lists m_free_lists; - pointer m_first_item; - pointer m_last_item; - All_items m_all_items; + pointer m_first_item = nullptr; + pointer m_last_item = nullptr; + All_items m_all_items = {}; mutable Mutex m_mutex; + time_stamp_t m_time_stamp = {}; - // This is a pointer, so that the definition of Compact_container does - // not require a complete type `T`. - Time_stamper_impl* m_time_stamper; }; template < class T, class Allocator > @@ -718,7 +724,7 @@ void Concurrent_compact_container::clear() size_type s = it->second; for (pointer pp = p + 1; pp != p + s - 1; ++pp) { if (type(pp) == USED) - m_alloc.destroy(pp); + std::allocator_traits::destroy(m_alloc, pp); } m_alloc.deallocate(p, s); } @@ -770,7 +776,7 @@ void Concurrent_compact_container:: for (size_type i = old_block_size; i >= 1; --i) { EraseCounterStrategy::set_erase_counter(*(new_block + i), 0); - m_time_stamper->initialize_time_stamp(new_block + i); + Time_stamper::initialize_time_stamp(new_block + i); put_on_free_list(new_block + i, fl); } } diff --git a/STL_Extension/include/CGAL/Handle.h b/STL_Extension/include/CGAL/Handle.h index ca3366524cb..0d652ccb4cb 100644 --- a/STL_Extension/include/CGAL/Handle.h +++ b/STL_Extension/include/CGAL/Handle.h @@ -40,31 +40,31 @@ class Handle typedef std::ptrdiff_t Id_type ; Handle() noexcept - : PTR{static_cast(0)} {} + : PTR(static_cast(0)) {} // FIXME: if the precondition throws in a noexcept function, the program terminates Handle(const Handle& x) noexcept { - CGAL_precondition( x.PTR.p != static_cast(0) ); - PTR.p = x.PTR.p; - CGAL_assume (PTR.p->count > 0); - PTR.p->count++; + CGAL_precondition( x.PTR != static_cast(0) ); + PTR = x.PTR; + CGAL_assume (PTR->count > 0); + PTR->count++; } ~Handle() { - if ( PTR.p && (--PTR.p->count == 0)) - delete PTR.p; + if ( PTR && (--PTR->count == 0)) + delete PTR; } Handle& operator=(const Handle& x) noexcept { - CGAL_precondition( x.PTR.p != static_cast(0) ); - x.PTR.p->count++; - if ( PTR.p && (--PTR.p->count == 0)) - delete PTR.p; - PTR.p = x.PTR.p; + CGAL_precondition( x.PTR != static_cast(0) ); + x.PTR->count++; + if ( PTR && (--PTR->count == 0)) + delete PTR; + PTR = x.PTR; return *this; } @@ -72,29 +72,25 @@ class Handle void reset() { - if (PTR.p) + if (PTR) { - if (--PTR.p->count==0) - delete PTR.p; - PTR.p=0; + if (--PTR->count==0) + delete PTR; + PTR=0; } } - int refs() const noexcept { return PTR.p->count; } + int + refs() const noexcept { return PTR->count; } - Id_type id() const noexcept { return PTR.p - static_cast(0); } + Id_type id() const noexcept { return PTR - static_cast(0); } - bool identical(const Handle& h) const noexcept { return PTR.p == h.PTR.p; } - - void* for_compact_container() const { return PTR.vp; } - void*& for_compact_container() { return PTR.vp; } + bool identical(const Handle& h) const noexcept { return PTR == h.PTR; } + void * for_compact_container() const { return PTR; } + void for_compact_container(void* p) { PTR = static_cast(p); } protected: - - union { - Rep* p; - void* vp; - } PTR; + Rep* PTR; }; //inline Handle::Id_type id(const Handle& x) { return x.id() ; } diff --git a/STL_Extension/include/CGAL/Object.h b/STL_Extension/include/CGAL/Object.h index 5a901eb3110..346afe964dd 100644 --- a/STL_Extension/include/CGAL/Object.h +++ b/STL_Extension/include/CGAL/Object.h @@ -132,10 +132,10 @@ class Object #ifndef CGAL_NO_DEPRECATED_CODE // The comparisons with nullptr are only there for Nef... - bool operator==(std::nullptr_t CGAL_assertion_code(n)) const - { CGAL_assertion(n == 0); return empty(); } - bool operator!=(std::nullptr_t CGAL_assertion_code(n)) const - { CGAL_assertion(n == 0); return !empty(); } + bool operator==(std::nullptr_t /*CGAL_assertion_code(n)*/) const + { /*CGAL_assertion(n == 0);*/ return empty(); } + bool operator!=(std::nullptr_t /*CGAL_assertion_code(n)*/) const + { /*CGAL_assertion(n == 0);*/ return !empty(); } #endif // CGAL_NO_DEPRECATED_CODE }; diff --git a/STL_Extension/include/CGAL/Time_stamper.h b/STL_Extension/include/CGAL/Time_stamper.h index 6d65ec3cfb1..f0cfe44a574 100644 --- a/STL_Extension/include/CGAL/Time_stamper.h +++ b/STL_Extension/include/CGAL/Time_stamper.h @@ -28,26 +28,12 @@ constexpr size_t rounded_down_log2(size_t n) template struct Time_stamper { - Time_stamper() - : time_stamp_() {} - - Time_stamper(const Time_stamper& ts) - : time_stamp_() - { - time_stamp_ = std::size_t(ts.time_stamp_); - } - - Time_stamper& operator=(const Time_stamper& ts) - { - time_stamp_ = std::size_t(ts.time_stamp_); - return *this; - } - static void initialize_time_stamp(T* pt) { pt->set_time_stamp(std::size_t(-1)); } - void set_time_stamp(T* pt) { + template + static void set_time_stamp(T* pt, time_stamp_t& time_stamp_) { if(pt->time_stamp() == std::size_t(-1)) { const std::size_t new_ts = time_stamp_++; pt->set_time_stamp(new_ts); @@ -96,23 +82,14 @@ struct Time_stamper return time_stamp(p_t1) < time_stamp(p_t2); } } - - void reset() { - time_stamp_ = 0; - } -private: -#ifdef CGAL_NO_ATOMIC - std::size_t time_stamp_; -#else - CGAL::cpp11::atomic time_stamp_; -#endif }; // end class template Time_stamper template struct No_time_stamp { public: - void set_time_stamp(T*) {} + template + static void set_time_stamp(T*, time_stamp_t&) {} static bool less(const T* p_t1,const T* p_t2) { return p_t1 < p_t2; } @@ -130,8 +107,6 @@ public: constexpr std::size_t shift = internal::rounded_down_log2(sizeof(T)); return reinterpret_cast(p) >> shift; } - - void reset() {} }; // end class template No_time_stamp // That class template is an auxiliary class. It has a diff --git a/STL_Extension/include/CGAL/assertions.h b/STL_Extension/include/CGAL/assertions.h index 57698d51da9..caa0237fc7d 100644 --- a/STL_Extension/include/CGAL/assertions.h +++ b/STL_Extension/include/CGAL/assertions.h @@ -54,9 +54,9 @@ namespace CGAL { // ===================== // failure functions // ----------------- -CGAL_EXPORT CGAL_NORETURN void assertion_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT CGAL_NORETURN void precondition_fail ( const char*, const char*, int, const char* = "") ; -CGAL_EXPORT CGAL_NORETURN void postcondition_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void assertion_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void precondition_fail ( const char*, const char*, int, const char* = "") ; +[[noreturn]] CGAL_EXPORT void postcondition_fail ( const char*, const char*, int, const char* = "") ; // warning function // ---------------- diff --git a/STL_Extension/include/CGAL/iterator.h b/STL_Extension/include/CGAL/iterator.h index 16733969b61..ea2b445b6f5 100644 --- a/STL_Extension/include/CGAL/iterator.h +++ b/STL_Extension/include/CGAL/iterator.h @@ -1480,8 +1480,6 @@ struct Range_iterator_type { typedef typename RangeRef::iterato template struct Range_iterator_type { typedef typename RangeRef::const_iterator type; }; - - } //namespace CGAL #include diff --git a/STL_Extension/test/STL_Extension/test_Compact_container.cpp b/STL_Extension/test/STL_Extension/test_Compact_container.cpp index 7581805f4ed..7be7166feff 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include @@ -71,7 +72,7 @@ public: bool operator< (const Node_2 &n) const { return rnd < n.rnd; } void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; template < class Cont > @@ -83,6 +84,11 @@ inline bool check_empty(const Cont &c) template < class Cont > void test(const Cont &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // Testing if all types are provided. typename Cont::value_type t0; @@ -319,22 +325,22 @@ int main() // Check the time stamper policies if(! boost::is_base_of, - C1::Time_stamper_impl>::value) + C1::Time_stamper>::value) { std::cerr << "Error timestamper of C1\n"; return 1; } if(! boost::is_base_of, - C2::Time_stamper_impl>::value) + C2::Time_stamper>::value) { std::cerr << "Error timestamper of C2\n"; return 1; } if(! boost::is_base_of, - C3::Time_stamper_impl>::value) + C3::Time_stamper>::value) { std::cerr << "Error timestamper of C3\n"; return 1; } if(! boost::is_base_of, - C4::Time_stamper_impl>::value) + C4::Time_stamper>::value) { std::cerr << "Error timestamper of C4\n"; return 1; } diff --git a/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp b/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp index aac89dc61d5..2d810602cde 100644 --- a/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp +++ b/STL_Extension/test/STL_Extension/test_Compact_container_is_used.cpp @@ -15,7 +15,7 @@ public: {} void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; int main() diff --git a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp index 2f4803c4fb2..d4fa4a1467a 100644 --- a/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp +++ b/STL_Extension/test/STL_Extension/test_Concurrent_compact_container.cpp @@ -33,7 +33,6 @@ struct Node_1 : public CGAL::Compact_container_base { Node_1() {} - Node_1(const Node_1& o) : time_stamp_(o.time_stamp_) {} bool operator==(const Node_1 &) const { return true; } bool operator!=(const Node_1 &) const { return false; } bool operator< (const Node_1 &) const { return false; } @@ -61,14 +60,14 @@ public: int rnd; Node_2() - : p(NULL), rnd(CGAL::get_default_random().get_int(0, 100)) {} + : p(nullptr), rnd(CGAL::get_default_random().get_int(0, 100)) {} bool operator==(const Node_2 &n) const { return rnd == n.rnd; } bool operator!=(const Node_2 &n) const { return rnd != n.rnd; } bool operator< (const Node_2 &n) const { return rnd < n.rnd; } void * for_compact_container() const { return p_cc; } - void * & for_compact_container() { return p_cc; } + void for_compact_container(void *p) { p_cc = p; } }; template < class Cont > @@ -89,11 +88,6 @@ public: : m_values(values), m_cont(cont), m_iterators(iterators) {} - Insert_in_CCC_functor(const Insert_in_CCC_functor &other) - : m_values(other.m_values), m_cont(other.m_cont), - m_iterators(other.m_iterators) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -118,11 +112,6 @@ public: : m_cont(cont), m_iterators(iterators) {} - Erase_in_CCC_functor(const Erase_in_CCC_functor &other) - : m_cont(other.m_cont), - m_iterators(other.m_iterators) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) @@ -149,19 +138,13 @@ public: m_free_elements(free_elements), m_num_erasures(num_erasures) {} - Insert_and_erase_in_CCC_functor(const Insert_and_erase_in_CCC_functor &other) - : m_values(other.m_values), m_cont(other.m_cont), - m_iterators(other.m_iterators), m_free_elements(other.m_free_elements), - m_num_erasures(other.m_num_erasures) - {} - void operator() (const tbb::blocked_range& r) const { for( size_t i = r.begin() ; i != r.end() ; ++i) { m_iterators[i] = m_cont.insert(m_values[i]); // Random-pick an element to erase - int index_to_erase = rand() % m_values.size(); + auto index_to_erase = rand() % m_values.size(); // If it exists bool comparand = false; if (m_free_elements[index_to_erase].compare_exchange_weak(comparand, true) ) @@ -183,6 +166,10 @@ private: template < class Cont > void test(const Cont &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); // Testing if all types are provided. typename Cont::value_type t0; diff --git a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh old mode 100644 new mode 100755 index e2911620838..dde1f1a2773 --- a/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh +++ b/Scripts/developer_scripts/Bundle_polyhedron_demo_with_appimage.sh @@ -1,8 +1,8 @@ #!/bin/bash -if [ "$1" == '--help' ]; then +if [ "$1" == '--help' -o ! -d "$1" -o ! -d "$2" ]; then echo "Usage: $0 " echo "Builds and packages the Polyhedron demo form the CGAL dir." exit 0 fi -docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro docker.io/cgal/bundle-3d-demo "/scripts/build.sh -j$3 && /scripts/deploy.sh" +docker run --rm -v "$2":/results:Z -v "$1":/cgal:ro,z -e "NUMBER_OF_DEDICATED_CORES=$3" docker.io/cgal/bundle-3d-demo diff --git a/Scripts/developer_scripts/create_new_release b/Scripts/developer_scripts/create_new_release index bbd9c5bf8b3..4a017ea4281 100755 --- a/Scripts/developer_scripts/create_new_release +++ b/Scripts/developer_scripts/create_new_release @@ -180,9 +180,13 @@ else fi # Set the major/minor/bugfix release numbers NUMBERS_DIR=${SOURCES_DIR}/Maintenance/release_building -MAJOR_NUMBER=`cat ${NUMBERS_DIR}/MAJOR_NUMBER` # 2 digits max -MINOR_NUMBER=`cat ${NUMBERS_DIR}/MINOR_NUMBER` # 2 digits max -BUGFIX_NUMBER=`cat ${NUMBERS_DIR}/BUGFIX_NUMBER` # 1 digit max +if [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then + MAJOR_NUMBER=`cat ${NUMBERS_DIR}/MAJOR_NUMBER` # 2 digits max + MINOR_NUMBER=`cat ${NUMBERS_DIR}/MINOR_NUMBER` # 2 digits max + BUGFIX_NUMBER=`cat ${NUMBERS_DIR}/BUGFIX_NUMBER` # 1 digit max +else + eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1) +fi # Do not show the bugfix number if it is 0. if [ x"$BUGFIX_NUMBER" != "x0" ]; then @@ -302,6 +306,9 @@ if [ -n "$DO_PUBLIC" ]; then else public_release_name="CGAL-${public_release_version}" fi + if ! [ -f ${NUMBERS_DIR}/MAJOR_NUMBER ]; then + eval $(cmake -DCGALCONFIGVERSIONFILE=${SOURCES_DIR}/CGALConfigVersion.cmake -P ${SOURCES_DIR}/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake 2>&1) + fi cmake -DGIT_REPO=${SOURCES_DIR} -DGENERATE_TARBALLS="ON" -DPUBLIC="ON" -DDESTINATION="${DESTINATION}" -DCGAL_VERSION="${public_release_version}" -DCGAL_VERSION_NR="${public_release_number}" -DVERBOSE="${VERBOSE}" -P ${SOURCES_DIR}/Scripts/developer_scripts/cgal_create_release_with_cmake.cmake tar -xf ${public_release_name}.tar.xz diff --git a/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake b/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake new file mode 100644 index 00000000000..4b5cfddd39c --- /dev/null +++ b/Scripts/developer_scripts/create_new_release_evaluate_versions.cmake @@ -0,0 +1,6 @@ +include(${CGALCONFIGVERSIONFILE}) +message("MAJOR_NUMBER=${CGAL_MAJOR_VERSION} +MINOR_NUMBER=${CGAL_MINOR_VERSION} +BUGFIX_NUMBER=${CGAL_BUGFIX_VERSION} +public_release_version=${CGAL_VERSION_PUBLIC_RELEASE_VERSION} +public_release_name=${CGAL_VERSION_PUBLIC_RELEASE_NAME}") diff --git a/Shape_detection/doc/Shape_detection/PackageDescription.txt b/Shape_detection/doc/Shape_detection/PackageDescription.txt index 5ace984878d..52001fe612e 100644 --- a/Shape_detection/doc/Shape_detection/PackageDescription.txt +++ b/Shape_detection/doc/Shape_detection/PackageDescription.txt @@ -59,12 +59,12 @@ Deprecated components. \cgalPkgSummaryBegin \cgalPkgAuthors{Sven Oesau, Yannick Verdie, Clément Jamin, Pierre Alliez, Florent Lafarge, Simon Giraudot, Thien Hoang, and Dmitry Anisimov} -\cgalPkgDesc{This CGAL package implements the Efficient RANSAC (RANdom SAmple Consensus) approach +\cgalPkgDesc{This package implements the Efficient RANSAC (RANdom SAmple Consensus) approach for detecting arbitrary shapes in an unorganized point set with unoriented normals and the Region Growing approach for detecting shapes in a set of arbitrary items. With the Efficient RANSAC approach, five canonical shapes can be detected: planes, spheres, cylinders, cones, and tori. Additional shapes can be detected, given a custom shape class by the user. -For the Region Growing approach, CGAL provides three particular shape detection components: +For the Region Growing approach, this package provides three particular shape detection components: detecting lines in a 2D point set, detecting planes in a 3D point set, and detecting planes on a polygon mesh.} \cgalPkgManuals{Chapter_Shape_Detection, PkgShapeDetectionRef} diff --git a/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp b/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp index 9d5880abc13..8ef9f285c0e 100644 --- a/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp +++ b/Spatial_searching/examples/Spatial_searching/distance_browsing.cpp @@ -35,7 +35,7 @@ int main() { std::cout << "The first 5 nearest neighbours with positive x-coord are: " << std::endl; for (int j=0; (j < 5)&&(it!=end); ++j,++it) - std::cout << (*it).first << " at squared distance = " << (*it).second << std::endl; + std::cout << (*it).first << " at squared distance = " << it->second << std::endl; return 0; } diff --git a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h index 785fbab2305..f3ad43ff563 100644 --- a/Spatial_searching/include/CGAL/Incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Incremental_neighbor_search.h @@ -141,7 +141,7 @@ namespace CGAL { typedef std::input_iterator_tag iterator_category; typedef Point_with_transformed_distance value_type; - typedef Point_with_transformed_distance* pointer; + typedef const Point_with_transformed_distance* pointer; typedef const Point_with_transformed_distance& reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; diff --git a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h index fbd97d783cf..9cdd46f26ef 100644 --- a/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h +++ b/Spatial_searching/include/CGAL/Orthogonal_incremental_neighbor_search.h @@ -515,7 +515,7 @@ namespace CGAL { typedef std::input_iterator_tag iterator_category; typedef Point_with_transformed_distance value_type; - typedef Point_with_transformed_distance* pointer; + typedef const Point_with_transformed_distance* pointer; typedef const Point_with_transformed_distance& reference; typedef std::size_t size_type; typedef std::ptrdiff_t difference_type; diff --git a/Spatial_sorting/include/CGAL/spatial_sort.h b/Spatial_sorting/include/CGAL/spatial_sort.h index aa38be26af8..90dd07bd966 100644 --- a/Spatial_sorting/include/CGAL/spatial_sort.h +++ b/Spatial_sorting/include/CGAL/spatial_sort.h @@ -111,7 +111,7 @@ void spatial_sort (RandomAccessIterator begin, RandomAccessIterator end, typedef std::iterator_traits ITraits; typedef typename ITraits::value_type value_type; - internal::spatial_sort(begin, end, k, policy, static_cast (0), + internal::spatial_sort(begin, end, k, policy, static_cast (nullptr), threshold_hilbert,threshold_multiscale,ratio); } diff --git a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h index 96ef666128f..ef546224112 100644 --- a/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h +++ b/Surface_mesh/include/CGAL/Surface_mesh/Surface_mesh.h @@ -1129,6 +1129,8 @@ public: } /// removes all vertices, halfedge, edges and faces. Collects garbage and clears all properties. + /// + /// After calling this method, the object is the same as a newly constructed object. The additional properties (such as normal vectors) are also removed and must thus be re-added if needed. void clear(); @@ -2838,20 +2840,33 @@ void Surface_mesh

:: clear() { - vprops_.resize(0); - hprops_.resize(0); - eprops_.resize(0); - fprops_.resize(0); + vprops_.clear(); + hprops_.clear(); + eprops_.clear(); + fprops_.clear(); - vprops_.shrink_to_fit(); - hprops_.shrink_to_fit(); - eprops_.shrink_to_fit(); - fprops_.shrink_to_fit(); + vprops_.resize(0); + hprops_.resize(0); + eprops_.resize(0); + fprops_.resize(0); - removed_vertices_ = removed_edges_ = removed_faces_ = 0; - vertices_freelist_ = edges_freelist_ = faces_freelist_ = (std::numeric_limits::max)(); - garbage_ = false; - anonymous_property_ = 0; + vprops_.shrink_to_fit(); + hprops_.shrink_to_fit(); + eprops_.shrink_to_fit(); + fprops_.shrink_to_fit(); + + vconn_ = add_property_map("v:connectivity").first; + hconn_ = add_property_map("h:connectivity").first; + fconn_ = add_property_map("f:connectivity").first; + vpoint_ = add_property_map("v:point").first; + vremoved_ = add_property_map("v:removed", false).first; + eremoved_ = add_property_map("e:removed", false).first; + fremoved_ = add_property_map("f:removed", false).first; + + removed_vertices_ = removed_edges_ = removed_faces_ = 0; + vertices_freelist_ = edges_freelist_ = faces_freelist_ = (std::numeric_limits::max)(); + garbage_ = false; + anonymous_property_ = 0; } //----------------------------------------------------------------------------- diff --git a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h index 86316179c41..6d24ecfcab3 100644 --- a/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h +++ b/Surface_mesh_shortest_path/include/CGAL/Surface_mesh_shortest_path/Surface_mesh_shortest_path.h @@ -257,12 +257,12 @@ public: return temp; } - bool operator==(const Source_point_iterator& other) + bool operator==(const Source_point_iterator& other) const { return m_iterator == other.m_iterator; } - bool operator!=(const Source_point_iterator& other) + bool operator!=(const Source_point_iterator& other) const { return m_iterator != other.m_iterator; } diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h index ada0f528d73..b37e714ee5e 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Curves_on_surface_topology.h @@ -4,7 +4,7 @@ namespace Surface_mesh_topology { /*! \ingroup PkgSurfaceMeshTopologyClasses - The class `Curves_on_surface_topology` provides methods to compute shortest non contracible cycles and to test homotopy on paths. Each object of this class is constructed from an external mesh, either a \ref CombinatorialMap "2D combinatorial map" or a model of a FaceGraph. It maintains a correspondence between this mesh and an internal representation, computed the first time an homotopy test is called. The user must not modify the input surface as long as homotopy tests are performed with this `Curves_on_surface_topology`. + The class `Curves_on_surface_topology` provides methods to compute shortest non contractible cycles and to test homotopy on paths. Each object of this class is constructed from an external mesh, either a \ref CombinatorialMap "2D combinatorial map" or a model of a FaceGraph. It maintains a correspondence between this mesh and an internal representation, computed the first time an homotopy test is called. The user must not modify the input surface as long as homotopy tests are performed with this `Curves_on_surface_topology`. \tparam Mesh a model of `CombinatorialMap` or of `FaceGraph` */ @@ -14,7 +14,7 @@ namespace Surface_mesh_topology { public: /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; @@ -53,7 +53,7 @@ namespace Surface_mesh_topology { template Path_on_surface compute_shortest_non_contractible_cycle_with_base_point(halfedge_descriptor dh, const WeightFunctor& wf=WeightFunctor()) const; - /*! returns a vector of darts representing a non-contractible curve with a minimal number of intersection with the graph of the mesh. This curve can be decribed by the alternating sequence of faces and vertices it goes through, so that each dart in the returned vector belongs to both a face and the next vertex in the alternating sequence. (Here, faces and vertices are viewed as subsets of darts.) The size of the returned vector is the face width of the mesh. + /*! returns a vector of darts representing a non-contractible curve with a minimal number of intersection with the graph of the mesh. This curve can be described by the alternating sequence of faces and vertices it goes through, so that each dart in the returned vector belongs to both a face and the next vertex in the alternating sequence. (Here, faces and vertices are viewed as subsets of darts.) The size of the returned vector is the face width of the mesh. */ std::vector compute_face_width() const; }; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h index 0a3b1f99806..bd7ead4deda 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Path_on_surface.h @@ -13,7 +13,7 @@ namespace Surface_mesh_topology { { public: /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; @@ -39,7 +39,7 @@ namespace Surface_mesh_topology { /// clears this path. void clear(); - /// returns `true` iff `hd` can be added at the end of this path. If `flip` is true, `hd`'s direction is reversed before checking + /// returns `true` iff `hd` can be added at the end of this path. If `flip` is true, the direction of `hd` is reversed before checking bool can_be_pushed(halfedge_descriptor hd, bool flip=false) const; /// adds `hd` at the end of this path. If `flip` is true, the opposite of `hd` is considered. diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h index db4bfee78f9..06fe49ab963 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/Polygonal_schema_min_items.h @@ -4,7 +4,7 @@ namespace Surface_mesh_topology { /*! \ingroup PkgSurfaceMeshTopologyClasses -The class `Polygonal_schema_min_items` defines a struct with a std::string as the information associated with darts, and no attribute is enabled. +The class `Polygonal_schema_min_items` defines a struct with a `std::string` as the information associated with darts, and no attribute is enabled. \cgalModels `PolygonalSchemaItems` diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h index 6801173ad08..e2a13b4bf5f 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/CGAL/draw_face_graph_with_paths.h @@ -4,7 +4,7 @@ namespace CGAL { \ingroup PkgDrawFaceGraphWithPaths opens a new window and draws `amesh`, either a 2D linear cell complex or a model of the FaceGraph concept, plus the paths lying on this mesh given in `apaths`. -A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires `CGAL_Qt5`, and is only available if the flag `CGAL_USE_BASIC_VIEWER` is defined at compile time. \tparam Mesh either a 2D linear cell complex or a model of the FaceGraph concept. \param amesh the mesh to draw. \param apaths the paths to draw, which should lie on `amesh`. @@ -17,7 +17,7 @@ void draw(const Mesh& amesh, \ingroup PkgDrawFaceGraphWithPaths opens a new window and draws `amesh`, either a 2D linear cell complex or a model of the FaceGraph concept, plus the paths lying on this mesh given in `apaths`. -A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires CGAL_Qt5, and is only available if the flag CGAL_USE_BASIC_VIEWER is defined at compile time. +A call to this function is blocking, that is the program continues as soon as the user closes the window. This function requires `CGAL_Qt5`, and is only available if the flag `CGAL_USE_BASIC_VIEWER` is defined at compile time. \tparam Mesh either a 2D linear cell complex or a model of the FaceGraph concept. \param amesh the mesh to draw. \param apaths the paths to draw, which should lie on `amesh`. diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h index e2ddc169269..c8ba31b3905 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchema.h @@ -48,7 +48,7 @@ public: /// returns true iff the facet containing `dh` is perforated. bool is_perforated(Dart_const_handle dh) const; - /// Shortcut for is_perforated(get_dart_labeled(s)). + /// Shortcut for `is_perforated(get_dart_labeled(s))`. bool is_perforated(const std::string & s) const; /// perforates the facet containing `dh`. Returns the number of darts of the face; 0 if the facet was already perforated. @@ -60,6 +60,6 @@ public: /// fills the facet containing `dh`. Returns the number of darts of the face; 0 if the facet was already filled. size_type fill_facet(Dart_handle dh); - /// Shortcut for fill_facet(get_dart_labeled(s)). + /// Shortcut for `fill_facet(get_dart_labeled(s))`. size_type fill_facet(const std::string & s); }; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h index ec6d956b8f1..a92d7a1af8b 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/PolygonalSchemaItems.h @@ -2,7 +2,7 @@ \ingroup PkgSurfaceMeshTopologyConcepts \cgalConcept - The concept `PolygonalSchemaItems` allows to customize a PolygonalSchema by choosing the information associated with darts, and by enabling and disabling some attributes. `%Dart_wrapper::%Dart_info`, should be a class having a public data member std::string m_label. + The concept `PolygonalSchemaItems` allows to customize a `PolygonalSchema` by choosing the information associated with darts, and by enabling and disabling some attributes. `%Dart_wrapper::%Dart_info`, should be a class having a public data member std::string m_label. \cgalRefines GenericMapItems diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h index cb2fe08f63b..291b0196170 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Concepts/WeightFunctor.h @@ -14,7 +14,7 @@ public: /// @{ /*! - %halfedge_descriptor type. A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. + A handle to `Dart` for combinatorial/generalized maps, or a halfedge descriptor for models of the `FaceGraph` concept. */ typedef unspecified_type halfedge_descriptor; diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt index 5a2e6da0e3c..45a0fcebbea 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/PackageDescription.txt @@ -21,7 +21,7 @@ \cgalPkgPicture{surface-mesh-topology-logo.png} \cgalPkgSummaryBegin \cgalPkgAuthor{Guillaume Damiand, Francis Lazarus} -\cgalPkgDesc{This package provides a toolbox for manipulating curves on a combinatorial surface from the topological viewpoint. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other.} +\cgalPkgDesc{This package provides a toolbox for manipulating curves on a combinatorial surface from the topological point of view. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other.} \cgalPkgManuals{Chapter_Surface_Mesh_Topology,PkgSurfaceMeshTopology} \cgalPkgSummaryEnd \cgalPkgShortInfoBegin diff --git a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt index 6d13664f032..b85cc68b45c 100644 --- a/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt +++ b/Surface_mesh_topology/doc/Surface_mesh_topology/Surface_mesh_topology.txt @@ -8,7 +8,7 @@ namespace CGAL { \cgalAutoToc \author Guillaume Damiand and Francis Lazarus -This package provides a toolbox for manipulating curves on a combinatorial surface from the topological viewpoint. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other. +This package provides a toolbox for manipulating curves on a combinatorial surface from the topological point of view. Two main functionalities are proposed. One is the computation of shortest curves that cannot be continuously deformed to a point. This includes the computation of the so-called edge width and face width of the vertex-edge graph of a combinatorial surface. The other functionality is the homotopy test for deciding if two given curves on a combinatorial surface can be continuously deformed one into the other. \section SMTopology Introduction @@ -25,7 +25,7 @@ A closed curve, either topological or combinatorial, that cannot be continuously - Given a surface mesh \f$\cal{M}\f$, compute a shortest non-contractible combinatorial curve without the previous vertex requirement. When all the edges have the same unit length, the length of a shortest non-contractible curve is known as the edge width of the surface, - Given a surface mesh \f$\cal{M}\f$, compute a shortest non-contractible topological curve. It can be assumed that this curve does not cross the edges of \f$\cal{M}\f$ and only passes through the vertices. It follows that the curve can be described by a circular sequence of traversed faces alternating with the vertices it passes through. The length of this curve (i.e., the number of vertices it passes through) is known as the face width of the surface. -It is important to clarify how we compare the lengths of two combinatorial curves in order to compute the shortest one. "Shortest" can be understood as "having the least amount of edges" or "having the smallest total length of its edges". In the former case, we consider that the mesh is unweighted; in the latter case, we consider that the mesh is weighted, and one must specify how the weight, or length, of each edge is calculated (see concept `WeightFunctor`). When the vertices of the mesh have Euclidean coordinates, the Eudlidean distance between two connected vertices defines a natural weight for the corresponding edge. A weight functor \link CGAL::Surface_mesh_topology::Euclidean_length_weight_functor `Euclidean_length_weight_functor`\endlink is provided for this purpose. +It is important to clarify how we compare the lengths of two combinatorial curves in order to compute the shortest one. "Shortest" can be understood as "having the least amount of edges" or "having the smallest total length of its edges". In the former case, we consider that the mesh is unweighted; in the latter case, we consider that the mesh is weighted, and one must specify how the weight, or length, of each edge is calculated (see concept `WeightFunctor`). When the vertices of the mesh have Euclidean coordinates, the Euclidean distance between two connected vertices defines a natural weight for the corresponding edge. A weight functor \link CGAL::Surface_mesh_topology::Euclidean_length_weight_functor `Euclidean_length_weight_functor`\endlink is provided for this purpose. The algorithm to find a shortest non-contractible curve through a specified vertex is based on the paper by Cabello et al. \cgalCite{cvl-ew-12}. The time complexity is linear, though in the weighted case it is raised by a logarithmic factor, assuming that the weight computation takes constant time per edge. Computing the edge width takes quadratic time by running the first function on each vertex, and its complexity is also raised by a logarithmic factor when considering a weighted map. Computing the face width consists of constructing the radial graph of the original mesh and computing the edge width of the radial graph. It thus takes quadratic time. Computing face width on weighted maps is currently not supported. diff --git a/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp index 35f13e026c0..84cd8900fe0 100644 --- a/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp +++ b/Surface_mesh_topology/examples/Surface_mesh_topology/edgewidth_lcc.cpp @@ -14,7 +14,8 @@ double cycle_length(const LCC_3& lcc, const Path_on_surface& cycle) double res=0; for (std::size_t i=0; i:: + run(mmap.get_fg(), it); + } + private: const Self & mmap; mutable typename Self::size_type msize; diff --git a/Surface_mesh_topology/include/CGAL/Path_on_surface.h b/Surface_mesh_topology/include/CGAL/Path_on_surface.h index 96a0c56a029..5eecbcb9b65 100644 --- a/Surface_mesh_topology/include/CGAL/Path_on_surface.h +++ b/Surface_mesh_topology/include/CGAL/Path_on_surface.h @@ -133,6 +133,10 @@ public: m_is_closed=false; } + /// @return true iff the prev index exists + bool prev_index_exists(std::size_t i) const + { return is_closed() || i>0; } + /// @return true iff the next index exists bool next_index_exists(std::size_t i) const { return is_closed() || i<(m_path.size()-1); } @@ -164,25 +168,25 @@ public: { return get_ith_dart(i); } /// @return the dart before the ith dart of the path, - /// nullptr if such a dart does not exist. + /// Map::null_handle if such a dart does not exist. Dart_const_handle get_prev_dart(std::size_t i) const { CGAL_assertion(i& edge_label_to_dart) { - if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) + if (dart_same_label!=CMap::null_handle && dart_opposite_label!=CMap::null_handle) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(prev_dart, res); } - if (dart_opposite_label!=nullptr) + if (dart_opposite_label!=CMap::null_handle) { cmap.template link_beta<2>(res, dart_opposite_label); } return res; @@ -111,13 +111,13 @@ namespace Surface_mesh_topology { std::unordered_map& edge_label_to_dart) { - if (dart_same_label!=nullptr && dart_opposite_label!=nullptr) + if (dart_same_label!=GMap::null_handle && dart_opposite_label!=GMap::null_handle) { std::cerr<<"Polygonal_schema ERROR: "<<"both labels "<(res, gmap.template alpha<0>(prev_dart)); } - if (dart_same_label!=nullptr) - { // Here dart_same_label!=nullptr + if (dart_same_label!=GMap::null_handle) + { // Here dart_same_label!=GMap::null_handle std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=dh2; gmap.info(dh2).m_label=s2; @@ -136,11 +136,11 @@ namespace Surface_mesh_topology { gmap.template sew<2>(res, dart_same_label); } else - { // Here either dart_opposite_label!=nullptr, or both are nullptr + { // Here either dart_opposite_label!=GMap::null_handle, or both are GMap::null_handle edge_label_to_dart[s]=res; gmap.info(res).m_label=s; - if (dart_opposite_label!=nullptr) + if (dart_opposite_label!=GMap::null_handle) { std::string s2=internal::opposite_label(s); edge_label_to_dart[s2]=res; @@ -304,7 +304,7 @@ namespace Surface_mesh_topology { std::cerr<<"Polygonal_schema ERROR: " <<"you try to end a facet" <<" but the facet is not yet started."<null_handle && prev_dart!=this->null_handle ); @@ -314,12 +314,12 @@ namespace Surface_mesh_topology { return first_dart; } - /// @return dart with the given label, nullptr if this dart does not exist. + /// @return dart with the given label, Map::null_handle if this dart does not exist. Dart_handle get_dart_labeled(const std::string& s) const { auto ite=edge_label_to_dart.find(s); if (ite==edge_label_to_dart.end()) - { return nullptr; } + { return Map::null_handle; } return ite->second; } diff --git a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h index 50980839814..fd5fbb83d0d 100644 --- a/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h +++ b/Surface_mesh_topology/include/CGAL/Surface_mesh_topology/internal/Shortest_noncontractible_cycle.h @@ -159,8 +159,8 @@ public: template Path compute_shortest_non_contractible_cycle(typename WeightFunctor::Weight_t* length, - const WeightFunctor& wf, - bool display_time=false) + const WeightFunctor& wf, + bool display_time=false) { CGAL::Timer t; if (display_time) diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h index e8b8a1abea8..550e83fb0e0 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2.h @@ -90,6 +90,7 @@ public: typedef typename Base::Traits_adaptor_2 Traits_adaptor_2; typedef typename Traits_adaptor_2::Point_2 Point_2; typedef typename Traits_adaptor_2::X_monotone_curve_2 X_monotone_curve_2; + typedef typename Traits_adaptor_2::Multiplicity Multiplicity; typedef typename Base::Event_queue_iterator Event_queue_iterator; typedef typename Event::Subcurve_iterator Event_subcurve_iterator; @@ -106,11 +107,14 @@ public: typedef CGAL::Surface_sweep_2::Equal_curve_pair Equal_curve_pair; typedef boost::unordered_set - Curve_pair_set; - - typedef std::vector Object_vector; - typedef random_access_input_iterator vector_inserter; + Curve_pair_set; + typedef std::pair Intersection_point; + typedef boost::variant + Intersection_result; + typedef std::vector Intersection_vector; + typedef random_access_input_iterator + vector_inserter; typedef typename Base::Subcurve_alloc Subcurve_alloc; protected: // Data members: @@ -121,7 +125,7 @@ protected: Curve_pair_set m_curves_pair_set; // A lookup table of pairs of Subcurves // that have been intersected. - std::vector m_x_objects; // Auxiliary vector for storing the + Intersection_vector m_x_objects; // Auxiliary vector for storing the // intersection objects. X_monotone_curve_2 sub_cv1; // Auxiliary varibales diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h index 6f6ce6dfd0a..1a50dfdcecb 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Curve_pair.h @@ -157,19 +157,19 @@ public: return (temp); } - bool operator==(const Self& other) + bool operator==(const Self& other) const { CGAL_precondition(m_container == other.m_container); return (m_index == other.m_index); } - bool operator!=(const Self& other) + bool operator!=(const Self& other) const { CGAL_precondition(m_container == other.m_container); return !(*this == other); } - unsigned int operator-(const Self& other) + unsigned int operator-(const Self& other) const { CGAL_precondition(m_container == other.m_container); return (m_index - other.m_index); diff --git a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h index 79c4930a4e2..a0d01f0329e 100644 --- a/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h +++ b/Surface_sweep_2/include/CGAL/Surface_sweep_2/Surface_sweep_2_impl.h @@ -514,9 +514,10 @@ template CGAL_SS_PRINT_CURVE(c2); CGAL_SS_PRINT_EOL(); - CGAL_assertion(event_for_overlap==NULL || event_for_overlap==this->m_currentEvent); + CGAL_assertion((event_for_overlap == nullptr) || + (event_for_overlap == this->m_currentEvent)); - typedef typename Geometry_traits_2::Multiplicity Multiplicity; + auto ctr_min = this->m_traits->construct_min_vertex_2_object();; CGAL_assertion(c1 != c2); @@ -529,12 +530,13 @@ template // handle overlapping curves with common ancesters Subcurve_vector all_leaves_diff; - Subcurve* first_parent=nullptr; - if (c1->originating_subcurve1()!=nullptr || c2->originating_subcurve2()!=nullptr) + Subcurve* first_parent = nullptr; + if ((c1->originating_subcurve1() != nullptr) || + (c2->originating_subcurve2() != nullptr)) { - // get the subcurve leaves of c1 and of c2. Then extract from the smallest set - // the subcurves leaves that are not in the other one. If empty, it means that - // a subcurves is completely contained in another one. + // get the subcurve leaves of c1 and of c2. Then extract from the smallest + // set the subcurves leaves that are not in the other one. If empty, it + // means that a subcurves is completely contained in another one. first_parent = c1; Subcurve* second_parent = c2; @@ -542,8 +544,7 @@ template Subcurve_vector all_leaves_second; first_parent->all_leaves(std::back_inserter(all_leaves_first)); second_parent->all_leaves(std::back_inserter(all_leaves_second)); - if (all_leaves_second.size() > all_leaves_first.size()) - { + if (all_leaves_second.size() > all_leaves_first.size()) { std::swap(first_parent,second_parent); std::swap(all_leaves_first,all_leaves_second); } @@ -553,105 +554,108 @@ template std::sort(all_leaves_first.begin(), all_leaves_first.end()); std::sort(all_leaves_second.begin(), all_leaves_second.end()); + // copies elements from all_leaves_second that are not in all_leaves_first std::set_difference(all_leaves_second.begin(), all_leaves_second.end(), all_leaves_first.begin(), all_leaves_first.end(), - std::back_inserter(all_leaves_diff)); // copies elements from all_leaves_second that are not in all_leaves_first + std::back_inserter(all_leaves_diff)); - if (all_leaves_second.size()==all_leaves_diff.size()) - { + if (all_leaves_second.size() == all_leaves_diff.size()) { // first_parent has no common parent with second_parent - all_leaves_diff.clear(); // clear so that it is not used by _create_overlapping_curve() + // clear so that it is not used by _create_overlapping_curve() + all_leaves_diff.clear(); } - else - if (all_leaves_diff.empty()) + else if (all_leaves_diff.empty()) { + // first_parent entirely contains second_parent + CGAL_SS_PRINT_TEXT("One overlapping curve entirely contains the other one"); + CGAL_SS_PRINT_EOL(); + + Event* left_event = (Event*) first_parent->left_event(); + Event* right_event = (Event*) first_parent->right_event(); + + if (! second_parent->is_start_point(left_event)) + left_event->add_curve_to_left(second_parent); + else + left_event->remove_curve_from_right(second_parent); + + CGAL_SS_PRINT_CURVE(c1); + CGAL_SS_PRINT_TEXT(" + "); + CGAL_SS_PRINT_CURVE(c2); + CGAL_SS_PRINT_TEXT(" => "); + CGAL_SS_PRINT_EOL(); + CGAL_SS_PRINT_TEXT(" "); + CGAL_SS_PRINT_CURVE(first_parent); + CGAL_SS_PRINT_EOL(); + + // Remove second_parent from the left curves of the right end + // and add it on the right otherwise + if (second_parent->is_end_point(right_event)) + right_event->remove_curve_from_left(second_parent); + else + _add_curve_to_right(right_event, second_parent); + + // add the overlapping curve kept of the right of the left end + right_event->add_curve_to_left(first_parent); + _add_curve_to_right(left_event, first_parent); + + this->m_visitor->found_overlap(c1, c2, first_parent); + + CGAL_SS_PRINT_END_EOL("computing intersection"); + return; + } + else { + CGAL_SS_PRINT_TEXT("Overlap with common ancestors (all_leaves_diff.size() = "); + CGAL_SS_PRINT_TEXT(std::to_string(all_leaves_diff.size()).c_str()); + CGAL_SS_PRINT_TEXT(")"); + CGAL_SS_PRINT_EOL(); + + // iteratively create the final overlapping (geometric) curve. + // This is needed rather than simply computing the intersection of + // the last curves of first_parent and second_parent as some traits + // classes (such as Arr_curve_data_traits_2) override the Intersect_2 + // functor and expects the curve to have no common ancesters + // (Arr_curve_data_traits_2 is used in the testsuite to sum up + // the overlapping degree of a curve) + CGAL_SS_PRINT_TEXT("First parent is: "); + CGAL_SS_PRINT_CURVE(first_parent); + CGAL_SS_PRINT_EOL(); + X_monotone_curve_2 xc = first_parent->last_curve(); + for (auto sc_it = all_leaves_diff.begin(); + sc_it != all_leaves_diff.end(); ++sc_it) { - // first_parent entirely contains second_parent - CGAL_SS_PRINT_TEXT("One overlapping curve entirely contains the other one"); + CGAL_SS_PRINT_TEXT("Inter with curve: "); + CGAL_SS_PRINT_CURVE((*sc_it)); CGAL_SS_PRINT_EOL(); - Event* left_event = (Event*) first_parent->left_event(); - Event* right_event = (Event*) first_parent->right_event(); - - if (!second_parent->is_start_point(left_event)) - left_event->add_curve_to_left(second_parent); - else - left_event->remove_curve_from_right(second_parent); - - CGAL_SS_PRINT_CURVE(c1); - CGAL_SS_PRINT_TEXT(" + "); - CGAL_SS_PRINT_CURVE(c2); - CGAL_SS_PRINT_TEXT(" => "); - CGAL_SS_PRINT_EOL(); - CGAL_SS_PRINT_TEXT(" "); - CGAL_SS_PRINT_CURVE(first_parent); - CGAL_SS_PRINT_EOL(); - - // Remove second_parent from the left curves of the right end - // and add it on the right otherwise - if (second_parent->is_end_point(right_event)) - right_event->remove_curve_from_left(second_parent); - else - _add_curve_to_right(right_event, second_parent); - - // add the overlapping curve kept of the right of the left end - right_event->add_curve_to_left(first_parent); - _add_curve_to_right(left_event, first_parent); - - this->m_visitor->found_overlap(c1, c2, first_parent); - - CGAL_SS_PRINT_END_EOL("computing intersection"); - return; + Intersection_vector xections; + auto intersector = this->m_traits->intersect_2_object(); + intersector(xc, (*sc_it)->last_curve(), vector_inserter(xections)); + CGAL_assertion(xections.size() == 1); + auto& item = xections.front(); + xc = *boost::get(&item); } - else{ - CGAL_SS_PRINT_TEXT("Overlap with common ancestors (all_leaves_diff.size() = "); - CGAL_SS_PRINT_TEXT(std::to_string(all_leaves_diff.size()).c_str()); - CGAL_SS_PRINT_TEXT(")"); - CGAL_SS_PRINT_EOL(); - // iteratively create the final overlapping (geometric) curve. - // This is needed rather than simply computing the intersection of - // the last curves of first_parent and second_parent as some traits - // classes (such as Arr_curve_data_traits_2) override the Intersect_2 - // functor and expects the curve to have no common ancesters - // (Arr_curve_data_traits_2 is used in the testsuite to sum up - // the overlapping degree of a curve) - CGAL_SS_PRINT_TEXT("First parent is: "); - CGAL_SS_PRINT_CURVE(first_parent); - CGAL_SS_PRINT_EOL(); - X_monotone_curve_2 xc = first_parent->last_curve(); - for (typename Subcurve_vector::iterator sc_it=all_leaves_diff.begin(); - sc_it!=all_leaves_diff.end(); ++sc_it) - { - CGAL_SS_PRINT_TEXT("Inter with curve: "); - CGAL_SS_PRINT_CURVE((*sc_it)); - CGAL_SS_PRINT_EOL(); + CGAL_assertion + (this->m_queueEventLess(ctr_min(xc), + event_for_overlap == nullptr ? + this->m_currentEvent : event_for_overlap) == + EQUAL); - std::vector inter_res; - - this->m_traits->intersect_2_object()(xc, - (*sc_it)->last_curve(), - vector_inserter(inter_res)); - CGAL_assertion(inter_res.size()==1); - CGAL_assertion( CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front())!=nullptr ); - xc = *CGAL::object_cast< X_monotone_curve_2 >(&inter_res.front()); - } - - CGAL_assertion( this->m_queueEventLess(this->m_traits->construct_min_vertex_2_object()(xc), - event_for_overlap==NULL ? this->m_currentEvent : event_for_overlap) - == EQUAL); - - _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, event_for_overlap); - CGAL_SS_PRINT_END_EOL("computing intersection (overlap with common ancestors)"); - return; - } + _create_overlapping_curve(xc, c1 , c2, all_leaves_diff, first_parent, + event_for_overlap); + CGAL_SS_PRINT_END_EOL("computing intersection (overlap with common ancestors)"); + return; + } } + auto ps_x_fnc = this->m_traits->parameter_space_in_x_2_object(); + auto ps_y_fnc = this->m_traits->parameter_space_in_y_2_object(); + // do compute the intersection of the two curves vector_inserter vi(m_x_objects) ; vector_inserter vi_end(m_x_objects); - vi_end = - this->m_traits->intersect_2_object()(c1->last_curve(), c2->last_curve(), vi); + auto intersector = this->m_traits->intersect_2_object(); + vi_end = intersector(c1->last_curve(), c2->last_curve(), vi); if (vi == vi_end) { CGAL_SS_PRINT_END_EOL("Computing intersection (no intersection)"); @@ -660,29 +664,19 @@ template // The two subCurves may start at the same point, in that case we ignore the // first intersection point. - - const Arr_parameter_space ps_x1 = - this->m_traits->parameter_space_in_x_2_object()(c1->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_y1 = - this->m_traits->parameter_space_in_y_2_object()(c1->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_x2 = - this->m_traits->parameter_space_in_x_2_object()(c2->last_curve(), - ARR_MIN_END); - const Arr_parameter_space ps_y2 = - this->m_traits->parameter_space_in_y_2_object()(c2->last_curve(), - ARR_MIN_END); + Arr_parameter_space ps_x1 = ps_x_fnc(c1->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_y1 = ps_y_fnc(c1->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_x2 = ps_x_fnc(c2->last_curve(), ARR_MIN_END); + Arr_parameter_space ps_y2 = ps_y_fnc(c2->last_curve(), ARR_MIN_END); if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) && ((ps_x1 != ARR_INTERIOR) || (ps_y1 != ARR_INTERIOR)) && this->m_traits->is_closed_2_object()(c1->last_curve(), ARR_MIN_END) && this->m_traits->is_closed_2_object()(c2->last_curve(), ARR_MIN_END)) { - if ( object_cast >(&(*vi)) != nullptr - && this->m_traits->equal_2_object() - (this->m_traits->construct_min_vertex_2_object()(c1->last_curve()), - this->m_traits->construct_min_vertex_2_object()(c2->last_curve()))) + if ((boost::get(&(*vi)) != nullptr) && + this->m_traits->equal_2_object()(ctr_min(c1->last_curve()), + ctr_min(c2->last_curve()))) { CGAL_SS_PRINT_TEXT("Skipping common left endpoint on boundary ..."); CGAL_SS_PRINT_EOL(); @@ -698,7 +692,7 @@ template vector_inserter vi_last = vi_end; --vi_last; - if (object_cast >(&(*vi_last)) != nullptr) { + if (boost::get(&(*vi_last)) != nullptr) { CGAL_SS_PRINT_TEXT("Skipping common right endpoint..."); CGAL_SS_PRINT_EOL(); --vi_end; @@ -708,18 +702,10 @@ template // In case both right curve-ends have boundary conditions and are not // open, check whether the right endpoints are the same. If they are, // skip the last intersection point. - const Arr_parameter_space ps_x1 = - this->m_traits->parameter_space_in_x_2_object()(c1->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_y1 = - this->m_traits->parameter_space_in_y_2_object()(c1->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_x2 = - this->m_traits->parameter_space_in_x_2_object()(c2->last_curve(), - ARR_MAX_END); - const Arr_parameter_space ps_y2 = - this->m_traits->parameter_space_in_y_2_object()(c2->last_curve(), - ARR_MAX_END); + Arr_parameter_space ps_x1 = ps_x_fnc(c1->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_y1 = ps_y_fnc(c1->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_x2 = ps_x_fnc(c2->last_curve(), ARR_MAX_END); + Arr_parameter_space ps_y2 = ps_y_fnc(c2->last_curve(), ARR_MAX_END); if ((ps_x1 == ps_x2) && (ps_y1 == ps_y2) && ((ps_x1 != ARR_INTERIOR) || (ps_y2 != ARR_INTERIOR)) && @@ -733,8 +719,7 @@ template vector_inserter vi_last = vi_end; --vi_last; - if (object_cast >(&(*vi_last)) != nullptr) - { + if (boost::get(&(*vi_last)) != nullptr) { CGAL_SS_PRINT_TEXT("Skipping common right endpoint on boundary..."); CGAL_SS_PRINT_EOL(); --vi_end; @@ -743,12 +728,11 @@ template } } - const std::pair* xp_point; - // Efi: why not skipping in a loop?check only one (that is, why not in a loop)? - // SL: curves are split and no event strictly before the current event should be reported + // SL: curves are split and no event strictly before the current event should + // be reported if (vi != vi_end) { - xp_point = object_cast >(&(*vi)); + const Intersection_point* xp_point = boost::get(&(*vi)); if (xp_point != nullptr) { // Skip the intersection point if it is not larger than the current // event. @@ -762,9 +746,8 @@ template bool first_i = true; for (; vi != vi_end; ++vi) { - unsigned int multiplicity = 0; - - xp_point = object_cast >(&(*vi)); + Multiplicity multiplicity = 0; + const Intersection_point* xp_point = boost::get(&(*vi)); if (xp_point != nullptr) { Point_2 xp = xp_point->first; multiplicity = xp_point->second; @@ -773,13 +756,14 @@ template _create_intersection_point(xp, multiplicity, c1, c2); } else { - X_monotone_curve_2 icv = *object_cast(&(*vi)); + const X_monotone_curve_2 icv = *boost::get(&(*vi)); // CGAL_assertion(icv != nullptr); CGAL_SS_PRINT_TEXT("Found an overlap"); CGAL_SS_PRINT_EOL(); + // event_for_overlap is only valid for the first intersection _create_overlapping_curve(icv, c1 , c2, all_leaves_diff, first_parent, - first_i ? event_for_overlap:NULL); // event_for_overlap is only valid for the first intersection + first_i ? event_for_overlap : NULL); } first_i = false; } diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h index 082daba0ec3..edb509658cd 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSFaceBase_2.h @@ -183,7 +183,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h index a677dbb722c..37f979d4717 100644 --- a/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h +++ b/TDS_2/doc/TDS_2/Concepts/TriangulationDSVertexBase_2.h @@ -118,7 +118,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void* p); /// @} diff --git a/TDS_2/include/CGAL/Triangulation_data_structure_2.h b/TDS_2/include/CGAL/Triangulation_data_structure_2.h index ed684feef47..a9d7a057439 100644 --- a/TDS_2/include/CGAL/Triangulation_data_structure_2.h +++ b/TDS_2/include/CGAL/Triangulation_data_structure_2.h @@ -105,8 +105,13 @@ protected: public: Triangulation_data_structure_2(); Triangulation_data_structure_2(const Tds &tds); + Triangulation_data_structure_2(Triangulation_data_structure_2&& tds) + noexcept(noexcept(Face_range(std::move(tds._faces))) && + noexcept(Vertex_range(std::move(tds._vertices)))); + ~Triangulation_data_structure_2(); Tds& operator= (const Tds &tds); + Tds& operator= (Tds&& tds) noexcept(noexcept(Tds(std::move(tds)))); void swap(Tds &tds); //ACCESS FUNCTIONS @@ -642,9 +647,6 @@ public: Triangulation_default_data_structure_2(const Geom_traits& = Geom_traits()) : Tds() {} - - Triangulation_default_data_structure_2(const Tdds &tdds) - : Tds(tdds) {} }; //for backward compatibility @@ -657,8 +659,6 @@ public: typedef Triangulation_data_structure_using_list_2 Tdsul; Triangulation_data_structure_using_list_2(): Tds() {} - Triangulation_data_structure_using_list_2(const Tdsul &tdsul) - : Tds(tdsul) {} }; @@ -675,6 +675,17 @@ Triangulation_data_structure_2(const Tds &tds) copy_tds(tds); } +template < class Vb, class Fb> +Triangulation_data_structure_2 :: +Triangulation_data_structure_2(Tds &&tds) + noexcept(noexcept(Face_range(std::move(tds._faces))) && + noexcept(Vertex_range(std::move(tds._vertices)))) + : _dimension(std::exchange(tds._dimension, -2)) + , _faces(std::move(tds._faces)) + , _vertices(std::move(tds._vertices)) +{ +} + template < class Vb, class Fb> Triangulation_data_structure_2 :: ~Triangulation_data_structure_2() @@ -682,7 +693,7 @@ Triangulation_data_structure_2 :: clear(); } -//assignement +//copy-assignment template < class Vb, class Fb> Triangulation_data_structure_2& Triangulation_data_structure_2 :: @@ -692,6 +703,18 @@ operator= (const Tds &tds) return *this; } +//move-assignment +template < class Vb, class Fb> +Triangulation_data_structure_2& +Triangulation_data_structure_2 :: +operator= (Tds &&tds) noexcept(noexcept(Tds(std::move(tds)))) +{ + _faces = std::move(tds._faces); + _vertices = std::move(tds._vertices); + _dimension = std::exchange(tds._dimension, -2); + return *this; +} + template < class Vb, class Fb> void Triangulation_data_structure_2:: @@ -799,7 +822,7 @@ is_edge(Vertex_handle va, Vertex_handle vb, { Face_handle fc = va->face(); Face_handle start = fc; - if (fc == 0) return false; + if (fc == nullptr) return false; int inda, indb; do { inda=fc->index(va); @@ -1032,7 +1055,9 @@ insert_dim_up(Vertex_handle w, bool orient) for ( ; lfit != faces_list.end() ; ++lfit) { f = * lfit; - g = create_face(f); //calls copy constructor of face + g = create_face(f->vertex(0),f->vertex(1),f->vertex(2), + f->neighbor(0),f->neighbor(1),f->neighbor(2)); + f->set_vertex(dim,v); g->set_vertex(dim,w); set_adjacency(f, dim, g, dim); diff --git a/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h b/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h index 6ecb08f6757..bf5aa71b9a2 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_circulators_2.h @@ -71,8 +71,8 @@ public: bool operator!=(const Face_handle &fh) const { return pos != fh; } bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Face& operator*() const @@ -152,8 +152,8 @@ public: { return pos->vertex(_ri) != vh; } bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Vertex& operator*() const @@ -231,8 +231,8 @@ public: bool operator==(const Edge_circulator &vc) const; bool operator!=(const Edge_circulator &vc) const; bool is_empty() const; - bool operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; - bool operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const; + bool operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; + bool operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const; Edge* operator->() const { edge.first=pos; @@ -338,18 +338,18 @@ return (_v == Vertex_handle() || pos == Face_handle() ); template < class Tds > inline bool Triangulation_ds_face_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle() ); } template < class Tds > inline bool Triangulation_ds_face_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return ! (*this == nullptr); } @@ -462,18 +462,18 @@ is_empty() const template < class Tds > inline bool Triangulation_ds_vertex_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle()); } template < class Tds > inline bool Triangulation_ds_vertex_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return !(*this == nullptr); } @@ -584,18 +584,18 @@ is_empty() const template < class Tds > inline bool Triangulation_ds_edge_circulator_2 :: -operator==(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator==(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return (_v == Vertex_handle() || pos == Face_handle()); } template < class Tds > inline bool Triangulation_ds_edge_circulator_2 :: -operator!=(std::nullptr_t CGAL_triangulation_assertion_code(n)) const +operator!=(std::nullptr_t /*CGAL_triangulation_assertion_code(n)*/) const { - CGAL_triangulation_assertion( n == nullptr); + //CGAL_triangulation_assertion( n == nullptr); return !(*this == nullptr); } diff --git a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h index 7fa6d99f5aa..cbe8b8e1d49 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_face_base_2.h @@ -79,7 +79,7 @@ public: // For use by Compact_container. void * for_compact_container() const {return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container();} + void for_compact_container(void* p) { N[0].for_compact_container(p);} static int ccw(int i) {return Triangulation_cw_ccw_2::ccw(i);} diff --git a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h index 1d5df47f476..ba0386f747f 100644 --- a/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h +++ b/TDS_2/include/CGAL/Triangulation_ds_vertex_base_2.h @@ -49,7 +49,7 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _f.for_compact_container(); } - void * & for_compact_container() { return _f.for_compact_container(); } + void for_compact_container(void* p) { _f.for_compact_container(p); } private: Face_handle _f; diff --git a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h index ae2e35b13d8..619b959937e 100644 --- a/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h +++ b/TDS_2/test/TDS_2/include/CGAL/_test_cls_tds_2.h @@ -44,6 +44,11 @@ template void _test_cls_tds_2( const Tds &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Tds::Vertex_range Vertex_range; typedef typename Tds::Face_range Face_range; @@ -129,6 +134,34 @@ _test_cls_tds_2( const Tds &) assert(tds3.number_of_vertices() == 4); assert(tds3.is_valid() ); + // Test move-constructors and move-assignments + { + Tds tds7 = tds3; + Tds tds8{std::move(tds7)}; + Tds tds9 = tds3; + Tds tds10; + tds10 = std::move(tds9); + Tds tds11 = Tds(tds3); // construct from a temporary + Tds tds12 = std::move(tds11); + + assert(tds7.is_valid()); + assert(tds8.is_valid()); + assert(tds9.is_valid()); + assert(tds10.is_valid()); + assert(tds11.is_valid()); + assert(tds12.is_valid()); + assert(tds7.dimension()==-2); + assert(tds8.dimension()==1); + assert(tds9.dimension()==-2); + assert(tds10.dimension()==1); + assert(tds11.dimension()==-2); + assert(tds12.dimension()==1); + tds11.~Tds(); + // check tds12 is still valid after the destruction of tds11 + assert(tds12.is_valid()); + assert(tds12.dimension()==1); + } + Vertex_handle w4 = tds4.insert_first(); Vertex_handle v4_1 = tds4.insert_second(); Vertex_handle v4_2 = tds4.insert_dim_up(w4,true); diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h index eed775ffac6..0c7108a3d67 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSCellBase_3.h @@ -136,7 +136,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h index 14c6293b902..9435ee7e9e5 100644 --- a/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h +++ b/TDS_3/doc/TDS_3/Concepts/TriangulationDSVertexBase_3.h @@ -116,7 +116,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *); /*! Inputs the non-combinatorial information given by the vertex. diff --git a/TDS_3/include/CGAL/Triangulation_data_structure_3.h b/TDS_3/include/CGAL/Triangulation_data_structure_3.h index 6e154098cb5..52200b7a795 100644 --- a/TDS_3/include/CGAL/Triangulation_data_structure_3.h +++ b/TDS_3/include/CGAL/Triangulation_data_structure_3.h @@ -231,6 +231,15 @@ public: copy_tds(tds); } + Triangulation_data_structure_3(Tds && tds) + noexcept(noexcept(Cell_range(std::move(tds._cells))) && + noexcept(Vertex_range(std::move(tds._vertices)))) + : _dimension(std::exchange(tds._dimension, -2)) + , _cells(std::move(tds._cells)) + , _vertices(std::move(tds._vertices)) + { + } + Tds & operator= (const Tds & tds) { if (&tds != this) { @@ -240,6 +249,17 @@ public: return *this; } + Tds & operator= (Tds && tds) + noexcept(noexcept(Tds(std::move(tds)))) + { + _cells = std::move(tds._cells); + _vertices = std::move(tds._vertices); + _dimension = std::exchange(tds._dimension, -2); + return *this; + } + + ~Triangulation_data_structure_3() = default; // for the rule-of-five + size_type number_of_vertices() const { return vertices().size(); } int dimension() const {return _dimension;} @@ -917,12 +937,6 @@ public: *output++ = e; return *this; } - Facet_it& operator=(const Facet_it& f) { - output = f.output; - filter = f.filter; - return *this; - } - Facet_it(const Facet_it&)=default; }; Facet_it facet_it() { return Facet_it(output, filter); @@ -1047,6 +1061,15 @@ public: } } + // Implement the rule-of-five, to please the diagnostic + // `cppcoreguidelines-special-member-functions` of clang-tidy. + // Instead of defaulting those special member functions, let's + // delete them, to prevent any misuse. + Vertex_extractor(const Vertex_extractor&) = delete; + Vertex_extractor(Vertex_extractor&&) = delete; + Vertex_extractor& operator=(const Vertex_extractor&) = delete; + Vertex_extractor& operator=(Vertex_extractor&&) = delete; + ~Vertex_extractor() { for(std::size_t i=0; i < tmp_vertices.size(); ++i){ diff --git a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h index ce2539753d2..ced30ffe6c1 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_cell_base_3.h @@ -160,10 +160,10 @@ public: void set_neighbors(Cell_handle n0, Cell_handle n1, Cell_handle n2, Cell_handle n3) { - CGAL_triangulation_precondition( this != &*n0 ); - CGAL_triangulation_precondition( this != &*n1 ); - CGAL_triangulation_precondition( this != &*n2 ); - CGAL_triangulation_precondition( this != &*n3 ); + CGAL_triangulation_precondition( this != n0.operator->() ); + CGAL_triangulation_precondition( this != n1.operator->() ); + CGAL_triangulation_precondition( this != n2.operator->() ); + CGAL_triangulation_precondition( this != n3.operator->() ); N[0] = n0; N[1] = n1; N[2] = n2; @@ -180,7 +180,7 @@ public: // For use by Compact_container. void * for_compact_container() const { return N[0].for_compact_container(); } - void * & for_compact_container() { return N[0].for_compact_container(); } + void for_compact_container(void* p) { N[0].for_compact_container(p); } // TDS internal data access functions. TDS_data& tds_data() { return _tds_data; } diff --git a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h index fc3067b6f02..3322157b797 100644 --- a/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h +++ b/TDS_3/include/CGAL/Triangulation_ds_vertex_base_3.h @@ -59,8 +59,8 @@ public: // For use by the Compact_container. void * for_compact_container() const { return _c.for_compact_container(); } - void * & for_compact_container() - { return _c.for_compact_container(); } + void for_compact_container(void* p) + { _c.for_compact_container(p); } private: Cell_handle _c; diff --git a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h index 5352d97cace..1364bf8b137 100644 --- a/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h +++ b/TDS_3/test/TDS_3/include/CGAL/_test_cls_tds_3.h @@ -26,6 +26,11 @@ template void _test_cls_tds_3( const Tds &) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Tds::Vertex_range Vertex_range; typedef typename Tds::Cell_range Cell_range; @@ -115,6 +120,34 @@ _test_cls_tds_3( const Tds &) std::cout << "ok" << std::endl; assert(tds6.is_valid()); + // Test move-constructors and move-assignments + { + Tds tds7 = tds5; + Tds tds8{std::move(tds7)}; + Tds tds9 = tds5; + Tds tds10; + tds10 = std::move(tds9); + Tds tds11 = Tds(tds5); // construct from a temporary + Tds tds12 = std::move(tds11); + + assert(tds7.is_valid()); + assert(tds8.is_valid()); + assert(tds9.is_valid()); + assert(tds10.is_valid()); + assert(tds11.is_valid()); + assert(tds12.is_valid()); + assert(tds7.dimension()==-2); + assert(tds8.dimension()==2); + assert(tds9.dimension()==-2); + assert(tds10.dimension()==2); + assert(tds11.dimension()==-2); + assert(tds12.dimension()==2); + tds11.~Tds(); + // check tds12 is still valid after the destruction of tds11 + assert(tds12.is_valid()); + assert(tds12.dimension()==2); + } + std::cout << " Insert are tested in test_triangulation_3 " << std::endl; std::cout << " Iterator and circulator are tested in test_triangulation_3 " << std::endl; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h new file mode 100644 index 00000000000..6a55d55b842 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingCellBase_3.h @@ -0,0 +1,13 @@ +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines MeshCellBase_3 + +Cell base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. + +\cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3`. + +*/ +class RemeshingCellBase_3 +{}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h new file mode 100644 index 00000000000..8f001943705 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingTriangulationTraits_3.h @@ -0,0 +1,135 @@ + +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines TriangulationTraits_3 + +The concept `RemeshingTriangulationTraits_3` is the first template parameter +of the class `Remeshing_triangulation_3`. It defines the geometric objects +(points, segments, triangles, and tetrahedra) forming the triangulation together with a few +geometric predicates and constructions on these objects. + +\cgalHasModel All models of `Kernel`. + +\sa `CGAL::Triangulation_3` +*/ + +class RemeshingTriangulationTraits_3 { +public: + +/// \name Types +/// @{ + +/*! +A constructor object model of `ConstructCrossProductVector_3` +*/ +typedef unspecified_type Construct_cross_product_vector_3; + +/*! +A constructor object model of `ConstructVector_3` +*/ +typedef unspecified_type Construct_vector_3; + +/*! +A constructor object model of `ConstructScaledVector_3 ` +*/ +typedef unspecified_type Construct_scaled_vector_3; + +/*! +A constructor object model of `ConstructSumOfVectors_3` +*/ +typedef unspecified_type Construct_sum_of_vectors_3; + +/*! +A constructor object model of `ConstructOppositeVector_3` +*/ +typedef unspecified_type Construct_opposite_vector_3; + +/*! +A constructor object model of `ComputeSquaredLength_3` +*/ +typedef unspecified_type Compute_squared_length_3; + +/*! +A constructor object model of `ConstructDividedVector_3` +*/ +typedef unspecified_type Construct_divided_vector_3; + +/*! +A constructor object model of `ConstructTranslatedPoint_3` +*/ +typedef unspecified_type Construct_translated_point_3; + +/*! +A constructor object model of `ConstructMidpoint_3` +*/ +typedef unspecified_type Construct_midpoint_3; + +/*! +A constructor obeject model of `ComputeApproximateDihedralAngle_3` +*/ +typedef unspecified_type Compute_approximate_dihedral_angle_3; + +/////*! +////A predicate object that must provide the function operator +//// +////`Comparison_result operator()(Point_3 p, Point_3 q)`, +//// +////which returns `EQUAL` if the two points are equal. Otherwise it must +////return a consistent order for any two points chosen in a same line. +////*/ +////typedef unspecified_type Compare_xyz_3; + + +/// @} + + +/// \name Operations +/// The following functions give access to the predicate and construction objects: +/// @{ + +/*! +*/ +Construct_cross_product_vector_3 construct_cross_product_vector_3_object(); + +/*! +*/ +Construct_vector_3 construct_vector_3_object(); + +/*! +*/ +Construct_scaled_vector_3 construct_scaled_vector_3_object(); + +/*! +*/ +Construct_sum_of_vectors_3 construct_sum_of_vectors_3_object(); + +/*! +*/ +Construct_opposite_vector_3 construct_opposite_vector_3_object(); + +/*! +*/ +Compute_squared_length_3 compute_squared_length_3_object(); + +/*! +*/ +Construct_divided_vector_3 construct_divided_vector_3_object(); + +/*! +*/ +Construct_translated_point_3 construct_translated_point_3_object(); + +/*! +*/ +Construct_midpoint_3 construct_midpoint_3_object(); + +/*! +*/ +Compute_approximate_dihedral_angle_3 compute_approximate_dihedral_angle_3_object(); + +/// @} + +}; /* end RemeshingTriangulationTraits_3 */ + diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h new file mode 100644 index 00000000000..fa524edef74 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Concepts/RemeshingVertexBase_3.h @@ -0,0 +1,13 @@ +/*! +\ingroup PkgTetrahedralRemeshingConcepts +\cgalConcept + +\cgalRefines MeshVertexBase_3 + +Vertex base concept to be used in the triangulation type given to the function `CGAL::tetrahedral_isotropic_remeshing()`. + +\cgalHasModel `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3`. + +*/ +class RemeshingVertexBase_3 +{}; diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in new file mode 100644 index 00000000000..a7812ca0fd3 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Doxyfile.in @@ -0,0 +1,28 @@ +@INCLUDE = ${CGAL_DOC_PACKAGE_DEFAULTS} +PROJECT_NAME = "CGAL ${CGAL_DOC_VERSION} - Tetrahedral Remeshing" + +#custom options for this package +EXTRACT_ALL = false +HIDE_UNDOC_CLASSES = true +WARN_IF_UNDOCUMENTED = false + +# macros to be used inside the code +ALIASES += "cgalNamedParamsBegin=
Named Parameters
" +ALIASES += "cgalNamedParamsEnd=
" +ALIASES += "cgalParamBegin{1}=\ref Remeshing_\1 \"\1\"" +ALIASES += "cgalParamEnd=" + +#macros for NamedParameters.txt +ALIASES += "cgalNPTableBegin=
" +ALIASES += "cgalNPTableEnd=
" +ALIASES += "cgalNPBegin{1}=\1 " +ALIASES += "cgalNPEnd=" + +EXAMPLE_PATH += ${CGAL_Tetrahedral_remeshing_EXAMPLE_DIR} + +EXCLUDE = ${CGAL_PACKAGE_INCLUDE_DIR}/CGAL/Tetrahedral_remeshing/internal + +#MACRO_EXPANSION = YES +#EXPAND_ONLY_PREDEF = YES +#EXPAND_AS_DEFINED = CGAL_PMP_NP_TEMPLATE_PARAMETERS \ +# CGAL_PMP_NP_CLASS diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt new file mode 100644 index 00000000000..953042d5f33 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/NamedParameters.txt @@ -0,0 +1,100 @@ +/*! +\defgroup Remeshing_namedparameters Named Parameters for Tetrahedral Remeshing +\ingroup PkgTetrahedralRemeshingRef + +\cgalHeading{How to use BGL Optional Named Parameters} + +The notion of named parameters was introduced in the BGL. +Details can be found from: https://www.boost.org/libs/graph/doc/bgl_named_params.html. +Named parameters enable the user to specify only those parameters which are really needed, by name, +making the parameter ordering not required. +See \ref BGLNamedParameters for more information on how to use them. + +The sequence of named parameters should start with `CGAL::parameters::`. +The function `CGAL::parameters::all_default()` can be used to indicate +that default values of optional named parameters are used. + + +\cgalHeading{List of Available Named Parameters} + +In this package, functions optional parameters are implemented as BGL optional named parameters and listed below. + +In the following, we assume that the following types are provided as template parameters of tetrahedral remeshing +functions. Note that the type may be more specific for some functions. + +
    +
  • `Triangulation` implements a `Triangulation_3` with specific vertex base and cell base.
  • +
+ +\cgalNPTableBegin + +\cgalNPBegin{number_of_iterations} +\anchor Remeshing_number_of_iterations +the number of iterations for the full sequence of atomic operations +(edge splits, edge collapses, edge flips, smoothing and projection to the initial surface) +performed to reach the input target edge length while improving the quality of dihedral angles +in the mesh.\n +\b Type : `std::size_t` \n +\b Default value is `1` +\cgalNPEnd + +\cgalNPBegin{remesh_boundaries} +\anchor Remeshing_remesh_boundaries +a Boolean that states whether the boundaries should be remeshed or +exactly preserved by the remeshing process. +Boundaries are between the exterior and the interior, +between two subdomains, between the areas selected or not for remeshing +(cf \ref Remeshing_cell_is_selected_map), +or defined by \ref Remeshing_edge_is_constrained_map +and \ref Remeshing_facet_is_constrained_map. +If `true`, they are remeshed. Otherwise, they cannot be modified at all by the remeshing process.\n +\b Type : `bool` \n +\b Default value is `true` +\cgalNPEnd + +\cgalNPBegin{edge_is_constrained_map} +\anchor Remeshing_edge_is_constrained_map +is a property map containing information about edges of the input triangulation +being marked as constrained or not.\n +Type: a class model of `ReadWritePropertyMap` with +`std::pair` as key type and +`bool` as value type. +The pairs must be ordered to ensure consistency. +During the meshing process, the set of constrained edges evolves consistently with +edge splits and collapses, so the property map must be writable. +It must be default constructible. +\n +Default: a default property map where no edge is constrained +\cgalNPEnd + +\cgalNPBegin{facet_is_constrained_map} +\anchor Remeshing_facet_is_constrained_map +is a property map containing information about facets of the input triangulation +being marked as constrained or not.\n +Type: a class model of `ReadPropertyMap` with +`Triangulation::%Facet` as key type and `bool` as value type. +It is not updated throughout the remeshing process. +It must be default constructible. +\n +Default: a default property map where no facet is constrained +\cgalNPEnd + +\cgalNPBegin{cell_is_selected_map} +\anchor Remeshing_cell_is_selected_map +is a property map containing information about cells of the input triangulation +being marked as selected or not for tetrahedral remeshing. +Only selected cells are modified (and possibly their neighbors if surfaces are +modified) by the remeshing process. Unselected cells will not be modified.\n +\b Type : a class model of `ReadWritePropertyMap` with +`Triangulation::%Cell_handle` as key type and `bool` as value type. +During the meshing process, the set of selected cells evolves consistently with +the atomic operations that are performed, +so the property map must be writable. +It must be default constructible.\n +Default: a default property map where all cells of the domain +(i.e. with a non-zero `Subdomain_index`) are selected. +\cgalNPEnd + +\cgalNPTableEnd + +*/ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt new file mode 100644 index 00000000000..b0935baf35a --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/PackageDescription.txt @@ -0,0 +1,52 @@ +// Tetrahedral Remeshing + +/// \defgroup PkgTetrahedralRemeshingRef Tetrahedral Remeshing Reference +/// \defgroup PkgTetrahedralRemeshingConcepts Concepts +/// \ingroup PkgTetrahedralRemeshingRef + +/// \defgroup PkgTetrahedralRemeshingClasses Classes +/// \ingroup PkgTetrahedralRemeshingRef + +/*! +\addtogroup PkgTetrahedralRemeshingRef + +\cgalPkgDescriptionBegin{Tetrahedral Remeshing,PkgTetrahedralRemeshing} +\cgalPkgPicture{bimba_back_small.png} + +\cgalPkgSummaryBegin +\cgalPkgAuthors{Jane Tournois, Noura Faraj} +\cgalPkgDesc{ +The package provides a function for remeshing tetrahedral meshes, +targetting high quality meshes with respect to dihedral angles.} +\cgalPkgManuals{Chapter_Tetrahedral_Remeshing,PkgTetrahedralRemeshingRef} +\cgalPkgSummaryEnd + +\cgalPkgShortInfoBegin +\cgalPkgSince{5.1} +\cgalPkgDependsOn{\ref PkgTriangulation3} +\cgalPkgBib{faraj2016mvr} +\cgalPkgLicense{\ref licensesGPL "GPL"} +\cgalPkgDemo{Polyhedron demo,polyhedron_3.zip} +\cgalPkgShortInfoEnd + +\cgalPkgDescriptionEnd + +\cgalClassifedRefPages + +\cgalCRPSection{Concepts} + +- `RemeshingTriangulationTraits_3` +- `RemeshingVertexBase_3` +- `RemeshingCellBase_3` + +\cgalCRPSection{Classes} + +- `CGAL::Tetrahedral_remeshing::Remeshing_vertex_base_3` +- `CGAL::Tetrahedral_remeshing::Remeshing_cell_base_3` +- `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` + +\cgalCRPSection{Function Templates} + +- `CGAL::tetrahedral_isotropic_remeshing()` + +*/ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt new file mode 100644 index 00000000000..bca4311f67d --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/Tetrahedral_remeshing.txt @@ -0,0 +1,101 @@ +namespace CGAL { +/*! + +\mainpage User Manual +\anchor Chapter_Tetrahedral_Remeshing +\anchor userchaptertetrahedralremeshing + +\cgalAutoToc +\authors Jane Tournois, Noura Faraj + +\image html bimba_back.png +\image latex bimba_back.png +
+ +\section secTetRemeshing Multi-Material Isotropic Tetrahedral Remeshing + +This package implements an algorithm for quality tetrahedral remeshing, +introduced by N.Faraj et al in \cgalCite{faraj2016mvr}. +This practical iterative remeshing algorithm is designed to remesh +multi-material tetrahedral meshes, by iteratively performing a sequence of +elementary operations such as edge splits, edge collapses, edge flips, +and vertex relocations following a Laplacian smoothing. +The algorithm results in high-quality uniform isotropic meshes, +with the desired mesh density, +while preserving the input geometric curve and surface features. + +Specific remeshing rules have been designed to satisfy the following criteria. +First, the algorithm preserves the geometric complex topology, including +multi-material surface patches and polyline features. Polyline features +can be defined as intersections between more than two subdomains, or listed by +the user. Second, it has been made possible to remesh only a selection of cells, +instead of remeshing the whole domain, while preserving or remeshing the +interface surfaces between the preserved and the remeshed tetrahedra. + +All the local atomic operations that are performed by the algorithm +preserve the input topology of the geometric complex. + +The tetrahedral remeshing algorithm improves the quality of dihedral angles, +while targeting the user-defined uniform sizing field and preserving the +topology of the feature complex, as highlighted by Figure \cgalFigureRef{Remesh_liver}. + +\cgalFigureBegin{Remesh_liver, tetrahedral_remeshing_before_after.png} +Tetrahedral mesh, improved by the uniform tetrahedral remeshing algorithm. +(Left) Before remeshing, dihedral angles were in the interval [0.7; 178.9]. +(Right) After remeshing and keeping the same density, +dihedral angles are the interval [12,7; 157.7]. +\cgalFigureEnd + +Experimental evidence shows that a higher number of remeshing iterations +leads to a mesh with a improved fidelity to the sizing criterion, +and higher quality dihedral angles. + +\section secTetRemeshingAPI API + +The tetrahedral remeshing algorithm is implemented as a single free function +`CGAL::tetrahedral_isotropic_remeshing()` that +takes only two required parameters: the input triangulation, and the desired edge length, +which drives the remeshing process. + +\ref BGLNamedParameters are used to deal with optional parameters. +The page \ref Remeshing_namedparameters provides a description +of their usage, and of all the available parameters for tuning +the remeshing process and results. + + +\section secTetRemeshingExamples Examples + +\subsection ssecEx1 Tetrahedral Remeshing Example + +The following example shows the simplest use of the tetrahedral remeshing function. +The only required parameter is a given target edge length that drives the remeshing process +towards a high-quality tetrahedral mesh with improved dihedral angles, and a more +uniform mesh, with edge lengths getting closer to the input parameter value. + +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp } + + +\subsection ssecEx2 Tetrahedral Remeshing of A Selection + +Optional BGL named parameters offer more precise +control on the remeshing process. In this example, a triangulation with two subdomains +(defined by indices stored in cells) is given as input, but only one +(defined by the `Subdomain_index` 2) +of its subdomains is remeshed. + +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp } + + +\subsection ssecEx3 Tetrahedral Remeshing With Polyline Features + +Optional BGL named parameters offer more precise +control on the remeshing process. In this example, a triangulation +with polyline features that should be preserved - though resampled - +during the remeshing process, is given as input. +Preserving all surfaces exactly could also be achieved by +setting the named parameter `remesh_boundaries` to `false`. + +\cgalExample{Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp } + +*/ +} /* namespace CGAL */ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies new file mode 100644 index 00000000000..30913764fab --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/dependencies @@ -0,0 +1,10 @@ +Manual +Kernel_23 +STL_Extension +Algebraic_foundations +Circulator +Stream_support +Triangulation_3 +BGL +Mesh_3 +TDS_3 diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt new file mode 100644 index 00000000000..e8c4a45bee1 --- /dev/null +++ b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/examples.txt @@ -0,0 +1,7 @@ +/*! + +\example Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp +\example Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp +\example Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp + +*/ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png new file mode 100644 index 00000000000..45ec300bc67 Binary files /dev/null and b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back.png differ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png new file mode 100644 index 00000000000..5cfbd7e3fd8 Binary files /dev/null and b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/bimba_back_small.png differ diff --git a/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png new file mode 100644 index 00000000000..de0380aaad4 Binary files /dev/null and b/Tetrahedral_remeshing/doc/Tetrahedral_remeshing/fig/tetrahedral_remeshing_before_after.png differ diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..ecc37356c72 --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,27 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +cmake_minimum_required(VERSION 3.1...3.14) + +project( Tetrahedral_remeshing_Examples ) + +# CGAL and its components +find_package( CGAL REQUIRED ) +if ( NOT CGAL_FOUND ) + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() +endif() + +# Boost and its components +find_package( Boost REQUIRED ) +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + + +# Creating entries for all C++ files with "main" routine +# ########################################################## +create_single_source_cgal_program( "tetrahedral_remeshing_example.cpp" ) +create_single_source_cgal_program( "tetrahedral_remeshing_with_features.cpp") +create_single_source_cgal_program( "tetrahedral_remeshing_of_one_subdomain.cpp") diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp new file mode 100644 index 00000000000..da292fe7d0a --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_example.cpp @@ -0,0 +1,29 @@ +#include + +#include +#include + +#include +#include "tetrahedral_remeshing_generate_input.h" + +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + + +int main(int argc, char* argv[]) +{ + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; + + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::generate_input_one_subdomain(nbv, tr); + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); + + return EXIT_SUCCESS; +} diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h new file mode 100644 index 00000000000..7f020ae5c6a --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_generate_input.h @@ -0,0 +1,191 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + template + void generate_input_two_subdomains(const std::size_t& nbv, Tr& tr) + { + CGAL::Random rng; + + typedef typename Tr::Point Point; + typedef typename Tr::Cell_handle Cell_handle; + + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const typename Tr::Geom_traits::Plane_3 + plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); + + for (Cell_handle c : tr.finite_cell_handles()) + { + if (plane.has_on_positive_side( + CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()))) + c->set_subdomain_index(1); + else + c->set_subdomain_index(2); + } + CGAL_assertion(tr.is_valid(true)); + } + + + template + void generate_input_one_subdomain(const std::size_t nbv, Tr& tr) + { + CGAL::Random rng; + + typedef typename Tr::Point Point; + std::vector pts; + while (pts.size() < nbv) + { + const double x = rng.get_double(-1., 1.); + const double y = rng.get_double(-1., 1.); + const double z = rng.get_double(-1., 1.); + + pts.push_back(Point(x, y, z)); + } + tr.insert(pts.begin(), pts.end()); + + for (typename Tr::Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + CGAL_assertion(tr.is_valid(true)); + } + + template + void add_edge(typename Tr::Vertex_handle v1, + typename Tr::Vertex_handle v2, + const Tr& tr, + boost::unordered_set >& constraints) + { + typename Tr::Cell_handle c; + int i, j; + if (tr.is_edge(v1, v2, c, i, j)) + constraints.insert(std::make_pair(v1, v2)); + } + + template + void make_constraints_from_cube_edges( + Tr& tr, + boost::unordered_set >& constraints) + { + typedef typename Tr::Point Point; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + + const Point p0(-2., -2., -2.); + const Point p1(-2., -2., -2.); + const Point p2(2., -2., -2.); + const Point p3(2., -2., 2.); + const Point p4(-2., 2., -2.); + const Point p5(-2., 2., 2.); + const Point p6(2., 2., -2.); + const Point p7(2., 2., 2.); + + typename Tr::Locate_type lt; + int li, lj; + Cell_handle c = tr.locate(p0, lt, li, lj); + Vertex_handle v0 = c->vertex(li); + c = tr.locate(p1, lt, li, lj); + Vertex_handle v1 = c->vertex(li); + + c = tr.locate(p2, lt, li, lj); + Vertex_handle v2 = c->vertex(li); + c = tr.locate(p3, lt, li, lj); + Vertex_handle v3 = c->vertex(li); + + c = tr.locate(p4, lt, li, lj); + Vertex_handle v4 = c->vertex(li); + c = tr.locate(p5, lt, li, lj); + Vertex_handle v5 = c->vertex(li); + + c = tr.locate(p6, lt, li, lj); + Vertex_handle v6 = c->vertex(li); + c = tr.locate(p7, lt, li, lj); + Vertex_handle v7 = c->vertex(li); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + } + + template + void generate_input_cube(const std::size_t& n, + Tr& tr, + boost::unordered_set >& constraints) + { + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + CGAL::Random rng; + + // points in a sphere + std::vector pts; + while (pts.size() < n) + pts.push_back(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(pts.begin(), pts.end()); + + // vertices of a larger cube + Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); + Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + + Vertex_handle v2 = tr.insert(Point(2., -2., -2.)); + Vertex_handle v3 = tr.insert(Point(2., -2., 2.)); + + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); + Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); + + Vertex_handle v6 = tr.insert(Point(2., 2., -2.)); + Vertex_handle v7 = tr.insert(Point(2., 2., 2.)); + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + + CGAL_assertion(tr.is_valid(true)); + } +} +} \ No newline at end of file diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp new file mode 100644 index 00000000000..6f108c48789 --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_of_one_subdomain.cpp @@ -0,0 +1,42 @@ +#include + +#include +#include + +#include "tetrahedral_remeshing_generate_input.h" + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + + +struct Cells_of_subdomain +{ +private: + const int m_subdomain; + +public: + Cells_of_subdomain(const int& subdomain) + : m_subdomain(subdomain) + {} + + bool operator()(Remeshing_triangulation::Cell_handle c) const + { + return m_subdomain == c->subdomain_index(); + } +}; + +int main(int argc, char* argv[]) +{ + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + const std::size_t nbv = (argc > 2) ? atoi(argv[2]) : 1000; + + Remeshing_triangulation tr; + CGAL::Tetrahedral_remeshing::generate_input_two_subdomains(nbv, tr); + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, + CGAL::parameters::cell_selector(Cells_of_subdomain(2))); + + return EXIT_SUCCESS; +} + diff --git a/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp new file mode 100644 index 00000000000..581dd0a85db --- /dev/null +++ b/Tetrahedral_remeshing/examples/Tetrahedral_remeshing/tetrahedral_remeshing_with_features.cpp @@ -0,0 +1,94 @@ +#include + +#include +#include + +#include + +#include + +#include +#include + +#include "tetrahedral_remeshing_generate_input.h" + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Vertex_handle Vertex_handle; +typedef Remeshing_triangulation::Cell_handle Cell_handle; +typedef Remeshing_triangulation::Edge Edge; + +class Constrained_edges_property_map +{ +public: + typedef bool value_type; + typedef bool reference; + typedef std::pair key_type; + typedef boost::read_write_property_map_tag category; + +private: + boost::unordered_set* m_set_ptr; + +public: + Constrained_edges_property_map() + : m_set_ptr(NULL) + {} + Constrained_edges_property_map(boost::unordered_set* set_) + : m_set_ptr(set_) + {} + +public: + friend void put(Constrained_edges_property_map& map, + const key_type& k, + const bool b) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + if (b) map.m_set_ptr->insert(k); + else map.m_set_ptr->erase(k); + } + + friend value_type get(const Constrained_edges_property_map& map, + const key_type& k) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + return (map.m_set_ptr->count(k) > 0); + } +}; + +void set_subdomain(Remeshing_triangulation& tr, const int index) +{ + for (Remeshing_triangulation::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + cit->set_subdomain_index(index); + } +} + +int main(int argc, char* argv[]) +{ + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; + const int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; + const int nbv = (argc > 3) ? atoi(argv[3]) : 500; + + Remeshing_triangulation t3; + boost::unordered_set > constraints; + + CGAL::Tetrahedral_remeshing::generate_input_cube(nbv, t3, constraints); + + make_constraints_from_cube_edges(t3, constraints); + + CGAL_assertion(t3.is_valid()); + + CGAL::tetrahedral_isotropic_remeshing(t3, target_edge_length, + CGAL::parameters::edge_is_constrained_map( + Constrained_edges_property_map(&constraints)) + .number_of_iterations(nb_iter)); + + return EXIT_SUCCESS; +} + diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h new file mode 100644 index 00000000000..e64f67c41f2 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_cell_base_3.h @@ -0,0 +1,65 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H +#define CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H + +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +struct Fake_MD_C +{ + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; +}; +} + +/*! +\ingroup PkgTetrahedralRemeshingClasses + +The class `Remeshing_cell_base_3` is a model of the concept `MeshCellBase_3`. +It is designed to serve as cell base class for the 3D triangulation +used in the tetrahedral remeshing process. + +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. + +\tparam Cb is a cell base class from which `Remeshing_cell_base_3` derives. +It must be a model of the `TriangulationCellBase_3` concept. +It has the default value `Triangulation_cell_base_3`. + +\cgalModels `MeshCellBase_3` + +*/ +#ifndef DOXYGEN_RUNNING +template > +using Remeshing_cell_base_3 + = CGAL::Mesh_cell_base_3; +#else +template > +class Remeshing_cell_base_3; +#endif + +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif //CGAL_TET_ADAPTIVE_REMESHING_CELL_BASE_3_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h new file mode 100644 index 00000000000..1a25ab1aace --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_triangulation_3.h @@ -0,0 +1,77 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H +#define CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H + +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +/*! +\ingroup PkgTetrahedralRemeshingClasses + +The class `Remeshing_triangulation_3` +is a class template which provides a valid triangulation type +that can be used as the 3D triangulation input for +the tetrahedral remeshing process. + +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. + +\tparam Concurrency_tag enables sequential versus parallel implementation of the +triangulation data structure. +Possible values are `Sequential_tag` (the default), `Parallel_tag`, +and `Parallel_if_available_tag`. + +\tparam Vb is a model of `RemeshingVertexBase_3`. It has the default value ` Remeshing_vertex_base_3`. +\tparam Cb is a model of `RemeshingCellBase_3`. It has the default value ` Remeshing_cell_base_3`. + +*/ +template, + typename Cb = Remeshing_cell_base_3 +> +class Remeshing_triangulation_3 + : public CGAL::Triangulation_3 > +{ +public: + typedef Vb Remeshing_Vb; + typedef Cb Remeshing_Cb; + + typedef CGAL::Triangulation_data_structure_3< + Remeshing_Vb, Remeshing_Cb, Concurrency_tag> Tds; + typedef CGAL::Triangulation_3 Base; + + using Base::Base; +}; + +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif // CGAL_TETRAHEDRAL_REMESHING_TRIANGULATION_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h new file mode 100644 index 00000000000..2d056e8e244 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Remeshing_vertex_base_3.h @@ -0,0 +1,67 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H +#define CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H + +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ + +struct Fake_MD_V +{ + typedef int Subdomain_index; + typedef int Surface_patch_index; + typedef int Index; +}; + +} // internal + +/*! +\ingroup PkgTetrahedralRemeshingClasses + +The class `Remeshing_vertex_base_3` is a model of the concept `MeshVertexBase_3`. +It is designed to serve as vertex base class for the 3D triangulation +used in the tetrahedral remeshing process. + +\tparam Gt is the geometric traits class. +It has to be a model of the concept `RemeshingTriangulationTraits_3`. + +\tparam Vb is a vertex base class from which `Remeshing_vertex_base_3` derives. +It must be a model of the `TriangulationVertexBase_3` concept. +It has the default value `Triangulation_vertex_base_3`. + +\cgalModels `MeshVertexBase_3` +*/ +#ifndef DOXYGEN_RUNNING +template > +using Remeshing_vertex_base_3 + = CGAL::Mesh_vertex_base_3; +#else +template > +class Remeshing_vertex_base_3; +#endif + +}//end namespace Tetrahedral_remeshing + +}//end namespace CGAL + +#endif //CGAL_TET_ADAPTIVE_REMESHING_VERTEX_BASE_3_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h new file mode 100644 index 00000000000..53448be56a8 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Sizing_field.h @@ -0,0 +1,37 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_SIZING_FIELD_H +#define CGAL_SIZING_FIELD_H + +#include + +namespace CGAL +{ +/*! +* Sizing field virtual class +*/ +template +class Sizing_field +{ +public: + typedef Kernel K; + typedef typename Kernel::FT FT; + typedef typename Kernel::Point_3 Point_3; + +public: + virtual FT operator()(const Point_3& p) const = 0; +}; + +}//end namespace CGAL + +#endif //CGAL_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h new file mode 100644 index 00000000000..59c7264f502 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/Uniform_sizing_field.h @@ -0,0 +1,45 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_UNIFORM_SIZING_FIELD_H +#define CGAL_UNIFORM_SIZING_FIELD_H + +#include + +#include + +namespace CGAL +{ +template +class Uniform_sizing_field : Sizing_field +{ +private: + typedef Sizing_field Base; +public: + typedef typename Base::FT FT; + typedef typename Base::Point_3 Point_3; + + Uniform_sizing_field(const FT& size) + : m_size(size) + {} + + FT operator()(const Point_3&) const + { + return m_size; + } +private: + FT m_size; +}; + +}//end namespace CGAL + +#endif //CGAL_UNIFORM_SIZING_FIELD_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h new file mode 100644 index 00000000000..07f6e3e3286 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/FMLS.h @@ -0,0 +1,815 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_TETRAHEDRAL_REMESHING_FMLS_H +#define CGAL_TETRAHEDRAL_REMESHING_FMLS_H + +#include + +// ------------------------------------------- +// FMLS +// A Fast Moving Least Square operator for 3D +// points sets. +// ------------------------------------------- + +#include +#include +#include + +#include +#include +#include + +#include + +#include + + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +// -------------------------------------------------------------- +// MLS Projection +// -------------------------------------------------------------- + +inline double wendland(double x, double h) +{ + x = CGAL::abs(x); + if (x < h) + return CGAL::square(CGAL::square(1 - x / h)) * (4 * x / h + 1); + else + return 0.0; +} + +//inline void setPNSample(std::vector& p, +// const std::size_t& i, +// const float x, const float y, const float z, +// const float nx, const float ny, const float nz) +//{ +// p[6 * i] = x; +// p[6 * i + 1] = y; +// p[6 * i + 2] = z; +// p[6 * i + 3] = nx; +// p[6 * i + 4] = ny; +// p[6 * i + 5] = nz; +//} + +template +inline CGAL::Vector_3 projectOn(const CGAL::Vector_3& x, + const CGAL::Vector_3& N, + const CGAL::Vector_3& P) +{ + typename Gt::Compute_scalar_product_3 scalar_product + = Gt().compute_scalar_product_3_object(); + + typename Gt::FT w = scalar_product((x - P), N); + return x - (N * w); +} + +template +inline typename Gt::FT length(const CGAL::Vector_3& v) +{ + return CGAL::approximate_sqrt(v.squared_length()); +} + +template +inline typename Gt::FT distance(const CGAL::Vector_3& v1, + const CGAL::Vector_3& v2) +{ + CGAL::Vector_3 diff(v1.x() - v2.x(), + v1.y() - v2.y(), + v1.z() - v2.z()); + return length(diff); +} + +template +inline void weightedPointCombination(const CGAL::Vector_3& x, + const CGAL::Vector_3& pi, + const CGAL::Vector_3& ni, + double sigma_s, bool bilateral, double sigma_r, + bool hermite, + CGAL::Vector_3& c, CGAL::Vector_3& nc, double& sumW) +{ + double w = wendland(distance(x, pi), sigma_s); + if (bilateral) + w *= wendland(length(x - projectOn(x, ni, pi)), sigma_r); + if (hermite) + c += w * projectOn(x, ni, pi); + else + c += w * pi; + nc += w * ni; + sumW += w; +} + +template +class FMLS +{ + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::FT FT; + +public: + // FMLS provide MLS projection and filtering from a point set. + // The underlying data structure is a simple list of float in the PN format + // A PN object is a list of 6xfloat32 chunk : + // x0,y0,z0,nx0,ny0,nz0,x1,y1,z1,nx1,ny1,nz1,... + // with {xi,yi,zi} the position and {nxi,nyi,nzi} the normal vector of the + // i-th point sample. A PN can be read from and write to file directly + // (identity serialization) and is handled as a simple float32 pointer. + // + // Use the 'fast*' methods. Brute force methods are inserted only for comparison. + // + // Memory policy: a FMLS class manages itself al its belonging objects. + // Therefore, PN and filtered PN lists are the property of this class, and should + // be copied if modified outside the class. + FMLS() + { + PNSize = 0; + PNScale = 1.0f; + MLSRadius = 0.1f; + bilateralRange = 0.05f; + bilateral = false; + hermite = false; + numIter = 1; + } + + // -------------------------------------------------------------- + // Main Interface + // -------------------------------------------------------------- + +// std::vector createPN(std::size_t size) +// { +// return std::vector(size * SURFEL_SIZE); +// } + + void setPN(const std::vector& newPN, + const std::size_t newPNSize, + const double& pointSpacing) + { + freeCPUMemory(); + PN = newPN; + PNSize = newPNSize; + computePNScale(); + MLSRadius = 3 * pointSpacing / PNScale; + grid.clear(); + grid.init(PN, PNSize, MLSRadius * PNScale); + } + + // Compute, according to the current point sampling stored in FMLS, the MLS projection + // of p and store the resulting position in q and normal in n. + void fastProjectionCPU(const Vector_3& p, Vector_3& q, Vector_3& n) const + { + double sigma_s = PNScale * MLSRadius; + double sigma_r = bilateralRange; + + const Vector_3 g = (p - Vector_3(grid.getMinMax()[0], grid.getMinMax()[1], grid.getMinMax()[2])) / sigma_s; + + std::array gxyz; + for (int j = 0; j < 3; ++j) + { + if (g[j] < 0.) + gxyz[j] = 0; + if (g[j] >= grid.getRes()[j]) + gxyz[j] = grid.getRes()[j] - 1; + else + gxyz[j] = static_cast(std::floor(g[j])); + } + + std::array minIt; + std::array maxIt; + for (std::size_t j = 0; j < 3; ++j) + { + if (gxyz[j] == 0) + minIt[j] = 0; + else + minIt[j] = gxyz[j] - 1; + if (gxyz[j] == grid.getRes()[j] - 1) + maxIt[j] = (grid.getRes()[j] - 1); + else + maxIt[j] = gxyz[j] + 1; + } + Vector_3 c = CGAL::NULL_VECTOR; + double sumW = 0.f; + std::array it; + for (it[0] = minIt[0]; it[0] <= maxIt[0]; it[0]++) + for (it[1] = minIt[1]; it[1] <= maxIt[1]; it[1]++) + for (it[2] = minIt[2]; it[2] <= maxIt[2]; it[2]++) { + std::size_t gridIndex = grid.getLUTElement(it[0], it[1], it[2]); + if (gridIndex == 2 * PNSize) + continue; + std::size_t neigh = grid.getCellIndicesSize(it[0], it[1], it[2]); + for (std::size_t j = 0; j < neigh; j++) { + std::size_t k = grid.getIndicesElement(it[0], it[1], it[2], j); + Vector_3 pk(PN[6 * k], PN[6 * k + 1], PN[6 * k + 2]); + Vector_3 nk(PN[6 * k + 3], PN[6 * k + 4], PN[6 * k + 5]); + weightedPointCombination(p, pk, nk, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); + } + } + if (sumW == 0.f) { + n = Vector_3(1.f, 0.f, 0.f); + q = p; + } + else { + c /= sumW; + normalize(n, Gt()); + q = projectOn(p, n, c); + } + } + +// // Compute the MLS projection of the list of point stored in pv and store the resulting +// // positions and normal in qv. qv must be preallocated to stroe 6*pvSize float32. +// // The strid indicates the offsets in qv (the defautl value of 3 means that the qv +// // is compact: pv={x0,y0,z0,x1,y1,z1...}. If pv contains also normals for instance, +// // the stride should be set to 6. +// void fastProjectionCPU(const std::vector& pv, +// const std::size_t pvSize, +// std::vector& qv, +// std::size_t stride = 3) const +// { +// for (std::size_t i = 0; i < pvSize; i++) +// { +// Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); +// Vector_3 q, n; +// for (unsigned int j = 0; j < numIter; j++) +// { +// q = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// fastProjectionCPU(p, q, n); +// p = q; +// } +// setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); +// } +// } + +// // Brute force version. O(PNSize) complexity. For comparison only. +// void projectionCPU(const Vector_3& x, Vector_3& q, Vector_3& n) +// { +// float sigma_s = MLSRadius * PNScale; +// float sigma_r = bilateralRange; +// Vector_3 p(x); +// for (unsigned int k = 0; k < numIter; k++) { +// Vector_3 c = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// float sumW = 0.f; +// for (unsigned int j = 0; j < PNSize; j++) { +// Vector_3 pj(PN[6 * j], PN[6 * j + 1], PN[6 * j + 2]); +// Vector_3 nj(PN[6 * j + 3], PN[6 * j + 4], PN[6 * j + 5]); +// weightedPointCombination(p, pj, nj, sigma_s, bilateral, sigma_r, hermite, c, n, sumW); +// } +// c /= sumW; +// n.normalize(); +// q = projectOn(p, n, c); +// p = q; +// } +// } +// +// // Brute force version. O(pvSize*PNSize) complexity. For comparison only. +// void projectionCPU(const std::vector& pv, +// unsigned int pvSize, +// std::vector& qv, +// unsigned int stride = 3) +// { +// for (int i = 0; i < int(pvSize); i++) { +// Vector_3 p(pv[stride * i], pv[stride * i + 1], pv[stride * i + 2]); +// Vector_3 q, n; +// for (unsigned int j = 0; j < numIter; j++) { +// q = CGAL::NULL_VECTOR; +// n = CGAL::NULL_VECTOR; +// projectionCPU(p, q, n); +// p = q; +// } +// setPNSample(qv, i, q[0], q[1], q[2], n[0], n[1], n[2]); +// } +// } + + // -------------------------------------------------------------- + // Accessors + // -------------------------------------------------------------- + + // Number of elements of the PN. One elemnt is a 6-float32 chunk. + inline std::size_t getPNSize() const { return PNSize; } + inline std::vector& getPN() { return PN; } + inline const std::vector& getPN() const { return PN; } + + // Min/Max corners of PN's bounding volume + inline const double* getMinMax() const { return grid.getMinMax(); } + // Radius of the bounding sphere of the PN + inline double getPNScale() const { return PNScale; } + // Normalized MLS support size + inline double getMLSRadius() const { return MLSRadius; } + inline void setMLSRadius(double s) { MLSRadius = s; grid.clear(); grid.init(PN, PNSize, MLSRadius * PNScale); } + // Bilateral weighting for feature preservation (inspired by [Jones 2003]). + inline bool isBilateral() const { return bilateral; } + inline void toggleBilateral(bool b) { bilateral = b; } + // Bilateral support size for the range weight + inline double getBilateralRange() const { return bilateralRange; } + inline void setBilateralRange(double r) { bilateralRange = r; } + // Hermite interpolation [Alexa 2009] + inline bool isHermite() const { return hermite; } + inline void toggleHermite(bool b) { hermite = b; } + // Fix number of iterations of the MLS projection + inline unsigned int getNumOfIter() const { return numIter; } + inline void setNumOfIter(unsigned int i) { numIter = i; } + + // -------------------------------------------------------------- + // Misc. + // -------------------------------------------------------------- + + // Size of a point sample in bytes (6xfloat32: 3 for position and normal + static const unsigned int SURFEL_SIZE = 24; + +private: + + void computePNScale() + { + Vector_3 c = CGAL::NULL_VECTOR; + for (std::size_t i = 0; i < PNSize; i++) + c += Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + c /= (double)PNSize; + PNScale = 0.; + for (std::size_t i = 0; i < PNSize; i++) { + double r = distance(c, Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (r > PNScale) + PNScale = r; + } + } + + // -------------------------------------------------------------- + // 3D Grid Structure + // -------------------------------------------------------------- + // -------------------------------------------------------------- + // Grid data structure for fast r-ball neighborhood query + // -------------------------------------------------------------- + + class Grid + { + public: + Grid() + : minMax() + , cellSize(1.f) + , res() + , LUT() + , indices() + {} + ~Grid() + { + clear(); + } + + void init(const std::vector& PN, std::size_t PNSize, double sigma_s) + { + cellSize = sigma_s; + for (std::size_t i = 0; i < 3; i++) { + minMax[i] = PN[i]; + minMax[3 + i] = PN[i]; + } + for (std::size_t i = 0; i < PNSize; i++) + for (std::size_t j = 0; j < 3; j++) { + if (PN[6 * i + j] < minMax[j]) + minMax[j] = PN[6 * i + j]; + if (PN[6 * i + j] > minMax[3 + j]) + minMax[3 + j] = PN[6 * i + j]; + } + for (std::size_t i = 0; i < 3; i++) { + minMax[i] -= 0.001f; + minMax[3 + i] += 0.001f; + } + for (std::size_t i = 0; i < 3; i++) + res[i] = (std::size_t)ceil((minMax[3 + i] - minMax[i]) / cellSize); + std::size_t LUTSize = res[0] * res[1] * res[2]; + LUT.resize(LUTSize); + LUT.assign(LUTSize, 0); + + std::size_t nonEmptyCells = 0; + Vector_3 gMin(minMax[0], minMax[1], minMax[2]); + Vector_3 gMax(minMax[3], minMax[4], minMax[5]); + for (std::size_t i = 0; i < PNSize; i++) { + std::size_t index = getLUTIndex(Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2])); + if (LUT[index] == 0) + nonEmptyCells++; + LUT[index]++; + } + std::size_t indicesSize = PNSize + nonEmptyCells; + indices.reserve(indicesSize); + indices.assign(indicesSize, 0); + + std::size_t cpt = 0; + for (std::size_t i = 0; i < res[0]; i++) + for (std::size_t j = 0; j < res[1]; j++) + for (std::size_t k = 0; k < res[2]; k++) { + std::size_t index = getLUTIndex(i, j, k); + if (LUT[index] != 0) { + indices[cpt] = LUT[index]; + LUT[index] = cpt; + cpt += indices[cpt] + 1; + indices[cpt - 1] = 0; // local iterator for subsequent filling + } + else + LUT[index] = 2 * PNSize; + } + for (std::size_t i = 0; i < PNSize; i++) { + Vector_3 p = Vector_3(PN[6 * i], PN[6 * i + 1], PN[6 * i + 2]); + std::size_t indicesIndex = getLUTElement(p); + std::size_t totalCount = indices[indicesIndex]; + std::size_t countIndex = indicesIndex + totalCount; + std::size_t currentCount = indices[countIndex]; + if (currentCount < indices[indicesIndex]) + indices[countIndex]++; + std::size_t pIndex = indicesIndex + 1 + currentCount; + indices[pIndex] = i; + } + } + + void clear() + { + cellSize = 1.f; + } + + // Accessors + + inline const std::array getMinMax() const { return minMax; } + inline const std::array getRes() const { return res; } + inline double getCellSize() const { return cellSize; } + inline std::vector& getLUT() { return LUT; } + inline const std::vector& getLUT() const { return LUT; } + inline std::size_t getLUTIndex(const std::size_t i, + const std::size_t j, + const std::size_t k) const + { + return k * res[0] * res[1] + j * res[0] + i; + } + inline std::size_t getLUTElement(const std::size_t i, + const std::size_t j, + const std::size_t k) const + { + return LUT[getLUTIndex(i, j, k)]; + } + std::size_t getLUTIndex(const Vector_3& x) const + { + const Vector_3 vp = (x - Vector_3(minMax[0], minMax[1], minMax[2])) / cellSize; + std::array p; + for (int j = 0; j < 3; j++) + { + if (vp[j] < 0) + p[j] = 0; + if (vp[j] >= res[j]) + p[j] = res[j] - 1; + else + p[j] = static_cast(std::floor(vp[j])); + } + std::size_t index = p[2] * res[0] * res[1] + + p[1] * res[0] + + p[0]; + return index; + } + inline std::size_t getLUTElement(const Vector_3& x) const { + return LUT[getLUTIndex(x)]; + } + inline std::vector& getIndices() { return indices; } + inline const std::vector& getIndices() const { return indices; } + inline std::size_t getCellIndicesSize(std::size_t i, + std::size_t j, + std::size_t k) const { + return indices[getLUTElement(i, j, k)]; + } + inline std::size_t getIndicesElement(std::size_t i, + std::size_t j, + std::size_t k, + std::size_t e) const { + return indices[getLUTElement(i, j, k) + 1 + e]; + } + + private: + std::array minMax; + double cellSize; + std::array res; + std::vector LUT; // 3D Index Look-Up Table + std::vector indices; // 3D Grid data + }; + + + // -------------------------------------------------------------- + // Memory Managment + // -------------------------------------------------------------- + + void freeCPUMemory() + { + PN.clear(); + PNSize = 0; + } + + // -------------------------------------------------------------- + // CPU Data + // -------------------------------------------------------------- + + std::vector PN; + std::size_t PNSize; + double PNScale; // size of the bounding sphere radius + double MLSRadius; + double bilateralRange; + bool bilateral; + bool hermite; + unsigned int numIter; + Grid grid; +}; + +template +void createMLSSurfaces(Subdomain__FMLS& subdomain_FMLS, + Subdomain__FMLS_indices& subdomain_FMLS_indices, + const VerticesNormalsMap& vertices_normals, + const VerticesSurfaceIndices& vertices_surface_indices, + const C3t3& c3t3, + const int upsample = 2) // can be 0, 1 or 2 +{ + typedef typename C3t3::Surface_patch_index Surface_index; + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Edge Edge; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Point_3 Point_3; + typedef typename Gt::Vector_3 Vector_3; + + typedef typename VerticesSurfaceIndices::mapped_type VertexSurfaces; + typedef typename VerticesSurfaceIndices::const_iterator VerticesSurfaceIterator; + + const Tr& tr = c3t3.triangulation(); + + //createAreaWeightedUpSampledMLSSurfaces(0); + //return ; + subdomain_FMLS.clear(); + subdomain_FMLS_indices.clear(); + + typedef boost::unordered_map SurfaceIndexMap; + + SurfaceIndexMap current_subdomain_FMLS_indices; + SurfaceIndexMap subdomain_sample_numbers; + + //Count the number of vertices for each boundary surface (i.e. one per label) + for (const Vertex_handle vit : tr.finite_vertex_handles()) + { + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for(const Surface_index& si : v_surface_indices) + { + subdomain_sample_numbers[si]++; + } + } + + if (upsample > 0) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Up sampling MLS " << upsample << std::endl; +#endif + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + if (upsample == 1) + subdomain_sample_numbers[surf_i] ++; + else if (upsample == 2) + subdomain_sample_numbers[surf_i] += 4; + } + } + + std::vector< std::vector > pns; + + std::size_t count = 0; + //Memory allocation for the point plus normals of the point samples + for (typename SurfaceIndexMap::iterator it = subdomain_sample_numbers.begin(); + it != subdomain_sample_numbers.end(); ++it) + { + current_subdomain_FMLS_indices[it->first] = count; + pns.push_back(std::vector(it->second * 6, 0.)); + count++; + } + + std::vector current_v_count(count, 0); + std::vector point_spacing(count, 0.); + std::vector point_spacing_count(count, 0); + + //Allocation of the PN + for (Vertex_handle vit : tr.finite_vertex_handles()) + { + VerticesSurfaceIterator sit = vertices_surface_indices.find(vit); + if (sit == vertices_surface_indices.end()) + continue; + + const VertexSurfaces& v_surface_indices = vertices_surface_indices.at(vit); + CGAL_assertion(vit->in_dimension() <= 2); + + for (const Surface_index& surf_i : v_surface_indices) + { + const std::size_t& fmls_id = current_subdomain_FMLS_indices[surf_i]; + + const Point_3& p = point(vit->point()); + + pns[fmls_id][6 * current_v_count[fmls_id]] = p.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = p.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = p.z(); + + const Vector_3& normal = vertices_normals.at(vit).at(surf_i); + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + + typedef std::pair Edge_vv; + if (upsample == 0) + { + std::unordered_set > edgeMap; + + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + for (int i = 0; i < 2; i++) + { + for (int j = i + 1; j < 3; j++) + { + Edge edge(fit->first, indices(fit->second,i), indices(fit->second,j)); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + Edge_vv e = make_vertex_pair(vh0, vh1); + if ( vertices_surface_indices.find(vh0) != vertices_surface_indices.end() + && vertices_surface_indices.find(vh1) != vertices_surface_indices.end() + && edgeMap.find(e) == edgeMap.end()) + { + edgeMap.insert(e); + + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + const std::size_t fmls_id = current_subdomain_FMLS_indices[surf_i]; + + point_spacing[fmls_id] += CGAL::approximate_sqrt( + CGAL::squared_distance(point(vh0->point()), point(vh1->point()))); + point_spacing_count[fmls_id] ++; + } + } + } + } + } + + if (upsample > 0) + { + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + const Surface_index surf_i = c3t3.surface_patch_index(*fit); + + const std::size_t fmls_id = current_subdomain_FMLS_indices[surf_i]; + + Vertex_handle vhs[3] = { fit->first->vertex(indices(fit->second, 0)), + fit->first->vertex(indices(fit->second, 1)), + fit->first->vertex(indices(fit->second, 2)) }; + Vector_3 points[3] = { Vector_3(CGAL::ORIGIN, point(vhs[0]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[1]->point())), + Vector_3(CGAL::ORIGIN, point(vhs[2]->point())) }; + Vector_3 normals[3] = { vertices_normals.at(vhs[0]).at(surf_i), + vertices_normals.at(vhs[1]).at(surf_i), + vertices_normals.at(vhs[2]).at(surf_i) }; + + std::vector points_to_add; + std::vector n_points_to_add; + + //Add the barycenter of the facet + Vector_3 barycenter = (points[0] + points[1] + points[2]) / 3.; + Vector_3 n_barycenter = (normals[0] + normals[1] + normals[2]); + + n_barycenter = n_barycenter / CGAL::approximate_sqrt((n_barycenter * n_barycenter)); + + points_to_add.push_back(barycenter); + n_points_to_add.push_back(n_barycenter); + + if (upsample == 1) + { + for (int i = 0; i < 3; i++) + { + Vector_3 space_1 = barycenter - points[i]; + + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_1 * space_1); + point_spacing_count[fmls_id] ++; + } + } + else if (upsample == 2) + { + for (int i = 0; i < 3; i++) + { + int i1 = (i + 1) % 3; + int i2 = (i + 2) % 3; + + Vector_3 p = (barycenter + points[i1] + points[i2]) / 3.; + Vector_3 n = (n_barycenter + normals[i1] + normals[i2]); + + n = n / CGAL::sqrt(n * n); + + points_to_add.push_back(p); + n_points_to_add.push_back(n); + + Vector_3 space_1 = p - barycenter; + Vector_3 space_2 = p - points[i1]; + Vector_3 space_3 = p - points[i2]; + + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_1 * space_1); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_2 * space_2); + point_spacing[fmls_id] += CGAL::approximate_sqrt(space_3 * space_3); + + point_spacing_count[fmls_id] += 3; + } + } + for (std::size_t i = 0; i < points_to_add.size(); i++) + { + Vector_3& point = points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id]] = point.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 1] = point.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 2] = point.z(); + + Vector_3& normal = n_points_to_add[i]; + + pns[fmls_id][6 * current_v_count[fmls_id] + 3] = normal.x(); + pns[fmls_id][6 * current_v_count[fmls_id] + 4] = normal.y(); + pns[fmls_id][6 * current_v_count[fmls_id] + 5] = normal.z(); + + current_v_count[fmls_id]++; + } + } + } + + + std::size_t nb_of_mls_to_create = 0; + double average_point_spacing = 0; + + //Cretaing the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + nb_of_mls_to_create++; + + double current_point_spacing = point_spacing[it->second] / point_spacing_count[it->second]; + point_spacing[it->second] = current_point_spacing; + + average_point_spacing += current_point_spacing; + } + } + + average_point_spacing = average_point_spacing / nb_of_mls_to_create; + + subdomain_FMLS.resize(nb_of_mls_to_create, FMLS()); + + count = 0; + //Creating the actual MLS surfaces + for (typename SurfaceIndexMap::iterator it = current_subdomain_FMLS_indices.begin(); + it != current_subdomain_FMLS_indices.end(); ++it) + { + if (current_v_count[it->second] > 3) + { + const double current_point_spacing = point_spacing[it->second]; + + //subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS[count].setPN(pns[it->second], + current_v_count[it->second], + current_point_spacing); + // subdomain_FMLS[count].toggleHermite(true); + subdomain_FMLS_indices[it->first] = count; + + count++; + } + else { + std::cout << "Problem of number for MLS : " << current_v_count[it->second] << std::endl; + } + } +} + +} // internal +} // Tetrahedral_remeshing +} // CGAL + +#endif //CGAL_TETRAHEDRAL_REMESHING_FMLS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h new file mode 100644 index 00000000000..4e163f07372 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/collapse_short_edges.h @@ -0,0 +1,1310 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H +#define CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +enum Edge_type { FEATURE, BOUNDARY, INSIDE, MIXTE, + NO_COLLAPSE, INVALID, IMAGINARY, MIXTE_IMAGINARY, HULL_EDGE }; +enum Collapse_type { TO_MIDPOINT, TO_V0, TO_V1, IMPOSSIBLE }; +enum Result_type { VALID, + V_PROBLEM, C_PROBLEM, E_PROBLEM, + TOPOLOGICAL_PROBLEM, ORIENTATION_PROBLEM, SHARED_NEIGHBOR_PROBLEM }; + +template +class CollapseTriangulation +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Triangulation::Point Point_3; + typedef typename C3t3::Triangulation::Geom_traits::Vector_3 Vector_3; + +public: + CollapseTriangulation(C3t3& c3t3, + const Edge& e, + Collapse_type _collapse_type) + : collapse_type(_collapse_type) + , v0_init(e.first->vertex(e.second)) + , v1_init(e.first->vertex(e.third)) + { + typedef std::array Facet; // 3 = id + typedef std::array Tet_with_ref; // first 4 = id, fifth = reference + + std::unordered_set cells_to_insert; + c3t3.triangulation().finite_incident_cells(v0_init, + std::inserter(cells_to_insert, cells_to_insert.end())); + c3t3.triangulation().finite_incident_cells(v1_init, + std::inserter(cells_to_insert, cells_to_insert.end())); + + make_cells_set_manifold(c3t3, cells_to_insert); + + std::unordered_set vertices_to_insert; + for (Cell_handle ch : cells_to_insert) + { + for(int i = 0; i < 4; ++i) + vertices_to_insert.insert(ch->vertex(i)); + } + + CGAL_assertion(vertices_to_insert.end() + != std::find(vertices_to_insert.begin(), vertices_to_insert.end(), v1_init)); + CGAL_assertion(vertices_to_insert.end() + != std::find(vertices_to_insert.begin(), vertices_to_insert.end(), v0_init)); + + std::unordered_map v2i;/*vertex of main tr - vertex of collapse tr*/ + + //To add the vertices only once + std::vector points; + int index = 0; + for (Vertex_handle vh : vertices_to_insert) + { + if (v2i.find(vh) == v2i.end()) + { + points.push_back(vh->point()); + v2i.insert(std::make_pair(vh, index++)); + } + } + + std::vector finite_cells; + for (Cell_handle ch : cells_to_insert) + { + Tet_with_ref t = { { v2i.at(ch->vertex(0)), + v2i.at(ch->vertex(1)), + v2i.at(ch->vertex(2)), + v2i.at(ch->vertex(3)), + ch->subdomain_index() } }; + finite_cells.push_back(t); + } + + // finished + std::vector new_vertices; + std::map border_facets; + if (CGAL::build_triangulation(triangulation, + points, finite_cells, border_facets, + new_vertices, false/*verbose*/)) + { + CGAL_assertion(triangulation.tds().is_valid()); + CGAL_assertion(triangulation.infinite_vertex() == new_vertices[0]); + + // update() + vh0 = new_vertices[v2i.at(v0_init) + 1]; + vh1 = new_vertices[v2i.at(v1_init) + 1]; + + Cell_handle ch; + int i0, i1; + not_an_edge = true; + CGAL_assertion(triangulation.tds().is_vertex(vh0)); + CGAL_assertion(triangulation.tds().is_vertex(vh1)); + if (triangulation.is_edge(vh0, vh1, ch, i0, i1)) + { + edge = Edge(ch, i0, i1); + not_an_edge = false; + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + else + std::cout << "Warning : CollapseTriangulation is not valid!" << std::endl; +#endif + } + + void make_cells_set_manifold(const C3t3& c3t3, + std::unordered_set& cells) + { + typedef Vertex_handle Vh; + typedef std::array FV; + typedef std::pair EV; + + boost::unordered_map facets; + for (Cell_handle c : cells) + { + for (int i = 0; i < 4; ++i) + { + const FV fvi = make_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + typename boost::unordered_map::iterator fit = facets.find(fvi); + if(fit == facets.end()) + facets.insert(std::make_pair(fvi, 1)); + else + fit->second++; + } + } + + boost::unordered_map edges; + for (const std::pair& fvv : facets) + { + if(fvv.second != 1) + continue; + + for (int i = 0; i < 3; ++i) + { + const EV evi = make_vertex_pair(fvv.first[i], fvv.first[(i + 1) % 3]); + typename boost::unordered_map::iterator eit = edges.find(evi); + if (eit == edges.end()) + edges.insert(std::make_pair(evi, 1)); + else + eit->second++; + } + } + + for (const std::pair& evv : edges) + { + if (evv.second != 2) + { + c3t3.triangulation().finite_incident_cells(evv.first.first, + std::inserter(cells, cells.begin())); + c3t3.triangulation().finite_incident_cells(evv.first.second, + std::inserter(cells, cells.begin())); + } + } + } + + Result_type collapse() + { + if (not_an_edge) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "CollapseTriangulation::Not an edge..." << std::endl; +#endif + return E_PROBLEM; + } + else + { + Vector_3 v0_new_pos = vec(vh0->point()); + + if (collapse_type == TO_MIDPOINT){ + v0_new_pos = v0_new_pos + 0.5 * Vector_3(point(vh0->point()), point(vh1->point())); + } + else if (collapse_type == TO_V1){ + v0_new_pos = vec(point(vh1->point())); + } + + boost::unordered_set invalid_cells; + + typedef typename Tr::Cell_circulator Cell_circulator; + Cell_circulator circ = triangulation.incident_cells(edge); + Cell_circulator done = circ; + + std::vector cells_to_remove; + + //Update the vertex before removing it + std::vector find_incident; + triangulation.incident_cells(vh0, std::back_inserter(find_incident)); + + std::vector cells_to_update; + triangulation.incident_cells(vh1, std::back_inserter(cells_to_update)); + + do + { + int v0_id = circ->index(vh0); + int v1_id = circ->index(vh1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + int ch_id_in_n0 = n0_ch->index(circ); + int ch_id_in_n1 = n1_ch->index(circ); + + if (n0_ch->has_neighbor(n1_ch)) + return SHARED_NEIGHBOR_PROBLEM; + + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + + Subdomain_index si_n0 = n0_ch->subdomain_index(); + Subdomain_index si_n1 = n1_ch->subdomain_index(); + Subdomain_index si = circ->subdomain_index(); + + if (si_n0 != si && si_n1 != si) + return TOPOLOGICAL_PROBLEM; + + if ( triangulation.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && triangulation.is_infinite(n1_ch->vertex(ch_id_in_n1))) + return TOPOLOGICAL_PROBLEM; + + if ( triangulation.is_infinite(n0_ch) + && triangulation.is_infinite(n1_ch) + && !triangulation.is_infinite(circ)) + return TOPOLOGICAL_PROBLEM; + + cells_to_remove.push_back(circ); + + invalid_cells.insert(circ); + + } while (++circ != done); + + + vh0->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + vh1->set_point(Point_3(v0_new_pos.x(), v0_new_pos.y(), v0_new_pos.z())); + + Vertex_handle infinite_vertex = triangulation.infinite_vertex(); + + bool v0_updated = false; + for (const Cell_handle ch : find_incident) + { + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + vh0->set_cell(ch); + v0_updated = true; + } + } + } + + //Update the vertex before removing it + for (Cell_handle ch : cells_to_update) + { + if (invalid_cells.find(ch) == invalid_cells.end()) //valid cell + { + ch->set_vertex(ch->index(vh1), vh0); + + if (triangulation.is_infinite(ch)) + infinite_vertex->set_cell(ch); + else { + if (!v0_updated) { + vh0->set_cell(ch); + v0_updated = true; + } + } + } + } + + if (!v0_updated){ + std::cout << "CollapseTriangulation::PB i cell not valid!!!" << std::endl; + return V_PROBLEM; + } + triangulation.tds().delete_vertex(vh1); + + //Removing cells + for (Cell_handle ch : cells_to_remove){ + triangulation.tds().delete_cell(ch); + } + + for (Cell_handle cit : triangulation.finite_cell_handles()) + { + if (!is_well_oriented(triangulation, cit)) + return ORIENTATION_PROBLEM; + if (!triangulation.tds().is_valid(cit, true)) + return C_PROBLEM; + } + + for (Vertex_handle vit : triangulation.finite_vertex_handles()) + { + if (!triangulation.tds().is_valid(vit, true)) + return V_PROBLEM; + } + + //int si_nb_vh0 = nb_incident_subdomains(vh0, c3t3); + //int si_nb_vh1 = nb_incident_subdomains(vh1, c3t3); + //int vertices_subdomain_nb_vh0 = std::max(si_nb_vh0, si_nb_vh1); + //bool is_on_hull_vh0 = is_on_convex_hull(vh0, c3t3) || is_on_convex_hull(vh1, c3t3); + + //if( is_valid_for_domains() ) + return VALID; + + // return TOPOLOGICAL_PROBLEM; + } + } + +protected: + Tr triangulation; + + const Collapse_type collapse_type; + + const Vertex_handle v0_init; + const Vertex_handle v1_init; + + Vertex_handle vh0; + Vertex_handle vh1; + + Edge edge; + + bool not_an_edge; +}; + + + +template +Collapse_type get_collapse_type(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + bool update_v0 = false; + bool update_v1 = false; + get_edge_info(edge, update_v0, update_v1, c3t3, cell_selector); + + if (update_v0 && update_v1) return TO_MIDPOINT; + else if (update_v0) return TO_V1; + else if (update_v1) return TO_V0; + else return IMPOSSIBLE; +} + +//template +//Edge_type get_edge_type(const typename C3t3::Edge& edge, +// const C3t3& c3t3) +//{ +// typedef typename C3t3::Vertex_handle Vertex_handle; +// typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; +// typedef typename C3t3::Subdomain_index Subdomain_index; + +// const Vertex_handle & v0 = edge.first->vertex(edge.second); +// const Vertex_handle & v1 = edge.first->vertex(edge.third); + +// const int dim0 = c3t3.in_dimension(v0); +// const int dim1 = c3t3.in_dimension(v1); + +// const bool is_v0_on_hull = is_on_convex_hull(v0, c3t3); +// const bool is_v1_on_hull = is_on_convex_hull(v1, c3t3); + +// if (c3t3.is_in_complex(edge)) +// return FEATURE; + +// else if (dim0 == 3 && dim1 == 3) +// return INSIDE; + +// else if (dim0 == 2 && dim1 == 2) +// { +// Cell_circulator circ = c3t3.triangulation().incident_cells(edge); +// Cell_circulator done = circ; + +// std::vector indices; +// do +// { +// Subdomain_index current_si = circ->subdomain_index(); + +// if (std::find(indices.begin(), indices.end(), current_si) == indices.end()) { +// indices.push_back(current_si); +// } + +// Subdomain_index si_n0 = circ->neighbor(circ->index(v0))->subdomain_index(); +// Subdomain_index si_n1 = circ->neighbor(circ->index(v1))->subdomain_index(); +// if (si_n0 == si_n1 && si_n0 != current_si) +// return NO_COLLAPSE; + +// } while (++circ != done); + +// const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); +// const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + +// if (indices.size() >= (std::min)(nb_si_v0, nb_si_v1)) { +// return BOUNDARY; +// } +// } + +// //std::cerr << "ERROR : get_edge_type did not return anything valid!" << std::endl; +// return NO_COLLAPSE; +//} + +template +bool is_valid_collapse(const typename C3t3::Edge& edge, + const C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + int v0_id = circ->index(v0); + int v1_id = circ->index(v1); + + Cell_handle n0_ch = circ->neighbor(v0_id); + Cell_handle n1_ch = circ->neighbor(v1_id); + + if (n0_ch->has_vertex(v0) + || n1_ch->has_vertex(v1) + || n0_ch->has_neighbor(n1_ch)) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (c3t3.is_in_complex(edge)) + ++nb_invalid_collapse_short; +#endif + return false; + } + } + while (++circ != done); + + return true; +} + +template +bool is_valid_collapse(const typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + const typename C3t3::Triangulation::Point& new_pos, + const C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Triangulation::Point Point; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_test_midpoint++; + else if (collapse_type == TO_V1) + nb_test_v1++; + else + nb_test_v0++; + } +#endif + + if (collapse_type == TO_V1 || collapse_type == TO_MIDPOINT) + { + std::vector cells_to_check; + c3t3.triangulation().finite_incident_cells(v0, + std::back_inserter(cells_to_check)); + + for (const Cell_handle ch : cells_to_check) + { + if (!ch->has_vertex(v1)) + { + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point()}; + pts[ch->index(v0)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v1++; + } +#endif + return false; + } + } + } + } + if (collapse_type == TO_V0 || collapse_type == TO_MIDPOINT) + { + std::vector cells_to_check; + c3t3.triangulation().finite_incident_cells(v1, + std::back_inserter(cells_to_check)); + + for (const Cell_handle ch : cells_to_check) + { + if (!ch->has_vertex(v0)) + { + //check orientation + boost::array pts = { ch->vertex(0)->point(), + ch->vertex(1)->point(), + ch->vertex(2)->point(), + ch->vertex(3)->point() }; + pts[ch->index(v1)] = new_pos; + if (CGAL::orientation(point(pts[0]), point(pts[1]), point(pts[2]), point(pts[3])) + != CGAL::POSITIVE) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + { + if (collapse_type == TO_MIDPOINT) + nb_orientation_midpoint++; + else + nb_orientation_v0++; + } +#endif + return false; + } + } + } + } + + return is_valid_collapse(edge, c3t3); +} + +template +bool facet_has_edge(const Facet& f, const Vh v0, const Vh v1) +{ + std::array, 3> edges = {{ {{1,2}}, {{2,3}}, {{3,1}} }}; + + for (int i = 0; i < 3; ++i) + { + const std::array& ei = edges[i]; + if ( f.first->vertex((f.second + ei[0]) % 4) == v0 + && f.first->vertex((f.second + ei[1]) % 4) == v1) + return true; + if ( f.first->vertex((f.second + ei[0]) % 4) == v1 + && f.first->vertex((f.second + ei[1]) % 4) == v0) + return true; + } + return false; +} + +template +bool collapse_preserves_surface_star(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Triangulation::Point& new_pos, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Geom_traits::Vector_3 Vector_3; + typedef typename Tr::Geom_traits::Point_3 Point_3; + + const Tr& tr = c3t3.triangulation(); + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + if (c3t3.in_dimension(v0) != 2 || c3t3.in_dimension(v1) != 2) + return true;//other cases should not be treated here + + typename Tr::Geom_traits gt = c3t3.triangulation().geom_traits(); + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = gt.construct_opposite_vector_3_object(); + typename Tr::Geom_traits::Compute_scalar_product_3 + product = gt.compute_scalar_product_3_object(); + typename Tr::Geom_traits::Construct_normal_3 + normal = gt.construct_normal_3_object(); + + boost::unordered_set facets; + tr.finite_incident_facets(v0, std::inserter(facets, facets.end())); + tr.finite_incident_facets(v1, std::inserter(facets, facets.end())); + +// note : checking a 2nd ring of facets does not change the result +// boost::unordered_set ring2; +// for (const Facet& f : facets) +// { +// for (int i = 1; i < 4; ++i) +// { +// Vertex_handle vi = f.first->vertex((f.second + i) % 4); +// tr.finite_incident_facets(vi, std::inserter(ring2, ring2.end())); +// } +// } +// facets.insert(ring2.begin(), ring2.end()); + + Vector_3 reference_normal = CGAL::NULL_VECTOR; + //Point_3 reference_c; + for (const Facet& f : facets) + { + if (!is_boundary(c3t3, f, cell_selector)) + continue; + if (facet_has_edge(f, v0, v1)) + continue; //this facet will collapse if collapse happens + + std::array pts = {{ point(f.first->vertex((f.second + 1) % 4)->point()), + point(f.first->vertex((f.second + 2) % 4)->point()), + point(f.first->vertex((f.second + 3) % 4)->point()) }}; + if(f.second % 2 == 0) + std::swap(pts[0], pts[1]); + + Vector_3 n_before_collapse = normal(pts[0], pts[1], pts[2]); + + const Facet& mf = tr.mirror_facet(f); + bool do_opp = false; + if ( c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + { + n_before_collapse = opp(n_before_collapse); + do_opp = true; + } + + if (reference_normal == CGAL::NULL_VECTOR) + { + //reference_c = CGAL::centroid(pts[0], pts[1], pts[2]); + reference_normal = n_before_collapse; + } + + // check after move + for (int i = 0; i < 3; ++i) + { + const Vertex_handle vi = f.first->vertex((f.second + i + 1) % 4); + if (vi == v0 || vi == v1) + { + if (f.second % 2 == 0) + { + if(i == 0) pts[1] = point(new_pos); + else if(i == 1) pts[0] = point(new_pos); + else pts[2] = point(new_pos); + } + else + pts[i] = point(new_pos); + break; + } + } + + Vector_3 n_after_collapse = normal(pts[0], pts[1], pts[2]); + if(do_opp) + n_after_collapse = opp(n_after_collapse); + + const double dotref = product(reference_normal, n_after_collapse); + if(dotref < 0) + return false; + const double dot = product(n_before_collapse, n_after_collapse); + if(dot < 0) + return false; + +// if (dot * dotref < 0) +// { +// std::cout << "collapse edge : " << std::endl; +// std::cout << point(v0->point()) << " " << point(v1->point()) << std::endl; +// std::cout << "facet : " << std::endl; +// std::cout << pts[0] << " " << pts[1] << " " << pts[2] << std::endl; +// +// Point_3 c = CGAL::centroid(pts[0], pts[1], pts[2]); +// std::cout << "n_before_collapse "; +// std::cout << c << " " << (c + n_before_collapse) << std::endl; +// std::cout << "n_after_collapse "; +// std::cout << c << " " << (c + n_after_collapse) << std::endl; +// std::cout << "reference_normal "; +// std::cout << reference_c << " " << (reference_c + reference_normal) << std::endl; +// std::cout << std::endl; +// } +// if (dotref < 0 || dot < 0) +// return false; + } + + return true; +} + +template +bool are_edge_lengths_valid(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const typename C3t3::Triangulation::Point& new_pos, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const CellSelector& cell_selector, + const bool /* adaptive */ = false) +{ + //SqLengthMap::key_type is Vertex_handle + //SqLengthMap::value_type is double + typedef typename C3t3::Triangulation::Geom_traits::FT FT; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Vertex_handle Vertex_handle; + + const Vertex_handle v1 = edge.first->vertex(edge.second); + const Vertex_handle v2 = edge.first->vertex(edge.third); + + boost::unordered_map edges_sqlength_after_collapse; + + std::vector inc_edges; + c3t3.triangulation().finite_incident_edges(v1, + std::back_inserter(inc_edges)); + c3t3.triangulation().finite_incident_edges(v2, + std::back_inserter(inc_edges)); + + for (const Edge& ei : inc_edges) + { + if (is_outside(ei, c3t3, cell_selector)) + continue; + + Vertex_handle vh = ei.first->vertex(ei.second); + if (vh == v1 || vh == v2) + vh = ei.first->vertex(ei.third); + if (vh == v1 || vh == v2) + continue; + + if (edges_sqlength_after_collapse.find(vh) == edges_sqlength_after_collapse.end()) + { + const FT sqlen = CGAL::squared_distance(new_pos, point(vh->point())); + + //if (adaptive){ + // if (is_boundary_edge(ei) || is_hull_edge(ei)){ + // if (sqlen_i > split_length) + // return false; + // } + // else if (sqlen_i > 4.*getAimedLength(ei, aimed_length) / 3.){// && is_in_complex(ei) ){ + // return false; + // } + //} + //else { + + if (sqlen > sqhigh) { + return false; + } + //} + edges_sqlength_after_collapse[vh] = sqlen; + } + } + + return true; +} + +template +void merge_surface_patch_indices(const typename C3t3::Facet& f1, + const typename C3t3::Facet& f2, + C3t3& c3t3) +{ + const bool in_cx_f1 = c3t3.is_in_complex(f1); + const bool in_cx_f2 = c3t3.is_in_complex(f2); + + if (in_cx_f1 && !in_cx_f2) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f1); + f2.first->set_surface_patch_index(f2.second, patch); + } + else if (in_cx_f2 && !in_cx_f1) + { + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); + f1.first->set_surface_patch_index(f1.second, patch); + } + else if(in_cx_f1 && in_cx_f2) + { + CGAL_assertion(c3t3.surface_patch_index(f1) == c3t3.surface_patch_index(f2)); + + typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(f2); + c3t3.remove_from_complex(f2); + f2.first->set_surface_patch_index(f2.second, patch); + } +} + +template +typename C3t3::Vertex_handle +collapse(const typename C3t3::Cell_handle ch, + const int to, const int from, + C3t3& c3t3) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = ch->vertex(to); + Vertex_handle vh1 = ch->vertex(from); + + + //Update the vertex before removing it + std::vector find_incident; + tr.incident_cells(vh0, std::back_inserter(find_incident)); + + std::vector cells_to_update; + tr.incident_cells(vh1, std::back_inserter(cells_to_update)); + + boost::container::small_vector inc_cells; + Cell_circulator circ = tr.incident_cells(ch, to, from); + Cell_circulator done = circ; + do + { + for (int i = 0; i < 4; ++i) + { + const Vertex_handle vi = circ->vertex(i); + if (vi != vh0 && vi != vh1) + { + const Facet fi(circ, i); + if (c3t3.is_in_complex(fi)) + c3t3.remove_from_complex(fi); + } + } + inc_cells.push_back(circ); + } + while (++circ != done); + + bool valid = true; + std::vector cells_to_remove; + boost::unordered_set invalid_cells; + + for(const Cell_handle c : inc_cells) + { + const int v0_id = c->index(vh0); + const int v1_id = c->index(vh1); + + Cell_handle n0_ch = c->neighbor(v0_id); + Cell_handle n1_ch = c->neighbor(v1_id); + + const int ch_id_in_n0 = n0_ch->index(c); + const int ch_id_in_n1 = n1_ch->index(c); + + //Merge surface patch indices + merge_surface_patch_indices(Facet(n0_ch, ch_id_in_n0), + Facet(n1_ch, ch_id_in_n1), + c3t3); + + //Update neighbors before removing cell + n0_ch->set_neighbor(ch_id_in_n0, n1_ch); + n1_ch->set_neighbor(ch_id_in_n1, n0_ch); + + //Update vertices cell pointer + for (int i = 0; i < 3; i++) + { + int vid = Tr::vertex_triple_index(ch_id_in_n0, i); + n0_ch->vertex(vid)->set_cell(n0_ch); + } + for (int i = 0; i < 3; i++) + { + int vid = Tr::vertex_triple_index(ch_id_in_n1, i); + n1_ch->vertex(vid)->set_cell(n1_ch); + } + + if (tr.is_infinite(n0_ch->vertex(ch_id_in_n0)) + && tr.is_infinite(n1_ch->vertex(ch_id_in_n1))) + { + std::cout << "Collapse infinite issue!" << std::endl; + return Vertex_handle(); + } + cells_to_remove.push_back(c); + + invalid_cells.insert(c); + } + + const Vertex_handle infinite_vertex = tr.infinite_vertex(); + + bool v0_updated = false; + for (const Cell_handle c : find_incident) + { + if (invalid_cells.find(c) == invalid_cells.end())//valid cell + { + if (tr.is_infinite(c)) + infinite_vertex->set_cell(c); + //else { + vh0->set_cell(c); + v0_updated = true; + //} + } + } + + // update complex edges + const std::array, 6> edges + = { { {{0,1}}, {{0,2}}, {{0,3}}, {{1,2}}, {{1,3}}, {{2,3}} } }; //vertex indices in cells + const Vertex_handle vkept = vh0; + const Vertex_handle vdeleted = vh1; + for (const Cell_handle c : cells_to_update) + { + for (const std::array& ei : edges) + { + Vertex_handle eiv0 = c->vertex(ei[0]); + Vertex_handle eiv1 = c->vertex(ei[1]); + if (eiv1 == vdeleted && eiv0 != vkept) //replace eiv1 by vkept + { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(eiv0, vkept, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + else if (eiv0 == vdeleted && eiv1 != vkept) //replace eiv0 by vkept + { + if (c3t3.is_in_complex(eiv0, eiv1)) + { + c3t3.add_to_complex(vkept, eiv1, c3t3.curve_index(eiv0, eiv1)); + c3t3.remove_from_complex(eiv0, eiv1); + } + } + } + } + + // update complex facets + + //Update the vertex before removing it + for (const Cell_handle c : cells_to_update) + { + if (invalid_cells.find(c) == invalid_cells.end()) //valid cell + { + c->set_vertex(c->index(vh1), vh0); + + if (tr.is_infinite(c)) + infinite_vertex->set_cell(c); + //else { + if (!v0_updated) { + vh0->set_cell(c); + v0_updated = true; + } + //} + } + } + + if (!v0_updated) + std::cout << "PB i cell not valid!!!" << std::endl; + + // Delete vertex + c3t3.triangulation().tds().delete_vertex(vh1); + + // Delete cells + for (Cell_handle cell_to_remove : cells_to_remove) + { + // remove cell + if (c3t3.is_in_complex(cell_to_remove)) + c3t3.remove_from_complex(cell_to_remove); + c3t3.triangulation().tds().delete_cell(cell_to_remove); + } + + if (!valid){ + std::cout << "Global triangulation collapse bug!!" << std::endl; + return Vertex_handle(); + } + + return vh0; +} + + +template +typename C3t3::Vertex_handle collapse(typename C3t3::Edge& edge, + const Collapse_type& collapse_type, + C3t3& c3t3) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Triangulation::Point Point_3; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + const int dim_vh0 = c3t3.in_dimension(vh0); + const int dim_vh1 = c3t3.in_dimension(vh1); + + Vertex_handle vh = Vertex_handle(); + + const Point_3 p0 = vh0->point(); + const Point_3 p1 = vh1->point(); + + //Collapse at mid point + if (collapse_type == TO_MIDPOINT) + { + Point_3 new_position(CGAL::midpoint(point(vh0->point()), point(vh1->point()))); + vh0->set_point(new_position); + vh1->set_point(new_position); + + vh = collapse(edge.first, edge.second, edge.third, c3t3); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); + } + else //Collapse at vertex + { + if (collapse_type == TO_V1) + { + vh0->set_point(p1); + vh = collapse(edge.first, edge.third, edge.second, c3t3); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); + } + else //Collapse at v0 + { + if (collapse_type == TO_V0) + { + vh1->set_point(p0); + vh = collapse(edge.first, edge.second, edge.third, c3t3); + c3t3.set_dimension(vh, (std::min)(dim_vh0, dim_vh1)); + } + else + CGAL_assertion(false); + } + } + return vh; +} + +template +typename C3t3::Vertex_handle collapse_edge(typename C3t3::Edge& edge, + C3t3& c3t3, + const typename C3t3::Triangulation::Geom_traits::FT& sqhigh, + const bool /* protect_boundaries */, + CellSelector cell_selector, + Visitor& ) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Point Point; + typedef typename Tr::Vertex_handle Vertex_handle; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Collapse_type collapse_type = get_collapse_type(edge, c3t3, cell_selector); + +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + const bool in_cx = c3t3.is_in_complex(edge); + if (in_cx && collapse_type == IMPOSSIBLE) + nb_impossible++; +#endif + + if (collapse_type == IMPOSSIBLE) + return Vertex_handle(); + + Point new_pos; + switch(collapse_type) + { + case TO_V0: + new_pos = v0->point(); break; + case TO_V1: + new_pos = v1->point(); break; + default: + CGAL_assertion(collapse_type == TO_MIDPOINT); + new_pos = Point(CGAL::midpoint(point(v0->point()), point(v1->point()))); + } + + if (!is_valid_collapse(edge, collapse_type, new_pos, c3t3)) + { +#ifdef TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS + if (collapse_type == TO_MIDPOINT) + { + // with TO_MIDPOINT, we are authorized to test TO_V0 and TO_V1 + if (is_valid_collapse(edge, TO_V0, v0->point(), c3t3)) + { + collapse_type = TO_V0; + new_pos = v0->point(); + } + else if (is_valid_collapse(edge, TO_V1, v1->point(), c3t3)) + { + collapse_type = TO_V1; + new_pos = v1->point(); + } + else + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_invalid_collapse++; +#endif + return Vertex_handle(); + } + } + else +#endif //TET_REMESHING_COLLAPSE_FALLBACK_EXPERIMENTS + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_invalid_collapse++; +#endif + return Vertex_handle(); + } + } + + if (are_edge_lengths_valid(edge, c3t3, new_pos, sqhigh, cell_selector/*, adaptive = false*/) + && collapse_preserves_surface_star(edge, c3t3, new_pos, cell_selector)) + { + CGAL_assertion_code(typename Tr::Cell_handle dc); + CGAL_assertion_code(int di); + CGAL_assertion_code(int dj); + CGAL_assertion(c3t3.triangulation().is_edge(edge.first->vertex(edge.second), + edge.first->vertex(edge.third), dc, di, dj)); + + CollapseTriangulation local_tri(c3t3, edge, collapse_type); + + Result_type res = local_tri.collapse(); + if (res == VALID) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + if (in_cx) + nb_valid_collapse++; +#endif + return collapse(edge, collapse_type, c3t3); + } + } +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + else if (in_cx) + nb_invalid_lengths++; +#endif + return Vertex_handle(); +} + +template +bool can_be_collapsed(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector) +{ + if (is_outside(e, c3t3, cell_selector)) + return false; + + if (protect_boundaries) + { + if (c3t3.is_in_complex(e)) + return false; + else if (is_boundary(c3t3, e, cell_selector)) + return false; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (!is_internal(e, c3t3, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } +#endif + + CGAL_assertion(is_internal(e, c3t3, cell_selector)); + return true; + } + else + { + return true; + } +} + +template +void collapse_short_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& low, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + + typedef typename T3::Geom_traits Gt; + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type short_edge; + + T3& tr = c3t3.triangulation(); + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Collapse short edges (" << low << ", " << high << ")..."; + std::cout.flush(); + std::size_t nb_collapses = 0; +#endif + const FT sq_low = low*low; + const FT sq_high = high*high; + + //collect long edges + Boost_bimap short_edges; + for (const Edge& e : tr.finite_edges()) + { + if (!can_be_collapsed(e, c3t3, protect_boundaries, cell_selector)) + continue; + + FT sqlen = sql(tr.segment(e)); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(e), sqlen)); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + debug::dump_edges(short_edges, "short_edges.polylines.txt"); + + std::ofstream short_success("short_collapse_success.polylines.txt"); + std::ofstream short_fail("short_collapse_fail.polylines.txt"); + std::ofstream short_cancel("short_collapse_canceled.polylines.txt"); +#endif + + while(!short_edges.empty()) + { + //the edge with shortest length + typename Boost_bimap::right_map::iterator eit = short_edges.right.begin(); + Edge_vv e = eit->second; + short_edges.right.erase(eit); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + FT sqlen = eit->first; + std::cout << "\rCollapse... (" << short_edges.left.size() << " short edges, "; + std::cout << std::sqrt(sqlen) << ", "; + std::cout << nb_collapses << " collapses)"; + std::cout.flush(); +#endif + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_vertex(e.first) + && tr.tds().is_vertex(e.second) + && tr.tds().is_edge(e.first, e.second, cell, i1, i2) + && tr.segment(Edge(cell, i1, i2)).squared_length() < sq_low) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const typename T3::Point p1 = e.first->point(); + const typename T3::Point p2 = e.second->point(); +#endif + + Edge edge(cell, i1, i2); + + if (!can_be_collapsed(edge, c3t3, protect_boundaries, cell_selector)) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + short_cancel << "2 " << point(p1) << " " << point(p2) << std::endl; +#endif + continue; + } + + Vertex_handle vh = collapse_edge(edge, c3t3, sq_high, + protect_boundaries, cell_selector, + visitor); + if (vh != Vertex_handle()) + { + std::vector incident_short; + c3t3.triangulation().finite_incident_edges(vh, + std::back_inserter(incident_short)); + for (const Edge& eshort : incident_short) + { + if (!can_be_collapsed(eshort, c3t3, protect_boundaries, cell_selector)) + continue; + + const FT sqlen = sql(tr.segment(eshort)); + if (sqlen < sq_low) + short_edges.insert(short_edge(make_vertex_pair(eshort), sqlen)); + } + + //debug::dump_c3t3(c3t3, "dump_after_collapse"); + //CGAL_assertion(c3t3.triangulation().tds().is_valid()); +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + ++nb_collapses; +#endif + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (vh != Vertex_handle()) + short_success << "2 " << point(p1) << " " << point(p2) << std::endl; + else + short_fail << "2 " << point(p1) << " " << point(p2) << std::endl; +#endif + } + }//end loop on short_edges +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + short_success.close(); + short_fail.close(); +#endif + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_collapses << " collapses)." << std::endl; +#endif +} +} +} +} + +#endif // CGAL_INTERNAL_COLLAPSE_SHORT_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h new file mode 100644 index 00000000000..15474f84825 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/compute_c3t3_statistics.h @@ -0,0 +1,214 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H +#define CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H + +#include + +#include +#include +#include +#include + +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +template +void compute_statistics(const Triangulation& tr, + CellSelector cell_selector, + const char* filename = "statistics_c3t3.txt") +{ + typedef Triangulation Tr; + typedef typename Tr::Geom_traits Gt; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Gt::Point_3 Point; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_cells_iterator Finite_cells_iterator; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + + std::size_t nb_edges = 0; + double total_edges = 0; + std::size_t nb_angle = 0; + double total_angle = 0; + + double min_edges_length = (std::numeric_limits::max)(); + double max_edges_length = 0.; + + double smallest_edge_radius = (std::numeric_limits::max)(); + double smallest_radius_radius = (std::numeric_limits::max)(); + double biggest_v_sma_cube = 0.; + double max_dihedral_angle = 0.; + double min_dihedral_angle = 180.; + + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + const Cell_handle cell = fit->first; + const int& index = fit->second; + if (!cell_selector(cell) || !cell_selector(cell->neighbor(index))) + continue; + + const Point& pa = point(cell->vertex((index + 1) & 3)->point()); + const Point& pb = point(cell->vertex((index + 2) & 3)->point()); + const Point& pc = point(cell->vertex((index + 3) & 3)->point()); + + double edges[3]; + edges[0] = (CGAL::sqrt(CGAL::squared_distance(pa, pb))); + edges[1] = (CGAL::sqrt(CGAL::squared_distance(pa, pc))); + edges[2] = (CGAL::sqrt(CGAL::squared_distance(pb, pc))); + for (int i = 0; i < 3; ++i) + { + if (edges[i] < min_edges_length){ min_edges_length = edges[i]; } + if (edges[i] > max_edges_length){ max_edges_length = edges[i]; } + total_edges += edges[i]; + ++nb_edges; + } + } + + double mean_edges_length = total_edges / (double)nb_edges; + + typename Gt::Compute_approximate_dihedral_angle_3 approx_dihedral_angle + = tr.geom_traits().compute_approximate_dihedral_angle_3_object(); + + std::size_t nb_tets = 0; + boost::unordered_set selected_vertices; + std::vector sub_ids; + for (Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); + ++cit) + { + const Subdomain_index& si = cit->subdomain_index(); + if (si == Subdomain_index() || !cell_selector(cit)) + continue; + + ++nb_tets; + if (std::find(sub_ids.begin(), sub_ids.end(), si) == sub_ids.end()) + sub_ids.push_back(cit->subdomain_index()); + for (int i = 0; i < 4; ++i) + selected_vertices.insert(cit->vertex(i)); + + const Point& p0 = point(cit->vertex(0)->point()); + const Point& p1 = point(cit->vertex(1)->point()); + const Point& p2 = point(cit->vertex(2)->point()); + const Point& p3 = point(cit->vertex(3)->point()); + double v = CGAL::abs(tr.tetrahedron(cit).volume()); + if (v == 0.) + { + std::cout << "degenerate cell :\n\t"; + std::cout << p0 << "\n\t" << p1 << "\n\t" << p2 << "\n\t" << p3 << std::endl; + } + double circumradius = (v == 0.) + ? CGAL::sqrt(CGAL::squared_radius(p0, p1, p2)) + : CGAL::sqrt(CGAL::squared_radius(p0, p1, p2, p3)); + + //find shortest edge + double edges[6]; + edges[0] = CGAL::sqrt(CGAL::squared_distance(p0, p1)); + edges[1] = CGAL::sqrt(CGAL::squared_distance(p0, p2)); + edges[2] = CGAL::sqrt(CGAL::squared_distance(p0, p3)); + edges[3] = CGAL::sqrt(CGAL::squared_distance(p2, p1)); + edges[4] = CGAL::sqrt(CGAL::squared_distance(p2, p3)); + edges[5] = CGAL::sqrt(CGAL::squared_distance(p1, p3)); + + double min_edge = edges[0]; + for (int i = 1; i < 6; ++i) + { + if (edges[i] < min_edge) + min_edge = edges[i]; + } + + double sumar = CGAL::sqrt(CGAL::squared_area(p0, p1, p2)) + + CGAL::sqrt(CGAL::squared_area(p1, p2, p3)) + + CGAL::sqrt(CGAL::squared_area(p2, p3, p0)) + + CGAL::sqrt(CGAL::squared_area(p3, p1, p0)); + double inradius = 3. * v / sumar; + double smallest_edge_radius_ = min_edge / circumradius*CGAL::sqrt(6.) / 4.;//*sqrt(6)/4 so that the perfect tet ratio is 1 + double smallest_radius_radius_ = inradius / circumradius * 3.; //*3 so that the perfect tet ratio is 1 instead of 1/3 + double biggest_v_sma_cube_ = v / std::pow(min_edge, 3) * 6. * CGAL::sqrt(2.);//*6*sqrt(2) so that the perfect tet ratio is 1 instead + + if (smallest_edge_radius_ < smallest_edge_radius) + smallest_edge_radius = smallest_edge_radius_; + + if (smallest_radius_radius_ < smallest_radius_radius) + smallest_radius_radius = smallest_radius_radius_; + + if (biggest_v_sma_cube_ > biggest_v_sma_cube) + biggest_v_sma_cube = biggest_v_sma_cube_; + + double a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p1, p2, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p2, p1, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p0, p3, p1, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p2, p0, p3))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p1, p3, p0, p2))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + a = CGAL::to_double(CGAL::abs(approx_dihedral_angle(p2, p3, p0, p1))); + if (a < min_dihedral_angle) { min_dihedral_angle = a; } + if (a > max_dihedral_angle) { max_dihedral_angle = a; } + total_angle += a; + ++nb_angle; + } + + std::size_t nb_subdomains = sub_ids.size(); + //std::size_t nb_vertices = d->c3t3.number_of_vertices_in_complex(); + + std::ofstream ofs(filename); + if (!ofs) + return; + + ofs << "Nb subdomains : " << nb_subdomains << std::endl; + ofs << "Total number of vertices : " << tr.number_of_vertices() << std::endl; + ofs << "Number of selected cells : " << nb_tets << std::endl; + ofs << "Number of selected vertices : " << selected_vertices.size() << std::endl; + ofs << std::endl; + ofs << "Min dihedral angle : " << min_dihedral_angle << std::endl; + ofs << "Max dihedral angle : " << max_dihedral_angle << std::endl; + ofs << std::endl; + ofs << "Shortest edge : " << min_edges_length << std::endl; + ofs << "Longest edge : " << max_edges_length << std::endl; + ofs << "Average edge length : " << mean_edges_length << std::endl; + + ofs.close(); +} + +}//end namespace internal +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif // CGAL_TR_INTERNAL_COMPUTE_C3T3_STATISTICS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h new file mode 100644 index 00000000000..7a31fd3ed20 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/flip_edges.h @@ -0,0 +1,1198 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_INTERNAL_FLIP_EDGES_H +#define CGAL_INTERNAL_FLIP_EDGES_H + +#include + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +enum Flip_Criterion{ MIN_ANGLE_BASED, AVERAGE_ANGLE_BASED, + VALENCE_BASED, VALENCE_MIN_DH_BASED }; + +//template +//void flip_inside_edges(std::vector&) +//{ +// //TODO +//} + +//outer_mirror_facets contains the set of facets of the outer hull +//of the set of cells modified by the flip operation, +//"seen from" outside +//i.e. for each facet f among those, f.first has not been modified by flip +template +void update_c3t3_facets(C3t3& c3t3, + const CellSet& cells_to_update, + const FacetSet& outer_mirror_facets) +{ + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + + for (Cell_handle c : cells_to_update) + { + //their subdomain indices have not been modified because we kept the same cells + //surface patch indices need to be fixed though + for (int i = 0; i < 4; ++i) + { + const Facet f(c, i); + const Facet mf = c3t3.triangulation().mirror_facet(f); + if (outer_mirror_facets.find(mf) != outer_mirror_facets.end()) + { + //we are on the border of the modified zone, c3t3 info is valid outside, + //on mirror facet + const typename C3t3::Surface_patch_index patch = c3t3.surface_patch_index(mf); + if (c3t3.is_in_complex(mf)) + f.first->set_surface_patch_index(f.second, patch); + else + f.first->set_surface_patch_index(f.second, Surface_patch_index()); + } + else + { + //we are inside the modified zone, c3t3 info is not valid anymore + if (c3t3.is_in_complex(f) || c3t3.is_in_complex(mf)) + { + f.first->set_surface_patch_index(f.second, Surface_patch_index()); + mf.first->set_surface_patch_index(mf.second, Surface_patch_index()); + } + } + } + } +} + +template +Sliver_removal_result flip_3_to_2(typename C3t3::Edge& edge, + C3t3& c3t3, + const std::vector& vertices_around_edge, + const Flip_Criterion& criterion) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::FT FT; + + //Edge to face flip + Tr& tr = c3t3.triangulation(); + + Cell_circulator circ = tr.incident_cells(edge); + Cell_circulator done = circ; + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + //Select 2 cells to keep and update and one to remove + Cell_handle ch0 = Cell_handle(circ++); + Cell_handle ch1 = Cell_handle(circ++); + Cell_handle cell_to_remove = Cell_handle(circ++); + if (circ != done) + { + std::cout << "Wrong flip function" << std::endl; + return NOT_FLIPPABLE; + } + + //Check structural validity + Cell_handle c; + int i0, i1, i3; + if (tr.is_facet(vertices_around_edge[0], vertices_around_edge[1], vertices_around_edge[2], + c, i0, i1, i3)) + return NOT_FLIPPABLE; + + //Check topological validity + const typename C3t3::Subdomain_index subdomain = ch0->subdomain_index(); + if ( subdomain != ch1->subdomain_index() + || subdomain != cell_to_remove->subdomain_index() + || ch1->subdomain_index() != cell_to_remove->subdomain_index()) + return NOT_FLIPPABLE; + + Vertex_handle vh2; + Vertex_handle vh3; + + for (int i = 0; i < 3; ++i){ + if (!ch0->has_vertex(vertices_around_edge[i])) + vh2 = vertices_around_edge[i]; + else if (!ch1->has_vertex(vertices_around_edge[i])) + vh3 = vertices_around_edge[i]; + } + + int vh0_id = ch0->index(vh0); + int vh1_id = ch1->index(vh1); + + //Check if flip valid + if (!is_well_oriented(tr, vh2, + ch0->vertex(indices(vh0_id, 0)), + ch0->vertex(indices(vh0_id, 1)), + ch0->vertex(indices(vh0_id, 2))) + || !is_well_oriented(tr, vh3, + ch1->vertex(indices(vh1_id, 0)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))) + return NOT_FLIPPABLE; + + ///********************VALIDITY CHECK***************************/ + //double curr_min_dh; + //bool check_validity = false; + //std::vector pre_sliver_Removal_cells; + //if (check_validity){ + // pre_sliver_Removal_cells.clear(); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch0->vertex(0)->point(), ch0->vertex(1)->point(), ch0->vertex(2)->point(), ch0->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(ch1->vertex(0)->point(), ch1->vertex(1)->point(), ch1->vertex(2)->point(), ch1->vertex(3)->point())); + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_to_remove->vertex(0)->point(), cell_to_remove->vertex(1)->point(), + // cell_to_remove->vertex(2)->point(), cell_to_remove->vertex(3)->point())); + + // curr_min_dh = min_dihedral_angle(ch0); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(ch1)); + // curr_min_dh = std::min(curr_min_dh, min_dihedral_angle(cell_to_remove)); + + // pre_sliver_Removal_vertices.clear(); + // for (int i = 0; i < vertices_around_edge.size(); ++i){ + // pre_sliver_Removal_vertices.push_back(Point_3(vertices_around_edge[i]->point())); + // } + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); + //} + /*************************************************************/ + + + 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)); + + //Result worst dihedral angle + if (curr_min_dh > min_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)))) + return NO_BEST_CONFIGURATION; + } + else if (criterion == AVERAGE_ANGLE_BASED) + { + //Current worst dihedral angle + double average_min_dh = min_dihedral_angle(tr, ch0); + average_min_dh += min_dihedral_angle(tr, ch1); + average_min_dh += min_dihedral_angle(tr, cell_to_remove); + + average_min_dh /= 3.; + + FT new_average_min_dh = 0.5 * + (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)), + ch1->vertex(indices(vh1_id, 1)), + ch1->vertex(indices(vh1_id, 2)))); + //Result worst dihedral angle + if (average_min_dh > new_average_min_dh) + return NO_BEST_CONFIGURATION; + } + + //Keep the facets + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + boost::unordered_set outer_mirror_facets; + + FaceMapIndex facet_map_indices; + std::vector mirror_facets; + circ = Cell_circulator(done); + do + { + // facet opposite to vh0 + int curr_vh0_id = circ->index(vh0); + Facet n_vh0_facet = tr.mirror_facet(Facet(circ, curr_vh0_id)); + + outer_mirror_facets.insert(n_vh0_facet); + + Facet_vvv face0 = make_vertex_triple(circ->vertex(indices(curr_vh0_id, 0)), + circ->vertex(indices(curr_vh0_id, 1)), + circ->vertex(indices(curr_vh0_id, 2))); + + typename FaceMapIndex::iterator it = facet_map_indices.find(face0); + if (it == facet_map_indices.end()) + { + facet_map_indices[face0] = mirror_facets.size(); + mirror_facets.push_back(n_vh0_facet); + } + + // facet opposite to vh1 + int curr_vh1_id = circ->index(vh1); + Facet n_vh1_facet = tr.mirror_facet(Facet(circ, curr_vh1_id)); + + outer_mirror_facets.insert(n_vh1_facet); + + Facet_vvv face1 = make_vertex_triple(circ->vertex(indices(curr_vh1_id, 0)), + circ->vertex(indices(curr_vh1_id, 1)), + circ->vertex(indices(curr_vh1_id, 2))); + it = facet_map_indices.find(face1); + if (it == facet_map_indices.end()) + { + facet_map_indices[face1] = mirror_facets.size(); + mirror_facets.push_back(n_vh1_facet); + } + } + while (++circ != done); + + /* + c3t3.remove_from_complex( ch0 ); + c3t3.remove_from_complex( ch1 ); + c3t3.remove_from_complex( cell_to_remove ); + + tr.flip(edge); + + for( int i = 0 ; i < facets.size() ; i ++ ){ + Cell_handle new_cell = facets[i].first->neighbor( facets[i].second ); + c3t3.add_to_complex( new_cell, si ); + } + */ + + //Update cells + ch0->set_vertex(vh0_id, vh2); + ch1->set_vertex(vh1_id, vh3); + + // "New" cells are not created, only modified/updated + std::vector cells_to_update; + cells_to_update.push_back(ch0); + cells_to_update.push_back(ch1); + + //Update adjacencies and vertices' cells + for (Cell_handle ch : cells_to_update) + { + for (int v = 0; v < 4; ++v) + { + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v, 0)), + ch->vertex(indices(v, 1)), + ch->vertex(indices(v, 2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = mirror_facets.size(); + mirror_facets.push_back(Facet(ch, v)); + } + else + { + Facet mirror_facet = mirror_facets[it->second]; + + //Update neighbor + mirror_facet.first->set_neighbor(mirror_facet.second, ch); + ch->set_neighbor(v, mirror_facet.first); + } + ch->vertex(v)->set_cell(ch); + } + } + + // Update c3t3 + update_c3t3_facets(c3t3, cells_to_update, outer_mirror_facets); + + c3t3.remove_from_complex(cell_to_remove); + tr.tds().delete_cell(cell_to_remove); + + /********************VALIDITY CHECK***************************/ + //if (check_validity) + //{ + // post_sliver_Removal_cells.clear(); + // post_sliver_Removal_cells.push_back(ch0); + // post_sliver_Removal_cells.push_back(ch1); + + // double new_min_dh = min_dihedral_angle(ch0); + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(ch1)); + + // post_sliver_Removal_vertices.clear(); + // post_sliver_Removal_vertices.push_back(vh2); + // post_sliver_Removal_vertices.push_back(vh3); + + // if (!is_well_oriented(ch0)) + // return INVALID_ORIENTATION; + // if (!is_well_oriented(ch1)) + // return INVALID_ORIENTATION; + // if (!tr.is_valid(ch0)) + // return INVALID_CELL; + // if (!tr.is_valid(ch1)) + // return INVALID_CELL; + + // for (int i = 0; i < 4; ++i){ + // if (!tr.is_valid(ch0->neighbor(i))) + // return INVALID_CELL; + // if (!tr.is_valid(ch1->neighbor(i))) + // return INVALID_CELL; + // if (!tr.tds().is_valid(ch0->vertex(i))) + // return INVALID_VERTEX; + // if (!tr.tds().is_valid(ch1->vertex(i))){ + // return INVALID_VERTEX; + // } + // } + + // if ((curr_min_dh - new_min_dh) > 0.01){ + // std::cout << "Three_to_two_flip::Flip not improving the quality: " << curr_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + //} + /***********************************************************/ + + return VALID_FLIP; +} + +template +void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh2, + typename C3t3::Vertex_handle vh3, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + 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(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do + { + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = curr_fcirc->first->vertex(indices(curr_fcirc->second, i)); + if ( curr_vertex != vh0 + && curr_vertex != vh1 + && (curr_vertex == vh2 || curr_vertex == vh3)) + { + vh = curr_vertex; + Facet_circulator facet_circulator(curr_fcirc); + Facet_circulator facet_done(curr_fcirc); + + facet_done--; + facet_circulator++; + facet_circulator++; + + bool is_edge = false; + do + { + //Get the ids of the opposite vertices + for (int j = 0; j < 3; ++j) + { + Vertex_handle curr = facet_circulator->first->vertex( + indices(facet_circulator->second, j)); + if (curr != vh0 && curr != vh1) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(curr, vh, ch, i0, i1)) + is_edge = true; + } + } + } while (++facet_circulator != facet_done); + + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); + } + } + nb_cells_around_edge++; + } + while (++curr_fcirc != curr_fdone); + + if (nb_cells_around_edge < 4) + return; + + //Facets that will be used to create new cells i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells i.e. all the facets opposite to vh0 will be set to vh: facet.first->set_vertex( facet.second, vh ) + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + + 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 + if (!cell_circulator->has_vertex(vh)) + { + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); + } + } while (++cell_circulator != done); + + + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (const Facet& fi : facets) + { + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + 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)))); + } + else + { + keep = false; + break; + } + } + } + + if (keep && (curr_min_dh < min_flip_dihedral_angle || !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))); + } + } +} + +template +void find_best_flip_to_improve_dh(C3t3& c3t3, + typename C3t3::Edge& edge, + CandidatesQueue& candidates, + double curr_min_dh, + bool is_sliver_well_oriented = true, + int e_id = 0) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + 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(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + Facet_circulator curr_fcirc = tr.incident_facets(edge); + Facet_circulator curr_fdone = curr_fcirc; + + //Only keep the possible flips + std::vector opposite_vertices; + int nb_cells_around_edge = 0; + do + { + Vertex_handle vh; + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = curr_fcirc->first->vertex( + indices(curr_fcirc->second, i)); + if (curr_vertex != vh0 && curr_vertex != vh1) + { + vh = curr_vertex; + break; + } + } + + Facet_circulator facet_circulator = curr_fcirc; + Facet_circulator facet_done = curr_fcirc; + + facet_done--; + facet_circulator++; + facet_circulator++; + bool is_edge = false; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + 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)) + is_edge = true; + } + } + } while (++facet_circulator != facet_done); + + if (!is_edge && !tr.is_infinite(vh)) + opposite_vertices.push_back(vh); + + nb_cells_around_edge++; + } + while (++curr_fcirc != curr_fdone); + if (nb_cells_around_edge < 4) + return; + + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh: + // facet.first->set_vertex( facet.second, vh ) + + Cell_circulator cell_circulator = tr.incident_cells(edge); + Cell_circulator done = cell_circulator; + + 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 + if (!cell_circulator->has_vertex(vh)) + { + //Facets opposite to vh0 + Facet facet_vh0(cell_circulator, cell_circulator->index(vh0)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + + facets.push_back(facet_vh1); + facets.push_back(facet_vh0); + } + } + while (++cell_circulator != done); + + FT min_flip_dihedral_angle = (std::numeric_limits::max)(); + for (const Facet& fi : facets) + { + if (!tr.is_infinite(fi.first)) + { + if (is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + 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)))); + } + else + { + keep = false; + break; + } + } + } + + if (keep && (curr_min_dh < min_flip_dihedral_angle || !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))); + } + } +} + +template +Sliver_removal_result flip_n_to_m(C3t3& c3t3, + typename C3t3::Edge& edge, + typename C3t3::Vertex_handle vh, + Visitor& visitor, + bool check_validity = false) +{ + CGAL_USE(check_validity); + // std::cout << "n_to_m_flip::start" << std::endl; + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Facet Facet; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + + Vertex_handle vh0 = edge.first->vertex(edge.second); + Vertex_handle vh1 = edge.first->vertex(edge.third); + + //This vertex will have its valence augmenting a lot, + //TODO take the best one + + //TODO!!!! Check that the created edges do not exist!!! + + Facet_circulator facet_circulator = tr.incident_facets(edge); + Facet_circulator done_facet_circulator = facet_circulator; + bool look_for_vh_iterator = true; + do + { + facet_circulator++; + + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + if (facet_circulator->first->vertex(indices(facet_circulator->second, i)) == vh) + look_for_vh_iterator = false; + } + } while (facet_circulator != done_facet_circulator && look_for_vh_iterator); + + if (look_for_vh_iterator) { + std::cout << "Vertex not an opposite of the edge!!" << std::endl; + return NOT_FLIPPABLE; + } + + Facet_circulator facet_done(facet_circulator); + facet_done--; + facet_circulator++; + facet_circulator++; + + std::vector vertices_around_edge; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle curr_vertex = facet_circulator->first->vertex( + 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)) + 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 + boost::unordered_set neighbor_facets; + + //Facets that will be used to create new cells + // i.e. all the facets opposite to vh1 and don't have vh + std::vector facets_for_new_cells; + + //Facets that will be used to update cells + // i.e. all the facets opposite to vh0 will be set to vh : + // facet.first->set_vertex( facet.second, vh ) + std::vector facets_for_updated_cells; + + Cell_circulator cell_circulator = tr.incident_cells(edge); + 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)); + + //Facets opposite to vh1 + Facet facet_vh1(cell_circulator, cell_circulator->index(vh1)); + neighbor_facets.insert(tr.mirror_facet(facet_vh1)); + + //Store it if it do not have vh + if (cell_circulator->has_vertex(vh)) { + to_remove.push_back(cell_circulator); + } + else + { + facets_for_new_cells.push_back(facet_vh1); + facets_for_updated_cells.push_back(facet_vh0); + } + // + // if( ! is_well_oriented( cell_circulator ) ) + // return WRONG; + } + while (++cell_circulator != done); + + //Check that the result will be valid + for (const Facet& fi : facets_for_new_cells) + { + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + for (const Facet& fi : facets_for_updated_cells) + { + if ( !tr.is_infinite(fi.first) + && !is_well_oriented(tr, vh, fi.first->vertex(indices(fi.second, 0)), + fi.first->vertex(indices(fi.second, 1)), + fi.first->vertex(indices(fi.second, 2)))) + return NOT_FLIPPABLE; + } + + ///********************VALIDITY CHECK***************************/ + //double current_min_dh = DBL_MAX; + + //if (check_validity){ + + // pre_sliver_Removal_cells.clear(); + // do{ + // pre_sliver_Removal_cells.push_back(K::Tetrahedron_3(cell_circulator->vertex(0)->point(), cell_circulator->vertex(1)->point(), + // cell_circulator->vertex(2)->point(), cell_circulator->vertex(3)->point())); + + // if (!tr.is_infinite(cell_circulator)) + // current_min_dh = std::min(current_min_dh, min_dihedral_angle(cell_circulator)); + // } while (++cell_circulator != done); + + // pre_sliver_Removal_vertices.clear(); + // pre_sliver_Removal_vertices.push_back(vh->point()); + + // previous_edges.clear(); + // previous_edges.push_back(std::make_pair(vh0->point(), vh1->point())); + //} + ///*************************************************************/ + + //Subdomain index? + typename C3t3::Subdomain_index subdomain = to_remove[0]->subdomain_index(); + visitor.before_flip(to_remove[0]); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + for (std::size_t i = 1; i < to_remove.size(); ++i) + CGAL_assertion(subdomain == to_remove[i]->subdomain_index()); +#endif + + std::vector cells_to_update; + + //Create new cells + for (const Facet& fi : facets_for_new_cells) + { + Cell_handle new_cell = tr.tds().create_cell(); + + for (int v = 0; v < 4; v++){ + new_cell->set_vertex(v, fi.first->vertex(v)); + } + + new_cell->set_vertex(fi.second, vh); + + c3t3.add_to_complex(new_cell, subdomain); + visitor.after_flip(new_cell); + cells_to_update.push_back(new_cell); + } + + //Update_existing cells + for (const Facet& fi : facets_for_updated_cells) + { + fi.first->set_vertex(fi.second, vh); + cells_to_update.push_back(fi.first); + } + + typedef CGAL::Triple Facet_vvv; + typedef boost::unordered_map FaceMapIndex; + + FaceMapIndex facet_map_indices; + std::vector facets; + + for (const Facet& f : neighbor_facets) + { + Cell_handle ch = f.first; + int v = f.second; + + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), + ch->vertex(indices(v,1)), + ch->vertex(indices(v,2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); + } + } + + //Update adjacencies and vertices cells + for (Cell_handle ch : cells_to_update) + { + for (int v = 0; v < 4; v++) + { + Facet_vvv face = make_vertex_triple(ch->vertex(indices(v,0)), + ch->vertex(indices(v,1)), + ch->vertex(indices(v,2))); + typename FaceMapIndex::iterator it = facet_map_indices.find(face); + if (it == facet_map_indices.end()) + { + facet_map_indices[face] = facets.size(); + facets.push_back(Facet(ch, v)); + } + else + { + Facet facet = facets[it->second]; + + //Update neighbor + facet.first->set_neighbor(facet.second, ch); + ch->set_neighbor(v, facet.first); + } + ch->vertex(v)->set_cell(ch); + } + } + + // Update c3t3 + update_c3t3_facets(c3t3, cells_to_update, neighbor_facets); + + //Remove cells + for (Cell_handle ch : to_remove) + { + c3t3.remove_from_complex(ch); + tr.tds().delete_cell(ch); + } + + ///********************VALIDITY CHECK***************************/ + //if (check_validity){ + + // double new_min_dh = DBL_MAX; + + // post_sliver_Removal_cells.clear(); + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // post_sliver_Removal_cells.push_back(cells_to_update[i]); + + // if (!tr.is_infinite(cells_to_update[i])) + // new_min_dh = std::min(new_min_dh, min_dihedral_angle(cells_to_update[i])); + // } + + // post_sliver_Removal_vertices.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // post_sliver_Removal_vertices.push_back(vertices_around_edge[i]); + // } + + // current_edges.clear(); + // for (unsigned int i = 0; i < vertices_around_edge.size(); ++i){ + // current_edges.push_back(std::make_pair(vertices_around_edge[i]->point(), vh->point())); + // } + + + // for (unsigned int i = 0; i < cells_to_update.size(); ++i){ + // if (!tr.is_valid(cells_to_update[i])) + // return INVALID_CELL; + + // for (int v = 0; v < 4; v++){ + // if (!tr.is_valid(cells_to_update[i]->neighbor(v))) + // return INVALID_CELL; + + // if (!tr.tds().is_valid(cells_to_update[i]->vertex(v))) + // return INVALID_VERTEX; + + // } + // } + + // if ((current_min_dh - new_min_dh) > 0.01){ + // std::cout << pre_sliver_Removal_cells.size() << " to " << post_sliver_Removal_cells.size() << " flip not improving the quality: " << + // current_min_dh << " to " << new_min_dh << std::endl; + // return INVALID_CELL; + // } + + //} + ///***********************************************************/ + + // std::cout << "n_to_m_flip::end with success" << std::endl; + + return VALID_FLIP; +} + + +template +Sliver_removal_result flip_n_to_m(typename C3t3::Edge& edge, + C3t3& c3t3, + std::vector& boundary_vertices, + const Flip_Criterion& criterion, + 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; + + //std::cout << "n_to_m_flip " << boundary_vertices.size() << std::endl; + if (criterion == MIN_ANGLE_BASED) + { + std::priority_queue candidates; + + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + FT curr_min_dh = min_dihedral_angle(tr, circ++); + while (circ != done) + { + curr_min_dh = (std::min)(curr_min_dh, min_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); + else + find_best_flip_to_improve_dh(c3t3, edge, candidates, curr_min_dh); + + bool flip_performed = false; + while (!candidates.empty() && !flip_performed) + { + Angle_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; + + if (curr_min_dh >= curr_cost_vpair.first) + return NO_BEST_CONFIGURATION; + + result = flip_n_to_m(c3t3, edge, curr_cost_vpair.second.first, visitor); + + if (result != NOT_FLIPPABLE) + flip_performed = true; + } + } + + return result; +} + +template +Sliver_removal_result find_best_flip(typename C3t3::Edge& edge, + C3t3& c3t3, + const Flip_Criterion& criterion, + Visitor& visitor) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename Tr::Facet_circulator Facet_circulator; + + Tr& tr = c3t3.triangulation(); + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + Facet_circulator circ = tr.incident_facets(edge); + Facet_circulator done = circ; + + //Identify the vertices around this edge + boost::unordered_set vertices_around_edge; + bool boundary_edge = false; + bool hull_edge = false; + + boost::unordered_set boundary_vertices; +// boost::unordered_set hull_vertices; + do + { + //Get the ids of the opposite vertices + for (int i = 0; i < 3; ++i) + { + Vertex_handle vi = circ->first->vertex(indices(circ->second, i)); + if (vi != v0 && vi != v1) + { + vertices_around_edge.insert(vi); + + if ( circ->first->subdomain_index() + != circ->first->neighbor(circ->second)->subdomain_index()) + { + boundary_edge = true; + boundary_vertices.insert(vi); + } + + if ( tr.is_infinite(circ->first) + != tr.is_infinite(circ->first->neighbor(circ->second))) + { + hull_edge = true; + //hull_vertices.insert(vi); + } + } + } + } + while (++circ != done); + + + //Check if not feature edge + if (boundary_vertices.size() > 2) + return NOT_FLIPPABLE; + + // perform flip when possible + Sliver_removal_result res = NOT_FLIPPABLE; + if (vertices_around_edge.size() == 3) + { + if (!boundary_edge && !hull_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); + } + } + else + { + //TODO fix for hull edges + // if( hull_edge ) + // return n_to_m_flip( edge, hull_vertices, flip_criterion, check_validity ); + if (!hull_edge) + { + std::vector vertices; + vertices.insert(vertices.end(), boundary_vertices.begin(), boundary_vertices.end()); + res = flip_n_to_m(edge, c3t3, vertices, criterion, visitor); + //return n_to_m_flip(edge, boundary_vertices, flip_criterion); + } + } + + + return res; +} + + +template +std::size_t flip_all_edges(const std::vector& edges, + C3t3& c3t3, + const Flip_Criterion& criterion, + Visitor& visitor) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Edge Edge; + + Tr& tr = c3t3.triangulation(); + + std::size_t count = 0; + for (const VertexPair vp : edges) + { + Cell_handle ch; + int i0, i1; + if (tr.is_edge(vp.first, vp.second, ch, i0, i1)) + { + Edge edge(ch, i0, i1); + + Sliver_removal_result res = find_best_flip(edge, c3t3, criterion, visitor); + if (res == INVALID_CELL || res == INVALID_VERTEX || res == INVALID_ORIENTATION) + { + std::cout << "FLIP PROBLEM!!!!" << std::endl; + return count; + } + if (res == VALID_FLIP) + { + ++count; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + std::cout << "\rFlip... ("; + std::cout << count << " flips)"; + std::cout.flush(); +#endif + } + } + } + return count; +} + +template +void flip_edges(C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + CGAL_USE(protect_boundaries); + typedef typename C3T3::Triangulation T3; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Flip edges..."; + std::cout.flush(); + std::size_t nb_flips = 0; +#endif + + //const Flip_Criterion criterion = VALENCE_MIN_DH_BASED; + + //collect long edges + + //compute vertices normals map? + + // typedef typename C3T3::Surface_patch_index Surface_patch_index; + // typedef boost::unordered_map Spi_map; + //if (!protect_boundaries) + //{ + // std::cout << "\tBoundary flips" << std::endl; + // //Boundary flip + // std::vector boundary_vertices_valences; + // std::vector boundary_edges; + + // collectBoundaryEdges(boundary_edges); + + // computeVerticesValences(boundary_vertices_valences); + + // if (criterion == VALENCE_BASED) + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, VALENCE_BASED); + // else + // flipBoundaryEdges(boundary_edges, boundary_vertices_valences, MIN_ANGLE_BASED); + //} + + std::vector inside_edges; + get_internal_edges(c3t3, + cell_selector, + std::back_inserter(inside_edges)); + + //if (criterion == VALENCE_BASED) + // flip_inside_edges(inside_edges); + //else + //{ +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + nb_flips = +#endif + flip_all_edges(inside_edges, c3t3, MIN_ANGLE_BASED, visitor); + //} + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_flips << " flips)." << std::endl; +#endif +} + +}//namespace internal +}//namespace Tetrahedral_remeshing +}//namespace CGAL + +#endif // CGAL_INTERNAL_FLIP_EDGES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h new file mode 100644 index 00000000000..04e20d13d92 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/smooth_vertices.h @@ -0,0 +1,713 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_INTERNAL_SMOOTH_VERTICES_H +#define CGAL_INTERNAL_SMOOTH_VERTICES_H + +#include + +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +template +class Tetrahedral_remeshing_smoother +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Edge Edge; + typedef typename Tr::Facet Facet; + + typedef typename Tr::Geom_traits Gt; + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point_3; + +private: + typedef CGAL::Tetrahedral_remeshing::internal::FMLS FMLS; + std::vector subdomain_FMLS; + boost::unordered_map subdomain_FMLS_indices; + +public: + template + void init(const C3t3& c3t3, const CellSelector& cell_selector) + { + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); + + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); + + // Build MLS Surfaces + createMLSSurfaces(subdomain_FMLS, + subdomain_FMLS_indices, + vertices_normals, + vertices_surface_indices, + c3t3); + } + +private: + + Vector_3 project_on_tangent_plane(const Vector_3& gi, + const Vector_3& pi, + const Vector_3& normal) + { + Vector_3 diff = pi - gi; + return gi + (normal * diff) * normal; + } + + template + boost::optional + find_adjacent_facet_on_surface(const Facet& f, + const Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) + { + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + typedef typename Tr::Facet_circulator Facet_circulator; + + if (c3t3.is_in_complex(edge)) + return {}; //do not "cross" complex edges + //they are likely to be sharp and not to follow the > 0 dot product criterion + + const Surface_patch_index& patch = c3t3.surface_patch_index(f); + const Facet& mf = c3t3.triangulation().mirror_facet(f); + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fend = fcirc; + do + { + const Facet fi = *fcirc; + if (f != fi + && mf != fi + && is_boundary(c3t3, fi, cell_selector) + && patch == c3t3.surface_patch_index(fi)) + { + return canonical_facet(fi); //"canonical" is important + } + } while (++fcirc != fend); + + return {}; + } + + template + Vector_3 compute_normal(const Facet& f, + const Vector_3& reference_normal, + const Gt& gt) + { + typename Gt::Construct_opposite_vector_3 + opp = gt.construct_opposite_vector_3_object(); + typename Gt::Compute_scalar_product_3 + scalar_product = gt.compute_scalar_product_3_object(); + + Vector_3 n = CGAL::Tetrahedral_remeshing::normal(f, gt); + if (scalar_product(n, reference_normal) < 0.) + n = opp(n); + + return n; + } + + template + void compute_vertices_normals(const C3t3& c3t3, + VertexNormalsMap& normals_map, + const CellSelector& cell_selector) + { + typename Tr::Geom_traits gt = c3t3.triangulation().geom_traits(); + typename Tr::Geom_traits::Construct_opposite_vector_3 + opp = gt.construct_opposite_vector_3_object(); + + const Tr& tr = c3t3.triangulation(); + + //collect all facet normals + boost::unordered_map fnormals; + for (const Facet& f : tr.finite_facets()) + { + if (is_boundary(c3t3, f, cell_selector)) + { + const Facet cf = canonical_facet(f); + fnormals[cf] = CGAL::NULL_VECTOR; + } + } + + for (const std::pair& fn : fnormals) + { + if(fn.second != CGAL::NULL_VECTOR) + continue; + + const Facet& f = fn.first; + const Facet& mf = tr.mirror_facet(f); + CGAL_assertion(is_boundary(c3t3, f, cell_selector)); + + Vector_3 start_ref = CGAL::Tetrahedral_remeshing::normal(f, tr.geom_traits()); + if (c3t3.triangulation().is_infinite(mf.first) + || c3t3.subdomain_index(mf.first) < c3t3.subdomain_index(f.first)) + start_ref = opp(start_ref); + fnormals[f] = start_ref; + + std::list facets; + facets.push_back(f); + while (!facets.empty()) + { + const Facet ff = facets.front(); + facets.pop_front(); + + const typename C3t3::Cell_handle ch = f.first; + const std::array, 3> edges + = {{ {{(ff.second + 1) % 4, (ff.second + 2) % 4}}, //edge 1-2 + {{(ff.second + 2) % 4, (ff.second + 3) % 4}}, //edge 2-3 + {{(ff.second + 3) % 4, (ff.second + 1) % 4}} //edge 3-1 + }}; //vertex indices in cells + + const Vector_3& ref = fnormals[f]; + for (const std::array& ei : edges) + { + Edge edge(ch, ei[0], ei[1]); + if (boost::optional neighbor + = find_adjacent_facet_on_surface(f, edge, c3t3, cell_selector)) + { + const Facet neigh = *neighbor; //already a canonical_facet + if (fnormals[neigh] == CGAL::NULL_VECTOR) //check it's not already computed + { + fnormals[neigh] = compute_normal(neigh, ref, gt); + facets.push_back(neigh); + } + } + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream osf("dump_facet_normals.polylines.txt"); +#endif + for (const auto& fn : fnormals) + { + const Facet& f = fn.first; + const Vector_3& n = fn.second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + typename Tr::Geom_traits::Point_3 fc + = CGAL::centroid(point(f.first->vertex(indices(f.second, 0))->point()), + point(f.first->vertex(indices(f.second, 1))->point()), + point(f.first->vertex(indices(f.second, 2))->point())); + osf << "2 " << fc << " " << (fc + n) << std::endl; +#endif + const Surface_patch_index& surf_i = c3t3.surface_patch_index(f); + + for (int i = 0; i < 3; ++i) + { + const Vertex_handle vi = f.first->vertex(indices(f.second, i)); + typename VertexNormalsMap::iterator patch_vector_it = normals_map.find(vi); + + if (patch_vector_it == normals_map.end() + || patch_vector_it->second.find(surf_i) == patch_vector_it->second.end()) + { + normals_map[vi][surf_i] = n; + } + else + { + normals_map[vi][surf_i] += n; + } + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + osf.close(); + std::ofstream os("dump_normals.polylines.txt"); + boost::unordered_map > ons_map; +#endif + + //normalize the computed normals + for (typename VertexNormalsMap::iterator vnm_it = normals_map.begin(); + vnm_it != normals_map.end(); ++vnm_it) + { + //value type is map + for (typename VertexNormalsMap::mapped_type::iterator it = vnm_it->second.begin(); + it != vnm_it->second.end(); ++it) + { + Vector_3& n = it->second; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + auto p = point(vnm_it->first->point()); + os << "2 " << p << " " << (p + n) << std::endl; +#endif + + CGAL::Tetrahedral_remeshing::normalize(n, c3t3.triangulation().geom_traits()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const Surface_patch_index si = it->first; + if (ons_map.find(si) == ons_map.end()) + ons_map[si] = std::vector(); + ons_map[si].push_back(typename Tr::Geom_traits::Segment_3(p, p + n)); +#endif + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os.close(); + for (auto& kv : ons_map) + { + std::ostringstream oss; + oss << "dump_normals_normalized_" << kv.first << ".polylines.txt"; + std::ofstream ons(oss.str()); + for (auto s : kv.second) + ons << "2 " << s.source() << " " << s.target() << std::endl; + ons.close(); + } +#endif + } + + boost::optional project(const Surface_patch_index& si, + const Vector_3& gi) + { + CGAL_assertion(subdomain_FMLS_indices.find(si) != subdomain_FMLS_indices.end()); + CGAL_assertion(!std::isnan(gi.x()) && !std::isnan(gi.y()) && !std::isnan(gi.z())); + + Vector_3 point(gi.x(), gi.y(), gi.z()); + Vector_3 res_normal = CGAL::NULL_VECTOR; + Vector_3 result(point); + + const FMLS& fmls = subdomain_FMLS[subdomain_FMLS_indices.at(si)]; + + int it_nb = 0; + const int max_it_nb = 5; + const double epsilon = fmls.getPNScale() / 1000.; + const double sq_eps = CGAL::square(epsilon); + + do + { + point = result; + + fmls.fastProjectionCPU(point, result, res_normal); + + if (std::isnan(result[0]) || std::isnan(result[1]) || std::isnan(result[2])) { + std::cout << "MLS error detected si " //<< si + << "\t(size : " << fmls.getPNSize() << ")" + << "\t(point = " << point << " )" << std::endl; + return {}; + } + } while ((result - point).squared_length() > sq_eps && ++it_nb < max_it_nb); + + return Vector_3(result[0], result[1], result[2]); + } + + template + void check_inversion_and_move(const typename Tr::Vertex_handle v, + const typename Tr::Point& final_pos, + const CellRange& inc_cells, + const Tr& /* tr */) + { + const typename Tr::Point backup = v->point(); //backup v's position + const typename Tr::Geom_traits::Point_3 pv = point(backup); + + 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)); + + bool valid_try = true; + for (const typename Tr::Cell_handle ci : inc_cells) + { + if (CGAL::POSITIVE != CGAL::orientation(point(ci->vertex(0)->point()), + point(ci->vertex(1)->point()), + point(ci->vertex(2)->point()), + point(ci->vertex(3)->point()))) + { + frac = 0.9 * frac; + valid_try = false; + break; + } + } + 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); + } + + void collect_vertices_surface_indices( + const C3t3& c3t3, + boost::unordered_map >& vertices_surface_indices) + { + for (typename C3t3::Facets_in_complex_iterator + fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + const Surface_patch_index& surface_index = c3t3.surface_patch_index(*fit); + + for (int i = 0; i < 3; i++) + { + const Vertex_handle vi = fit->first->vertex(indices(fit->second, i)); + + std::vector& v_surface_indices = vertices_surface_indices[vi]; + if (std::find(v_surface_indices.begin(), v_surface_indices.end(), surface_index) == v_surface_indices.end()) + v_surface_indices.push_back(surface_index); + } + } + } + +public: + template + void smooth_vertices(C3T3& c3t3, + const bool protect_boundaries, + const CellSelector& cell_selector) + { + typedef typename C3T3::Cell_handle Cell_handle; + typedef typename Gt::FT FT; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::ofstream os_surf("smooth_surfaces.polylines.txt"); + std::ofstream os_surf0("smooth_surfaces0.polylines.txt"); + std::ofstream os_vol("smooth_volume.polylines.txt"); +#endif + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Smooth vertices..."; + std::cout.flush(); + std::size_t nb_done = 0; +#endif + + Tr& tr = c3t3.triangulation(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES + //collect a map of vertices surface indices + boost::unordered_map > vertices_surface_indices; + collect_vertices_surface_indices(c3t3, vertices_surface_indices); +#endif + //collect a map of normals at surface vertices + boost::unordered_map > vertices_normals; + compute_vertices_normals(c3t3, vertices_normals, cell_selector); + + //smooth() + const std::size_t nbv = tr.number_of_vertices(); + boost::unordered_map vertex_id; + std::vector smoothed_positions(nbv, CGAL::NULL_VECTOR); + std::vector neighbors(nbv, -1); + + //collect ids + std::size_t id = 0; + for (const Vertex_handle v : tr.finite_vertex_handles()) + { + vertex_id[v] = id++; + } + + //collect incident cells + std::vector > + inc_cells(nbv, boost::container::small_vector()); + for (const Cell_handle c : tr.finite_cell_handles()) + { + for (int i = 0; i < 4; ++i) + { + const std::size_t idi = vertex_id[c->vertex(i)]; + inc_cells[idi].push_back(c); + } + } + + if (!protect_boundaries) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES + /////////////// EDGES IN COMPLEX ////////////////// + //collect neighbors + for (const Edge& e : tr.finite_edges()) + { + if (c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + + if (!c3t3.is_in_complex(vh0)) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!c3t3.is_in_complex(vh1)) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + if (!c3t3.is_in_complex(vh0) && on_feature_v1) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!c3t3.is_in_complex(vh1) && on_feature_v0) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + // Smooth + for (Vertex_handle v : tr.finite_vertex_handles()) + { + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / neighbors[vid]; + Vector_3 final_position = CGAL::NULL_VECTOR; + + std::size_t count = 0; + 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) + { + Vector_3 normal_projection + = project_on_tangent_plane(smoothed_position, current_pos, vertices_normals[v][si]); + + //Check if the mls surface exists to avoid degenerated cases + if (boost::optional mls_projection = project(si, normal_projection)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + normal_projection; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = smoothed_position; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + // move vertex + v->set_point(typename Tr::Point( + final_position.x(), final_position.y(), final_position.z())); + } + else if (neighbors[vid] > 0) + { + Vector_3 final_position = CGAL::NULL_VECTOR; + + int count = 0; + 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) + { + //Check if the mls surface exists to avoid degenerated cases + + if (boost::optional mls_projection = project(si, current_pos)) { + final_position = final_position + *mls_projection; + } + else { + final_position = final_position + current_pos; + } + count++; + } + + if (count > 0) + final_position = final_position / static_cast(count); + else + final_position = current_pos; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + // move vertex + v->set_point( + typename Tr::Point(final_position.x(), final_position.y(), final_position.z())); + } + } +#endif //CGAL_TETRAHEDRAL_REMESHING_SMOOTH_SHARP_EDGES + + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, -1); + + /////////////// EDGES ON SURFACE, BUT NOT IN COMPLEX ////////////////// + for (const Edge& e : tr.finite_edges()) + { + if (is_boundary(c3t3, e, cell_selector) && !c3t3.is_in_complex(e)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + const bool on_feature_v0 = is_on_feature(vh0); + const bool on_feature_v1 = is_on_feature(vh1); + + if (!on_feature_v0) + neighbors[i0] = (std::max)(0, neighbors[i0]); + if (!on_feature_v1) + neighbors[i1] = (std::max)(0, neighbors[i1]); + + if (!on_feature_v0) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(p1.x(), p1.y(), p1.z()); + neighbors[i0]++; + } + if (!on_feature_v1) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(p0.x(), p0.y(), p0.z()); + neighbors[i1]++; + } + } + } + + for (Vertex_handle v : tr.finite_vertex_handles()) + { + if (v->in_dimension() != 2) + continue; + + const std::size_t& vid = vertex_id.at(v); + if (neighbors[vid] > 1) + { + Vector_3 smoothed_position = smoothed_positions[vid] / static_cast(neighbors[vid]); + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + Vector_3 final_position = CGAL::NULL_VECTOR; + + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + Vector_3 normal_projection = project_on_tangent_plane(smoothed_position, + current_pos, + vertices_normals[v][si]); + + if (boost::optional mls_projection = project(si, normal_projection)) + final_position = final_position + *mls_projection; + else + final_position = smoothed_position; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf << "2 " << current_pos << " " << final_position << std::endl, +#endif + check_inversion_and_move(v, typename Tr::Point( + final_position.x(), final_position.y(), final_position.z()), + inc_cells[vid], + tr); + } + else if (neighbors[vid] > 0) + { + const Surface_patch_index si = surface_patch_index(v, c3t3); + CGAL_assertion(si != Surface_patch_index()); + + const Vector_3 current_pos(CGAL::ORIGIN, point(v->point())); + + if (boost::optional mls_projection = project(si, current_pos)) + { + const typename Tr::Point new_pos(CGAL::ORIGIN + *mls_projection); + check_inversion_and_move(v, new_pos, inc_cells[vid], tr); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_surf0 << "2 " << current_pos << " " << new_pos << std::endl; +#endif + } + } + } + } + CGAL_assertion(CGAL::Tetrahedral_remeshing::debug::are_cell_orientations_valid(tr)); + //// end if(!protect_boundaries) + + smoothed_positions.assign(nbv, CGAL::NULL_VECTOR); + neighbors.assign(nbv, 0/*for dim 3 vertices, start counting directly from 0*/); + + ////////////// INTERNAL VERTICES /////////////////////// + for (const Edge& e : tr.finite_edges()) + { + if (!is_outside(e, c3t3, cell_selector)) + { + const Vertex_handle vh0 = e.first->vertex(e.second); + const Vertex_handle vh1 = e.first->vertex(e.third); + + const std::size_t& i0 = vertex_id.at(vh0); + const std::size_t& i1 = vertex_id.at(vh1); + + if (c3t3.in_dimension(vh0) == 3) + { + const Point_3& p1 = point(vh1->point()); + smoothed_positions[i0] = smoothed_positions[i0] + Vector_3(CGAL::ORIGIN, p1); + neighbors[i0]++; + } + if (c3t3.in_dimension(vh1) == 3) + { + const Point_3& p0 = point(vh0->point()); + smoothed_positions[i1] = smoothed_positions[i1] + Vector_3(CGAL::ORIGIN, p0); + neighbors[i1]++; + } + } + } + + for (Vertex_handle v : tr.finite_vertex_handles()) + { + const std::size_t& vid = vertex_id.at(v); + if (c3t3.in_dimension(v) == 3 && neighbors[vid] > 1) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + ++nb_done; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << "2 " << point(v->point()); +#endif + const Vector_3 p = smoothed_positions[vid] / static_cast(neighbors[vid]); + check_inversion_and_move(v, typename Tr::Point(p.x(), p.y(), p.z()), inc_cells[vid], tr); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + os_vol << " " << point(v->point()) << std::endl; +#endif + } + } + 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; +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + c3t3.triangulation(), "c3t3_vertices_after_smoothing"); + os_surf.close(); + os_vol.close(); +#endif + } + +};//end class Tetrahedral_remeshing_smoother +}//namespace internal +}//namespace Tetrahedral_adaptive_remeshing +}//namespace CGAL + +#endif //CGAL_INTERNAL_SMOOTH_VERTICES_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h new file mode 100644 index 00000000000..f75c940d080 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/split_long_edges.h @@ -0,0 +1,333 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_INTERNAL_SPLIT_LONG_EDGES_H +#define CGAL_INTERNAL_SPLIT_LONG_EDGES_H + +#include + +#include +#include +#include +#include +#include + +#include + +#include +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +template +typename C3t3::Vertex_handle split_edge(const typename C3t3::Edge& e, + C3t3& c3t3) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename Tr::Geom_traits::Point_3 Point; + typedef typename Tr::Facet Facet; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell_circulator Cell_circulator; + + Tr& tr = c3t3.triangulation(); + const Vertex_handle v1 = e.first->vertex(e.second); + const Vertex_handle v2 = e.first->vertex(e.third); + + const Point m = tr.geom_traits().construct_midpoint_3_object() + (point(v1->point()), point(v2->point())); + + //backup subdomain info of incident cells before making changes + short dimension = (c3t3.is_in_complex(e)) ? 1 : 3; + boost::unordered_map cells_info; + boost::unordered_map > facets_info; + + // check orientation and collect incident cells to avoid circulating twice + boost::container::small_vector inc_cells; + Cell_circulator circ = tr.incident_cells(e); + Cell_circulator end = circ; + do + { + inc_cells.push_back(circ); + if (tr.is_infinite(circ)) + { + ++circ; + continue; + } + + //1st half-cell + std::array pts = { point(circ->vertex(0)->point()), + point(circ->vertex(1)->point()), + point(circ->vertex(2)->point()), + point(circ->vertex(3)->point()) }; + const int i1 = circ->index(v1); + const Point p1 = pts[i1]; + pts[i1] = m; + if(CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return Vertex_handle(); + + //2nd half-cell + pts[i1] = p1; + pts[circ->index(v2)] = m; + if (CGAL::orientation(pts[0], pts[1], pts[2], pts[3]) != CGAL::POSITIVE) + return Vertex_handle(); + + ++circ; + } + while (circ != end); + + for(Cell_handle c : inc_cells) + { + const int index_v1 = c->index(v1); + const int index_v2 = c->index(v2); + + //keys are the opposite facets to the ones not containing e, + //because they will not be modified + const Subdomain_index subdomain = c3t3.subdomain_index(c); + const Facet opp_facet1 = tr.mirror_facet(Facet(c, index_v1)); + const Facet opp_facet2 = tr.mirror_facet(Facet(c, index_v2)); + + // volume data + cells_info.insert(std::make_pair(opp_facet1, subdomain)); + cells_info.insert(std::make_pair(opp_facet2, subdomain)); + if (c3t3.is_in_complex(c)) + c3t3.remove_from_complex(c); + + // surface data for facets of the cells to be split + const int findex = CGAL::Triangulation_utils_3::next_around_edge(index_v1, index_v2); + if (c3t3.is_in_complex(c, findex)) + { + if (dimension == 3) + dimension = 2; + } + Surface_patch_index patch = c3t3.surface_patch_index(c, findex); + Vertex_handle opp_vertex = c->vertex(findex); + facets_info.insert(std::make_pair(opp_facet1, + std::make_pair(opp_vertex, patch))); + facets_info.insert(std::make_pair(opp_facet2, + std::make_pair(opp_vertex, patch))); + + if(c3t3.is_in_complex(c, findex)) + c3t3.remove_from_complex(c, findex); + } + + // insert midpoint + Vertex_handle new_v = tr.tds().insert_in_edge(e); + new_v->set_point(typename Tr::Point(m)); + new_v->set_dimension(dimension); + + // update c3t3 with subdomain and surface patch indices + std::vector new_cells; + tr.incident_cells(new_v, std::back_inserter(new_cells)); + for (Cell_handle new_cell : new_cells) + { + const Facet fi(new_cell, new_cell->index(new_v)); + const Facet mfi = tr.mirror_facet(fi); + + //get subdomain info back + CGAL_assertion(cells_info.find(mfi) != cells_info.end()); + Subdomain_index n_index = cells_info.at(mfi); + if (Subdomain_index() != n_index) + c3t3.add_to_complex(new_cell, n_index); + else + new_cell->set_subdomain_index(Subdomain_index()); + + // get surface info back + CGAL_assertion(facets_info.find(mfi) != facets_info.end()); + const std::pair v_and_opp_patch = facets_info.at(mfi); + + // facet opposite to new_v (status wrt c3t3 is unchanged) + new_cell->set_surface_patch_index(new_cell->index(new_v), + mfi.first->surface_patch_index(mfi.second)); + + // new half-facet (added or not to c3t3 depending on the stored surface patch index) + if (Surface_patch_index() == v_and_opp_patch.second) + new_cell->set_surface_patch_index(new_cell->index(v_and_opp_patch.first), + Surface_patch_index()); + else + c3t3.add_to_complex(new_cell, + new_cell->index(v_and_opp_patch.first), + v_and_opp_patch.second); + + // newly created internal facet + for (int i = 0; i < 4; ++i) + { + const Vertex_handle vi = new_cell->vertex(i); + if (vi == v1 || vi == v2) + { + new_cell->set_surface_patch_index(i, Surface_patch_index()); + break; + } + } + + //the 4th facet (new_v, v_and_opp_patch.first, v1 or v2) + // will have its patch tagged from the other side, if needed + } + + return new_v; +} + +template +bool can_be_split(const typename C3T3::Edge& e, + const C3T3& c3t3, + const bool protect_boundaries, + CellSelector cell_selector) +{ + if (is_outside(e, c3t3, cell_selector)) + return false; + + if (protect_boundaries) + { + if (c3t3.is_in_complex(e)) + return false; + else if (is_boundary(c3t3, e, cell_selector)) + return false; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (!is_internal(e, c3t3, cell_selector)) + { + std::cerr << "e is not inside!?" << std::endl; + typename C3T3::Vertex_handle v1 = e.first->vertex(e.second); + typename C3T3::Vertex_handle v2 = e.first->vertex(e.third); + std::cerr << v1->point() << " " << v2->point() << std::endl; + } +#endif + + CGAL_assertion(is_internal(e, c3t3, cell_selector)); + return true; + } + else + { + return true; + } +} + +template +void split_long_edges(C3T3& c3t3, + const typename C3T3::Triangulation::Geom_traits::FT& high, + const bool protect_boundaries, + CellSelector cell_selector, + Visitor& visitor) +{ + typedef typename C3T3::Triangulation T3; + typedef typename T3::Cell_handle Cell_handle; + typedef typename T3::Edge Edge; + typedef typename T3::Finite_edges_iterator Finite_edges_iterator; + typedef typename T3::Vertex_handle Vertex_handle; + typedef typename std::pair Edge_vv; + + typedef typename T3::Geom_traits Gt; + typedef typename T3::Geom_traits::FT FT; + typedef boost::bimap< + boost::bimaps::set_of, + boost::bimaps::multiset_of > > Boost_bimap; + typedef typename Boost_bimap::value_type long_edge; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Split long edges (" << high << ")..."; + std::cout.flush(); + std::size_t nb_splits = 0; +#endif + const FT sq_high = high*high; + + //collect long edges + T3& tr = c3t3.triangulation(); + Boost_bimap long_edges; + for (Finite_edges_iterator eit = tr.finite_edges_begin(); + eit != tr.finite_edges_end(); ++eit) + { + Edge e = *eit; + if (!can_be_split(e, c3t3, protect_boundaries, cell_selector)) + continue; + + typename Gt::Compute_squared_length_3 sql + = tr.geom_traits().compute_squared_length_3_object(); + FT sqlen = sql(tr.segment(e)); + if (sqlen > sq_high) + long_edges.insert(long_edge(make_vertex_pair(e), sqlen)); + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + debug::dump_edges(long_edges, "long_edges.polylines.txt"); + + std::ofstream ofs("midpoints.off"); + ofs << "OFF" << std::endl; + ofs << long_edges.size() << " 0 0" << std::endl; +#endif + while(!long_edges.empty()) + { + //the edge with longest length + typename Boost_bimap::right_map::iterator eit = long_edges.right.begin(); + Edge_vv e = eit->second; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + const double sqlen = eit->first; +#endif + long_edges.right.erase(eit); + + Cell_handle cell; + int i1, i2; + if ( tr.tds().is_edge(e.first, e.second, cell, i1, i2)) + { + Edge edge(cell, i1, i2); + + //check that splittability has not changed + if (!can_be_split(edge, c3t3, protect_boundaries, cell_selector)) + continue; + + visitor.before_split(tr, edge); + Vertex_handle vh = split_edge(edge, c3t3); + + if(vh != Vertex_handle()) + visitor.after_split(tr, vh); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if (vh != Vertex_handle()) + ofs << vh->point() << std::endl; +#endif + +#if defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS) \ +|| defined(CGAL_TETRAHEDRAL_REMESHING_VERBOSE) + if (vh != Vertex_handle()) + ++nb_splits; +#endif + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS + std::cout << "\rSplit (" << high << ")... (" + << long_edges.left.size() << " long edges, " + << "length = " << std::sqrt(sqlen) << ", " + << nb_splits << " splits)"; + std::cout.flush(); +#endif + } + }//end loop on long_edges + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + if(ofs.is_open()) + ofs.close(); +#endif + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << " done (" << nb_splits << " splits)." << std::endl; +#endif +} + +} // internal +} // Tetrahedral_remeshing +} // CGAL + +#endif // CGAL_INTERNAL_SPLIT_LONG_EDGES_H 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 new file mode 100644 index 00000000000..fb4234781ee --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_adaptive_remeshing_impl.h @@ -0,0 +1,554 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef TETRAHEDRAL_REMESHING_IMPL_H +#define TETRAHEDRAL_REMESHING_IMPL_H + +#include + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE_PROGRESS +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#endif + +#include +#include + +#include +#include +#include +#include + +#include +#include + + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ +namespace internal +{ +class Default_remeshing_visitor +{ +public: + template + void before_split(const Tr& /* tr */, const typename Tr::Edge& /* e */) {} + template + void after_split(const Tr& /* tr */, const typename Tr::Vertex_handle /* new_v */) {} + + template + void after_add_cell(CellHandleOld /* co */, CellHandleNew /* cn */) const {} + + template + void before_flip(const CellHandle /* c */) {} + template + void after_flip(CellHandle /* c */) {} +}; + +template +struct All_cells_selected +{ + typedef typename Tr::Cell_handle argument_type; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + + typedef bool result_type; + + result_type operator()(const argument_type c) const + { + return c->subdomain_index() != Subdomain_index(); + } +}; + +template +struct No_constraint_pmap +{ +public: + typedef Primitive key_type; + typedef bool value_type; + typedef value_type& reference; + typedef boost::read_write_property_map_tag category; + + friend bool get(const No_constraint_pmap&, const key_type&) { + return false; + } + friend void put(No_constraint_pmap&, const key_type&, const bool) {} +}; + +template +class Adaptive_remesher +{ + typedef Triangulation Tr; + typedef typename Tr::Geom_traits::FT FT; + + typedef CGAL::Mesh_complex_3_in_triangulation_3 C3t3; + + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Subdomain_index Subdomain_index; + typedef typename C3t3::Surface_patch_index Surface_patch_index; + + typedef Tetrahedral_remeshing_smoother Smoother; + +private: + C3t3 m_c3t3; + const SizingFunction& m_sizing; + const bool m_protect_boundaries; + CellSelector m_cell_selector; + Visitor& m_visitor; + Smoother m_vertex_smoother;//initialized with initial surface + + C3t3* m_c3t3_pbackup; + Triangulation* m_tr_pbackup; //backup to re-swap triangulations when done + +public: + Adaptive_remesher(Triangulation& tr + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) + : m_c3t3() + , m_sizing(sizing) + , m_protect_boundaries(protect_boundaries) + , m_cell_selector(cell_selector) + , m_visitor(visitor) + , m_c3t3_pbackup(NULL) + , m_tr_pbackup(&tr) + { + m_c3t3.triangulation().swap(tr); + + init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "00-init"); +#endif + } + + Adaptive_remesher(C3t3& c3t3 + , const SizingFunction& sizing + , const bool protect_boundaries + , EdgeIsConstrainedMap ecmap + , FacetIsConstrainedMap fcmap + , CellSelector cell_selector + , Visitor& visitor + ) + : m_c3t3() + , m_sizing(sizing) + , m_protect_boundaries(protect_boundaries) + , m_cell_selector(cell_selector) + , m_visitor(visitor) + , m_c3t3_pbackup(&c3t3) + , m_tr_pbackup(NULL) + { + m_c3t3.swap(c3t3); + + init_c3t3(ecmap, fcmap); + m_vertex_smoother.init(m_c3t3, m_cell_selector); + +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "00-init"); +#endif + } + + bool input_is_c3t3() const + { + return m_c3t3_pbackup != NULL; + } + + void split() + { + CGAL_assertion(check_vertex_dimensions()); + + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + const FT emax = FT(4)/FT(3) * target_edge_length; + split_long_edges(m_c3t3, emax, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "1-split"); +#endif + } + + void collapse() + { + CGAL_assertion(check_vertex_dimensions()); + + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + FT emin = FT(4)/FT(5) * target_edge_length; + FT emax = FT(4)/FT(3) * target_edge_length; + collapse_short_edges(m_c3t3, emin, emax, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "2-collapse"); +#endif + } + + void flip() + { + flip_edges(m_c3t3, m_protect_boundaries, + m_cell_selector, m_visitor); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "3-flip"); +#endif + } + + void smooth() + { + m_vertex_smoother.smooth_vertices(m_c3t3, m_protect_boundaries, m_cell_selector); + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); +#ifdef CGAL_DUMP_REMESHING_STEPS + CGAL::Tetrahedral_remeshing::debug::dump_c3t3(m_c3t3, "4-smooth"); +#endif + } + + bool resolution_reached() + { + const FT target_edge_length = m_sizing(CGAL::ORIGIN); + + FT emax = FT(4) / FT(3) * target_edge_length; + FT emin = FT(4) / FT(5) * target_edge_length; + + FT sqmax = emax * emax; + FT sqmin = emin * emin; + + typedef typename Tr::Edge Edge; + for (Edge e : tr().finite_edges()) + { + // skip protected edges + if (m_protect_boundaries) + { + if( m_c3t3.is_in_complex(e) + || is_boundary(m_c3t3, e, m_cell_selector)) + continue; + } + + FT sqlen = tr().segment(e).squared_length(); + if (sqlen < sqmin || sqlen > sqmax) + return false; + } + std::cout << "Resolution reached" << std::endl; + return true; + } + + //peel off slivers + std::size_t postprocess(const double sliver_angle = 0.1) + { + if (m_protect_boundaries) + return 0; + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Postprocess..."; + std::cout.flush(); +#endif + + std::size_t nb_slivers_peel = 0; + for (Cell_handle cit : tr().finite_cell_handles()) + { + if(m_c3t3.is_in_complex(cit) && min_dihedral_angle(tr(), cit) < sliver_angle) + { + for (int i = 0; i < 4; ++i) + { + if (!m_c3t3.is_in_complex(cit->neighbor(i))) + { + m_c3t3.remove_from_complex(cit); + ++nb_slivers_peel; + } + } + } + } + + CGAL_assertion(tr().tds().is_valid(true)); + CGAL_assertion(debug::are_cell_orientations_valid(tr())); + +#ifdef CGAL_DUMP_REMESHING_STEPS + 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; +#endif + return nb_slivers_peel; + } + + void finalize() + { + if (m_c3t3_pbackup != NULL) + m_c3t3_pbackup->swap(m_c3t3); + else + m_tr_pbackup->swap(m_c3t3.triangulation()); + } + +private: + void init_c3t3(const EdgeIsConstrainedMap& ecmap, + const FacetIsConstrainedMap& fcmap) + { +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::size_t nbc = 0; + std::size_t nbf = 0; + std::size_t nbe = 0; + std::size_t nbv = 0; +#endif + //tag cells + for (Cell_handle cit : tr().finite_cell_handles()) + { + if (m_cell_selector(cit)) + { + const Subdomain_index index = cit->subdomain_index(); + if(!input_is_c3t3()) + m_c3t3.remove_from_complex(cit); + m_c3t3.add_to_complex(cit, index); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbc; +#endif + } + if (!input_is_c3t3()) + { + for (int i = 0; i < 4; ++i) + { + if (cit->vertex(i)->in_dimension() == -1) + cit->vertex(i)->set_dimension(3); + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + else if (input_is_c3t3() && m_c3t3.is_in_complex(cit)) + ++nbc; +#endif + } + + //tag facets + typedef typename Tr::Facet Facet; + for (const Facet& f : tr().finite_facets()) + { + const Facet mf = tr().mirror_facet(f); + const Subdomain_index s1 = f.first->subdomain_index(); + const Subdomain_index s2 = mf.first->subdomain_index(); + if (s1 != s2 + || get(fcmap, f) + || get(fcmap, mf) + || (m_c3t3_pbackup == NULL && f.first->is_facet_on_surface(f.second))) + { + Surface_patch_index patch = f.first->surface_patch_index(f.second); + if(patch == Surface_patch_index()) + set_surface_patch_index_to_default(s1, s2, patch); + m_c3t3.add_to_complex(f, patch); + + const int i = f.second; + for (int j = 0; j < 3; ++j) + { + Vertex_handle vij = f.first->vertex(Tr::vertex_triple_index(i, j)); + if (vij->in_dimension() == -1 || vij->in_dimension() > 2) + vij->set_dimension(2); + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbf; +#endif + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_facets_in_complex(m_c3t3, "facets_in_complex.off"); +#endif + + //tag edges + typedef typename Tr::Edge Edge; + for (const Edge& e : tr().finite_edges()) + { + if (m_c3t3.is_in_complex(e)) + { + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.second)) <= 1); + CGAL_assertion(m_c3t3.in_dimension(e.first->vertex(e.third)) <= 1); +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif + continue; + } + + if (get(ecmap, CGAL::Tetrahedral_remeshing::make_vertex_pair(e)) + || nb_incident_subdomains(e, m_c3t3) > 2 + || nb_incident_surface_patches(e, m_c3t3) > 1) + { + m_c3t3.add_to_complex(e, 1); + + Vertex_handle v = e.first->vertex(e.second); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + + v = e.first->vertex(e.third); + if (v->in_dimension() == -1 || v->in_dimension() > 1) + v->set_dimension(1); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbe; +#endif + } + } +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + CGAL::Tetrahedral_remeshing::debug::dump_edges_in_complex(m_c3t3, "edges_in_complex.polylines.txt"); +#endif + + //tag vertices + unsigned int corner_id = 0; + for (Vertex_handle vit : tr().finite_vertex_handles()) + { + if ( vit->in_dimension() == 0 + || nb_incident_complex_edges(vit, m_c3t3) > 2) + { + if(!m_c3t3.is_in_complex(vit)) + m_c3t3.add_to_complex(vit, ++corner_id); + + if (vit->in_dimension() == -1 || vit->in_dimension() > 0) + vit->set_dimension(0); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + ++nbv; +#endif + } + } + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + std::cout << "C3t3 ready :" << std::endl; + std::cout << "\t cells = " << nbc << std::endl; + std::cout << "\t facets = " << nbf << std::endl; + std::cout << "\t edges = " << nbe << std::endl; + std::cout << "\t vertices = " << nbv << std::endl; + + CGAL::Tetrahedral_remeshing::debug::dump_vertices_by_dimension( + m_c3t3.triangulation(), "c3t3_vertices_"); +#endif + } + +private: + bool check_vertex_dimensions() + { + for (Vertex_handle vit : tr().finite_vertex_handles()) + { + // dimension is -1 for Mesh_3 "far points" + // for other vertices, it is in [0; 3] + if (vit->in_dimension() < -1 || vit->in_dimension() > 3) + return false; + } + return true; + } + + template + void set_surface_patch_index_to_default(const Subdomain_index&, + const Subdomain_index&, + PatchIndex& patch) + { + if(m_c3t3.number_of_facets() == 0) + patch = 1; + else + patch = m_c3t3.surface_patch_index(*m_c3t3.facets_in_complex_begin()); + } + + void set_surface_patch_index_to_default(const Subdomain_index& s1, + const Subdomain_index& s2, + std::pair& patch) + { + patch = (s1 < s2) ? std::make_pair(s1, s2) : std::make_pair(s2, s1); + } + +public: + Tr& tr() + { + return m_c3t3.triangulation(); + } + const Tr& tr() const + { + return m_c3t3.triangulation(); + } + + void remesh(const std::size_t& max_it, + const std::size_t& nb_extra_iterations) + { + std::size_t it_nb = 0; + while (it_nb < max_it) + { + ++it_nb; +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " #" << std::endl; +#endif + if (!resolution_reached()) + { + split(); + collapse(); + } + flip(); + smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), m_cell_selector, ossi.str().c_str()); +#endif + } + + while (it_nb < max_it + nb_extra_iterations) + { + ++it_nb; + + flip(); + smooth(); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "# Iteration " << it_nb << " (flip and smooth only) done : " + << tr().number_of_vertices() + << " vertices #" << std::endl; +#endif +#ifdef CGAL_DUMP_REMESHING_STEPS + std::ostringstream ossi; + ossi << "statistics_" << it_nb << ".txt"; + Tetrahedral_remeshing::internal::compute_statistics( + tr(), m_cell_selector, ossi.str().c_str()); +#endif + } + + postprocess(); //peel off boundary slivers + + finalize(); + //Warning : triangulation() is now empty + } + +};//end class Adaptive_remesher + +}//end namespace internal +}//end namespace Tetrahedral_remeshing +}//end namespace CGAL + +#endif //TETRAHEDRAL_REMESHING_IMPL_H 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 new file mode 100644 index 00000000000..d8e18c6d8fe --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/internal/tetrahedral_remeshing_helpers.h @@ -0,0 +1,1418 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef CGAL_INTERNAL_TET_REMESHING_HELPERS_H +#define CGAL_INTERNAL_TET_REMESHING_HELPERS_H + +#include + +#include +#include + +#include +#include +#include +#include + +#include + +namespace CGAL +{ +namespace Tetrahedral_remeshing +{ + +enum Subdomain_relation { EQUAL, DIFFERENT, INCLUDED, INCLUDES }; +enum Sliver_removal_result { INVALID_ORIENTATION, INVALID_CELL, INVALID_VERTEX, + NOT_FLIPPABLE, EDGE_PROBLEM, VALID_FLIP, NO_BEST_CONFIGURATION, EXISTING_EDGE }; + +template +CGAL::Point_3 point(const CGAL::Point_3& p) +{ + return p; +} +template +CGAL::Point_3 point(const CGAL::Weighted_point_3& wp) +{ + typename K::Construct_point_3 pt = K().construct_point_3_object(); + return pt(wp); +} + +template +CGAL::Vector_3 vec(const CGAL::Point_3& p) +{ + typename K::Construct_vector_3 v = K().construct_vector_3_object(); + return v(CGAL::ORIGIN, p); +} +template +CGAL::Vector_3 vec(const CGAL::Weighted_point_3& wp) +{ + return vec(point(wp)); +} + + +const int indices_table[4][3] = { { 3, 1, 2 }, + { 3, 2, 0 }, + { 3, 0, 1 }, + { 2, 1, 0 } }; + +int indices(const int& i, const int& j) +{ + CGAL_assertion(i < 4 && j < 3); + if(i < 4 && j < 3) + return indices_table[i][j]; + else + return -1; +} + +template +typename Gt::FT dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Gt& gt) +{ + return gt.compute_approximate_dihedral_angle_3_object()(p, q, r, s); +} + +template +typename Geom_traits::FT min_dihedral_angle(const Point& p, + const Point& q, + const Point& r, + const Point& s, + const Geom_traits& gt) +{ + typedef typename Geom_traits::FT FT; + 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)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(p, s, q, r, gt)); + min_dh = (std::min)(a, min_dh); + + 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)); + min_dh = (std::min)(a, min_dh); + + a = CGAL::abs(dihedral_angle(r, s, p, q, gt)); + min_dh = (std::min)(a, min_dh); + + return min_dh; +} + +template +typename Tr::Geom_traits::FT min_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 min_dihedral_angle(point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point()), + tr.geom_traits()); +} + +template +typename Tr::Geom_traits::FT min_dihedral_angle(const Tr& tr, + const typename Tr::Cell_handle c) +{ + return min_dihedral_angle(tr, + c->vertex(0), + c->vertex(1), + c->vertex(2), + c->vertex(3)); +} + +template +typename Tr::Geom_traits::Vector_3 facet_normal(const Tr& tr, + const typename Tr::Facet& f) +{ + const typename Tr::Geom_traits gt = tr.geom_traits(); + typename Tr::Geom_traits::Construct_normal_3 cn + = gt.construct_normal_3_object(); + return cn(point(f.first->vertex((f.second + 1) % 4)->point()), + point(f.first->vertex((f.second + 2) % 4)->point()), + point(f.first->vertex((f.second + 3) % 4)->point())); +} + +template +std::pair make_vertex_pair(const Vh v1, const Vh v2) +{ + if (v2 < v1) return std::make_pair(v2, v1); + else return std::make_pair(v1, v2); +} + +template +std::pair +make_vertex_pair(const typename Tr::Edge& e) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + Vertex_handle v1 = e.first->vertex(e.second); + Vertex_handle v2 = e.first->vertex(e.third); + return make_vertex_pair(v1, v2); +} + +template +CGAL::Triple make_vertex_triple(const Vh vh0, const Vh vh1, const Vh vh2) +{ + CGAL::Triple ft(vh0, vh1, vh2); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + if (ft.template get<2>() < ft.template get<1>()) std::swap(ft.template get<1>(), ft.template get<2>()); + if (ft.template get<1>() < ft.template get<0>()) std::swap(ft.template get<0>(), ft.template get<1>()); + return ft; +} + +template +std::array make_vertex_array(const Vh vh0, const Vh vh1, const Vh vh2) +{ + std::array ft = { {vh0, vh1, vh2} }; + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + if (ft[2] < ft[1]) std::swap(ft[1], ft[2]); + if (ft[1] < ft[0]) std::swap(ft[0], ft[1]); + return ft; +} + +template +Facet canonical_facet(const Facet& f) +{ + const typename Facet::first_type c = f.first; + const int i = f.second; + const typename Facet::first_type c2 = c->neighbor(i); + return (c2 < c) ? std::make_pair(c2, c2->index(c)) : std::make_pair(c, i); +} + +template +bool is_on_feature(const VertexHandle v) +{ + return (v->in_dimension() == 1 || v->in_dimension() == 0); +} + +template +bool is_well_oriented(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 CGAL::POSITIVE == tr.geom_traits().orientation_3_object()( + point(v0->point()), + point(v1->point()), + point(v2->point()), + point(v3->point())); +} + +template +bool is_well_oriented(const Tr& tr, const typename Tr::Cell_handle ch) +{ + return is_well_oriented(tr, ch->vertex(0), ch->vertex(1), + ch->vertex(2), ch->vertex(3)); +} + +template +bool is_boundary(const C3T3& c3t3, + const typename C3T3::Facet& f, + const CellSelector& cell_selector) +{ + return c3t3.is_in_complex(f) + || cell_selector(f.first) != cell_selector(f.first->neighbor(f.second)); +} + +template +bool is_boundary(const C3T3& c3t3, + const typename C3T3::Triangulation::Edge& e, + CellSelector cell_selector) +{ + typedef typename C3T3::Triangulation Tr; + typedef typename Tr::Facet_circulator Facet_circulator; + typedef typename Tr::Facet Facet; + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(e); + Facet_circulator fend = fcirc; + + do + { + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) + return true; + } + while (++fcirc != fend); + + return false; +} + +template +bool is_boundary_edge(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return is_boundary(c3t3, Edge(cell, i0, i1), cell_selector); + else + return false; +} + +template +bool is_boundary_vertex(const typename C3t3::Vertex_handle& v, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + for(const Facet& f : facets) + { + if (c3t3.is_in_complex(f)) + return true; + if (cell_selector(f.first) ^ cell_selector(f.first->neighbor(f.second))) + return true; + } + return false; +} + +template +typename C3t3::Surface_patch_index surface_patch_index(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Surface_patch_index Surface_patch_index; + typedef typename C3t3::Facet Facet; + std::vector facets; + c3t3.triangulation().incident_facets(v, std::back_inserter(facets)); + + for(const Facet& f : facets) + { + if (c3t3.is_in_complex(f)) + return c3t3.surface_patch_index(f); + } + return Surface_patch_index(); +} + +template +bool is_edge_in_complex(const typename C3t3::Vertex_handle& v0, + const typename C3t3::Vertex_handle& v1, + const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Cell_handle Cell_handle; + + Cell_handle cell; + int i0, i1; + if (c3t3.triangulation().tds().is_edge(v0, v1, cell, i0, i1)) + return c3t3.is_in_complex(Edge(cell, i0, i1)); + else + return false; +} + +template +OutputIterator incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for (std::size_t i = 0; i < cells.size(); ++i) + *oit++ = cells[i]->subdomain_index(); + + return oit; +} + +template +OutputIterator incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + + Cell_circulator circ = c3t3.triangulation().incident_cells(e); + Cell_circulator end = circ; + do + { + *oit++ = circ->subdomain_index(); + } while (++circ != end); + + return oit; +} + +template +OutputIterator incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3, + OutputIterator oit) +{ + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + typedef typename C3t3::Triangulation::Facet Facet; + + Facet_circulator circ = c3t3.triangulation().incident_facets(e); + Facet_circulator end = circ; + do + { + const Facet& f = *circ; + if(c3t3.is_in_complex(f)) + *oit++ = c3t3.surface_patch_index(f); + } + while (++circ != end); + + return oit; +} + +template +std::size_t nb_incident_subdomains(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(v, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_subdomains(const typename C3t3::Edge& e, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + boost::unordered_set indices; + incident_subdomains(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_surface_patches(const typename C3t3::Edge& e, + const C3t3& c3t3) +{ + typedef typename C3t3::Surface_patch_index Surface_patch_index; + + boost::unordered_set indices; + incident_surface_patches(e, c3t3, std::inserter(indices, indices.begin())); + + return indices.size(); +} + +template +std::size_t nb_incident_complex_edges(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + boost::unordered_set edges; + c3t3.triangulation().finite_incident_edges(v, std::inserter(edges, edges.begin())); + + std::size_t count = 0; + for (const Edge& e : edges) + { + if (c3t3.is_in_complex(e)) + ++count; + } + return count; +} + + +template +bool is_feature(const typename C3t3::Vertex_handle v, + const typename C3t3::Vertex_handle neighbor, + const C3t3& c3t3) +{ + typename C3t3::Cell_handle ch; + int i0, i1; + if (c3t3.triangulation().is_edge(v, neighbor, ch, i0, i1)) + { + typename C3t3::Edge edge(ch, i0, i1); + return c3t3.is_in_complex(edge); + } + return false; +} + +template +bool is_feature(const typename C3t3::Vertex_handle v, const C3t3& c3t3) +{ + typedef typename C3t3::Edge Edge; + + if (c3t3.number_of_corners() > 0) + { + return c3t3.is_in_complex(v); + } + else if (nb_incident_subdomains(v, c3t3) > 3) + { + std::vector edges; + c3t3.triangulation().finite_incident_edges(v, std::back_inserter(edges)); + + int feature_count = 0; + for(const Edge& ei : edges) + { + if (c3t3.is_in_complex(ei)) + { + feature_count++; + if (feature_count >= 3) + return true; + } + } + } + return false; +} + +/** +* returns true iff `v` is on the outer hull of c3t3.triangulation() +* i.e. finite and incident to at least one infinite cell +*/ +template +bool is_on_convex_hull(const typename C3t3::Vertex_handle v, + const C3t3& c3t3) +{ + if (v == c3t3.triangulation().infinite_vertex()) + return true; + + //on hull == incident to infinite cell + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + for (Cell_handle ci : cells) + { + if (c3t3.triangulation().is_infinite(ci)) + return true; + } + return false; +} + +/** +* returns true iff `edge` is on the outer hull +* of c3t3.triangulation() +* i.e. finite and incident to at least one infinite cell +*/ +template +bool is_on_convex_hull(const typename C3t3::Edge & edge, + const C3t3& c3t3) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + if (c3t3.triangulation().is_infinite(circ)) + return true; + } while (++circ != done); + + return false; +} + +template +bool is_outside(const typename C3t3::Edge & edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + do + { + // is cell in complex? + if (c3t3.is_in_complex(circ)) + return false; + // does circ belong to the selection? + if (cell_selector(circ)) + return false; + + ++circ; + } while (circ != done); + + return true; //all incident cells are outside or infinite +} + +template +bool is_selected(const typename C3t3::Vertex_handle v, + const C3t3& c3t3, + CellSelector cell_selector) +{ + typedef typename C3t3::Triangulation::Cell_handle Cell_handle; + + std::vector cells; + c3t3.triangulation().incident_cells(v, std::back_inserter(cells)); + + for(Cell_handle c : cells) + { + if (cell_selector(c)) + return true; + } + return false; +} + +template +bool is_internal(const typename C3t3::Edge& edge, + const C3t3& c3t3, + CellSelector cell_selector) +{ + const typename C3t3::Vertex_handle vs = edge.first->vertex(edge.second); + const typename C3t3::Vertex_handle vt = edge.first->vertex(edge.third); + + typedef typename C3t3::Triangulation::Cell_circulator Cell_circulator; + Cell_circulator circ = c3t3.triangulation().incident_cells(edge); + Cell_circulator done = circ; + + const typename C3t3::Subdomain_index si = circ->subdomain_index(); + do + { + if (c3t3.triangulation().is_infinite(circ)) + return false; + if (si != circ->subdomain_index()) + return false; + if (!cell_selector(circ)) + return false; + if (c3t3.is_in_complex( + circ, + CGAL::Triangulation_utils_3::next_around_edge(circ->index(vs), circ->index(vt)))) + return false; + } while (++circ != done); + + return true; +} + +template +void normalize(typename Gt::Vector_3& v, const Gt& gt) +{ + typedef typename Gt::FT FT; + + const FT norm = CGAL::approximate_sqrt(gt.compute_squared_length_3_object()(v)); + if (norm != FT(0)) + v = gt.construct_divided_vector_3_object()(v, norm); +} + +template +typename Gt::Vector_3 normal(const Facet& f, const Gt& gt) +{ + typedef typename Gt::Vector_3 Vector_3; + typedef typename Gt::Point_3 Point; + typedef typename Gt::FT FT; + + Point p0 = point(f.first->vertex((f.second + 1) % 4)->point()); + Point p1 = point(f.first->vertex((f.second + 2) % 4)->point()); + const Point& p2 = point(f.first->vertex((f.second + 3) % 4)->point()); + + if (f.second % 2 == 0)//equivalent to the commented orientation test + std::swap(p0, p1); + + Vector_3 n = gt.construct_cross_product_vector_3_object()( + gt.construct_vector_3_object()(p1, p2), + gt.construct_vector_3_object()(p1, p0)); + + //cross-product(AB, AC)'s norm is the area of the parallelogram + //formed by these 2 vectors. + //the triangle's area is half of it + return gt.construct_scaled_vector_3_object()(n, FT(1) / FT(2)); +} + +template +OutputIterator get_internal_edges(const C3t3& c3t3, + CellSelector cell_selector, + OutputIterator oit)/*holds Edges*/ +{ + for (typename C3t3::Triangulation::Finite_edges_iterator + eit = c3t3.triangulation().finite_edges_begin(); + eit != c3t3.triangulation().finite_edges_end(); + ++eit) + { + const typename C3t3::Edge& e = *eit; + if (is_internal(e, c3t3, cell_selector)) + { + *oit++ = make_vertex_pair(e); + } + } + return oit; +} + +template +bool topology_test(const typename C3t3::Edge& edge, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + typedef typename C3t3::Cell_handle Cell_handle; + typedef typename C3t3::Edge Edge; + typedef typename C3t3::Facet Facet; + typedef typename C3t3::Triangulation::Facet_circulator Facet_circulator; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + // the "topology test" checks that : + // no incident non-boundary facet has 3 boundary edges + // no incident boundary facet has 3 feature edges + + Facet_circulator fcirc = c3t3.triangulation().incident_facets(edge); + Facet_circulator fdone = fcirc; + do + { + if (c3t3.triangulation().is_infinite(fcirc->first)) + continue; + + const Facet& f = *fcirc; + if (is_boundary(c3t3, f, cell_selector)) + //boundary : check that facet does not have 3 feature edges + { + //Get the ids of the opposite vertices + for (int i = 1; i < 4; i++) + { + Vertex_handle vi = f.first->vertex((f.second + i) % 4); + if (vi != v0 && vi != v1 && nb_incident_subdomains(vi, c3t3) > 1) + { + if (is_edge_in_complex(v0, vi, c3t3) + && is_edge_in_complex(v1, vi, c3t3)) + return false; + } + } + } + else //non-boundary : check that facet does not have 3 boundary edges + { + const Cell_handle circ = f.first; + const int i = f.second; + if (is_boundary(c3t3, Edge(circ, (i + 1) % 4, (i + 2) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 2) % 4, (i + 3) % 4), cell_selector) + && is_boundary(c3t3, Edge(circ, (i + 3) % 4, (i + 1) % 4), cell_selector)) + return false; + } + } while (++fcirc != fdone); + + return true; +} + +template +Subdomain_relation compare_subdomains(const typename C3t3::Vertex_handle v0, + const typename C3t3::Vertex_handle v1, + const C3t3& c3t3) +{ + typedef typename C3t3::Subdomain_index Subdomain_index; + + std::vector subdomains_v0; + incident_subdomains(v0, c3t3, std::back_inserter(subdomains_v0)); + std::sort(subdomains_v0.begin(), subdomains_v0.end()); + + std::vector subdomains_v1; + incident_subdomains(v1, c3t3, std::back_inserter(subdomains_v1)); + std::sort(subdomains_v1.begin(), subdomains_v1.end()); + + if (subdomains_v0.size() == subdomains_v1.size()) + { + for (unsigned int i = 0; i < subdomains_v0.size(); i++) + if (subdomains_v0[i] != subdomains_v1[i]) + return DIFFERENT; + return EQUAL; + } + else + { + std::vector + intersection((std::min)(subdomains_v0.size(), subdomains_v1.size()), -1); + typename std::vector::iterator + end_it = std::set_intersection(subdomains_v0.begin(), subdomains_v0.end(), + subdomains_v1.begin(), subdomains_v1.end(), + intersection.begin()); + std::ptrdiff_t intersection_size = (end_it - intersection.begin()); + + if (subdomains_v0.size() > subdomains_v1.size() + && intersection_size == std::ptrdiff_t(subdomains_v1.size())) + { + return INCLUDES; + } + else if (intersection_size == std::ptrdiff_t(subdomains_v0.size())) { + return INCLUDED; + } + } + return DIFFERENT; +} + +template +void get_edge_info(const typename C3t3::Edge& edge, + bool& update_v0, + bool& update_v1, + const C3t3& c3t3, + const CellSelector& cell_selector) +{ + typedef typename C3t3::Vertex_handle Vertex_handle; + + update_v0 = false; + update_v1 = false; + + const Vertex_handle v0 = edge.first->vertex(edge.second); + const Vertex_handle v1 = edge.first->vertex(edge.third); + + const int dim0 = c3t3.in_dimension(v0); + const int dim1 = c3t3.in_dimension(v1); + + if (dim0 == 3) + { + CGAL_assertion(!is_on_convex_hull(v0, c3t3)); + update_v0 = true; + if (dim1 == 3) + { + CGAL_assertion(!is_on_convex_hull(v1, c3t3)); + update_v1 = true; + return; + } + else // dim1 is 2, 1, or 0 + return; + } + else if (dim1 == 3) + { + update_v1 = true; + return; + } + + // from now on, all cases lie on surfaces, or between surfaces + CGAL_assertion(dim0 != 3 && dim1 != 3); + + //feature edges and feature vertices + if (dim0 < 2 || dim1 < 2) + { + if (c3t3.is_in_complex(edge)) + { + if (!topology_test(edge, c3t3, cell_selector)) + { +#ifdef CGAL_DEBUG_TET_REMESHING_IN_PLUGIN + nb_topology_test++; +#endif + return; + } + const std::size_t nb_si_v0 = nb_incident_subdomains(v0, c3t3); + const std::size_t nb_si_v1 = nb_incident_subdomains(v1, c3t3); + + if (nb_si_v0 > nb_si_v1) { + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + else if (nb_si_v1 > nb_si_v0) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + } + else { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + return; + } + + if (dim0 == 2 && dim1 == 2) + { + if (is_boundary(c3t3, edge, cell_selector)) + { + if (!topology_test(edge, c3t3, cell_selector)) + return; + Subdomain_relation subdomain_rel = compare_subdomains(v0, v1, c3t3); + + //Vertices on the same surface + if (subdomain_rel == INCLUDES) { + update_v1 = true; + } + else if (subdomain_rel == INCLUDED) { + update_v0 = true; + } + else if (subdomain_rel == EQUAL) + { + if (c3t3.number_of_edges() == 0) + { + update_v0 = true; + update_v1 = true; + } + else + { + const bool v0_on_feature = is_on_feature(v0); + const bool v1_on_feature = is_on_feature(v1); + + if (v0_on_feature && v1_on_feature) { + if (c3t3.is_in_complex(edge)) { + if (!c3t3.is_in_complex(v0)) + update_v0 = true; + if (!c3t3.is_in_complex(v1)) + update_v1 = true; + } + } + else { + if (!v0_on_feature) { + update_v0 = true; + } + if (!v1_on_feature) { + update_v1 = true; + } + } + } + } + } + } +} + +namespace debug +{ + +// forward-declaration +template +void dump_cells(const CellRange& cells, const char* filename); + +template +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) + { + ofs << "2 " << point(it.first.first->point()) + << " " << point(it.first.second->point()) << std::endl; + } + ofs.close(); +} + +template +void dump_facet(const Facet& f, OutputStream& os) +{ + os << "4 "; + os << point(f.first->vertex((f.second + 1) % 4)->point()) << " " + << point(f.first->vertex((f.second + 2) % 4)->point()) << " " + << point(f.first->vertex((f.second + 3) % 4)->point()) << " " + << point(f.first->vertex((f.second + 1) % 4)->point()); + os << std::endl; +} + +template +void dump_facets(const FacetRange& facets, const char* filename) +{ + std::ofstream os(filename); + for (typename FacetRange::value_type f : facets) + { + dump_facet(f, os); + } + os.close(); +} + +template +void dump_polylines(const CellRange& cells, const char* filename) +{ + std::ofstream ofs(filename); + if (!ofs) return; + + for (typename CellRange::const_iterator it = cells.begin(); + it != cells.end(); ++it) + { + for (int i = 0; i < 4; ++i) + dump_facet(std::make_pair(*it, i), ofs); + } + ofs.close(); +} + +template +bool are_cell_orientations_valid(const Tr& tr) +{ + typedef typename Tr::Geom_traits::Point_3 Point_3; + typedef typename Tr::Facet Facet; + + std::set facets; + for (const typename Tr::Cell_handle ch : tr.finite_cell_handles()) + { + const Point_3& p0 = point(ch->vertex(0)->point()); + const Point_3& p1 = point(ch->vertex(1)->point()); + const Point_3& p2 = point(ch->vertex(2)->point()); + const Point_3& p3 = point(ch->vertex(3)->point()); + + const CGAL::Orientation o = CGAL::orientation(p0, p1, p2, p3); + if (o != CGAL::POSITIVE) + { + facets.insert(canonical_facet(Facet(ch, 0))); + facets.insert(canonical_facet(Facet(ch, 1))); + facets.insert(canonical_facet(Facet(ch, 2))); + facets.insert(canonical_facet(Facet(ch, 3))); + } + } + if (!facets.empty()) + { + std::cerr << "Warning : there are inverted cells!\n" + << "\tSee cells_with_negative_volume.polylines.txt" << std::endl; + dump_facets(facets, "cells_with_negative_volume.polylines.txt"); + } + return facets.empty(); +} + +template +void dump_surface_off(const Tr& tr, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) + { + nbf++; + for (int j = 1; j < 4; ++j) + { + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); + } + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << point(vit->second->point()) << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + if (tr.is_infinite(c) || tr.is_infinite(c->neighbor(i))) + { + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; + } + } + CGAL_assertion(nbf == nbf_print); + + ofs.close(); +} + +template +void dump_cells_off(const CellRange& cells, const Tr& /*tr*/, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + Bimap_t vertices; + int index = 0; + boost::unordered_set > facets; + + for (Cell_handle c : cells) + { + //collect vertices + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = c->vertex(i); + if (vertices.left.find(c->vertex(i)) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); + } + //collect facets + for (int i = 0; i < 4; ++i) + { + //if (tr.is_infinite(c->neighbor(i))) + { + std::array fi = make_vertex_array(c->vertex((i + 1) % 4), + c->vertex((i + 2) % 4), + c->vertex((i + 3) % 4)); + facets.insert(fi); + } + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.size() << " " << facets.size() << " 0" << std::endl << std::endl; + + for(const typename Bimap_t::right_map::value_type& v : vertices.right) + ofs << v.second->point().x() << " " + << v.second->point().y() << " " + << v.second->point().z() << std::endl; + + for(const std::array& f : facets) + ofs << "3 " << vertices.left.at(f[0]) << " " + << vertices.left.at(f[1]) << " " + << vertices.left.at(f[2]) << std::endl; + + ofs.close(); +} + +template +void dump_cells_off(const Tr& tr, const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Finite_facets_iterator Finite_facets_iterator; + typedef typename Tr::Finite_vertices_iterator Finite_vertices_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << tr.number_of_vertices() + << " " << tr.number_of_finite_facets() << " 0" << std::endl << std::endl; + + //collect and write vertices + Bimap_t vertices; + int index = 0; + for (Finite_vertices_iterator vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); ++vit) + { + vertices.left.insert(value_type(vit, index++)); + ofs << vit->point().x() << " " + << vit->point().y() << " " + << vit->point().z() << std::endl; + } + + //write facets + for (Finite_facets_iterator fit = tr.finite_facets_begin(); + fit != tr.finite_facets_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + } + ofs.close(); +} + +template +void dump_cells_polylines(const CellRange& cells, const char* filename) +{ + std::ofstream ofs(filename); + ofs.precision(17); + for (auto c : cells) + { + ofs << "2 " << point(c->vertex(0)->point()) << " " + << point(c->vertex(1)->point()) <vertex(0)->point()) << " " + << point(c->vertex(2)->point()) << std::endl; + ofs << "2 " << point(c->vertex(0)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + ofs << "2 " << point(c->vertex(1)->point()) << " " + << point(c->vertex(2)->point()) << std::endl; + ofs << "2 " << point(c->vertex(1)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + ofs << "2 " << point(c->vertex(2)->point()) << " " + << point(c->vertex(3)->point()) << std::endl; + } + ofs.close(); +} + +template +void dump_cells(const CellRange& cells, + const IndexRange& indices, + const char* filename) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Point Point; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + CGAL_assertion(indices.empty() || cells.size() == indices.size()); + + //collect vertices + Bimap_t vertices; + int index = 1; + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + for (int i = 0; i < 4; ++i) + { + Vertex_handle vi = (*cit)->vertex(i); + if (vertices.left.find(vi) == vertices.left.end()) + vertices.left.insert(value_type(vi, index++)); + } + } + + //write cells + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "MeshVersionFormatted 1" << std::endl; + ofs << "Dimension 3" << std::endl; + ofs << "Vertices" << std::endl << vertices.size() << std::endl; + for (typename Bimap_t::right_const_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); + ++vit) + { + const Point& p = vit->second->point(); + ofs << p.x() << " " << p.y() << " " << p.z() << " 2" << std::endl; + } + ofs << "Tetrahedra " << std::endl << cells.size() << std::endl; + typename IndexRange::const_iterator iit = indices.begin(); + for (typename CellRange::const_iterator cit = cells.begin(); + cit != cells.end(); + ++cit) + { + ofs << vertices.left.at((*cit)->vertex(0)) + << " " << vertices.left.at((*cit)->vertex(1)) + << " " << vertices.left.at((*cit)->vertex(2)) + << " " << vertices.left.at((*cit)->vertex(3)); + + if (iit == indices.end()) + ofs << " 1" << std::endl; + else + { + ofs << " " << (*iit) << std::endl; + ++iit; + } + } + ofs << "End" << std::endl; + ofs.close(); +} + +template +void dump_cells(const CellRange& cells, const char* filename) +{ + std::vector indices; + dump_cells(cells, indices, filename); +} + +template +void dump_cells_in_complex(const Tr& tr, const char* filename) +{ + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + if (cit->subdomain_index() > 0) + { + cells.push_back(cit); + indices.push_back(cit->subdomain_index()); + } + } + dump_cells(cells, indices, filename); +} + +template +void dump_facets_in_complex(const C3t3& c3t3, const char* filename) +{ + typedef typename C3t3::Triangulation Tr; + typedef typename Tr::Vertex_handle Vertex_handle; + typedef typename Tr::Cell_handle Cell_handle; + typedef typename C3t3::Facets_in_complex_iterator Facets_in_complex_iterator; + typedef boost::bimap Bimap_t; + typedef typename Bimap_t::left_map::value_type value_type; + + //collect vertices + Bimap_t vertices; + std::size_t nbf = 0; + int index = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + + nbf++; + for (int j = 1; j < 4; ++j) + { + Vertex_handle vij = c->vertex((i + j) % 4); + if (vertices.left.find(vij) == vertices.left.end()) + vertices.left.insert(value_type(vij, index++)); + } + } + + //write header + std::ofstream ofs(filename); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices.left.size() << " " << nbf << " 0" << std::endl << std::endl; + + // write vertices + for (typename Bimap_t::right_iterator vit = vertices.right.begin(); + vit != vertices.right.end(); ++vit) + { + ofs << point(vit->second->point()) << std::endl; + } + + //write facets + std::size_t nbf_print = 0; + for (Facets_in_complex_iterator fit = c3t3.facets_in_complex_begin(); + fit != c3t3.facets_in_complex_end(); ++fit) + { + Cell_handle c = fit->first; + int i = fit->second; + ofs << "3 " << vertices.left.at(c->vertex((i + 1) % 4)) << " " + << vertices.left.at(c->vertex((i + 2) % 4)) << " " + << vertices.left.at(c->vertex((i + 3) % 4)) << std::endl; + ++nbf_print; + } + CGAL_assertion(nbf == nbf_print); + + ofs.close(); +} + +template +void dump_edges_in_complex(const C3T3& c3t3, const char* filename) +{ + std::ofstream ofs(filename); + ofs.precision(17); + for (typename C3T3::Edges_in_complex_iterator eit = c3t3.edges_in_complex_begin(); + eit != c3t3.edges_in_complex_end(); ++eit) + { + const typename C3T3::Edge& e = *eit; + ofs << "2 " + << point(e.first->vertex(e.second)->point()) << " " + << point(e.first->vertex(e.third)->point()) << "\n"; + } + ofs.close(); +} + +template +void dump_cells_with_small_dihedral_angle(const Tr& tr, + const double angle_bound, + CellSelector cell_select, + const char* filename) +{ + typedef typename Tr::Cell_handle Cell_handle; + typedef typename Tr::Cell::Subdomain_index Subdomain_index; + std::vector cells; + std::vector indices; + + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + Cell_handle c = cit; + if ( c->subdomain_index() != Subdomain_index() + && cell_select(c) + && min_dihedral_angle(tr, c) < angle_bound) + { + + cells.push_back(c); + indices.push_back(c->subdomain_index()); + } + } + std::cout << "bad cells : " << cells.size() << std::endl; + dump_cells(cells, indices, filename); +} + +template +void dump_vertices_by_dimension(const Tr& tr, const char* prefix) +{ + typedef typename Tr::Vertex_handle Vertex_handle; + std::vector< std::vector > vertices_per_dimension(4); + + for (typename Tr::Finite_vertices_iterator + vit = tr.finite_vertices_begin(); + vit != tr.finite_vertices_end(); + ++vit) + { + if (vit->in_dimension() == -1) + continue;//far point + CGAL_assertion(vit->in_dimension() >= 0 && vit->in_dimension() < 4); + + vertices_per_dimension[vit->in_dimension()].push_back(vit); + } + + for (int i = 0; i < 4; ++i) + { + //dimension is i + const std::vector& vertices_di = vertices_per_dimension[i]; + + std::cout << "Dimension " << i << " : " << vertices_di.size() << std::endl; + + std::ostringstream oss; + oss << prefix << "_dimension_" << i << ".off"; + + std::ofstream ofs(oss.str()); + ofs.precision(17); + ofs << "OFF" << std::endl; + ofs << vertices_di.size() << " 0 0" << std::endl << std::endl; + + for (Vertex_handle vj : vertices_di) + { + ofs << point(vj->point()) << std::endl; + } + + ofs.close(); + } +} + +template +void dump_triangulation_cells(const Tr& tr, const char* filename) +{ + std::vector cells(tr.number_of_finite_cells()); + std::vector indices(tr.number_of_finite_cells()); + int i = 0; + for (typename Tr::Finite_cells_iterator cit = tr.finite_cells_begin(); + cit != tr.finite_cells_end(); ++cit) + { + cells[i] = cit; + indices[i++] = cit->subdomain_index(); + } + dump_cells(cells, indices, filename); +} + +template +void dump_binary(const C3t3& c3t3, const char* filename) +{ + std::ofstream os(filename, std::ios::binary | std::ios::out); + CGAL::Mesh_3::save_binary_file(os, c3t3); + os.close(); +} + +template +void dump_medit(const C3t3& c3t3, const char* filename) +{ + std::ofstream os(filename, std::ios::out); + c3t3.output_to_medit(os, true, true); + os.close(); +} + +template +void dump_c3t3(const C3t3& c3t3, const char* filename_no_extension) +{ + std::string filename_medit(filename_no_extension); + filename_medit.append(".mesh"); + dump_medit(c3t3, filename_medit.c_str()); + + std::string filename_binary(filename_no_extension); + filename_binary.append(".binary.cgal"); + dump_binary(c3t3, filename_binary.c_str()); +} + + +} //namespace debug +} //namespace Tetrahedral_remeshing +} //namespace CGAL + +#endif //CGAL_INTERNAL_TET_REMESHING_HELPERS_H diff --git a/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h new file mode 100644 index 00000000000..7ecfff2b82c --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/Tetrahedral_remeshing/tetrahedral_remeshing_io.h @@ -0,0 +1,55 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#include + +#include +#include + +namespace CGAL +{ +template +bool load_triangulation(std::istream& is, T3& t3) +{ + std::string s; + if (!(is >> s)) return false; + bool binary = (s == "binary"); + if (binary) { + if (!(is >> s)) return false; + } + if (s != "CGAL" || !(is >> s) || s != "c3t3") + return false; + + std::getline(is, s); + if (binary) CGAL::set_binary_mode(is); + else CGAL::set_ascii_mode(is); + is >> t3; + return bool(is); +} + +template +bool save_binary_triangulation(std::ostream& os, const T3& t3) +{ + os << "binary CGAL c3t3\n"; + CGAL::set_binary_mode(os); + return !!(os << t3); +} + +template +bool save_ascii_triangulation(std::ostream& os, const T3& t3) +{ + os << "CGAL c3t3\n"; + CGAL::set_ascii_mode(os); + return !!(os << t3); +} + +} \ No newline at end of file diff --git a/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h new file mode 100644 index 00000000000..7877002a0d5 --- /dev/null +++ b/Tetrahedral_remeshing/include/CGAL/tetrahedral_remeshing.h @@ -0,0 +1,402 @@ +// Copyright (c) 2020 GeometryFactory (France) and Telecom Paris (France). +// All rights reserved. +// +// This file is part of CGAL (www.cgal.org) +// +// $URL$ +// $Id$ +// SPDX-License-Identifier: GPL-3.0-or-later OR LicenseRef-Commercial +// +// +// Author(s) : Jane Tournois, Noura Faraj + +#ifndef TETRAHEDRAL_REMESHING_H +#define TETRAHEDRAL_REMESHING_H + +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include + +#ifdef CGAL_DUMP_REMESHING_STEPS +#include +#endif + +namespace CGAL +{ +/////////////////////////////////////////////////// +///////////////// TRIANGULATION_3 ///////////////// +/////////////////////////////////////////////////// +/*! +* \ingroup PkgTetrahedralRemeshingRef +* remeshes a tetrahedral mesh. +* +* It is recommended to use `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` +* for the first parameter, as it inherits from `Triangulation_3` with a `TDS` suitable for this function. +* +* This function takes as input a 3-dimensional triangulation +* and performs a sequence of atomic operations +* in order to generate as output a high quality mesh with a prescribed +* uniform density. +* These atomic operations are performed as follows: +* - edge splits, until all edges satisfy a prescribed length criterion, +* - edge collapses, until all edges satisfy a prescribed length criterion, +* - edge flips, to locally improve dihedral angles, until they can +* no longer be improved by flipping, +* - global smoothing by vertex relocations, +* - re-projection of boundary vertices to the initial surface. +* +* This remeshing function can deal with multi-domains, boundaries, and features. +* It preserves the geometry of +* subdomains throughout the remeshing process. +* +* Subdomains are defined by indices that +* are stored in the cells of the input triangulation, following the `MeshCellBase_3` +* concept (refined by `RemeshingCellBase_3`). +* The surfacic interfaces between subdomains are formed by facets whose two incident cells +* have different subdomain indices. +* The edges where three or more subdomains meet form feature polylines, +* and are considered as constrained edges. +* +* +* @tparam Traits is the geometric traits, model of `RemeshingTriangulationTraits_3` +* @tparam TDS is the triangulation data structure for `Triangulation_3`, +* model of ` TriangulationDataStructure_3`, +* with cell base model of `RemeshingCellBase_3` +* and vertex base model of `RemeshingVertexBase_3`. +* @tparam SLDS is an optional parameter for `Triangulation_3`, that +* specifies the type of the spatial lock data structure. +* @tparam NamedParameters a sequence of \ref Remeshing_namedparameters "Named Parameters" +* +* @param tr the triangulation to be remeshed, of type `Triangulation_3`. +* `Remeshing_triangulation` is a helper class that satisfies all the requirements +* of its template parameters. +* @param target_edge_length the uniform target edge length. This parameter provides a +* mesh density target for the remeshing algorithm. +* @param np optional sequence of \ref Remeshing_namedparameters "Named Parameters" +* among the ones listed below +* +* \cgalNamedParamsBegin +* \cgalParamBegin{number_of_iterations} the number of iterations for the full +* sequence of atomic operations +* performed (listed in the above description) +* \cgalParamEnd +* \cgalParamBegin{remesh_boundaries} If `false`, none of the input volume boundaries +* can be modified. +* Otherwise, the topology is preserved, but atomic operations can be performed on the +* surfaces, and along feature polylines, such that boundaries are remeshed. +* \cgalParamEnd +* \cgalParamBegin{edge_is_constrained_map} a property map containing the +* constrained - or - not status of each edge of `tr`. A constrained edge can be split +* or collapsed, but not flipped. +* \cgalParamEnd +* \cgalParamBegin{facet_is_constrained_map} a property map containing the +* constrained - or - not status of each facet of `tr`. A constrained facet can be split +* or collapsed, but not flipped. +* \cgalParamEnd +* \cgalParamBegin{cell_is_selected_map} a property map containing the +* selected - or - not status for each cell of `tr` for remeshing. +* Only selected cells are modified (and possibly their neighbors if surfaces are +* modified) by remeshing. +* By default, all cells with a non-zero `Subdomain_index` are selected. +* \cgalParamEnd +* \cgalNamedParamsEnd +* +* \sa `CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3` +* +* @todo implement non-uniform sizing field instead of uniform target edge length +*/ +template +void tetrahedral_isotropic_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length, + const NamedParameters& np) +{ + typedef CGAL::Triangulation_3 Triangulation; + tetrahedral_isotropic_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& /* p */) + {return target_edge_length;}, + np); +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Triangulation_3& tr, + const float& target_edge_length, + const NamedParameters& np) +{ + typedef CGAL::Triangulation_3 Triangulation; + tetrahedral_isotropic_remeshing( + tr, + [target_edge_length](const typename Triangulation::Point& /* p */) + {return target_edge_length; }, + np); +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Triangulation_3& tr, + const SizingFunction& sizing, + const NamedParameters& np) +{ + CGAL_assertion(tr.is_valid(true)); + + typedef CGAL::Triangulation_3 Tr; + + using parameters::choose_parameter; + using parameters::get_parameter; + + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), + true); + bool protect = !remesh_surfaces; + // bool adaptive = choose_parameter(get_parameter(np, internal_np::adaptive_size), + // false); + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), + 1); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_parameter(get_parameter(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); + + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; + typedef typename internal_np::Lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + No_edge()); + + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename internal_np::Lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), + No_facet()); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; + + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, Visitor> Remesher; + Remesher remesher(tr, sizing, protect + , ecmap, fcmap + , cell_select + , visitor); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.tr(), cell_select, "statistics_begin.txt"); +#endif + + // perform remeshing + std::size_t nb_extra_iterations = 3; + remesher.remesh(max_it, nb_extra_iterations); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle(tr, + angle_bound, cell_select, "bad_cells.mesh"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics(tr, + cell_select, "statistics_end.txt"); +#endif +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Triangulation_3& tr, + const double& target_edge_length) +{ + tetrahedral_isotropic_remeshing(tr, target_edge_length, + CGAL::parameters::all_default()); +} + +/////////////////////////////////////////////////// +/////// MESH_COMPLEX_3_IN_TRIANGULATION_3 ///////// +/////////////////////////////////////////////////// + +template +void tetrahedral_isotropic_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length, + const NamedParameters& np) +{ + tetrahedral_isotropic_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& /* p */) + {return target_edge_length; }, + np); +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const float& target_edge_length, + const NamedParameters& np) +{ + tetrahedral_isotropic_remeshing( + c3t3, + [target_edge_length](const typename Tr::Point& /*p*/) + {return target_edge_length; }, + np); +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const double& target_edge_length) +{ + return tetrahedral_isotropic_remeshing(c3t3, target_edge_length, + CGAL::parameters::all_default()); +} + +template +void tetrahedral_isotropic_remeshing( + CGAL::Mesh_complex_3_in_triangulation_3& c3t3, + const SizingFunction& sizing, + const NamedParameters& np) +{ + CGAL_assertion(c3t3.triangulation().tds().is_valid(true)); + + using parameters::get_parameter; + using parameters::choose_parameter; + + bool remesh_surfaces = choose_parameter(get_parameter(np, internal_np::remesh_boundaries), + true); + bool protect = !remesh_surfaces; + std::size_t max_it = choose_parameter(get_parameter(np, internal_np::number_of_iterations), 1); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::cell_selector_t, + NamedParameters, + Tetrahedral_remeshing::internal::All_cells_selected//default + > ::type SelectionFunctor; + SelectionFunctor cell_select + = choose_parameter(get_parameter(np, internal_np::cell_selector), + Tetrahedral_remeshing::internal::All_cells_selected()); + + typedef std::pair Edge_vv; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_edge; + typedef typename internal_np::Lookup_named_param_def < + internal_np::edge_is_constrained_t, + NamedParameters, + No_edge//default + > ::type ECMap; + ECMap ecmap = choose_parameter(get_parameter(np, internal_np::edge_is_constrained), + No_edge()); + + typedef typename Tr::Facet Facet; + typedef Tetrahedral_remeshing::internal::No_constraint_pmap No_facet; + typedef typename internal_np::Lookup_named_param_def < + internal_np::facet_is_constrained_t, + NamedParameters, + No_facet//default + > ::type FCMap; + FCMap fcmap = choose_parameter(get_parameter(np, internal_np::facet_is_constrained), + No_facet()); + + typedef typename internal_np::Lookup_named_param_def < + internal_np::remeshing_visitor_t, + NamedParameters, + Tetrahedral_remeshing::internal::Default_remeshing_visitor + > ::type Visitor; + Visitor visitor + = choose_parameter(get_parameter(np, internal_np::remeshing_visitor), + Tetrahedral_remeshing::internal::Default_remeshing_visitor()); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "Tetrahedral remeshing (" + << "nb_iter = " << max_it << ", " + << "protect = " << std::boolalpha << protect + << ")" << std::endl; + + std::cout << "Init tetrahedral remeshing..."; + std::cout.flush(); +#endif + + typedef Tetrahedral_remeshing::internal::Adaptive_remesher< + Tr, SizingFunction, ECMap, FCMap, SelectionFunctor, + Visitor, + CornerIndex, CurveIndex + > Remesher; + Remesher remesher(c3t3, sizing, protect + , ecmap, fcmap + , cell_select + , visitor); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + std::cout << "done." << std::endl; + Tetrahedral_remeshing::internal::compute_statistics( + remesher.tr(), + cell_select, "statistics_begin.txt"); +#endif + + // perform remeshing + std::size_t nb_extra_iterations = 3; + remesher.remesh(max_it, nb_extra_iterations); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_DEBUG + const double angle_bound = 5.0; + Tetrahedral_remeshing::debug::dump_cells_with_small_dihedral_angle( + c3t3.triangulation(), + angle_bound, cell_select, "bad_cells.mesh"); +#endif +#ifdef CGAL_TETRAHEDRAL_REMESHING_VERBOSE + Tetrahedral_remeshing::internal::compute_statistics( + c3t3.triangulation(), + cell_select, "statistics_end.txt"); +#endif +} + +}//end namespace CGAL + +#endif //TETRAHEDRAL_REMESHING_H diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright new file mode 100644 index 00000000000..a49b9cc8d1a --- /dev/null +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/copyright @@ -0,0 +1,2 @@ +GeometryFactory (France) +Telecom Paris (France) diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies new file mode 100644 index 00000000000..8004efd9b07 --- /dev/null +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/dependencies @@ -0,0 +1,31 @@ +Algebraic_foundations +Arithmetic_kernel +BGL +Cartesian_kernel +Circulator +Distance_2 +Distance_3 +Filtered_kernel +Hash_map +Homogeneous_kernel +Installation +Interval_support +Intersections_2 +Intersections_3 +Kernel_23 +Kernel_d +Mesh_3 +Modular_arithmetic +Number_types +Polygon +Polygon_mesh_processing +Profiling_tools +Property_map +Random_numbers +Spatial_sorting +STL_Extension +Stream_support +Tetrahedral_remeshing +TDS_3 +Triangulation_3 +Union_find diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/license.txt b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/license.txt new file mode 100644 index 00000000000..8bb8efcb72b --- /dev/null +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/license.txt @@ -0,0 +1 @@ +GPL (v3 or later) diff --git a/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/maintainer b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/maintainer new file mode 100644 index 00000000000..dd58aa4afc8 --- /dev/null +++ b/Tetrahedral_remeshing/package_info/Tetrahedral_remeshing/maintainer @@ -0,0 +1 @@ +Jane Tournois diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt new file mode 100644 index 00000000000..46119c8c74f --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/CMakeLists.txt @@ -0,0 +1,28 @@ +# Created by the script cgal_create_CMakeLists +# This is the CMake script for compiling a set of CGAL applications. + +cmake_minimum_required(VERSION 3.1...3.14) + +project( Tetrahedral_remeshing_Tests ) + +# CGAL and its components +find_package( CGAL REQUIRED ) +if ( NOT CGAL_FOUND ) + message(STATUS "This project requires the CGAL library, and will not be compiled.") + return() +endif() + +# Boost and its components +find_package( Boost REQUIRED ) +if ( NOT Boost_FOUND ) + message(STATUS "This project requires the Boost library, and will not be compiled.") + return() +endif() + + +# Creating entries for all C++ files with "main" routine +# ########################################################## +create_single_source_cgal_program( "test_tetrahedral_remeshing.cpp" ) +create_single_source_cgal_program( "test_tetrahedral_remeshing_with_features.cpp") +create_single_source_cgal_program( "test_tetrahedral_remeshing_of_one_subdomain.cpp") +create_single_source_cgal_program( "test_tetrahedral_remeshing_io.cpp") diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp new file mode 100644 index 00000000000..b3341824a82 --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing.cpp @@ -0,0 +1,63 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_DUMP_REMESHING_STEPS +#define CGAL_TETRAHEDRAL_REMESHING_DEBUG +//#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + +#include + +#include +#include +#include + +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +template +void generate_input_one_subdomain(const std::size_t nbv, T3& tr) +{ + CGAL::Random rng; + + typedef typename T3::Point Point; + std::vector pts; + while (pts.size() < nbv) + { + const float x = rng.uniform_real(-1.f, 1.f); + const float y = rng.uniform_real(-1.f, 1.f); + const float z = rng.uniform_real(-1.f, 1.f); + + pts.push_back(Point(x, y, z)); + } + tr.insert(pts.begin(), pts.end()); + + for (typename T3::Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + CGAL_assertion(tr.is_valid(true)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + std::ofstream out("data/triangulation_one_subdomain.binary.cgal", + std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(out, tr); + out.close(); +#endif +} + +int main(int argc, char* argv[]) +{ + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + Remeshing_triangulation tr; + generate_input_one_subdomain(1000, tr); + + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length); + + return EXIT_SUCCESS; +} diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp new file mode 100644 index 00000000000..c2cbe1406cc --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_io.cpp @@ -0,0 +1,78 @@ +#include + +#include +#include +#include + +#include + +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Cell_handle Cell_handle; + + +int main(int argc, char* argv[]) +{ + const unsigned int nbv = (argc > 1) ? atoi(argv[1]) : 100; + + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + std::vector points; + while (points.size() < nbv) + { + Point p(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.)); + points.push_back(p); + } + + + Remeshing_triangulation tr(points.begin(), points.end()); + + for (Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(1); + + std::cout << "save_ascii_triangulation : "; + std::cout.flush(); + std::ofstream out1("remeshing_triangulation.ascii.cgal", + std::ios_base::out); + bool ok = CGAL::save_ascii_triangulation(out1, tr); + out1.close(); + assert(ok); + std::cout << "done." << std::endl; + + Remeshing_triangulation tr1; + std::cout << "load_triangulation (ascii) : "; + std::cout.flush(); + std::ifstream in1("remeshing_triangulation.ascii.cgal", + std::ios_base::in); + ok = CGAL::load_triangulation(in1, tr1); + assert(ok); + std::cout << "done." << std::endl; + + std::cout << "save_binary_triangulation : "; + std::cout.flush(); + std::ofstream out2("remeshing_triangulation.binary.cgal", + std::ios_base::out | std::ios_base::binary); + ok = CGAL::save_binary_triangulation(out2, tr); + out2.close(); + assert(ok); + std::cout << "done." << std::endl; + + Remeshing_triangulation tr2; + std::cout << "load_triangulation (binary) : "; + std::cout.flush(); + std::ifstream in2("remeshing_triangulation.binary.cgal", + std::ios_base::in | std::ios_base::binary); + ok = CGAL::load_triangulation(in2, tr2); + assert(ok); + std::cout << "done." << std::endl; + + return EXIT_SUCCESS; +} diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp new file mode 100644 index 00000000000..6133e647b0e --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_of_one_subdomain.cpp @@ -0,0 +1,81 @@ +#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + +#include + +#include +#include +#include + +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +void generate_input_two_subdomains(const std::size_t nbv, Remeshing_triangulation& tr) +{ + CGAL::Random rng; + + typedef Remeshing_triangulation::Point Point; + typedef Remeshing_triangulation::Cell_handle Cell_handle; + + while (tr.number_of_vertices() < nbv) + tr.insert(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + + const Remeshing_triangulation::Geom_traits::Plane_3 + plane(Point(0, 0, 0), Point(0, 1, 0), Point(0, 0, 1)); + + for (Cell_handle c : tr.finite_cell_handles()) + { + if (plane.has_on_positive_side( + CGAL::centroid(c->vertex(0)->point(), c->vertex(1)->point(), + c->vertex(2)->point(), c->vertex(3)->point()))) + c->set_subdomain_index(1); + else + c->set_subdomain_index(2); + } + CGAL_assertion(tr.is_valid(true)); + +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + std::ofstream os("data/triangulation_two_subdomains.binary.cgal", + std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(os, tr); + os.close(); +#endif +} + +struct Cells_of_subdomain +{ +private: + const int m_subdomain; + +public: + Cells_of_subdomain(const int& subdomain) + : m_subdomain(subdomain) + {} + + bool operator()(Remeshing_triangulation::Cell_handle c) const + { + return m_subdomain == c->subdomain_index(); + } +}; + +int main(int argc, char* argv[]) +{ + std::cout << "CGAL Random seed = " + << CGAL::get_default_random().get_seed() << std::endl; + + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.1; + + Remeshing_triangulation tr; + generate_input_two_subdomains(1000, tr); + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, + CGAL::parameters::cell_selector(Cells_of_subdomain(2))); + + return EXIT_SUCCESS; +} + diff --git a/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp new file mode 100644 index 00000000000..3ca850d78e6 --- /dev/null +++ b/Tetrahedral_remeshing/test/Tetrahedral_remeshing/test_tetrahedral_remeshing_with_features.cpp @@ -0,0 +1,161 @@ +#define CGAL_TETRAHEDRAL_REMESHING_VERBOSE +#define CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + +#include + +#include +#include +#include + +#include +#include + +#include + +#include +#include +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; + +typedef CGAL::Tetrahedral_remeshing::Remeshing_triangulation_3 Remeshing_triangulation; + +typedef Remeshing_triangulation::Point Point; +typedef Remeshing_triangulation::Vertex_handle Vertex_handle; +typedef Remeshing_triangulation::Cell_handle Cell_handle; +typedef Remeshing_triangulation::Edge Edge; + +class Constrained_edges_property_map +{ +public: + typedef bool value_type; + typedef bool reference; + typedef std::pair key_type; + typedef boost::read_write_property_map_tag category; + +private: + boost::unordered_set* m_set_ptr; + +public: + Constrained_edges_property_map() + : m_set_ptr(NULL) + {} + Constrained_edges_property_map(boost::unordered_set* set_) + : m_set_ptr(set_) + {} + +public: + friend void put(Constrained_edges_property_map& map, + const key_type& k, + const bool b) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + if (b) map.m_set_ptr->insert(k); + else map.m_set_ptr->erase(k); + } + + friend value_type get(const Constrained_edges_property_map& map, + const key_type& k) + { + CGAL_assertion(map.m_set_ptr != NULL); + CGAL_assertion(k.first < k.second); + return map.m_set_ptr->count(k) > 0; + } +}; + +void add_edge(Vertex_handle v1, + Vertex_handle v2, + const Remeshing_triangulation& tr, + boost::unordered_set >& constraints) +{ + Cell_handle c; + int i, j; + if(tr.is_edge(v1, v2, c, i, j)) + constraints.insert(std::make_pair(v1, v2)); +} + +void generate_input_cube(const std::size_t& n, + Remeshing_triangulation& tr, + boost::unordered_set >& constraints) +{ + CGAL::Random rng; + + // points in a sphere + std::vector pts; + while (pts.size() < n) + pts.push_back(Point(rng.get_double(-1., 1.), rng.get_double(-1., 1.), rng.get_double(-1., 1.))); + tr.insert(pts.begin(), pts.end()); + + // vertices of a larger cube + Vertex_handle v0 = tr.insert(Point(-2., -2., -2.)); + Vertex_handle v1 = tr.insert(Point(-2., -2., 2.)); + + Vertex_handle v2 = tr.insert(Point( 2., -2., -2.)); + Vertex_handle v3 = tr.insert(Point( 2., -2., 2.)); + + Vertex_handle v4 = tr.insert(Point(-2., 2., -2.)); + Vertex_handle v5 = tr.insert(Point(-2., 2., 2.)); + + Vertex_handle v6 = tr.insert(Point( 2., 2., -2.)); + Vertex_handle v7 = tr.insert(Point( 2., 2., 2.)); + + CGAL_assertion(tr.is_valid(true)); + + // writing file output +#ifdef CGAL_TETRAHEDRAL_REMESHING_GENERATE_INPUT_FILES + std::ofstream outfile("data/sphere_in_cube.tr.cgal", + std::ios_base::out | std::ios_base::binary); + CGAL::save_binary_triangulation(outfile, tr); + outfile.close(); +#endif + + // constrain cube edges + add_edge(v0, v1, tr, constraints); + add_edge(v1, v2, tr, constraints); + add_edge(v2, v3, tr, constraints); + add_edge(v3, v0, tr, constraints); + + add_edge(v4, v5, tr, constraints); + add_edge(v5, v6, tr, constraints); + add_edge(v6, v7, tr, constraints); + add_edge(v7, v4, tr, constraints); + + add_edge(v0, v4, tr, constraints); + add_edge(v1, v5, tr, constraints); + add_edge(v2, v6, tr, constraints); + add_edge(v3, v7, tr, constraints); + + CGAL_assertion(tr.is_valid(true)); +} + +void set_subdomain(Remeshing_triangulation& tr, const int index) +{ + for (Cell_handle c : tr.finite_cell_handles()) + c->set_subdomain_index(index); +} + +int main(int argc, char* argv[]) +{ + CGAL::Random rng; + std::cout << "CGAL Random seed = " << CGAL::get_default_random().get_seed() << std::endl; + + Remeshing_triangulation tr; + boost::unordered_set > constraints; + generate_input_cube(1000, tr, constraints); + + const double target_edge_length = (argc > 1) ? atof(argv[1]) : 0.02; + const int nb_iter = (argc > 2) ? atoi(argv[2]) : 1; + + set_subdomain(tr, 1); + assert(tr.is_valid()); + + CGAL::tetrahedral_isotropic_remeshing(tr, target_edge_length, + CGAL::parameters::edge_is_constrained_map( + Constrained_edges_property_map(&constraints)) + .number_of_iterations(nb_iter)); + + return EXIT_SUCCESS; +} + diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h index 5d38a4e9cf9..3c32f97f7c5 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSFullCell.h @@ -107,7 +107,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h index 2ef050f82fe..5e3def7d9bd 100644 --- a/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h +++ b/Triangulation/doc/Triangulation/Concepts/TriangulationDSVertex.h @@ -106,7 +106,7 @@ void * for_compact_container() const; /*! */ -void * & for_compact_container(); +void for_compact_container(void *p); /// @} diff --git a/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h b/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h index d5f0735c8e8..3b6508f6017 100644 --- a/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h +++ b/Triangulation/include/CGAL/TDS_full_cell_default_storage_policy.h @@ -44,7 +44,7 @@ struct TFC_data< Vertex_handle, Full_cell_handle, Dimen, TDS_full_cell_default_s : vertices_(dmax+1), neighbors_(dmax+1) {} void* for_compact_container() const { return vertices_.for_compact_container(); } - void* & for_compact_container() { return vertices_.for_compact_container(); } + void for_compact_container(void *p){ vertices_.for_compact_container(p); } int dimension() const { return ( vertices_.size() - 1 ); } void set_mirror_index(const int, const int) {} #ifdef BOOST_NO_INT64_T diff --git a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h index 125cc2e443f..83b48a441d5 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_full_cell.h +++ b/Triangulation/include/CGAL/Triangulation_ds_full_cell.h @@ -204,7 +204,7 @@ public: TDS_data & tds_data() { return tds_data_; } /* Concept */ void* for_compact_container() const { return combinatorics_.for_compact_container(); } - void* & for_compact_container() { return combinatorics_.for_compact_container(); } + void for_compact_container(void* p){ combinatorics_.for_compact_container(p); } bool is_valid(bool verbose = false, int = 0) const /* Concept */ { diff --git a/Triangulation/include/CGAL/Triangulation_ds_vertex.h b/Triangulation/include/CGAL/Triangulation_ds_vertex.h index c6528a1231d..aaa1e2067fc 100644 --- a/Triangulation/include/CGAL/Triangulation_ds_vertex.h +++ b/Triangulation/include/CGAL/Triangulation_ds_vertex.h @@ -102,7 +102,7 @@ public: public: // FOR MEMORY MANAGEMENT void* for_compact_container() const { return full_cell_.for_compact_container(); } - void* & for_compact_container() { return full_cell_.for_compact_container(); } + void for_compact_container(void *p){ full_cell_.for_compact_container(p); } }; // end of Triangulation_ds_vertex diff --git a/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h b/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h index f198464e874..54fca5abaea 100644 --- a/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h +++ b/Triangulation/include/CGAL/internal/Static_or_dynamic_array.h @@ -66,9 +66,9 @@ struct S_or_D_array< Containee, Dimension_tag< D >, WithCompactContainerHelper > { return (*this)[0].for_compact_container(); } - void* & for_compact_container() + void for_compact_container(void *p) { - return (*this)[0].for_compact_container(); + (*this)[0].for_compact_container(p); } }; @@ -101,7 +101,7 @@ struct S_or_D_array< Containee, Dynamic_dimension_tag, true > {} void* fcc_; void* for_compact_container() const { return fcc_; } - void* & for_compact_container() { return fcc_; } + void for_compact_container(void* p) { fcc_ = p; } }; } // end of namespace internal diff --git a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt index 90446677a4c..009f3845620 100644 --- a/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt +++ b/Triangulation_2/doc/Triangulation_2/Triangulation_2.txt @@ -152,6 +152,17 @@ Therefore, each edge of the triangulation is incident to exactly two faces and the set of faces of a triangulation is topologically equivalent to a two-dimensional sphere. + +Note that +the *infinite vertex* has no significant +coordinates and that no geometric predicate can be applied on it +nor on an infinite face. + +\cgalFigureBegin{Triangulation_2D_Fig_infinite_vertex,infinite.png} +Infinite vertex and infinite faces +\cgalFigureEnd + + This extends to lower dimensional triangulations arising in degenerate cases or when the triangulations as less than three vertices. @@ -162,16 +173,15 @@ topologically equivalent to a \f$ 1\f$-sphere. A zero dimensional triangulation, whose domain is reduced to a single point, is represented by two vertices that is topologically equivalent to a \f$ 0\f$-sphere. +This is illustrated in \cgalFigureRef{Triangulation_2D_Fig_low_dimensional} +and the example \ref Triangulation_2/low_dimensional.cpp +shows how to traverse a low dimensional triangulation. -Note that -the *infinite vertex* has no significant -coordinates and that no geometric predicate can be applied on it -nor on an infinite face. - -\cgalFigureBegin{Triangulation_2D_Fig_infinite_vertex,infinite.png} -Infinite vertex and infinite faces +\cgalFigureBegin{Triangulation_2D_Fig_low_dimensional,low_dimensional.svg} +Triangulations with zero, one, and two finite vertices. \cgalFigureEnd + \subsection Triangulation_2ARepresentationBasedonFaces A Representation Based on Faces and Vertices Because a triangulation is a set of @@ -1355,4 +1365,3 @@ Julia Flötotto, Monique Teillaud and Mariette Yvinec. */ } /* namespace CGAL */ - diff --git a/Triangulation_2/doc/Triangulation_2/examples.txt b/Triangulation_2/doc/Triangulation_2/examples.txt index 7061593de13..459982e56a2 100644 --- a/Triangulation_2/doc/Triangulation_2/examples.txt +++ b/Triangulation_2/doc/Triangulation_2/examples.txt @@ -21,4 +21,5 @@ \example Triangulation_2/polylines_triangulation.cpp \example Triangulation_2/segment_soup_to_polylines.cpp \example Triangulation_2/draw_triangulation_2.cpp +\example Triangulation_2/low_dimensional.cpp */ diff --git a/Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg b/Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg new file mode 100644 index 00000000000..147a847ec47 --- /dev/null +++ b/Triangulation_2/doc/Triangulation_2/fig/low_dimensional.svg @@ -0,0 +1,1028 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + v + + + + + + + + v + w + + 0 + 0 + 1 + 1 + 1 + 2 + 2 + 2 + 2 + 2 + 2 + 0 + 0 + 0 + 0 + 1 + 1 + + + + 1 + + + + + + + + + + + + + + + + + + + diff --git a/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp b/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp new file mode 100644 index 00000000000..fed87295eb0 --- /dev/null +++ b/Triangulation_2/examples/Triangulation_2/low_dimensional.cpp @@ -0,0 +1,74 @@ +#include + +#include +#include + +typedef CGAL::Exact_predicates_inexact_constructions_kernel K; +typedef CGAL::Triangulation_2 Triangulation; +typedef Triangulation::Vertex_handle Vertex_handle; +typedef Triangulation::Face_handle Face_handle; +typedef Triangulation::All_faces_iterator All_faces_iterator; +typedef Triangulation::All_edges_iterator All_edges_iterator; +typedef Triangulation::Point Point; + +int main() { + + Point p(0,0), q(1,0); + + Triangulation t; + + Vertex_handle inf = t.infinite_vertex(); + Face_handle fh = inf->face(); + assert(fh->vertex(0) == inf); + assert(fh->vertex(1) == Vertex_handle()); + assert(fh->vertex(2) == Vertex_handle()); + + assert(t.all_faces_begin() == t.all_faces_end()); + assert(t.all_edges_begin() == t.all_edges_end()); + + t.insert(p); + Vertex_handle pvh = t.finite_vertices_begin(); + Face_handle pfh = pvh->face(); + assert(pfh->neighbor(0) == fh); + + t.insert(q); + + assert(t.infinite_vertex()->face() == fh); + + assert( (fh->vertex(0) == inf) || (fh->vertex(1) == inf) ); + + std::cout << "After the insertion of the second point" <point() << " -- ";} + if (v1 == inf) {std::cout << "inf\n";}else{ std::cout<< v1->point() << std::endl;} + } + + std::cout << "Edge traversal by hand" << std::endl; + Face_handle done = fh; + do { + assert(fh->vertex(2) == Vertex_handle()); + assert(fh->neighbor(2) == Face_handle()); + Vertex_handle v0 = fh->vertex(0); + Vertex_handle v1 = fh->vertex(1); + std::cout << "Edge: "; + if (v0 == inf) {std::cout << "inf -- ";}else{ std::cout<< v0->point() << " -- ";} + if (v1 == inf) {std::cout << "inf\n";}else{ std::cout<< v1->point() << std::endl;} + fh = fh->neighbor(0); + } while (fh != done); + + std::cout << std::endl; + + return 0; +} diff --git a/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h index c5964f87ac2..e925bb4d102 100644 --- a/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_Delaunay_triangulation_2.h @@ -179,6 +179,19 @@ public: virtual ~Constrained_Delaunay_triangulation_2() {} + // Ensure rule-of-five: define the copy- and move- constructors + // as well as the copy- and move- assignment operators. + Constrained_Delaunay_triangulation_2( + const Constrained_Delaunay_triangulation_2 &) = default; + Constrained_Delaunay_triangulation_2( + Constrained_Delaunay_triangulation_2 &&) = default; + + Constrained_Delaunay_triangulation_2 & + operator=(const Constrained_Delaunay_triangulation_2 &) = default; + + Constrained_Delaunay_triangulation_2 & + operator=(Constrained_Delaunay_triangulation_2 &&) = default; + // FLIPS bool is_flipable(Face_handle f, int i, bool perturb = true) const; void flip(Face_handle& f, int i); diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h index 272aec6a330..bbb45c02a46 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_2.h @@ -51,6 +51,25 @@ struct CGAL_DEPRECATED No_intersection_tag : namespace internal { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + struct Indentation_level { + int n; + Indentation_level() : n(0) {} + friend std::ostream& operator<<(std::ostream& os, Indentation_level level) { + return os << std::string(2*level.n, ' '); + } + Indentation_level& operator++() { ++n; return *this; } + Indentation_level& operator--() { --n; return *this; } + struct Exit_guard { + Exit_guard(Indentation_level& level): level(level) { ++level; } + Exit_guard(const Exit_guard& other) : level(other.level) { ++level; } + Indentation_level& level; + ~Exit_guard() { --level; } + }; + Exit_guard open_new_scope() { return Exit_guard(*this); } + } cdt_2_indent_level; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS + template struct Itag { typedef typename boost::mpl::if_::Is_exact, @@ -87,6 +106,7 @@ public: typedef typename Triangulation::size_type size_type; typedef typename Triangulation::Locate_type Locate_type; typedef typename Triangulation::All_faces_iterator All_faces_iterator; + typedef typename Triangulation::Finite_edges_iterator Finite_edges_iterator; typedef typename Triangulation::Face_circulator Face_circulator; typedef typename Triangulation::Edge_circulator Edge_circulator; typedef typename Triangulation::Vertex_circulator Vertex_circulator; @@ -129,6 +149,8 @@ public: using Triangulation::geom_traits; using Triangulation::all_faces_begin; using Triangulation::all_faces_end; + using Triangulation::finite_edges_begin; + using Triangulation::finite_edges_end; using Triangulation::side_of_oriented_circle; using Triangulation::is_infinite; using Triangulation::collinear_between; @@ -148,6 +170,7 @@ public: using Triangulation::all_edges_begin; using Triangulation::all_edges_end; using Triangulation::mirror_index; + using Triangulation::mirror_edge; using Triangulation::orientation; #endif @@ -197,6 +220,17 @@ public: //TODO Is that destructor correct ? virtual ~Constrained_triangulation_2() {} + // Ensure rule-of-five: define the copy- and move- constructors + // as well as the copy- and move- assignment operators. + Constrained_triangulation_2(const Constrained_triangulation_2 &) = default; + Constrained_triangulation_2(Constrained_triangulation_2 &&) = default; + + Constrained_triangulation_2 & + operator=(const Constrained_triangulation_2 &) = default; + + Constrained_triangulation_2 & + operator=(Constrained_triangulation_2 &&) = default; + Constrained_edges_iterator constrained_edges_begin() const { @@ -537,7 +571,7 @@ public: { Edge_circulator ec=incident_edges(v), done(ec); bool are_there = false; - if (ec == 0) return are_there; + if (ec == nullptr) return are_there; do { if(is_constrained(*ec)) { *out++ = *ec; @@ -553,7 +587,7 @@ public: OutputItEdges incident_constraints(Vertex_handle v, OutputItEdges out) const { Edge_circulator ec=incident_edges(v), done(ec); - if (ec == 0) return out; + if (ec == nullptr) return out; do { if(is_constrained(*ec)) *out++ = *ec; ec++; @@ -656,6 +690,19 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) Vertex_handle v1, v2; bool insert_in_constrained_edge = false; + std::list > constrained_edges; + bool one_dimensional = false; + if(dimension() == 1){ + one_dimensional = true; + for(Finite_edges_iterator it = finite_edges_begin(); + it != finite_edges_end(); + ++it){ + if(is_constrained(*it)){ + constrained_edges.emplace_back(it->first->vertex(cw(it->second)), + it->first->vertex(ccw(it->second))); + } + } + } if ( lt == Triangulation::EDGE && loc->is_constrained(li) ) { if(boost::is_same::value) @@ -668,6 +715,18 @@ insert(const Point& a, Locate_type lt, Face_handle loc, int li) va = Triangulation::insert(a,lt,loc,li); + if(one_dimensional && (dimension() == 2)){ + for(const std::pair& vp : constrained_edges){ + Face_handle fh; + int i; + if(this->is_edge(vp.first, vp.second, fh,i)){ + fh->set_constraint(i,true); + boost::tie(fh,i) = mirror_edge(Edge(fh,i)); + fh->set_constraint(i,true); + } + } + } + if (insert_in_constrained_edge) update_constraints_incident(va, v1,v2); else if(lt != Triangulation::VERTEX) @@ -728,10 +787,25 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) std::stack > stack; stack.push(std::make_pair(vaa,vbb)); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; + internal::Indentation_level::Exit_guard exit_guard = CGAL::internal::cdt_2_indent_level.open_new_scope(); +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS while(! stack.empty()){ boost::tie(vaa,vbb) = stack.top(); stack.pop(); CGAL_triangulation_precondition( vaa != vbb); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint, stack pop=( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " ) remaining stack size: " + << stack.size() << '\n'; + CGAL_assertion(this->is_valid()); +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS Vertex_handle vi; Face_handle fr; @@ -767,10 +841,26 @@ insert_constraint(Vertex_handle vaa, Vertex_handle vbb) vi); if ( intersection) { if (vi != vaa && vi != vbb) { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vaa, vi] ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vi->time_stamp() << "= " << vi->point() + << " )\n"; + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vi, vbb] ( #" << vi->time_stamp() << "= " << vi->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS stack.push(std::make_pair(vaa,vi)); stack.push(std::make_pair(vi,vbb)); } else{ +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::insert_constraint stask push [vaa, vbb]( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS stack.push(std::make_pair(vaa,vbb)); } continue; @@ -814,6 +904,30 @@ find_intersected_faces(Vertex_handle vaa, // to deal with the case where the first crossed edge // is constrained +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::find_intersected_faces ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " )\n" + << CGAL::internal::cdt_2_indent_level + << "> current constrained edges are:\n"; + for(Constrained_edges_iterator edge_it = this->constrained_edges_begin(), + end = this->constrained_edges_end(); + edge_it != end; ++edge_it) + { + std::cerr < (#" + << edge_it->first->vertex(cw(edge_it->second))->time_stamp() + << ", #" + << edge_it->first->vertex(ccw(edge_it->second))->time_stamp() + << ")\n"; + } + std::cerr << CGAL::internal::cdt_2_indent_level + << "> current face is ( #" << current_face->vertex(0)->time_stamp() + << " #" << current_face->vertex(1)->time_stamp() + << " #" << current_face->vertex(2)->time_stamp() << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS + if(current_face->is_constrained(ind)) { vi=intersect(current_face, ind, vaa, vbb); return true; @@ -971,14 +1085,22 @@ intersect(Face_handle f, int i, const Point& pc = vcc->point(); const Point& pd = vdd->point(); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::intersect segment ( #" << vaa->time_stamp() << "= " << vaa->point() + << " , #" << vbb->time_stamp() << "= " << vbb->point() + << " ) with edge ( #"<< vcc->time_stamp() << "= " << vcc->point() + << " , #" << vdd->time_stamp() << "= " << vdd->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS Point pi; //creator for point is required here Itag itag = Itag(); bool ok = intersection(geom_traits(), pa, pb, pc, pd, pi, itag ); Vertex_handle vi; if ( !ok) { //intersection detected but not computed - int i = limit_intersection(geom_traits(), pa, pb, pc, pd, itag); - switch(i){ + int int_index = limit_intersection(geom_traits(), pa, pb, pc, pd, itag); + switch(int_index){ case 0 : vi = vaa; break; case 1 : vi = vbb; break; case 2 : vi = vcc; break; @@ -992,6 +1114,11 @@ intersect(Face_handle f, int i, remove_constrained_edge(f, i); vi = virtual_insert(pi, f); } +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::intersect, `vi` is ( #" << vi->time_stamp() << "= " << vi->point() + << " )\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS // vi == vc or vi == vd may happen even if intersection==true // due to approximate construction of the intersection @@ -1045,7 +1172,7 @@ update_constraints_incident(Vertex_handle va, //dimension() ==2 int cwi, ccwi, indf; Face_circulator fc=incident_faces(va), done(fc); - CGAL_triangulation_assertion(fc != 0); + CGAL_triangulation_assertion(fc != nullptr); do { indf = fc->index(va); cwi=cw(indf); @@ -1072,7 +1199,7 @@ clear_constraints_incident(Vertex_handle va) Edge_circulator ec=incident_edges(va), done(ec); Face_handle f; int indf; - if ( ec != 0){ + if ( ec != nullptr){ do { f = (*ec).first ; indf = (*ec).second; @@ -1247,6 +1374,14 @@ void Constrained_triangulation_2:: remove_constrained_edge(Face_handle f, int i) { +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + std::cerr << CGAL::internal::cdt_2_indent_level + << "CT_2::remove_constrained_edge ( #" + << f->vertex(cw(i))->time_stamp() + << ", #" + << f->vertex(ccw(i))->time_stamp() + << ")\n"; +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS f->set_constraint(i, false); if (dimension() == 2) (f->neighbor(i))->set_constraint(mirror_index(f,i), false); @@ -1259,7 +1394,7 @@ Constrained_triangulation_2:: remove_incident_constraints(Vertex_handle v) { Edge_circulator ec=incident_edges(v), done(ec); - if (ec == 0) return; + if (ec == nullptr) return; do { if(is_constrained(*ec)) { remove_constrained_edge((*ec).first, (*ec).second);} @@ -1518,7 +1653,8 @@ intersection(const Gt& gt, if(!result) return result; if(pi == pa || pi == pb || pi == pc || pi == pd) { #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS - std::cerr << " CT_2::intersection: intersection is an existing point " + std::cerr << CGAL::internal::cdt_2_indent_level + << " CT_2::intersection: intersection is an existing point " << pi << std::endl; #endif return result; @@ -1540,7 +1676,8 @@ intersection(const Gt& gt, if(do_overlap(bb, bbox(pd))) pi = pd; #ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS if(pi == pa || pi == pb || pi == pc || pi == pd) { - std::cerr << " CT_2::intersection: intersection SNAPPED to an existing point " + std::cerr << CGAL::internal::cdt_2_indent_level + << " CT_2::intersection: intersection SNAPPED to an existing point " << pi << std::endl; } #endif @@ -1578,6 +1715,17 @@ compute_intersection(const Gt& gt, construct_segment=gt.construct_segment_2_object(); Object result = compute_intersec(construct_segment(pa,pb), construct_segment(pc,pd)); +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS + typename Gt::Segment_2 s; + if(assign(s, result)) { + std::cerr << CGAL::internal::cdt_2_indent_level + << "compute_intersection: " << s << '\n'; + } + if(assign(pi, result)) { + std::cerr << CGAL::internal::cdt_2_indent_level + << "compute_intersection: " << pi << '\n'; + } +#endif // CGAL_CDT_2_DEBUG_INTERSECTIONS return assign(pi, result); } diff --git a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h index 0b19a9a5698..ac7f401174a 100644 --- a/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h +++ b/Triangulation_2/include/CGAL/Constrained_triangulation_plus_2.h @@ -217,6 +217,8 @@ public: , hierarchy(Vh_less_xy(this)) { copy_triangulation(ctp);} + Constrained_triangulation_plus_2(Constrained_triangulation_plus_2&&) = default; + virtual ~Constrained_triangulation_plus_2() {} Constrained_triangulation_plus_2 & operator=(const Constrained_triangulation_plus_2& ctp) @@ -225,6 +227,8 @@ public: return *this; } + Constrained_triangulation_plus_2& operator=(Constrained_triangulation_plus_2&&) = default; + template Constrained_triangulation_plus_2(InputIterator first, InputIterator last, @@ -415,7 +419,7 @@ public: ++beg; Face_container fc(*this); - Constraint_id head = 0, tail = 0; + Constraint_id head = nullptr, tail = nullptr; if(pos != beg){ // split off head --pos; @@ -496,7 +500,7 @@ public: return pos; } - Constraint_id head = 0, tail = 0; + Constraint_id head = nullptr, tail = nullptr; Vertices_in_constraint_iterator bit = vertices_in_constraint_begin(cid); Vertices_in_constraint_iterator pred = pos; --pred; diff --git a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h index b45bcb11f40..c8fc845f01b 100644 --- a/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h +++ b/Triangulation_2/include/CGAL/Delaunay_triangulation_2.h @@ -90,6 +90,11 @@ public: : Triangulation_2(tr) { CGAL_triangulation_postcondition(is_valid()); } + Delaunay_triangulation_2(Delaunay_triangulation_2&&) = default; + Delaunay_triangulation_2& operator=(const Delaunay_triangulation_2&) = default; + Delaunay_triangulation_2& operator=(Delaunay_triangulation_2&&) = default; + ~Delaunay_triangulation_2() = default; + template Delaunay_triangulation_2(InputIterator first, InputIterator last, const Gt& gt = Gt()) diff --git a/Triangulation_2/include/CGAL/Triangulation_2.h b/Triangulation_2/include/CGAL/Triangulation_2.h index 34b7968a10f..3f73f238eae 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2.h @@ -242,6 +242,7 @@ public: // CONSTRUCTORS Triangulation_2(const Geom_traits& geom_traits=Geom_traits()); Triangulation_2(const Triangulation_2 &tr); + Triangulation_2(Triangulation_2&&) = default; template Triangulation_2(InputIterator first, InputIterator last, @@ -254,6 +255,10 @@ public: //Assignement Triangulation_2 &operator=(const Triangulation_2 &tr); + Triangulation_2 &operator=(Triangulation_2 &&) = default; + + // Destructor + ~Triangulation_2() = default; //Helping void copy_triangulation(const Triangulation_2 &tr); @@ -628,7 +633,7 @@ std::ptrdiff_t insert(InputIterator first, InputIterator last, typename std::iterator_traits::value_type, Point > - >::type* = NULL) + >::type* = nullptr) #else template < class InputIterator > std::ptrdiff_t @@ -1016,7 +1021,7 @@ includes_edge(Vertex_handle va, Vertex_handle vb, Orientation orient; int indv; Edge_circulator ec = incident_edges(va), done(ec); - if (ec != 0) { + if (ec != nullptr) { do { //find the index of the other vertex of *ec indv = 3 - ((*ec).first)->index(va) - (*ec).second ; @@ -2597,7 +2602,7 @@ march_locate_2D_LFC(Face_handle start, }else { lfc = Line_face_circulator(start->vertex(0), this, t); } - if(lfc==0 || lfc.collinear_outside()){ + if(lfc==nullptr || lfc.collinear_outside()){ // point t lies outside or on the convex hull // we walk on the convex hull to find it out Face_circulator fc = incident_faces(infinite_vertex()); diff --git a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h index 8f6fbc7fbed..c3c26ce2470 100644 --- a/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_2/internal/Polyline_constraint_hierarchy_2.h @@ -154,10 +154,6 @@ public: public: Context() : enclosing(nullptr) {} - Context(const Context& hc) - : enclosing(hc.enclosing), pos(hc.pos) - {} - Vertex_it vertices_begin()const { return enclosing->skip_begin();} Vertex_it current()const {return pos;} Vertex_it vertices_end()const {return enclosing->skip_end();} @@ -187,9 +183,11 @@ public: , sc_to_c_map(Pair_compare(comp)) { } Polyline_constraint_hierarchy_2(const Polyline_constraint_hierarchy_2& ch); + Polyline_constraint_hierarchy_2(Polyline_constraint_hierarchy_2&&) = default; ~Polyline_constraint_hierarchy_2(){ clear();} void clear(); Polyline_constraint_hierarchy_2& operator=(const Polyline_constraint_hierarchy_2& ch); + Polyline_constraint_hierarchy_2& operator=(Polyline_constraint_hierarchy_2&& ch) = default; // Query bool is_subconstrained_edge(T va, T vb) const; @@ -499,7 +497,7 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { if(ctit->enclosing == first.vl_ptr()){ - ctit->enclosing = 0; + ctit->enclosing = nullptr; break; } } @@ -530,7 +528,7 @@ swap(Constraint_id first, Constraint_id second){ // and replace the context of the constraint for(Context_iterator ctit=hcl->begin(); ctit != hcl->end(); ctit++) { - if(ctit->enclosing == 0){ + if(ctit->enclosing == nullptr){ ctit->enclosing = second.vl_ptr(); break; } diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h index 264fab4c926..266c4964e03 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_2.h @@ -36,6 +36,7 @@ #include #include #include +#include namespace CGAL { @@ -82,13 +83,25 @@ public: private: // here is the stack of triangulations which form the hierarchy - Tr_Base* hierarchy[Triangulation_hierarchy_2__maxlevel]; + std::array hierarchy; boost::rand48 random; public: Triangulation_hierarchy_2(const Geom_traits& traits = Geom_traits()); Triangulation_hierarchy_2(const Triangulation_hierarchy_2& tr); + Triangulation_hierarchy_2(Triangulation_hierarchy_2&& other) + noexcept( noexcept(Tr_Base(std::move(other))) ) + : Tr_Base(std::move(other)) + , random(std::move(other.random)) + { + hierarchy[0] = this; + for(int i=1; i Triangulation_hierarchy_2(InputIterator first, InputIterator beyond, const Geom_traits& traits = Geom_traits()) @@ -102,6 +115,19 @@ public: } Triangulation_hierarchy_2 &operator=(const Triangulation_hierarchy_2& tr); + + Triangulation_hierarchy_2 & operator=(Triangulation_hierarchy_2&& other) + noexcept( noexcept(Triangulation_hierarchy_2(std::move(other))) ) + { + static_cast(*this) = std::move(other); + hierarchy[0] = this; + for(int i=1; i:: clear() { - for(int i=0;iclear(); + for(int i=0;iclear(); } @@ -723,7 +749,7 @@ locate_in_all(const Point& p, level--; } - for (int i=level+1; i 0) { pos[level]=position=hierarchy[level]->locate(p, position); // locate at that level from "position" diff --git a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h index 482d9897d33..e1e30c53706 100644 --- a/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h +++ b/Triangulation_2/include/CGAL/Triangulation_hierarchy_vertex_base_2.h @@ -41,13 +41,13 @@ public: }; Triangulation_hierarchy_vertex_base_2() - : Base(), _up(0), _down(0) + : Base() {} Triangulation_hierarchy_vertex_base_2(const Point & p, Face_handle f) - : Base(p,f), _up(0), _down(0) + : Base(p,f) {} Triangulation_hierarchy_vertex_base_2(const Point & p) - : Base(p), _up(0), _down(0) + : Base(p) {} Vertex_handle up() {return _up;} @@ -57,8 +57,8 @@ public: private: - Vertex_handle _up; // same vertex one level above - Vertex_handle _down; // same vertex one level below + Vertex_handle _up = nullptr; // same vertex one level above + Vertex_handle _down = nullptr; // same vertex one level below }; } //namespace CGAL diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h index 2635832ee69..ccc193bad99 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_const_Del_triangulation_2.h @@ -30,6 +30,16 @@ template void _test_cls_const_Del_triangulation(const Triangul&) { + // The following assertion is commented, because, in CT_plus_2, + // one uses `std::set` and `std::map`, and their move-constructors + // may throw. + // + // static_assert(std::is_nothrow_move_constructible::value, + // "move cstr is missing"); + + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + //typedef Triangulation Cls; typedef typename Triangul::Geom_traits Gt; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h index fbe4b9ae725..fb62d70e19b 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_constrained_triangulation_2.h @@ -92,6 +92,16 @@ template void _test_cls_constrained_triangulation(const Triang &) { + // The following assertion is commented, because, in CT_plus_2, + // one uses `std::set` and `std::map`, and their move-constructors + // may throw. + // + // static_assert(std::is_nothrow_move_constructible::value, + // "move cstr is missing"); + + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // typedef Triangulation Cls; typedef typename Triang::Geom_traits Gt; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h index d5088cb094d..b91d6eb534c 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_delaunay_triangulation_2.h @@ -39,6 +39,11 @@ template void _test_cls_delaunay_triangulation_2( const Del & ) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + //typedef Del Delaunay; typedef typename Del::Point Point; typedef typename Del::Locate_type Locate_type; diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h index 096b6bc5d7a..348428439f7 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_cls_triangulation_2.h @@ -39,6 +39,10 @@ template void _test_cls_triangulation_2( const Triangul & ) { + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); //typedef Triangulation Cls; // We assume the traits class has been tested already diff --git a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h index 45e4840383d..b472c7fc8d2 100644 --- a/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h +++ b/Triangulation_2/test/Triangulation_2/include/CGAL/_test_traits.h @@ -36,7 +36,6 @@ protected: double _x, _y; public: Triangulation_test_point() {} - Triangulation_test_point(const Point &p) : _x(p.test_x()), _y(p.test_y()) {} Triangulation_test_point(double x, double y) : _x(x), _y(y) {} Triangulation_test_point(double hx, double hy, double hw) : _x(hx/hw), _y(hy/hw) @@ -47,7 +46,6 @@ public: bool compare(const Point &p) const { return test_x()==p.test_x() && test_y()==p.test_y(); } bool uncompare(const Point &p) const { return !compare(p); } - Point &operator=(const Point &p) { _x=p.test_x(); _y=p.test_y(); return *this; } void test_set(TESTFT x, TESTFT y) { _x=x; _y=y; } bool operator==(const Point &p) const {return this->compare(p);} }; @@ -436,11 +434,6 @@ public: typedef Triangulation_test_Construct_ray_2 Construct_ray_2; - _Triangulation_test_traits() {} - _Triangulation_test_traits(const _Triangulation_test_traits &) {} - _Triangulation_test_traits &operator= - (const _Triangulation_test_traits &) { return *this; } - Less_x_2 less_x_2_object() const { return Less_x_2();} diff --git a/Triangulation_2/test/Triangulation_2/issue_4405.cpp b/Triangulation_2/test/Triangulation_2/issue_4405.cpp index 89199d56141..770cd6c761c 100644 --- a/Triangulation_2/test/Triangulation_2/issue_4405.cpp +++ b/Triangulation_2/test/Triangulation_2/issue_4405.cpp @@ -9,13 +9,43 @@ typedef CGAL::Epick Kernel; typedef Kernel::FT FieldNumberType; typedef Kernel::Point_2 Point2; typedef Kernel::Point_3 Point3; + +template +class My_vertex_base : public Vb { + std::size_t time_stamp_; +public: + My_vertex_base() : Vb(), time_stamp_(-1) { + } + + My_vertex_base(const My_vertex_base& other) : + Vb(other), + time_stamp_(other.time_stamp_) + {} + + typedef CGAL::Tag_true Has_timestamp; + + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + template < class TDS > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb2; + typedef My_vertex_base Other; + }; +}; + struct FaceInfo2 { unsigned long long m_id; }; typedef CGAL::Projection_traits_xy_3 TriangulationTraits; typedef CGAL::Triangulation_vertex_base_with_id_2 VertexBaseWithId; -typedef CGAL::Triangulation_vertex_base_2 VertexBase; +typedef My_vertex_base Vb2; +typedef CGAL::Triangulation_vertex_base_2 VertexBase; typedef CGAL::Triangulation_face_base_with_info_2 FaceBaseWithInfo; typedef CGAL::Constrained_triangulation_face_base_2 FaceBase; typedef CGAL::Triangulation_data_structure_2 TriangulationData; diff --git a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp index 5dc1d1c7afa..b4de0e1e0f7 100644 --- a/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp +++ b/Triangulation_2/test/Triangulation_2/test_cdt_degenerate_case.cpp @@ -1,3 +1,4 @@ +#define CGAL_CDT_2_DEBUG_INTERSECTIONS 1 #include #include #include @@ -5,7 +6,41 @@ typedef CGAL::Exact_predicates_inexact_constructions_kernel EPIC; typedef EPIC::Point_2 Point_2; -typedef CGAL::Triangulation_vertex_base_2 Vb; + +template +class My_vertex_base : public Vb { + std::size_t time_stamp_; +public: + My_vertex_base() : Vb(), time_stamp_(-1) { + } + + My_vertex_base(const My_vertex_base& other) : + Vb(other), + time_stamp_(other.time_stamp_) + {} + + typedef CGAL::Tag_true Has_timestamp; + + std::size_t time_stamp() const { + return time_stamp_; + } + void set_time_stamp(const std::size_t& ts) { + time_stamp_ = ts; + } + + template < class TDS > + struct Rebind_TDS { + typedef typename Vb::template Rebind_TDS::Other Vb2; + typedef My_vertex_base Other; + }; +}; + +#ifdef CGAL_CDT_2_DEBUG_INTERSECTIONS +typedef My_vertex_base > Vb; +#else +typedef CGAL::Triangulation_vertex_base_2 Vb; +#endif + typedef CGAL::Constrained_triangulation_face_base_2 Fb; typedef CGAL::Triangulation_data_structure_2 TDS; typedef CGAL::Exact_predicates_tag Itag; @@ -14,6 +49,7 @@ typedef CGAL::Constrained_triangulation_plus_2 CDTp2; template void test() { + std::cerr.precision(17); CDT cdt; cdt.insert_constraint(Point_2( 48.0923419883269, 299.7232779774145 ), Point_2( 66.05373710316852, 434.231770798343 )); diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h index e5dbec51447..108188ff824 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_3.h @@ -888,11 +888,6 @@ protected: : m_dt(dt), m_points(points), m_tls_hint(tls_hint) {} - // Constructor - Insert_point(const Insert_point& ip) - : m_dt(ip.m_dt), m_points(ip.m_points), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -968,12 +963,6 @@ protected: m_tls_hint(tls_hint) {} - // Constructor - Insert_point_with_info(const Insert_point_with_info& ip) - : m_dt(ip.m_dt), m_points(ip.m_points), m_infos(ip.m_infos), - m_indices(ip.m_indices), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1047,12 +1036,6 @@ protected: m_vertices_to_remove_sequentially(vertices_to_remove_sequentially) {} - // Constructor - Remove_point(const Remove_point& rp) - : m_dt(rp.m_dt), m_vertices(rp.m_vertices), - m_vertices_to_remove_sequentially(rp.m_vertices_to_remove_sequentially) - {} - // operator() void operator()(const tbb::blocked_range& r) const { diff --git a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h index f8ac6a7a232..14fc74d8490 100644 --- a/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h +++ b/Triangulation_3/include/CGAL/Delaunay_triangulation_cell_base_with_circumcenter_3.h @@ -63,6 +63,12 @@ public: : Cb(c), circumcenter_(c.circumcenter_ != nullptr ? new Point(*(c.circumcenter_)) : nullptr) {} + Delaunay_triangulation_cell_base_with_circumcenter_3 + (Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + : Cb(std::move(c)), circumcenter_(std::exchange(c.circumcenter_, nullptr)) + { + } + Delaunay_triangulation_cell_base_with_circumcenter_3& operator=(const Delaunay_triangulation_cell_base_with_circumcenter_3 &c) { @@ -71,6 +77,14 @@ public: return *this; } + Delaunay_triangulation_cell_base_with_circumcenter_3& + operator=(Delaunay_triangulation_cell_base_with_circumcenter_3 &&c) + { + Cb::operator=(std::move(c)); + circumcenter_ = std::exchange(c.circumcenter_, nullptr); + return *this; + } + Delaunay_triangulation_cell_base_with_circumcenter_3( Vertex_handle v0, Vertex_handle v1, Vertex_handle v2, Vertex_handle v3) diff --git a/Triangulation_3/include/CGAL/Regular_triangulation_3.h b/Triangulation_3/include/CGAL/Regular_triangulation_3.h index b1a55c9eabe..2e490a7c861 100644 --- a/Triangulation_3/include/CGAL/Regular_triangulation_3.h +++ b/Triangulation_3/include/CGAL/Regular_triangulation_3.h @@ -199,21 +199,38 @@ public: CGAL_triangulation_postcondition(is_valid()); } + Regular_triangulation_3(Regular_triangulation_3&& rt) + noexcept(noexcept(Tr_Base(std::move(rt)))) + : Tr_Base(std::move(rt)), hidden_point_visitor(this) + { + CGAL_triangulation_postcondition(is_valid()); + } + + ~Regular_triangulation_3() = default; + void swap(Regular_triangulation_3& tr) { - // The 'vertices' and 'hidden_points' members of 'hidden_point_visitor' should be empty - // as they are only filled (and cleared) during the insertion of a point. - // Hidden points are not stored there, but rather in cells. Thus, the only thing that must be set - // is the triangulation pointer. - Hidden_point_visitor new_hpv(this); - std::swap(hidden_point_visitor, new_hpv); - + // The 'vertices' and 'hidden_points' members of + // 'hidden_point_visitor' should be empty as they are only filled + // (and cleared) during the insertion of a point. Hidden points + // are not stored there, but rather in cells. Thus, the only thing + // that must be set is the triangulation pointer, and it is + // already correctly set. There is nothing to do about + // 'hidden_point_visitor'. Tr_Base::swap(tr); } - Regular_triangulation_3& operator=(Regular_triangulation_3 tr) + Regular_triangulation_3& operator=(const Regular_triangulation_3& tr) { - swap(tr); + Regular_triangulation_3 copy(tr); + copy.swap(*this); + return *this; + } + + Regular_triangulation_3& operator=(Regular_triangulation_3&& tr) + noexcept(noexcept(Regular_triangulation_3(std::move(tr)))) + { + Tr_Base::operator=(std::move(tr)); return *this; } @@ -1393,11 +1410,6 @@ protected: : m_rt(rt), m_points(points), m_tls_hint(tls_hint) {} - // Constructor - Insert_point(const Insert_point& ip) - : m_rt(ip.m_rt), m_points(ip.m_points), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1504,12 +1516,6 @@ protected: m_tls_hint(tls_hint) {} - // Constructor - Insert_point_with_info(const Insert_point_with_info &ip) - : m_rt(ip.m_rt), m_points(ip.m_points), m_infos(ip.m_infos), - m_indices(ip.m_indices), m_tls_hint(ip.m_tls_hint) - {} - // operator() void operator()(const tbb::blocked_range& r) const { @@ -1621,12 +1627,6 @@ protected: m_vertices_to_remove_sequentially(vertices_to_remove_sequentially) {} - // Constructor - Remove_point(const Remove_point& rp) - : m_rt(rp.m_rt), m_vertices(rp.m_vertices), - m_vertices_to_remove_sequentially(rp.m_vertices_to_remove_sequentially) - {} - // operator() void operator()(const tbb::blocked_range& r) const { diff --git a/Triangulation_3/include/CGAL/Triangulation_3.h b/Triangulation_3/include/CGAL/Triangulation_3.h index ed728066e72..e120cac0ad0 100644 --- a/Triangulation_3/include/CGAL/Triangulation_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_3.h @@ -179,7 +179,7 @@ public: void *get_lock_data_structure() const { - return 0; + return nullptr; } void set_lock_data_structure(void *) const {} @@ -245,7 +245,7 @@ protected: public: bool is_parallel() const { - return m_lock_ds != 0; + return m_lock_ds != nullptr; } // LOCKS @@ -731,6 +731,9 @@ public: CGAL_triangulation_expensive_postcondition(*this == tr); } + Triangulation_3(Triangulation_3&& tr) = default; + ~Triangulation_3() = default; + template < typename InputIterator > Triangulation_3(InputIterator first, InputIterator last, const GT& gt = GT(), Lock_data_structure *lock_ds = nullptr) @@ -757,21 +760,21 @@ public: init_tds(); } - Triangulation_3& operator=(Triangulation_3 tr) + Triangulation_3& operator=(const Triangulation_3& tr) { - // Because the parameter tr is passed by value, the triangulation passed - // as argument has been copied. - // The following 'swap' consumes the *copy* and the original triangulation - // is left untouched. - swap(tr); + Triangulation_3 copy(tr); + swap(copy); return *this; } + Triangulation_3& operator=(Triangulation_3&& tr) = default; + // HELPING FUNCTIONS - void swap(Triangulation_3& tr) + void swap(Triangulation_3& tr) noexcept { - std::swap(tr._gt, _gt); - std::swap(tr.infinite, infinite); + using std::swap; + swap(tr._gt, _gt); + swap(tr.infinite, infinite); _tds.swap(tr._tds); Base::swap(tr); } @@ -1139,7 +1142,7 @@ public: typename std::iterator_traits::value_type, Point > - >::type* = NULL) + >::type* = nullptr) #else template < class InputIterator > std::ptrdiff_t insert(InputIterator first, InputIterator last) diff --git a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h index c0326a14b2a..0831c09c656 100644 --- a/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h +++ b/Triangulation_3/include/CGAL/Triangulation_hierarchy_3.h @@ -50,6 +50,8 @@ #include #include +#include + #endif //CGAL_TRIANGULATION_3_DONT_INSERT_RANGE_OF_POINTS_WITH_INFO namespace CGAL { @@ -91,7 +93,7 @@ public: private: // here is the stack of triangulations which form the hierarchy - Tr_Base* hierarchy[maxlevel]; + std::array hierarchy; boost::rand48 random; void set_up_down(Vertex_handle up, Vertex_handle down) @@ -106,6 +108,18 @@ public: Triangulation_hierarchy_3(const Triangulation_hierarchy_3& tr); + Triangulation_hierarchy_3(Triangulation_hierarchy_3&& other) + noexcept( noexcept(Tr_Base(std::move(other))) ) + : Tr_Base(std::move(other)) + , random(std::move(other.random)) + { + hierarchy[0] = this; + for(int i=1; i Triangulation_hierarchy_3(InputIterator first, InputIterator last, const Geom_traits& traits = Geom_traits()) @@ -124,9 +138,32 @@ public: return *this; } - ~Triangulation_hierarchy_3(); + Triangulation_hierarchy_3 & operator=(Triangulation_hierarchy_3&& other) + noexcept( noexcept(Triangulation_hierarchy_3(std::move(other))) ) + { + static_cast(*this) = std::move(other); + hierarchy[0] = this; + for(int i=1; i &tr) } } -template -void -Triangulation_hierarchy_3:: -swap(Triangulation_hierarchy_3 &tr) -{ - Tr_Base::swap(tr); - for(int i=1; i -Triangulation_hierarchy_3:: -~Triangulation_hierarchy_3() -{ - clear(); - for(int i=1; i void Triangulation_hierarchy_3:: diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h index 8eef60ae345..f7d4579828c 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_delaunay_3.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -170,6 +171,11 @@ _test_cls_delaunay_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Test_location_policy::Location_policy Location_policy; // We assume the traits class has been tested already diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h index c9630054c56..fba2db023fd 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_regular_3.h @@ -15,12 +15,19 @@ #include #include #include +#include #include template void _test_cls_regular_3(const Triangulation &) { typedef Triangulation Cls; + + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + typedef typename Triangulation::Geom_traits Gt; CGAL_USE_TYPE(Gt); diff --git a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h index 015906a4e01..ded18a9175f 100644 --- a/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h +++ b/Triangulation_3/test/Triangulation_3/include/CGAL/_test_cls_triangulation_3.h @@ -15,6 +15,7 @@ #include #include #include +#include #include "_test_cls_iterator.h" #include "_test_cls_circulator.h" @@ -79,6 +80,11 @@ _test_cls_triangulation_3(const Triangulation &) { typedef Triangulation Cls; + static_assert(std::is_nothrow_move_constructible::value, + "move cstr is missing"); + static_assert(std::is_nothrow_move_assignable::value, + "move assignment is missing"); + // We assume the traits class has been tested already // actually, any traits is good if it has been tested diff --git a/Union_find/include/CGAL/Union_find.h b/Union_find/include/CGAL/Union_find.h index a76cf515856..16dc14bdb74 100644 --- a/Union_find/include/CGAL/Union_find.h +++ b/Union_find/include/CGAL/Union_find.h @@ -114,8 +114,7 @@ public: #ifdef _MSC_VER typedef CGAL_ALLOCATOR(Union_find_struct) allocator; #else - typedef typename A::template rebind Rebind; - typedef typename Rebind::other allocator; + typedef typename std::allocator_traits::template rebind_alloc allocator; #endif private: