00001 #ifndef OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CURVATURE_H
00002 #define OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_GRID_CURVATURE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <cmath>
00013 #include <OpenTissue/core/math/math_eigen_system_decomposition.h>
00014 #include <OpenTissue/core/containers/grid/util/grid_gradient.h>
00015 #include <OpenTissue/core/containers/grid/util/grid_hessian.h>
00016
00017 namespace OpenTissue
00018 {
00019 namespace grid
00020 {
00021
00033 template<typename grid_type, typename real_type>
00034 inline void curvature(
00035 grid_type const & grid
00036 , size_t i
00037 , size_t j
00038 , size_t k
00039 , real_type & K
00040 , real_type & G
00041 , real_type & k1
00042 , real_type & k2
00043 )
00044 {
00045 using std::min;
00046 using std::max;
00047 using std::pow;
00048 using std::sqrt;
00049
00050 typedef OpenTissue::math::Vector3<real_type> vector3_type;
00051 typedef OpenTissue::math::Matrix3x3<real_type> matrix3x3_type;
00052
00053 real_type limit_K = boost::numeric_cast<real_type>( 1. / min( grid.dx(), min( grid.dy(), grid.dz() ) ) );
00054
00055 vector3_type g;
00056 matrix3x3_type H;
00057 gradient( grid, i, j, k, g );
00058 hessian( grid, i, j, k, H );
00059 real_type h = g * g;
00060
00061
00062
00063
00064 if ( h == 0 )
00065 h = 1;
00066
00067 const static real_type exponent = boost::numeric_cast<real_type>( 3. / 2. );
00068 K = ( 1.0 / pow( h, exponent ) ) * (
00069 g( 0 ) * g( 0 ) * ( H( 1, 1 ) + H( 2, 2 ) ) - 2. * g( 1 ) * g( 2 ) * H( 1, 2 ) +
00070 g( 1 ) * g( 1 ) * ( H( 0, 0 ) + H( 2, 2 ) ) - 2. * g( 0 ) * g( 2 ) * H( 0, 2 ) +
00071 g( 2 ) * g( 2 ) * ( H( 0, 0 ) + H( 1, 1 ) ) - 2. * g( 0 ) * g( 1 ) * H( 0, 1 )
00072 );
00073
00074
00075
00076 K = min( K, limit_K );
00077 K = max( K, -limit_K );
00078
00079
00080 G = ( 1.0 / ( h * h ) ) * (
00081 g( 0 ) * g( 0 ) * ( H( 1, 1 ) * H( 2, 2 ) - H( 1, 2 ) * H( 1, 2 ) ) + 2. * g( 1 ) * g( 2 ) * ( H( 0, 2 ) * H( 0, 1 ) - H( 0, 0 ) * H( 1, 2 ) ) +
00082 g( 1 ) * g( 1 ) * ( H( 0, 0 ) * H( 2, 2 ) - H( 0, 2 ) * H( 0, 2 ) ) + 2. * g( 0 ) * g( 2 ) * ( H( 1, 2 ) * H( 0, 1 ) - H( 1, 1 ) * H( 0, 2 ) ) +
00083 g( 2 ) * g( 2 ) * ( H( 0, 0 ) * H( 1, 1 ) - H( 0, 1 ) * H( 0, 1 ) ) + 2. * g( 0 ) * g( 1 ) * ( H( 1, 2 ) * H( 0, 2 ) - H( 2, 2 ) * H( 0, 1 ) ) );
00084
00085 G = min( G, limit_K );
00086 G = max( G, -limit_K );
00087
00088 ral_type d = sqrt( K * K - G );
00089 k1 = K + d;
00090 k2 = K - d;
00091 }
00092
00113 template<typename grid_type, typename real_type>
00114 inline void eigen_curvature(
00115 grid_type const & grid
00116 , size_t i
00117 , size_t j
00118 , size_t k
00119 , real_type & k1
00120 , real_type & k2
00121 )
00122 {
00123 using std::min;
00124 using std::max;
00125 using std::pow;
00126 using std::sqrt;
00127
00128 typedef OpenTissue::math::Vector3<real_type> vector3_type;
00129 typedef OpenTissue::math::Matrix3x3<real_type> matrix3x3_type;
00130
00131
00132
00133 vector3_type g;
00134 matrix3x3_type H;
00135 gradient( grid, i, j, k, g );
00136 hessian( grid, i, j, k, H );
00137
00138 real_type recip_norm_g = 1. / sqrt( g * g );
00139
00140 vector3_type n = g * recip_norm_g;
00141
00142 matrix3x3_type I( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
00143 matrix3x3_type nnt = outer_prod( n, n );
00144 matrix3x3_type P = I - nnt;
00145
00146 matrix3x3_type S = -P * H * P * recip_norm_g;
00147
00148 matrix3x3_type V;
00149 vector3_type d;
00150 OpenTissue::math::eigen( S, V, d );
00151 size_t order[ 3 ];
00152 vector3_type abs_d = OpenTissue::fabs( d );
00153 get_increasing_order( abs_d, order );
00154 k1 = d( order[ 0 ] );
00155 k2 = d( order[ 1 ] );
00156
00157
00158 }
00159
00160
00161
00183 template<typename grid_type, typename real_type>
00184 inline void algebra_curvature(
00185 grid_type const & grid
00186 , size_t i
00187 , size_t j
00188 , size_t k
00189 , real_type & k1
00190 , real_type & k2
00191 )
00192 {
00193 using std::min;
00194 using std::max;
00195 using std::pow;
00196 using std::sqrt;
00197
00198 typedef OpenTissue::math::Vector3<real_type> vector3_type;
00199 typedef OpenTissue::math::Matrix3x3<real_type> matrix3x3_type;
00200
00201
00202 vector3_type g;
00203 matrix3x3_type H;
00204 gradient( grid, i, j, k, g );
00205 hessian( grid, i, j, k, H );
00206 real_type recip_norm_g = 1. / sqrt( g * g );
00207
00208 vector3_type n = g * recip_norm_g;
00209
00210 matrix3x3_type I( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
00211 matrix3x3_type nnt = outer_prod( n, n );
00212 matrix3x3_type P = I - nnt;
00213
00214 matrix3x3_type S = -P * H * P * recip_norm_g;
00215
00216 real_type M = trace(S);
00217 matrix3x3_type ST = trans(S);
00218 matrix3x3_type SST = S * ST;
00219 real_type K = trace(SST);
00220 k1 = 0.5 * ( M + sqrt( 2 * K * K - M * M ) );
00221 k2 = 0.5 * ( M - sqrt( 2 * K * K - M * M ) );
00222 }
00223
00224 }
00225 }
00226
00227
00228 #endif