Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_COMPUTE_MINIMUM_SINE_DIHEDRAL_ANGLE_QUALITY_MEASURE_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_COMPUTE_MINIMUM_SINE_DIHEDRAL_ANGLE_QUALITY_MEASURE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_is_number.h>
00013 #include <OpenTissue/core/math/math_basic_types.h>
00014 #include <OpenTissue/core/geometry/geometry_tetrahedron.h>
00015
00016 #include <boost/cast.hpp>
00017
00018 #include <cmath>
00019 #include <cassert>
00020
00021 namespace OpenTissue
00022 {
00023 namespace geometry
00024 {
00048 template<typename vector3_type>
00049 inline typename vector3_type::value_type
00050 compute_minimum_sine_dihedral_angle_quality_measure (
00051 vector3_type const & p0
00052 , vector3_type const & p1
00053 , vector3_type const & p2
00054 , vector3_type const & p3
00055 )
00056 {
00057 using std::sqrt;
00058 using std::min;
00059
00060 typedef typename vector3_type::value_type real_type;
00061 typedef OpenTissue::math::BasicMathTypes<real_type, size_t> math_types;
00062 typedef typename math_types::value_traits value_traits;
00063 typedef Tetrahedron<math_types> tetrahedron_type;
00064
00065 real_type const sqr2_mul_9_div_8 = boost::numeric_cast<real_type>( 1.5909902576697319299018998147359 );
00066
00067 vector3_type e_01 = (p0-p1);
00068 vector3_type e_12 = (p1-p2);
00069 vector3_type e_20 = (p2-p0);
00070 vector3_type e_03 = (p0-p3);
00071 vector3_type e_13 = (p1-p3);
00072 vector3_type e_23 = (p2-p3);
00073
00074 real_type A3 = value_traits::half() * length( cross( e_20, e_01 ) );
00075 real_type A2 = value_traits::half() * length( cross( e_01, e_03 ) );
00076 real_type A1 = value_traits::half() * length( cross( e_03, e_20 ) );
00077 real_type A0 = value_traits::half() * length( cross( e_12, e_13 ) );
00078
00079 assert( is_number( A0 ) || !"A0 was not a number" );
00080 assert( is_number( A1 ) || !"A1 was not a number" );
00081 assert( is_number( A2 ) || !"A2 was not a number" );
00082 assert( is_number( A3 ) || !"A3 was not a number" );
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093 if( !( A0 > value_traits::zero() || A0 < value_traits::zero()) )
00094 return value_traits::zero();
00095 if( !( A1 > value_traits::zero() || A1 < value_traits::zero()) )
00096 return value_traits::zero();
00097 if( !( A2 > value_traits::zero() || A2 < value_traits::zero()) )
00098 return value_traits::zero();
00099 if( !( A3 > value_traits::zero() || A3 < value_traits::zero()) )
00100 return value_traits::zero();
00101
00102 real_type l_01 = sqrt( inner_prod(e_01,e_01) );
00103 real_type l_12 = sqrt( inner_prod(e_12,e_12) );
00104 real_type l_20 = sqrt( inner_prod(e_20,e_20) );
00105 real_type l_03 = sqrt( inner_prod(e_03,e_03) );
00106 real_type l_13 = sqrt( inner_prod(e_13,e_13) );
00107 real_type l_23 = sqrt( inner_prod(e_23,e_23) );
00108
00109 tetrahedron_type T(p0,p1,p2,p3);
00110
00111 real_type c = sqr2_mul_9_div_8 * T.volume();
00112
00113 assert( is_number( c ) || !"factor c was not a number" );
00114
00115 real_type q1 = c * (l_01) / (A2*A3);
00116 real_type q2 = c * (l_12) / (A0*A3);
00117 real_type q3 = c * (l_20) / (A1*A3);
00118 real_type q4 = c * (l_03) / (A1*A2);
00119 real_type q5 = c * (l_13) / (A0*A2);
00120 real_type q6 = c * (l_23) / (A0*A1);
00121
00122 assert( is_number( q1 ) || !"q1 was not a number" );
00123 assert( is_number( q2 ) || !"q2 was not a number" );
00124 assert( is_number( q3 ) || !"q3 was not a number" );
00125 assert( is_number( q4 ) || !"q4 was not a number" );
00126 assert( is_number( q5 ) || !"q5 was not a number" );
00127 assert( is_number( q6 ) || !"q6 was not a number" );
00128
00129 real_type min_q = min( q1, min( q2, min( q3, min( q4, min( q5, q6 ) ) ) ) );
00130
00131 assert( is_number( min_q ) || !"minimum sine was not a number" );
00132
00133 return min_q;
00134 }
00135
00136 }
00137
00138 }
00139
00140
00141 #endif