Go to the documentation of this file.00001 #ifndef OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CIRCUMSCRIBED_SPHERE_H
00002 #define OPENTISSUE_CORE_GEOMETRY_GEOMETRY_CIRCUMSCRIBED_SPHERE_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_constants.h>
00013 #include <OpenTissue/core/math/math_precision.h>
00014
00015 #include <cmath>
00016 #include <cassert>
00017
00018 namespace OpenTissue
00019 {
00020 namespace geometry
00021 {
00022
00029 template<typename vector3_type, typename sphere_type>
00030 void compute_circumscribed_sphere(vector3_type const & p, sphere_type & sphere)
00031 {
00032 sphere = sphere_type(p, 0.0);
00033 }
00034
00042 template<typename vector3_type, typename sphere_type>
00043 void compute_circumscribed_sphere(vector3_type const & p0,vector3_type const & p1, sphere_type & sphere)
00044 {
00045 using std::sqrt;
00046 vector3_type d = p1 - p0;
00047 sphere = sphere_type((p0+p1)*.5, sqrt( d*d )*.5 );
00048 }
00049
00058 template<typename vector3_type, typename sphere_type>
00059 void compute_circumscribed_sphere(vector3_type const & p0, vector3_type const & p1, vector3_type const & p2, sphere_type & sphere)
00060 {
00061 using std::fabs;
00062 using std::sqrt;
00063
00064 typedef typename vector3_type::value_type real_type;
00065
00066 static real_type const epsilon = math::working_precision<real_type>();
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091 vector3_type kA = p0 - p2;
00092 vector3_type kB = p1 - p2;
00093 real_type AdA = kA * kA;
00094 real_type AdB = kA * kB;
00095 real_type BdB = kB * kB;
00096 real_type det = AdA*BdB-AdB*AdB;
00097
00098 if ( fabs(det) > epsilon )
00099 {
00100 real_type halfInvDet = 0.5/det;
00101 real_type u0 = halfInvDet*BdB*(AdA-AdB);
00102 real_type u1 = halfInvDet*AdA*(BdB-AdB);
00103 real_type u2 = 1.0-u0-u1;
00104 vector3_type tmp = u0*kA + u1*kB;
00105 sphere = sphere_type( u0*p0 + u1*p1 + u2*p2, sqrt(tmp*tmp) );
00106 }
00107 else
00108 {
00109
00110
00111 real_type l0 = length(p1 - p0);
00112 real_type l1 = length(p2 - p0);
00113 real_type l2 = length(p2 - p1);
00114 if(l0 >= l1 && l0>=l2)
00115 compute_circumscribed_sphere(p0,p1,sphere);
00116 else if(l1 >= l2 && l1>=l0)
00117 compute_circumscribed_sphere(p0,p2,sphere);
00118 else if(l2 >= l1 && l2>=l0)
00119 compute_circumscribed_sphere(p1,p2,sphere);
00120
00121
00122 }
00123 }
00124
00134 template<typename vector3_type, typename sphere_type>
00135 void compute_circumscribed_sphere(vector3_type const & p0, vector3_type const & p1, vector3_type const & p2, vector3_type const & p3, sphere_type & sphere)
00136 {
00137 using std::fabs;
00138 using std::sqrt;
00139 typedef typename vector3_type::value_type real_type;
00140 static real_type epsilon = math::working_precision<real_type>();
00141 vector3_type kE10 = p0 - p3;
00142 vector3_type kE20 = p1 - p3;
00143 vector3_type kE30 = p2 - p3;
00144 real_type A[3][3];
00145 A[0][0] = kE10 * kE10;
00146 A[0][1] = kE10 * kE20;
00147 A[0][2] = kE10 * kE30;
00148 A[1][0] = A[0][1];
00149 A[1][1] = kE20 * kE20;
00150 A[1][2] = kE20 * kE30;
00151 A[2][0] = A[0][2];
00152 A[2][1] = A[1][2];
00153 A[2][2] = kE30 * kE30;
00154 real_type B[3];
00155 B[0] = 0.5*A[0][0];
00156 B[1] = 0.5*A[1][1];
00157 B[2] = 0.5*A[2][2];
00158 real_type invA[3][3];
00159 invA[0][0] = A[1][1]*A[2][2] - A[1][2]*A[2][1];
00160 invA[0][1] = A[0][2]*A[2][1] - A[0][1]*A[2][2];
00161 invA[0][2] = A[0][1]*A[1][2] - A[0][2]*A[1][1];
00162 invA[1][0] = A[1][2]*A[2][0] - A[1][0]*A[2][2];
00163 invA[1][1] = A[0][0]*A[2][2] - A[0][2]*A[2][0];
00164 invA[1][2] = A[0][2]*A[1][0] - A[0][0]*A[1][2];
00165 invA[2][0] = A[1][0]*A[2][1] - A[1][1]*A[2][0];
00166 invA[2][1] = A[0][1]*A[2][0] - A[0][0]*A[2][1];
00167 invA[2][2] = A[0][0]*A[1][1] - A[0][1]*A[1][0];
00168
00169 real_type det3 = A[0][0]*invA[0][0] + A[0][1]*invA[1][0] + A[0][2]*invA[2][0];
00170
00171 if ( fabs(det3) > epsilon )
00172 {
00173 real_type inv_det = 1.0/det3;
00174
00175 int row, col;
00176 for (row = 0; row < 3; ++row)
00177 {
00178 for (col = 0; col < 3; ++col)
00179 invA[row][col] *= inv_det;
00180 }
00181
00182 real_type U[4];
00183 for (row = 0; row < 3; ++row)
00184 {
00185 U[row] = 0.0f;
00186 for (col = 0; col < 3; ++col)
00187 U[row] += invA[row][col]*B[col];
00188 }
00189
00190 U[3] = 1.0 - U[0] - U[1] - U[2];
00191 vector3_type tmp = U[0]*kE10 + U[1]*kE20 + U[2]*kE30;
00192 sphere = sphere_type( U[0]*p0 + U[1]*p1 + U[2]*p2 + U[3]*p3, sqrt(tmp*tmp) );
00193 }
00194 else
00195 {
00196
00197 real_type PA[2][2];
00198 real_type PB[2];
00199 PA[0][0] = A[0][0]*A[0][0] + A[1][0]*A[1][0] + A[2][0]*A[2][0];
00200 PA[0][1] = A[0][0]*A[0][1] + A[1][0]*A[1][1] + A[2][0]*A[2][1];
00201 PB[0] = A[0][0]*B[0] + A[1][0]*B[1] + A[2][0]*B[2];
00202 PA[1][0] = A[0][1]*A[0][0] + A[1][1]*A[1][0] + A[2][1]*A[2][0];
00203 PA[1][1] = A[0][1]*A[0][1] + A[1][1]*A[1][1] + A[2][1]*A[2][1];
00204 PB[1] = A[0][1]*B[0] + A[1][1]*B[1] + A[2][1]*B[2];
00205 real_type det = PA[0][0]*PA[1][1] - PA[1][0]*PA[0][1];
00206
00207 if(fabs(det) > epsilon)
00208 {
00209 real_type U[4];
00210 real_type inv_det = 1.0/det;
00211 U[0] = inv_det*( PB[0]*PA[1][1] - PB[1]*PA[0][1] );
00212 U[1] = inv_det*( PA[0][0]*PB[1] - PA[1][0]*PB[0] );
00213 U[2] = 0;
00214 U[3] = 1.0 - U[0] - U[1] - U[2];
00215 vector3_type tmp = U[0]*kE10 + U[1]*kE20 + U[2]*kE30;
00216 sphere = sphere_type( U[0]*p0 + U[1]*p1 + U[2]*p2 + U[3]*p3, sqrt(tmp*tmp) );
00217 }
00218 else
00219 {
00220
00221
00222 vector3_type m[4];
00223 m[0] = p0; m[1] = p1; m[2] = p2; m[3] = p3;
00224 real_type sqr_dist = 0;
00225 int s=0,t=0;
00226 for(int i=0;i<3;++i)
00227 for(int j=i+1;j<3;++j)
00228 {
00229 vector3_type d = m[i]-m[j];
00230 real_type tmp = d*d;
00231 if(tmp>sqr_dist)
00232 {
00233 sqr_dist = tmp;
00234 s = i;
00235 t = j;
00236 }
00237 }
00238 compute_circumscribed_sphere(m[s],m[t],sphere);
00239
00240 }
00241 }
00242
00243 }
00244
00245 }
00246 }
00247
00248
00249 #endif