diff --git a/Kernel_23/doc_tex/Kernel_23/kernel_toc.tex b/Kernel_23/doc_tex/Kernel_23/kernel_toc.tex index e63240844cf..3e5ab4c5406 100644 --- a/Kernel_23/doc_tex/Kernel_23/kernel_toc.tex +++ b/Kernel_23/doc_tex/Kernel_23/kernel_toc.tex @@ -101,6 +101,7 @@ \ccRefIdfierPage{CGAL::bisector} \\ \ccRefIdfierPage{CGAL::centroid} \\ \ccRefIdfierPage{CGAL::circumcenter} \\ +\ccRefIdfierPage{CGAL::compare_dihedral_angle} \\ \ccRefIdfierPage{CGAL::compare_distance_to_point} \\ \ccRefIdfierPage{CGAL::compare_signed_distance_to_line} \\ \ccRefIdfierPage{CGAL::compare_signed_distance_to_plane} \\ diff --git a/Kernel_23/doc_tex/Kernel_23_ref/Kernel.tex b/Kernel_23/doc_tex/Kernel_23_ref/Kernel.tex index f06fae3384a..32cc74520e1 100644 --- a/Kernel_23/doc_tex/Kernel_23_ref/Kernel.tex +++ b/Kernel_23/doc_tex/Kernel_23_ref/Kernel.tex @@ -485,6 +485,8 @@ If the result type is a number type, the prefix is \ccc{Compute_}: \ccGlue \ccNestedType{Less_distance_to_point_3}{a model of \ccc{Kernel::LessDistanceToPoint_3}} \ccGlue +\ccNestedType{Compare_dihedral_angle_3}{a model of \ccc{Kernel::CompareDihedralAngle_3}} +\ccGlue \ccNestedType{Compare_distance_3}{a model of \ccc{Kernel::CompareDistance_3}} \ccGlue \ccNestedType{Collinear_3}{a model of \ccc{Kernel::Collinear_3}} diff --git a/Kernel_23/doc_tex/Kernel_23_ref/Kernel_CompareDihedralAngle_3.tex b/Kernel_23/doc_tex/Kernel_23_ref/Kernel_CompareDihedralAngle_3.tex new file mode 100644 index 00000000000..301a7769422 --- /dev/null +++ b/Kernel_23/doc_tex/Kernel_23_ref/Kernel_CompareDihedralAngle_3.tex @@ -0,0 +1,45 @@ +\begin{ccRefFunctionObjectConcept}{Kernel::CompareDihedralAngle_3} + +A model for this must provide: + +\ccCreationVariable{fo} + +\ccMemberFunction{Comparison_result operator()(const K::Point_3& a1, + const K::Point_3& b1, + const K::Point_3& c1, + const K::Point_3& d1, + const K::Point_3& a2, + const K::Point_3& b2, + const K::Point_3& c2, + const K::Point_3& d2);} + {compares the dihedral angles $\theta_1$ and $\theta_2$, where + $\theta_i$ is the dihedral angle in the tetrahedron $(a_i, b_i, + c_i, d_i)$ at the edge $(a_i, b_i)$. These two angles are computed + in $[0, \pi]$. + The result is the same as \ccc{operator()(b1-a1, + c1-a1, d1-a1, b2-a2, c2-a2, d2-a2)}. + \ccPrecond{For $i \in \{1,2\}$, $a_i$, $b_i$, $c_i$ are not + collinear, and $a_i$, $b_i$, $d_i$ are not collinear.}} + +\ccMemberFunction{Comparison_result operator()(const K::Vector_3& u1, + const K::Vector_3& v1, + const K::Vector_3& w1, + const K::Vector_3& u2, + const K::Vector_3& v2, + const K::Vector_3& w2);} + {compares the dihedral angles $\theta_1$ and $\theta_2$, where + $\theta_i$ is the dihedral angle between the vectorial planes + defined by $(u_i, v_i)$ and $(u_i, w_i)$. These two angles are + computed in $[0, \pi]$. + \ccPrecond{For $i \in \{1,2\}$, $u_i$ and $v_i$ are not collinear, + and $u_i$ and $w_i$ are not collinear.}} + +\ccRefines +\ccc{AdaptableFunctor} (with three arguments) + +\ccSeeAlso +\ccRefIdfierPage{Kernel::CompareSquaredDistance_2} \\ +\ccRefIdfierPage{CGAL::compare_distance_to_point} \\ +\ccRefIdfierPage{CGAL::compare_squared_distance} \\ + +\end{ccRefFunctionObjectConcept} diff --git a/Kernel_23/doc_tex/Kernel_23_ref/compare_dihedral_angle.tex b/Kernel_23/doc_tex/Kernel_23_ref/compare_dihedral_angle.tex new file mode 100644 index 00000000000..eb0db497ed6 --- /dev/null +++ b/Kernel_23/doc_tex/Kernel_23_ref/compare_dihedral_angle.tex @@ -0,0 +1,35 @@ +\begin{ccRefFunction}{compare_dihedral_angle} + +\ccFunction{Comparison_result + compare_dihedral_angle(const Point_3& a1, + const Point_3& b1, + const Point_3& c1, + const Point_3& d1, + const Point_3& a2, + const Point_3& b2, + const Point_3& c2, + const Point_3& d2);} + {compares the dihedral angles $\theta_1$ and $\theta_2$, where + $\theta_i$ is the dihedral angle in the tetrahedron $(a_i, b_i, + c_i, d_i)$ at the edge $(a_i, b_i)$. These two angles are computed + in $[0, \pi]$. + The result is the same as \ccc{compare_dihedral_angle(b1-a1, + c1-a1, d1-a1, b2-a2, c2-a2, d2-a2)}. + \ccPrecond{For $i \in \{1,2\}$, $a_i$, $b_i$, $c_i$ are not collinear, + and $a_i$, $b_i$, $d_i$ are not collinear.}} + +\ccFunction{Comparison_result + compare_dihedral_angle(const K::Vector_3& u1, + const K::Vector_3& v1, + const K::Vector_3& w1, + const K::Vector_3& u2, + const K::Vector_3& v2, + const K::Vector_3& w2);} + {compares the dihedral angles $\theta_1$ and $\theta_2$, where + $\theta_i$ is the dihedral angle between the vectorial planes + defined by $(u_i, v_i)$ and $(u_i, w_i)$. These two angles are + computed in $[0, \pi]$. + \ccPrecond{For $i \in \{1,2\}$, $u_i$ and $v_i$ are not collinear, + and $u_i$ and $w_i$ are not collinear.}} + +\end{ccRefFunction} diff --git a/Kernel_23/doc_tex/Kernel_23_ref/main.tex b/Kernel_23/doc_tex/Kernel_23_ref/main.tex index adb4f730560..fe3e87bca19 100644 --- a/Kernel_23/doc_tex/Kernel_23_ref/main.tex +++ b/Kernel_23/doc_tex/Kernel_23_ref/main.tex @@ -160,6 +160,7 @@ in the kernel. \input{Kernel_23_ref/compare_signed_distance_to_line.tex} \input{Kernel_23_ref/compare_signed_distance_to_plane.tex} \input{Kernel_23_ref/compare_slopes.tex} +\input{Kernel_23_ref/compare_dihedral_angle.tex} \input{Kernel_23_ref/compare_squared_distance.tex} \input{Kernel_23_ref/compare_squared_radius.tex} \input{Kernel_23_ref/compare_x.tex} @@ -272,6 +273,7 @@ in the kernel. \input{Kernel_23_ref/Kernel_Collinear_2.tex} \input{Kernel_23_ref/Kernel_Collinear_3.tex} \input{Kernel_23_ref/Kernel_CompareAngleWithXAxis_2.tex} +\input{Kernel_23_ref/Kernel_CompareDihedralAngle_3.tex} \input{Kernel_23_ref/Kernel_CompareDistance_2.tex} \input{Kernel_23_ref/Kernel_CompareDistance_3.tex} \input{Kernel_23_ref/Kernel_CompareSlope_2.tex} diff --git a/Kernel_23/include/CGAL/Kernel/function_objects.h b/Kernel_23/include/CGAL/Kernel/function_objects.h index 86bcbfdb361..a46dde34b0e 100644 --- a/Kernel_23/include/CGAL/Kernel/function_objects.h +++ b/Kernel_23/include/CGAL/Kernel/function_objects.h @@ -3,6 +3,7 @@ // INRIA Sophia-Antipolis (France), Martin-Luther-University Halle-Wittenberg // (Germany), Max-Planck-Institute Saarbruecken (Germany), RISC Linz (Austria), // and Tel-Aviv University (Israel). All rights reserved. +// Copyright (c) 2009 GeometryFactory (France) // // This file is part of CGAL (www.cgal.org); you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public License as @@ -163,6 +164,89 @@ namespace CommonKernelFunctors { { return assign(t, o); } }; + template + class Compare_dihedral_angle_3 + { + typedef typename K::Point_3 Point_3; + typedef typename K::Vector_3 Vector_3; + public: + typedef typename K::Comparison_result result_type; + + result_type + operator()(const Point_3& a1, const Point_3& b1, + const Point_3& c1, const Point_3& d1, + const Point_3& a2, const Point_3& b2, + const Point_3& c2, const Point_3& d2) const + { + const Vector_3 ab1 = b1 - a1; + const Vector_3 ac1 = c1 - a1; + const Vector_3 ad1 = d1 - a1; + + const Vector_3 ab2 = b2 - a2; + const Vector_3 ac2 = c2 - a2; + const Vector_3 ad2 = d2 - a2; + return this->operator()(ab1, ac1, ad1, ab2, ac2, ad2); + } + + result_type + operator()(const Vector_3& ab1, const Vector_3& ac1, const Vector_3& ad1, + const Vector_3& ab2, const Vector_3& ac2, const Vector_3& ad2) + const + { + typedef typename K::FT FT; + typedef typename K::Construct_cross_product_vector_3 Cross_product; + Cross_product xproduct = K().construct_cross_product_vector_3_object(); + + const Vector_3 abac1 = xproduct(ab1, ac1); + const Vector_3 abad1 = xproduct(ab1, ad1); + const FT sc_prod_1 = abac1 * abad1; + + const Vector_3 abac2 = xproduct(ab2, ac2); + const Vector_3 abad2 = xproduct(ab2, ad2); + const FT sc_prod_2 = abac2 * abad2; + + CGAL_kernel_assertion_msg( abac1 != NULL_VECTOR, + "ab1 and ac1 are collinear" ); + CGAL_kernel_assertion_msg( abad1 != NULL_VECTOR, + "ab1 and ad1 are collinear" ); + CGAL_kernel_assertion_msg( abac2 != NULL_VECTOR, + "ab2 and ac2 are collinear" ); + CGAL_kernel_assertion_msg( abad2 != NULL_VECTOR, + "ab2 and ad2 are collinear" ); + + if(sc_prod_1 >= 0 ) { + if(sc_prod_2 >= 0) { + // the two cosinus are >= 0, cosinus is decreasing on [0,1] + return compare(CGAL::square(sc_prod_2)* + (abac1*abac1)*(abad1*abad1), + CGAL::square(sc_prod_1)* + (abac2*abac2)*(abad2*abad2)); + } + else { + return SMALLER; + } + } + else { + if(sc_prod_2 < 0) { + // the two cosinus are < 0, cosinus is increasing on [-1,0] + return compare(CGAL::square(sc_prod_1)* + (abac2*abac2)*(abad2*abad2), + CGAL::square(sc_prod_2)* + (abac1*abac1)*(abad1*abad1)); + } + else + return LARGER; + } + } + + // result_type + // operator()(const Tetrahedron_3& t1, const Tetrahedron_3& t2) const + // { + // return this->operator(t1[0], t1[1], t1[2], t1[3], + // t2[0], t2[1], t2[2], t2[3]); + // } + }; + template class Compute_area_3 { diff --git a/Kernel_23/include/CGAL/Kernel/global_functions_3.h b/Kernel_23/include/CGAL/Kernel/global_functions_3.h index 09c446ef95d..b5ec98d83ae 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_3.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_3.h @@ -260,6 +260,30 @@ collinear_are_strictly_ordered_along_line(const Point_3 &p, return internal::collinear_are_strictly_ordered_along_line(p, q, r, K()); } +template < class K > +inline +typename K::Comparison_result +compare_dihedral_angle(const Point_3& a1, const Point_3& b1, + const Point_3& c1, const Point_3& d1, + const Point_3& a2, const Point_3& b2, + const Point_3& c2, const Point_3& d2) +{ + return internal::compare_dihedral_angle(a1, b1, c1, d1, a2, b2, c2, d2, K()); +} + +template < class K > +inline +typename K::Comparison_result +compare_dihedral_angle(const Vector_3& ab1, + const Vector_3& ac1, + const Vector_3& ad1, + const Vector_3& ab2, + const Vector_3& ac2, + const Vector_3& ad2) +{ + return internal::compare_dihedral_angle(ab1, ac1, ad1, ab2, ac2, ad2, K()); +} + template < class K > inline typename K::Comparison_result 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 34a32da74c6..e6d4839f517 100644 --- a/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h +++ b/Kernel_23/include/CGAL/Kernel/global_functions_internal_3.h @@ -258,6 +258,37 @@ collinear_are_strictly_ordered_along_line( return k.collinear_are_strictly_ordered_along_line_3_object()(p, q, r); } + +template < class K > +inline +typename K::Comparison_result +compare_dihedral_angle(const typename K::Point_3& a1, + const typename K::Point_3& b1, + const typename K::Point_3& c1, + const typename K::Point_3& d1, + const typename K::Point_3& a2, + const typename K::Point_3& b2, + const typename K::Point_3& c2, + const typename K::Point_3& d2, + const K& k) +{ + return k.compare_dihedral_angle_3_object()(a1, b1, c1, d1, a2, b2, c2, d2); +} + +template < class K > +inline +typename K::Comparison_result +compare_dihedral_angle(const typename K::Vector_3& ab1, + const typename K::Vector_3& ac1, + const typename K::Vector_3& ad1, + const typename K::Vector_3& ab2, + const typename K::Vector_3& ac2, + const typename K::Vector_3& ad2, + const K& k) +{ + return k.compare_dihedral_angle_3_object()(ab1, ac1, ad1, ab2, ac2, ad2); +} + 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 41b398bba3b..3557ebce7d8 100644 --- a/Kernel_23/include/CGAL/Kernel/interface_macros.h +++ b/Kernel_23/include/CGAL/Kernel/interface_macros.h @@ -105,6 +105,8 @@ CGAL_Kernel_pred(Collinear_3, collinear_3_object) CGAL_Kernel_pred(Compare_angle_with_x_axis_2, compare_angle_with_x_axis_2_object) +CGAL_Kernel_pred(Compare_dihedral_angle_3, + compare_dihedral_angle_3_object) CGAL_Kernel_pred(Compare_distance_2, compare_distance_2_object) CGAL_Kernel_pred(Compare_distance_3, diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_compare_dihedral_angle_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_compare_dihedral_angle_3.h new file mode 100644 index 00000000000..414b6be6597 --- /dev/null +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_compare_dihedral_angle_3.h @@ -0,0 +1,97 @@ +// Copyright (c) 2009 GeometryFactory (France) +// +// This file is part of CGAL (www.cgal.org); you can redistribute it and/or +// modify it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; version 2.1 of the License. +// See the file LICENSE.LGPL distributed with CGAL. +// +// Licensees holding a valid commercial license may use this file in +// accordance with the commercial license agreement provided with the software. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +// +// $URL$ +// $Id$ +// +// +// Author(s) : Laurent Rineau +// + +template +bool +_test_compare_dihedral_angle_3(const R& rep) +{ + typedef typename R::Point_3 Point_3; + typedef typename R::Vector_3 Vector_3; + typename R::Compare_dihedral_angle_3 compare_dih_angle + = rep.compare_dihedral_angle_3_object(); + + for(int theta1 = -170; theta1 <= 180; theta1+= 10) { + const double angle1 = CGAL_PI*theta1/180.; + Point_3 p1(0, 0, -1); + Point_3 p2(0, 0, 1); + Point_3 p3(1, 0, 0); + Point_3 p4((int)(std::cos(angle1)*1000), (int)(std::sin(angle1)*1000), 0); + if(theta1 == 180) { + p4 = Point_3(-1, 0, 0); + } + for(int theta2 = -170; theta2 <= 180; theta2+= 10) { + // if(theta1 == theta2) continue; + const double angle2 = CGAL_PI*theta2/180.; + Point_3 q1(0, 1, 0); + Point_3 q2(0, -1, 0); + Point_3 q3(0, 0, 1); + Point_3 q4((int)(std::sin(angle2)*1000), 0, (int)(std::cos(angle2)*1000)); + if(theta2 == 180) { + q4 = Point_3(0, 0, -1); + } + const typename R::Comparison_result + comp_result = compare_dih_angle(p1, p2, p3, p4, q1, q2, q3, q4), + global_fct_call = CGAL::compare_dihedral_angle(p1, p2, p3, p4, q1, q2, q3, q4), + call_with_vectors = compare_dih_angle(p2 - p1, + p3 - p1, + p4 - p1, + q2 - q1, + q3 - q1, + q4 - q1), + call_fct_with_vectors = CGAL::compare_dihedral_angle(p2 - p1, + p3 - p1, + p4 - p1, + q2 - q1, + q3 - q1, + q4 - q1), + theorical_result = CGAL::compare(std::abs(theta1),std::abs(theta2)); + if(comp_result != theorical_result || + comp_result != global_fct_call || + comp_result != call_with_vectors || + comp_result != call_fct_with_vectors) { + std::cerr << "Error compare_dihedral_angle_3, with angles " + << theta1 << " and " << theta2 << std::endl; + std::cerr << "Results are: " + << comp_result << " " << global_fct_call << " " + << call_with_vectors << " " << call_fct_with_vectors << "\n"; + const Vector_3 u1 = p2 - p1; + const Vector_3 v1 = p3 - p1; + const Vector_3 w1 = p4 - p1; + const Vector_3 uv1 = cross_product(u1, v1); + const Vector_3 uw1 = cross_product(u1, w1); + const Vector_3 u2 = q2 - q1; + const Vector_3 v2 = q3 - q1; + const Vector_3 w2 = q4 - q1; + const Vector_3 uv2 = cross_product(u2, v2); + const Vector_3 uw2 = cross_product(u2, w2); + std::cerr << "Squared cosinus and signs are: \n" + << CGAL::to_double((uv1 * uw1) * (uv1 * uw1) / + ((uv1*uv1) * ( uw1*uw1))) << " " + << CGAL::sign(uv1*uw1) << "\n" + << CGAL::to_double((uv2 * uw2) * (uv2 * uw2) / + ((uv2*uv2) * ( uw2*uw2))) << " " + << CGAL::sign(uv2*uw2) << "\n"; + return false; + } + } + } + return true; +} + diff --git a/Kernel_23/test/Kernel_23/include/CGAL/_test_new_3.h b/Kernel_23/test/Kernel_23/include/CGAL/_test_new_3.h index 2fc8a4a0fe5..954bb8b4794 100644 --- a/Kernel_23/test/Kernel_23/include/CGAL/_test_new_3.h +++ b/Kernel_23/test/Kernel_23/include/CGAL/_test_new_3.h @@ -25,6 +25,7 @@ #include #include +#include #include @@ -559,6 +560,11 @@ test_new_3(const R& rep) bool tmp28a = less_signed_distance_to_plane(tmp8,p2,p3); (void) tmp28a; + { + bool tmp = _test_compare_dihedral_angle_3(rep); + assert(tmp); + } + typename R::Compare_distance_3 compare_dist = rep.compare_distance_3_object(); Comparison_result tmp34ab = compare_dist(p2,p3,p4);