diff --git a/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h b/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h index c23d442fa63..a7ccc4e66bb 100644 --- a/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h +++ b/Cartesian_kernel/include/CGAL/Cartesian/function_objects.h @@ -96,6 +96,13 @@ namespace CartesianKernelFunctors { r.x(), r.y(), r.z(), s.x(), s.y(), s.z()); } + + result_type + operator()(const Point_3& p, const Point_3& q, + const Point_3& r, const Vector_3& n) const + { + return enum_cast(orientation(p,q,r,r+n)); + } }; template diff --git a/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h b/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h index b3dc18a7bb4..878d361e3ef 100644 --- a/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h +++ b/Homogeneous_kernel/include/CGAL/Homogeneous/function_objects.h @@ -112,6 +112,13 @@ namespace HomogeneousKernelFunctors { const Point_3& r, const Point_3& s) const { return enum_cast(CGAL_NTS sign(c(q,p) * c(s,r))); } // FIXME: scalar product + + result_type + operator()(const Point_3& p, const Point_3& q, + const Point_3& r, const Vector_3& n) const + { + return enum_cast(orientation(p,q,r,r+n)); + } }; diff --git a/Installation/changes.html b/Installation/changes.html index c283b7dd5a8..1d423183635 100644 --- a/Installation/changes.html +++ b/Installation/changes.html @@ -205,11 +205,20 @@ and src/ directories).

2D and 3D Linear Geometry Kernel

    +
  • Breaking change: The function compare_slopes() was renamed compare_slope. +
  • Added a 2D and 3D weighted point class and predicates and constructions.
  • Add functions l_infinity_distance() for 2D and 3D.
  • +
  • Add a new functor in CGAL Kernel concept to compare the slope of two 3D segments. + All models of the Kernel concept now provide the functor Compare_slope_3, + and the free function compare_slope() is available. +
  • +
  • Add an operator in CGAL Kernel concept Angle_3 to qualify the angle + between the normal of the triangle given by three points, and a vector. +

3D Convex Hull

