Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CYLINDER_GROWTH_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CYLINDER_GROWTH_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_constants.h>
00014
00015 #include <OpenTissue/core/geometry/geometry_quadric.h>
00016 #include <cmath>
00017
00018 namespace OpenTissue
00019 {
00020 namespace geometry
00021 {
00022
00041 template<typename real_type, typename vector3_type, typename vector3_iterator>
00042 Quadric<real_type> cylindrical_growth(
00043 vector3_type const & center
00044 , real_type const & radius
00045 , vector3_type const & p
00046 , vector3_type const & q
00047 , vector3_type const & r
00048 , real_type const & alpha
00049 , vector3_iterator begin
00050 , vector3_iterator end
00051 , real_type & beta
00052 , vector3_type & s
00053 )
00054 {
00055 using std::fabs;
00056 using std::sqrt;
00057 using std::max;
00058
00059 typedef Quadric<real_type> quadric_type;
00060 assert(p!=q || !"cylindrical_growth(): non-unique point encountered");
00061 assert(p!=r || !"cylindrical_growth(): non-unique point encountered");
00062 assert(q!=r || !"cylindrical_growth(): non-unique point encountered");
00063
00064
00065 vector3_type np = normalize(p - center);
00066 vector3_type nq = normalize(q - center);
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 vector3_type u = p;
00080 vector3_type v = normalize(q-p);
00081 vector3_type w = normalize( cross( cross(v,r-p) , v ));
00082
00083 assert(fabs(v*w)<10e-5 || !"cylindrical_growth(): v and w were non-orthogonal");
00084
00085 quadric_type Q1 = make_sphere_quadric(radius,center);
00086 quadric_type Q2 = make_plane_product_quadric(p, np, q, nq);
00087 quadric_type Qprime = Q1 + Q2*alpha;
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 real_type A00 = v*(Qprime.m_A*v);
00100 real_type A01 = v*(Qprime.m_A*w);
00101 real_type A10 = w*(Qprime.m_A*v);
00102 real_type A11 = w*(Qprime.m_A*w);
00103 real_type B0 = (Qprime.m_A*u + Qprime.m_B)*v;
00104 real_type B1 = (Qprime.m_A*u + Qprime.m_B)*w;
00105 real_type C = u*(Qprime.m_A*u) + 2.0*Qprime.m_B*u + Qprime.m_C;
00106
00107 assert(fabs(A01-A10)<10e-7 || !"cylindrical_growth(): A matrix was non-symmetrical");
00108
00109
00110
00111 real_type a_coef = 1;
00112 real_type b_coef = - (A00 + A11);
00113 real_type c_coef = A00*A11 - A10*A01;
00114 real_type d = max(0.,b_coef*b_coef - 4*a_coef*c_coef);
00115 d = sqrt(d);
00116 assert(d>=0 || !"cylinder_growth(): d was negative");
00117
00118 real_type eig0;
00119 if(b_coef>0)
00120 eig0 = (-b_coef - d)/(2.0*a_coef);
00121 else
00122 eig0 = (-b_coef + d)/(2.0*a_coef);
00123 real_type eig1 = c_coef / (a_coef*eig0);
00124
00125 assert(is_number(eig0) || !"cylinder_growth(): eigenvalue was nan");
00126 assert(is_number(eig1) || !"cylinder_growth(): eigenvalue was nan");
00127 assert(eig0!=0 || !"cylinder_growth(): eigenvalue was zero");
00128 assert(eig1!=0 || !"cylinder_growth(): eigenvalue was zero");
00129
00130
00131 real_type vec0_0,vec0_1,vec1_0,vec1_1,_A00,_A11;
00132
00133 _A00 = (A00-eig0);
00134 _A11 = (A11-eig0);
00135
00136 if(fabs(_A00)>0 && fabs(_A11))
00137 {
00138
00139 assert( _A00 || _A11 || !"cylinder_growth(): A00 and A11 were both zero");
00140 if(fabs(_A00) > fabs(_A11))
00141 {
00142 vec0_0 = - A01 / _A00;
00143 vec0_1 = 1;
00144 }
00145 else
00146 {
00147 vec0_0 = 1;
00148 vec0_1 = - A10 / _A11;
00149 }
00150 assert(is_number(vec0_0) || !"cylinder_growth(): eigenvector coordinate was nan");
00151 assert(is_number(vec0_1) || !"cylinder_growth(): eigenvector coordinate was nan");
00152 real_type lgh_vec0 = sqrt(vec0_0*vec0_0 + vec0_1*vec0_1);
00153 assert(lgh_vec0>0);
00154 vec0_0 /= lgh_vec0;
00155 vec0_1 /= lgh_vec0;
00156 assert(is_number(vec0_0) || !"cylinder_growth(): eigenvector coordinate was nan");
00157 assert(is_number(vec0_1) || !"cylinder_growth(): eigenvector coordinate was nan");
00158
00159 }
00160 else
00161 {
00162 vec0_0 = 1;
00163 vec0_1 = 0;
00164 }
00165
00166
00167
00168 vec1_0 = - vec0_1;
00169 vec1_1 = vec0_0;
00170
00171
00172
00173
00174
00175 real_type detA = A00*A11 - A10*A01;
00176 real_type detA0 = -B0*A11 + B1*A01;
00177 real_type detA1 = -A00*B1 + A10*B0;
00178 real_type c0 = detA0/detA;
00179 real_type c1 = detA1/detA;
00180 assert(is_number(c0) || !"cylinder_growth(): minpoint coordinate was nan" );
00181 assert(is_number(c1) || !"cylinder_growth(): minpoint coordinate was nan" );
00182
00183 real_type dn = c0*(A00*c0+A01*c1) + c1*(A10*c0+A11*c1) + 2.0* c0*B0+c1*B1 + C;
00184 real_type radius0 = sqrt(-dn/eig0);
00185 real_type radius1 = sqrt(-dn/eig1);
00186
00187 assert(is_number(radius0) || !"cylinder_growth(): radius 0 was nan" );
00188 assert(is_number(radius1) || !"cylinder_growth(): radius 1 was nan" );
00189 assert(radius0>0 || !"cylinder_growth(): radius 0 was negative" );
00190 assert(radius1>0 || !"cylinder_growth(): radius 1 was negative" );
00191
00192
00193
00194 vector3_type ellipse_center = u + v*c0 + w*c1;
00195 vector3_type axis0 = normalize(v*vec0_0 + w*vec0_1);
00196 vector3_type axis1 = normalize(v*vec1_0 + w*vec1_1);
00197
00198 quadric_type Q3 = make_cylinder_quadric(ellipse_center,axis0,radius0,axis1,radius1);
00199 beta = math::detail::highest<real_type>();
00200 for(vector3_iterator x = begin;x!=end;++x)
00201 {
00202 vector3_type dxp = (*x - p);
00203 if((dxp*np < 0))
00204 {
00205 real_type q3 = Q3( (*x) );
00206 if (q3 < 0)
00207 {
00208 real_type q12 = - Qprime( (*x) );
00209 assert(q12 <= 0 || !"cylinder_growth(): Q1 + alpha Q2 was non-empty");
00210 real_type tst = - q12 / q3;
00211 if( 0 <= tst && tst < beta )
00212 {
00213 beta = tst;
00214 s = (*x);
00215 }
00216 }
00217 }
00218 }
00219 if( beta == math::detail::highest<real_type>() )
00220 beta = 0;
00221
00222 return (Q1 + (Q2*alpha) + (Q3*beta));
00223 }
00224
00225 }
00226 }
00227
00228
00229 #endif