diff --git a/Kernel_23/doc/Kernel_23/CGAL/Kernel/global_functions.h b/Kernel_23/doc/Kernel_23/CGAL/Kernel/global_functions.h index b8083e59cfb..c3370fd005c 100644 --- a/Kernel_23/doc/Kernel_23/CGAL/Kernel/global_functions.h +++ b/Kernel_23/doc/Kernel_23/CGAL/Kernel/global_functions.h @@ -38,7 +38,15 @@ const CGAL::Point_2& r, const CGAL::Point_2& s); /*! +returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending +on the angle formed by the two vectors `u` and `v`. +*/ +template +Angle angle(const CGAL::Vector_3& u, + const CGAL::Vector_3& v); + +/*! returns `CGAL::OBTUSE`, `CGAL::RIGHT` or `CGAL::ACUTE` depending on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of the angle). @@ -48,6 +56,29 @@ Angle angle(const CGAL::Point_3& p, const CGAL::Point_3& q, const CGAL::Point_3& r); +/*! +returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending +on the angle formed by the two vectors `pq`, `rs`. The returned value is +the same as `angle(q - p, s - r)`. +*/ +template +Angle angle(const CGAL::Point_3&p, + const CGAL::Point_3&q, + const CGAL::Point_3&r, + const CGAL::Point_3&s); + +/*! +returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending +on the angle formed by the normal of the triangle `pqr` and the vector `v`. +*/ + +template +Angle angle(const CGAL::Point_3&p, + const CGAL::Point_3&q, + const CGAL::Point_3&r, + const CGAL::Vector_3&v); + + /*! returns an approximation of the signed dihedral angle in the tetrahedron `pqrs` of edge `pq`. @@ -61,6 +92,7 @@ Kernel::FT approximate_dihedral_angle(const CGAL::Point_3& p, const CGAL::Point_3& r, const CGAL::Point_3& s); + /// @} @@ -793,16 +825,28 @@ const CGAL::Point_3& t); compares the slopes of the lines `l1` and `l2` */ template -Comparison_result compare_slopes(const CGAL::Line_2 &l1, +Comparison_result compare_slope(const CGAL::Line_2 &l1, const CGAL::Line_2 &l2); /*! -compares the slopes of the segments `s1` and `s2` +compares the slopes of the segments `s1` and `s2`, +where the slope is the variation of the `y`-coordinate +from the left to the right endpoint of the segments. */ template -Comparison_result compare_slopes(const CGAL::Segment_2 &s1, +Comparison_result compare_slope(const CGAL::Segment_2 &s1, const CGAL::Segment_2 &s2); +/*! +compares the slopes of the segments `(p,q)` and `(r,s)`, +where the slope is the variation of the `z`-coordinate from the first +to the second point of the segment divided by the length of the segment. +*/ +template +Comparison_result compare_slope(const CGAL::Point_3 &p, + const CGAL::Point_3 &q, + const CGAL::Point_3 &r, + const CGAL::Point_3 &s); /// @} /// \defgroup compare_squared_distance_grp CGAL::compare_squared_distance() diff --git a/Kernel_23/doc/Kernel_23/Concepts/FunctionObjectConcepts.h b/Kernel_23/doc/Kernel_23/Concepts/FunctionObjectConcepts.h index a7c6a47ba91..a3f2f3604a6 100644 --- a/Kernel_23/doc/Kernel_23/Concepts/FunctionObjectConcepts.h +++ b/Kernel_23/doc/Kernel_23/Concepts/FunctionObjectConcepts.h @@ -62,20 +62,20 @@ public: /// @{ /*! - returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending - on the angle formed by the two vectors `u` and `v`. - */ - Angle operator()(const Kernel::Vector_3&u, - const Kernel::Vector_3&v); + returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending + on the angle formed by the two vectors `u` and `v`. + */ + Angle operator()(const Kernel::Vector_3&u, + const Kernel::Vector_3&v); /*! - returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending - on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of + returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending + on the angle formed by the three points `p`, `q`, `r` (`q` being the vertex of the angle). The returned value is the same as `operator()(p - q, r - q)`. - */ - Angle operator()(const Kernel::Point_3&p, - const Kernel::Point_3&q, - const Kernel::Point_3&r); + */ + Angle operator()(const Kernel::Point_3&p, + const Kernel::Point_3&q, + const Kernel::Point_3&r); /*! returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending @@ -85,7 +85,16 @@ public: Angle operator()(const Kernel::Point_3&p, const Kernel::Point_3&q, const Kernel::Point_3&r, - const Kernel::Point_3&s); + const Kernel::Point_3&s); + + /*! + returns \ref CGAL::OBTUSE, \ref CGAL::RIGHT or \ref CGAL::ACUTE depending + on the angle formed by the normal of the triangle `pqr` and the vector `v`. + */ + Angle operator()(const Kernel::Point_3&p, + const Kernel::Point_3&q, + const Kernel::Point_3&r, + const Kernel::Vector_3&v); /// @} }; /* end Kernel::Angle_3 */ @@ -991,7 +1000,9 @@ public: const Kernel::Line_2& l2); /*! - compares the slopes of the segments `s1` and `s2` + compares the slopes of the segments `s1` and `s2`, + where the slope is the variation of the `y`-coordinate + from the left to the right endpoint of the segments. */ Comparison_result operator()(const Kernel::Segment_2& s1, const Kernel::Segment_2& s2); @@ -1000,6 +1011,42 @@ public: }; /* end Kernel::CompareSlope_2 */ + +/*! + \ingroup PkgKernel23ConceptsFunctionObjects + \cgalConcept + + \cgalRefines `AdaptableFunctor` (with two arguments) + + \sa `compare_slopes_grp` + +*/ +class CompareSlope_3 { +public: + + /// \name Operations + /// A model of this concept must provide: + /// @{ + + + /*! + compares the slopes of the segments `(p,q)` and `(r,s)`, + where the slope is the variation of the `z`-coordinate + from the first to the second point of the segment divided + by the length of the segment. + */ + Comparison_result operator()(const Kernel::Point_3& p, + const Kernel::Point_3& q, + const Kernel::Point_3& r, + const Kernel::Point_3& s); + + + /// @} + +}; /* end Kernel::CompareSlope_3 */ + + + /*! \ingroup PkgKernel23ConceptsFunctionObjects \cgalConcept diff --git a/Kernel_23/doc/Kernel_23/Concepts/Kernel.h b/Kernel_23/doc/Kernel_23/Concepts/Kernel.h index fe5dcf86dfd..52ff08feba3 100644 --- a/Kernel_23/doc/Kernel_23/Concepts/Kernel.h +++ b/Kernel_23/doc/Kernel_23/Concepts/Kernel.h @@ -1433,6 +1433,11 @@ public: */ typedef unspecified_type Compare_xyz_3; + /*! + a model of `Kernel::CompareSlope_3` + */ + typedef unspecified_type Compare_slope_3; + /*! a model of `Kernel::CompareSquaredDistance_3` */ diff --git a/Kernel_23/doc/Kernel_23/PackageDescription.txt b/Kernel_23/doc/Kernel_23/PackageDescription.txt index 878c8a27db1..aa5e95fc237 100644 --- a/Kernel_23/doc/Kernel_23/PackageDescription.txt +++ b/Kernel_23/doc/Kernel_23/PackageDescription.txt @@ -276,6 +276,7 @@ - `Kernel::CompareDistance_2` - `Kernel::CompareDistance_3` - `Kernel::CompareSlope_2` +- `Kernel::CompareSlope_3` - `Kernel::ComparePowerDistance_2` - `Kernel::ComparePowerDistance_3` - `Kernel::CompareSquaredDistance_2` diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 29c766aaa5e..d1d300c52ae 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -752,6 +752,36 @@ namespace CommonKernelFunctors { } }; + template + class Compare_slope_3 + { + typedef typename K::FT FT; + typedef typename K::Point_3 Point_3; + public: + typedef typename K::Comparison_result result_type; + + result_type operator()(const Point_3& p, const Point_3& q, const Point_3& r, const Point_3& s) const + { + Comparison_result sign_pq = compare(q.z(),p.z()); + Comparison_result sign_rs = compare(s.z(),r.z()); + + if(sign_pq != sign_rs){ + return compare(static_cast(sign_pq), static_cast(sign_rs)); + } + + if((sign_pq == EQUAL) && (sign_rs == EQUAL)){ + return EQUAL; + } + + CGAL_assertion( (sign_pq == sign_rs) && (sign_pq != EQUAL) ); + + Comparison_result res = CGAL::compare(square(p.z() - q.z()) * (square(r.x()-s.x())+square(r.y()-s.y())), + square(r.z() - s.z()) * (square(p.x()-q.x())+square(p.y()-q.y()))); + return (sign_pq == SMALLER) ? opposite(res) : res; + } + + }; + template class Compare_squared_distance_2 { diff --git a/Kernel_23/include/CGAL/Kernel/global_functions_2.h b/Kernel_23/include/CGAL/Kernel/global_functions_2.h index c892b4280b7..acdd7f9cfa6 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_2.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_2.h @@ -342,18 +342,41 @@ compare_lexicographically_xy(const Point_2 &p, template < class K > inline typename K::Comparison_result -compare_slopes(const Line_2 &l1, const Line_2 &l2) +compare_slope(const Line_2 &l1, const Line_2 &l2) { - return internal::compare_slopes(l1, l2, K()); + return internal::compare_slope(l1, l2, K()); } template < class K > inline typename K::Comparison_result +compare_slope(const Segment_2 &s1, const Segment_2 &s2) +{ + return internal::compare_slope(s1, s2, K()); +} + + +#ifndef CGAL_NO_DEPRECATED_CODE +// kept for backward compatibility +template < class K > +CGAL_DEPRECATED_MSG("This function is deprecated. CGAL::compare_slope() should be used instead") +inline +typename K::Comparison_result +compare_slopes(const Line_2 &l1, const Line_2 &l2) +{ + return internal::compare_slope(l1, l2, K()); +} + +// kept for backward compatibility +template < class K > +CGAL_DEPRECATED_MSG("This function is deprecated. CGAL::compare_slope() should be used instead") +inline +typename K::Comparison_result compare_slopes(const Segment_2 &s1, const Segment_2 &s2) { - return internal::compare_slopes(s1, s2, K()); + return internal::compare_slope(s1, s2, K()); } +#endif template < class K > inline diff --git a/Kernel_23/include/CGAL/Kernel/global_functions_3.h b/Kernel_23/include/CGAL/Kernel/global_functions_3.h index 30605491fb6..5471df92d42 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_3.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_3.h @@ -59,6 +59,15 @@ angle(const Point_3 &p, const Point_3 &q, return internal::angle(p, q, r, s, K()); } +template +inline +Angle +angle(const Point_3 &p, const Point_3 &q, + const Point_3 &r, const Vector_3 &v) +{ + return internal::angle(p, q, r, v, K()); +} + template < class K > inline typename K::FT @@ -354,6 +363,17 @@ compare_power_distance(const Point_3 &r, return internal::compare_power_distance(r, p, q, K()); } +template < class K > +inline +typename K::Comparison_result +compare_slope(const Point_3 &p, + const Point_3 &q, + const Point_3 &r, + const Point_3 &s) +{ + return internal::compare_slope(p, q, r, s, K()); +} + template < class K > inline typename K::Comparison_result diff --git a/Kernel_23/include/CGAL/Kernel/global_functions_internal_2.h b/Kernel_23/include/CGAL/Kernel/global_functions_internal_2.h index b5367d6b14f..a7ee11a7604 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_internal_2.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_internal_2.h @@ -370,8 +370,8 @@ compare_signed_distance_to_line(const typename K::Line_2& l, template < class K > inline typename K::Comparison_result -compare_slopes(const typename K::Line_2 &l1, - const typename K::Line_2 &l2, const K& k) +compare_slope(const typename K::Line_2 &l1, + const typename K::Line_2 &l2, const K& k) { return k.compare_slope_2_object()(l1, l2); } @@ -379,8 +379,8 @@ compare_slopes(const typename K::Line_2 &l1, template < class K > inline typename K::Comparison_result -compare_slopes(const typename K::Segment_2 &s1, - const typename K::Segment_2 &s2, const K& k) +compare_slope(const typename K::Segment_2 &s1, + const typename K::Segment_2 &s2, const K& k) { return k.compare_slope_2_object()(s1, s2); } diff --git a/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h b/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h index 7c603de5ccd..7d36aa83359 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h @@ -70,6 +70,18 @@ angle(const typename K::Point_3 &p, return k.angle_3_object()(p, q, r, s); } +template +inline +typename K::Angle +angle(const typename K::Point_3 &p, + const typename K::Point_3 &q, + const typename K::Point_3 &r, + const typename K::Vector_3 &v, + const K &k) +{ + return k.angle_3_object()(p, q, r, v); +} + template < class K > inline typename K::FT @@ -413,6 +425,18 @@ compare_power_distance(const typename K::Point_3 &r, return k.compare_power_distance_3_object()(r, p, q); } +template < class K > +inline +typename K::Comparison_result +compare_slope(const typename K::Point_3 &p, + const typename K::Point_3 &q, + const typename K::Point_3 &r, + const typename K::Point_3 &s, + const K& k) +{ + return k.compare_slope_3_object()(p, q, r, s); +} + template < class K > inline typename K::Comparison_result diff --git a/Kernel_23/include/CGAL/Kernel/interface_macros.h b/Kernel_23/include/CGAL/Kernel/interface_macros.h index dc8206caa67..329573d08f7 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -126,6 +126,8 @@ CGAL_Kernel_pred_RT(Compare_power_distance_3, compare_power_distance_3_object) CGAL_Kernel_pred(Compare_slope_2, compare_slope_2_object) +CGAL_Kernel_pred(Compare_slope_3, + compare_slope_3_object) CGAL_Kernel_pred(Compare_squared_distance_2, compare_squared_distance_2_object) CGAL_Kernel_pred(Compare_squared_distance_3, diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_angle.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_angle.h index eb11c1e3f2f..17b2bbbf889 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_angle.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_angle.h @@ -33,6 +33,7 @@ _test_angle(const R&) typedef CGAL::Point_3 Point_3; typedef CGAL::Vector_2 Vector_2; + typedef CGAL::Vector_3 Vector_3; Point_2 p(RT(2),RT(1)); Point_2 q(RT(5),RT(4)); @@ -67,6 +68,12 @@ _test_angle(const R&) assert( CGAL::angle( org3 - sz, sz - sy) == CGAL::OBTUSE ); assert( CGAL::angle( org3 - sx, sy - sx) == CGAL::ACUTE ); + Vector_3 vz(RT0, RT0, RT1); + Vector_3 vcoplanar(RT1, RT1, RT0); + Vector_3 vmz(RT0, RT0, -RT1); + assert( CGAL::angle( org3, sx, sy, vz) == CGAL::ACUTE ); + assert( CGAL::angle( org3, sx, sy, vcoplanar) == CGAL::RIGHT ); + assert( CGAL::angle( org3, sx, sy, vmz) == CGAL::OBTUSE ); return true; } diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_line_2.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_line_2.h index 49b2e1f57b9..9f4a61e81d2 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_line_2.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_line_2.h @@ -93,36 +93,36 @@ _test_fct_line_2(const R& ) Line_2 l2(p3, p2); Line_2 l3(p4, p6); - assert( CGAL::compare_slopes(l1,l2) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l1,l3) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l3,l1) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l1,l2) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l1,l3) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l3,l1) == CGAL::EQUAL ); std::cout <<'.'; // horizontal lines Line_2 l4(p3, p8); Line_2 l5(p4, p9); - assert( CGAL::compare_slopes(l4, l5) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l3, l4) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l4, l3) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l4, l5) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l3, l4) == CGAL::LARGER ); + assert( CGAL::compare_slope(l4, l3) == CGAL::SMALLER ); std::cout <<'.'; // parallel lines Line_2 l5a(p6, p7); Line_2 l5b(p11, p1); - assert( CGAL::compare_slopes(l5a, l5b) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l5a, l5b) == CGAL::EQUAL ); assert( CGAL::parallel(l5a, l5b) ); // two positive slopes Line_2 l6(p2, p4); Line_2 l7(p2, p6); Line_2 l8(p7, p10); - assert( CGAL::compare_slopes(l6, l6) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l6, l7) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l7, l6) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l6, l8) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l8, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l6) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l6, l7) == CGAL::LARGER ); + assert( CGAL::compare_slope(l7, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l8) == CGAL::LARGER ); + assert( CGAL::compare_slope(l8, l6) == CGAL::SMALLER ); assert( CGAL::parallel(l6, l6) ); assert( ! CGAL::parallel(l6, l7) ); assert( ! CGAL::parallel(l7, l6) ); @@ -130,14 +130,14 @@ _test_fct_line_2(const R& ) assert( ! CGAL::parallel(l8, l6) ); // vertical and positive slope - assert( CGAL::compare_slopes(l1, l6) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l6, l1) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l1, l6) == CGAL::LARGER ); + assert( CGAL::compare_slope(l6, l1) == CGAL::SMALLER ); assert( ! CGAL::parallel(l1, l6) ); assert( ! CGAL::parallel(l6, l1) ); // horizontal and positive slope - assert( CGAL::compare_slopes(l5, l6) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l6, l5) == CGAL::LARGER ); + assert( CGAL::compare_slope(l5, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l5) == CGAL::LARGER ); assert( ! CGAL::parallel(l5, l6) ); assert( ! CGAL::parallel(l6, l5) ); @@ -148,28 +148,28 @@ _test_fct_line_2(const R& ) Line_2 l10(p9, p8); Line_2 l11(p5, p3); - assert( CGAL::compare_slopes(l9, l10) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l10, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l11, l10) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l10) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l10, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l11, l10) == CGAL::LARGER ); assert( ! CGAL::parallel(l9, l10) ); assert( ! CGAL::parallel(l10, l9) ); assert( ! CGAL::parallel(l11, l10) ); // vertical and negative slope - assert( CGAL::compare_slopes(l2, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l2) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l2, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l2) == CGAL::SMALLER ); assert( ! CGAL::parallel(l2, l9) ); assert( ! CGAL::parallel(l9, l2) ); // horizontal and negative slope - assert( CGAL::compare_slopes(l5, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l5) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l5, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l5) == CGAL::SMALLER ); std::cout <<'.'; // positive and negative slope - assert( CGAL::compare_slopes(l6, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l7) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l7) == CGAL::SMALLER ); assert( ! CGAL::parallel(l6, l9) ); assert( ! CGAL::parallel(l9, l7) ); diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_point_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_point_3.h index b052ae6bf87..6ec40703966 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_point_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_point_3.h @@ -233,6 +233,21 @@ _test_fct_point_3(const R& ) assert( CGAL::compare_squared_radius(p0, p1, p2, p3, four) == CGAL::EQUAL ); } + { + CGAL::Point_3 p0(0,0,1), p1(0,0,2), p2(1,0,1), p3(1,0,2), p4(1,0,3); + assert( CGAL::compare_slope(p0, p2, p1, p3) == CGAL::EQUAL ); + assert( CGAL::compare_slope(p0, p2, p0, p3) == CGAL::SMALLER ); + assert( CGAL::compare_slope(p0, p2, p1, p2) == CGAL::LARGER ); + assert( CGAL::compare_slope(p0, p3, p0, p2) == CGAL::LARGER ); + assert( CGAL::compare_slope(p0, p3, p0, p4) == CGAL::SMALLER ); + assert( CGAL::compare_slope(p0, p3, p1, p2) == CGAL::LARGER ); + assert( CGAL::compare_slope(p1, p2, p0, p2) == CGAL::SMALLER ); + assert( CGAL::compare_slope(p1, p2, p0, p3) == CGAL::SMALLER ); + assert( CGAL::compare_slope(p1, p2, p4, p0) == CGAL::LARGER ); + + } + + assert(CGAL::l_infinity_distance(p1,p2) == FT(11)); assert(CGAL::l_infinity_distance(p1,p5) == FT(6)); // More tests, that require sqrt(). diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_segment_2.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_segment_2.h index a4f09851609..7293374b83c 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_segment_2.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_fct_segment_2.h @@ -51,43 +51,43 @@ _test_fct_segment_2(const R& ) Segment_2 l2(p3, p2); Segment_2 l3(p4, p6); - assert( CGAL::compare_slopes(l1,l2) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l1,l3) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l3,l1) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l1,l2) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l1,l3) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l3,l1) == CGAL::EQUAL ); std::cout <<'.'; // horizontal segments Segment_2 l4(p3, p8); Segment_2 l5(p4, p9); - assert( CGAL::compare_slopes(l4, l5) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l3, l4) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l4, l3) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l4, l5) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l3, l4) == CGAL::LARGER ); + assert( CGAL::compare_slope(l4, l3) == CGAL::SMALLER ); std::cout <<'.'; // parallel segments Segment_2 l5a(p6, p7); Segment_2 l5b(p11, p1); - assert( CGAL::compare_slopes(l5a, l5b) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l5a, l5b) == CGAL::EQUAL ); - // two positive slopes + // two positive slope Segment_2 l6(p2, p4); Segment_2 l7(p2, p6); Segment_2 l8(p7, p10); - assert( CGAL::compare_slopes(l6, l6) == CGAL::EQUAL ); - assert( CGAL::compare_slopes(l6, l7) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l7, l6) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l6, l8) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l8, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l6) == CGAL::EQUAL ); + assert( CGAL::compare_slope(l6, l7) == CGAL::LARGER ); + assert( CGAL::compare_slope(l7, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l8) == CGAL::LARGER ); + assert( CGAL::compare_slope(l8, l6) == CGAL::SMALLER ); // vertical and positive slope - assert( CGAL::compare_slopes(l1, l6) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l6, l1) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l1, l6) == CGAL::LARGER ); + assert( CGAL::compare_slope(l6, l1) == CGAL::SMALLER ); // horizontal and positive slope - assert( CGAL::compare_slopes(l5, l6) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l6, l5) == CGAL::LARGER ); + assert( CGAL::compare_slope(l5, l6) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l5) == CGAL::LARGER ); @@ -98,23 +98,23 @@ _test_fct_segment_2(const R& ) Segment_2 l10(p9, p8); Segment_2 l11(p5, p3); - assert( CGAL::compare_slopes(l9, l10) == CGAL::SMALLER ); - assert( CGAL::compare_slopes(l10, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l11, l10) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l10) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l10, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l11, l10) == CGAL::LARGER ); // vertical and negative slope - assert( CGAL::compare_slopes(l2, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l2) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l2, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l2) == CGAL::SMALLER ); // horizontal and negative slope - assert( CGAL::compare_slopes(l5, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l5) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l5, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l5) == CGAL::SMALLER ); std::cout <<'.'; // positive and negative slope - assert( CGAL::compare_slopes(l6, l9) == CGAL::LARGER ); - assert( CGAL::compare_slopes(l9, l7) == CGAL::SMALLER ); + assert( CGAL::compare_slope(l6, l9) == CGAL::LARGER ); + assert( CGAL::compare_slope(l9, l7) == CGAL::SMALLER ); std::cout << "done" << std::endl; return true; diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h index b1e0f2322c2..87617cdca5e 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/corefinement.h @@ -50,7 +50,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm, typedef Side_of_triangle_mesh Side_of_tm; // first check that the orientation of the current cc is consistant with its // parent cc containing it - bool new_is_parent_outward_oriented = internal::is_outward_oriented( + bool new_is_parent_outward_oriented = internal::is_outward_oriented( xtrm_vertices[xtrm_cc_id], tm, parameters::vertex_point_map(vpm)); if (new_is_parent_outward_oriented==is_parent_outward_oriented) return false; @@ -91,8 +91,8 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm, for (std::size_t i=1;i + get(vpm,xtrm_vertices[new_xtrm_cc_id]).z()) new_xtrm_cc_id=candidate; new_cc_handled.reset(candidate); cc_handled.set(candidate); } @@ -111,7 +111,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm, candidate < cc_not_handled.npos; candidate = cc_not_handled.find_next(candidate)) { - if(get(vpm,xtrm_vertices[candidate]) < get(vpm,xtrm_vertices[new_xtrm_cc_id])) + if(get(vpm,xtrm_vertices[candidate]).z() > get(vpm,xtrm_vertices[new_xtrm_cc_id]).z()) new_xtrm_cc_id = candidate; } @@ -129,7 +129,7 @@ bool recursive_does_bound_a_volume(const TriangleMesh& tm, * * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. * If `TriangleMesh` has an internal property map for `CGAL::face_index_t`, - * as a named parameter, then it must initialized. + * as a named parameter, then it must be initialized. * @tparam NamedParameters a sequence of \ref namedparameters * * @param tm a triangulated surface mesh @@ -182,7 +182,7 @@ bool does_bound_a_volume(const TriangleMesh& tm, const NamedParameters& np) boost::dynamic_bitset<> cc_handled(nb_cc, 0); - // extract the less-xyz vertex of each connected component + // extract a vertex with max z coordinate for each connected component std::vector xtrm_vertices(nb_cc, GT::null_vertex()); BOOST_FOREACH(vertex_descriptor vd, vertices(tm)) { @@ -190,18 +190,18 @@ bool does_bound_a_volume(const TriangleMesh& tm, const NamedParameters& np) if (xtrm_vertices[cc_id]==GT::null_vertex()) xtrm_vertices[cc_id]=vd; else - if (get(vpm, vd)get(vpm,xtrm_vertices[cc_id]).z()) xtrm_vertices[cc_id]=vd; } - //extract the less-xyz of all components + //extract a vertex with max z amongst all components std::size_t xtrm_cc_id=0; for(std::size_t id=1; idget(vpm,xtrm_vertices[xtrm_cc_id]).z()) xtrm_cc_id=id; bool is_parent_outward_oriented = - !internal::is_outward_oriented(xtrm_vertices[xtrm_cc_id], tm, np); + !internal::is_outward_oriented(xtrm_vertices[xtrm_cc_id], tm, np); return internal::recursive_does_bound_a_volume(tm, vpm, fid_map, xtrm_vertices, @@ -433,7 +433,7 @@ boolean_operation( TriangleMesh& tm1, * * @tparam TriangleMesh a model of `MutableFaceGraph`, `HalfedgeListGraph` and `FaceListGraph`. * If `TriangleMesh` has an internal property map for `CGAL::face_index_t`, - * as a named parameter, then it must initialized. + * as a named parameter, then it must be initialized. * * @tparam NamedParameters1 a sequence of \ref namedparameters * @tparam NamedParameters2 a sequence of \ref namedparameters diff --git a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h index 4c39e7684b0..f229d629972 100644 --- a/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h +++ b/Polygon_mesh_processing/include/CGAL/Polygon_mesh_processing/orientation.h @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -40,37 +41,100 @@ namespace CGAL { namespace Polygon_mesh_processing { namespace internal{ - template - struct Compare_vertex_points_xyz_3{ - Less_xyz less; - VPmap vpmap; - Compare_vertex_points_xyz_3(VPmap const& vpmap) - : vpmap(vpmap){} + template + struct Compare_vertex_points_z_3 + { + VPmap vpmap; + typename GT::Compare_z_3 compare_z; + + Compare_vertex_points_z_3(VPmap const& vpmap, const GT& gt) + : vpmap(vpmap) + , compare_z(gt.compare_z_3_object()) + {} typedef bool result_type; template bool operator()(vertex_descriptor v1, vertex_descriptor v2) const { - return less(get(vpmap, v1), get(vpmap, v2)); + return CGAL::SMALLER == compare_z(get(vpmap, v1), get(vpmap, v2)); } - }; - template - bool is_outward_oriented(typename boost::graph_traits::vertex_descriptor vd, - const PM& pmesh, + + template + bool is_outward_oriented(typename boost::graph_traits::vertex_descriptor v_max, + const PolygonMesh& pmesh, const NamedParameters& np) { - const typename Kernel::Vector_3& - normal_v_min = compute_vertex_normal(vd, pmesh, np); + using boost::choose_param; + using boost::get_param; - return normal_v_min[0] < 0 || ( - normal_v_min[0] == 0 && ( - normal_v_min[1] < 0 || - ( normal_v_min[1]==0 && normal_v_min[2] < 0 ) - ) - ); + //VertexPointMap + typedef typename GetVertexPointMap::const_type VPMap; + VPMap vpmap = choose_param(get_param(np, vertex_point), + get_const_property_map(vertex_point, pmesh)); + //Kernel + typedef typename GetGeomTraits::type GT; + GT gt = choose_param(get_param(np, geom_traits), GT()); + + //among the incoming edges of `v_max`, find one edge `e` with the minimal slope + typedef typename boost::graph_traits::halfedge_descriptor halfedge_descriptor; + halfedge_descriptor min_slope_he = halfedge(v_max, pmesh); + CGAL_assertion(v_max == target(min_slope_he, pmesh)); + + typename GT::Compare_slope_3 compare_slope = gt.compare_slope_3_object(); + BOOST_FOREACH(halfedge_descriptor he, halfedges_around_target(v_max, pmesh)) + { + CGAL_assertion(v_max == target(min_slope_he, pmesh)); + CGAL_assertion(v_max == target(he, pmesh)); + + if(CGAL::SMALLER == compare_slope(get(vpmap, source(he, pmesh)), + get(vpmap, v_max), + get(vpmap, source(min_slope_he, pmesh)), + get(vpmap, v_max))) + { + min_slope_he = he; + } + } + + // We compute the orientations of the two triangles incident to the edge + // of `min_slope_he` projected in the xy-plane. We can conclude using + // the 2D orientation of the 3D triangle that is the top one along the z-axis + // in the neighborhood of `min_slope_he`. + Projection_traits_xy_3 p_gt; + typename Projection_traits_xy_3::Orientation_2 orientation_2 = p_gt.orientation_2_object(); + + typename boost::property_traits::reference p1 = get(vpmap, source(min_slope_he, pmesh)); + typename boost::property_traits::reference p2 = get(vpmap, target(min_slope_he, pmesh)); + typename boost::property_traits::reference p3 = get(vpmap, target(next(min_slope_he, pmesh), pmesh)); + typename boost::property_traits::reference p4 = get(vpmap, target(next(opposite(min_slope_he, pmesh), pmesh), pmesh)); + + Orientation p1p2p3_2d = orientation_2(p1, p2, p3); + Orientation p2p1p4_2d = orientation_2(p2, p1, p4); + + CGAL_assertion( p1p2p3_2d!=COLLINEAR || p2p1p4_2d!=COLLINEAR ); // no self-intersection + + if ( p1p2p3_2d == COLLINEAR) + return p2p1p4_2d == LEFT_TURN; + if (p2p1p4_2d ==COLLINEAR) + return p1p2p3_2d == LEFT_TURN; + + // if the local dihedral angle is strictly larger that PI/2, we can conclude with any of two triangles + if (p1p2p3_2d==p2p1p4_2d) + return p1p2p3_2d == LEFT_TURN; + + typename GT::Orientation_3 orientation_3 = gt.orientation_3_object(); + + CGAL_assertion( orientation_3(p1, p2, p3, p4) != COPLANAR ); // same side of min_slope_he and no self-intersection + + // if p1p2p3_2d is left turn, then it must be the top face so that the orientation is outward oriented + if (p1p2p3_2d == LEFT_TURN) + return orientation_3(p1, p2, p3, p4) == NEGATIVE; + + // same test with the other face + CGAL_assertion(p2p1p4_2d == LEFT_TURN); + return orientation_3(p2, p1, p4, p3) == NEGATIVE; } } // end of namespace internal @@ -109,6 +173,11 @@ bool is_outward_oriented(const PolygonMesh& pmesh, CGAL_warning(CGAL::is_closed(pmesh)); CGAL_precondition(CGAL::is_valid(pmesh)); + //check for empty pmesh + CGAL_warning(faces(pmesh).first != faces(pmesh).second); + if (faces(pmesh).first == faces(pmesh).second) + return true; + using boost::choose_param; using boost::get_param; @@ -117,17 +186,19 @@ bool is_outward_oriented(const PolygonMesh& pmesh, VPMap vpmap = choose_param(get_param(np, vertex_point), get_const_property_map(vertex_point, pmesh)); //Kernel - typedef typename GetGeomTraits::type Kernel; - - internal::Compare_vertex_points_xyz_3 - less_xyz(vpmap); + typedef typename GetGeomTraits::type GT; + GT gt = choose_param(get_param(np, geom_traits), GT()); + //find the vertex with maximal z coordinate typename boost::graph_traits::vertex_iterator vbegin, vend; cpp11::tie(vbegin, vend) = vertices(pmesh); - typename boost::graph_traits::vertex_iterator v_min - = std::min_element(vbegin, vend, less_xyz); - return internal::is_outward_oriented(*v_min, pmesh, np); + internal::Compare_vertex_points_z_3 less_z(vpmap, gt); + typename boost::graph_traits::vertex_iterator v_max_it + = std::max_element(vbegin, vend, less_z); + typename boost::graph_traits::vertex_descriptor v_max = *v_max_it; + + return internal::is_outward_oriented(v_max, pmesh, np); } ///\cond SKIP_IN_MANUAL diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra1.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra1.off new file mode 100644 index 00000000000..ebb37d3fd94 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra1.off @@ -0,0 +1,12 @@ +OFF +4 4 0 + +0 0 0 +0.65000000000000002 -1.3 0.65000000000000002 +0.10000000000000001 -1 1 +2 -2 -0.5 +3 2 1 0 +3 1 3 0 +3 3 2 0 +3 3 1 2 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra2.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra2.off new file mode 100644 index 00000000000..0d18f67fd1d --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra2.off @@ -0,0 +1,12 @@ +OFF +4 4 0 + +0 0 0 +0.65000000000000002 -1.3 0.65000000000000002 +0.10000000000000001 -1 1 +-0.33420955685098419 -0.59067608503190883 0.55877066363146466 +3 2 1 0 +3 1 3 0 +3 3 2 0 +3 3 1 2 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra3.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra3.off new file mode 100644 index 00000000000..d83aa004308 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra3.off @@ -0,0 +1,12 @@ +OFF +4 4 0 + +0 1 0 +1 0 0 +0 0 0 +0 0 1 +3 0 1 2 +3 2 3 0 +3 1 3 2 +3 0 3 1 + diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra4.off b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra4.off new file mode 100644 index 00000000000..f0994dbb579 --- /dev/null +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/data/tetra4.off @@ -0,0 +1,12 @@ +OFF +4 4 0 + +0 0 1 +0 1 0.8 +-1 1 0.9 +1 0 0.5 + +3 0 1 2 +3 0 2 3 +3 0 3 1 +3 1 3 2 diff --git a/Polygon_mesh_processing/test/Polygon_mesh_processing/orient_polygon_mesh_test.cpp b/Polygon_mesh_processing/test/Polygon_mesh_processing/orient_polygon_mesh_test.cpp index a7718e6562d..05638068954 100644 --- a/Polygon_mesh_processing/test/Polygon_mesh_processing/orient_polygon_mesh_test.cpp +++ b/Polygon_mesh_processing/test/Polygon_mesh_processing/orient_polygon_mesh_test.cpp @@ -61,6 +61,12 @@ int main() { test_orient("data/elephant.off"); + test_orient("data-coref/cube.off"); + test_orient("data/tetra1.off"); + test_orient("data/tetra2.off"); + test_orient("data/tetra3.off"); + test_orient("data/tetra4.off"); + test_orient("data-coref/cube.off"); test_orient("data/elephant.off"); std::cerr << "All done." << std::endl;