Biomechanical Joint Model
 Author: Anderson Maciel

blob.cpp

Go to the documentation of this file.
00001 #include <math.h>
00002 #include "blob.h"
00003 
00004 #define max(a,b)  (((a) > (b)) ? (a) : (b))
00005 #define min(a,b)  (((a) < (b)) ? (a) : (b))
00006 
00007 
00008 //namespace MarchingCubes {
00009 
00010 #define SQR(x)       ((x) * (x))
00011 
00012 static bool ray_intersect_primitive(Ray &ray, const Quadric &quadric, REAL root[], REAL c){
00013 
00014         REAL k2,k1,k0;
00015         REAL s,t,t1,t2;
00016 
00017         // map ray into model local coordinate system
00018         VEC X0( quadric.T.fullMult(ray.O) );
00019         VEC R( quadric.T.mult(ray.D) );
00020 
00021         k2 = c * (SQR(R[0]) / quadric.a2 + 
00022                   SQR(R[1]) / quadric.b2 + 
00023                   SQR(R[2]) / quadric.c2);
00024         k1 = 2*c * (R[0]* X0[0] / quadric.a2 +
00025                     R[1]* X0[1] / quadric.b2 +
00026                     R[2]* X0[2] / quadric.c2);
00027         k0 = c * (SQR(X0[0]) / quadric.a2 +
00028                   SQR(X0[1]) / quadric.b2 +
00029                   SQR(X0[2]) / quadric.c2) - 1.;
00030                 
00031         s = SQR(k1) - 4.*k2*k0;
00032         root[0] = root[1] = -1.0;
00033         if (s < 0.) return(false);
00034         s = sqrt(s);
00035         t1 = 0.5*(-k1 + s)/k2;
00036         t2 = 0.5*(-k1 - s)/k2;
00037         t = max(t1,t2);
00038         root[0] = min(t1,t2);
00039         root[1] = t;
00040         if  (t <0.) return (false);
00041         ray.t = t;
00042         return(true);
00043 }
00044 
00045 bool Quadric::intersectedBy(Ray &ray, REAL root[]) const{ 
00046    return ray_intersect_primitive(ray, *this, root, 2.);
00047 }
00048 
00049 bool Blob::intersectedBy(Ray &ray, REAL root[]) const{ 
00050   return ray_intersect_primitive(ray, *this, root, 1.);
00051 }
00052 
00054 //                 ELLIPSOIDS                      //
00056 bool Ellipsoids::intersectedBy(Ray &ray) const{
00057    int n = quadlist.size();
00058    if ( n <=0 ) return false;
00059 
00060    REAL **interval = new REAL* [n]; // t1 and t2  intersection of ray with quadric 
00061    for (int i=0; i<n; i++) interval[i] = new REAL [2];
00062 
00063    // 1: find the blobs which have radius of influence to the ray 
00064    for ( int j=0; j<n; ++j)
00065       quadlist[j].intersectedBy(ray, interval[j]);
00066     
00067     // 2 : find the minimum t
00068     REAL t_min=infinity;
00069     for ( int k=0;k<n;k++) 
00070     {
00071        if (interval[k][0]>=0  && interval[k][0]<t_min)
00072           t_min = interval[k][0];
00073 
00074        if (interval[k][1]>=0 && interval[k][1]<t_min)
00075           t_min = interval[k][1];
00076     }
00077     
00078     ray.t = t_min;
00079     ray.P = ray.O + t_min*ray.D;
00080     delete [] interval;
00081     
00082     return (ray.segment==true)? (t_min >=0 && t_min <=1) : (t_min >=0 && t_min < infinity);
00083 }
00084 
00085 REAL Ellipsoids::getDistance(const VEC &U) const{   
00086 
00087    REAL k, t=-infinity;
00088    bool outside = true;
00089    static VEC X(3);
00090 
00091    for (vector<Quadric>::const_iterator quad=quadlist.begin(); quad!=quadlist.end(); ++quad)
00092    {
00093       // map point into quadric lcs
00094       X = quad->T.fullMult(U);
00095       k =  0.5 - (X[0]*X[0]/quad->a2 + X[1]*X[1]/quad->b2 + X[2]*X[2]/quad->c2);
00096 
00097       // right on the surface?
00098       if (fabs(k) < epsilon) return 0;
00099 
00100       if (outside && k<0)
00101       {
00102          if (k>t) t=k;
00103       }
00104 
00105       if (k>0) 
00106       {  
00107          if (outside == true)
00108          {          
00109             outside = false;
00110             t = k;
00111          }
00112          else if (k<t) t=k;
00113       }
00114    }
00115    return t;   
00116 }
00117 
00118 BBox Ellipsoids::getBoundingBox()
00119 {
00120    bbox.makeEmpty();
00121    VEC X(3), Y(3);
00122 
00123    for (vector<Quadric>::const_iterator quad_it = quadlist.begin(); 
00124         quad_it != quadlist.end(); ++quad_it)
00125    {
00126       BBox bb;
00127       X[0] = quad_it->a; X[1] = quad_it->b; X[2] = quad_it->c;
00128 
00129       // for each vertex of BBox
00130       for (int p=0; p<8; p++)
00131       {
00132          int sign[3]; 
00133          sign[0] = p&4; 
00134          sign[1] = p&2;
00135          sign[2] = p&1;    
00136  
00137          for (int k=0; k<3; k++) 
00138             Y[k] = (sign[k]==0)? X[k] : -X[k];
00139 
00140          Y = quad_it->M.fullMult(Y);  // point mult
00141             
00142          // Y now contains world coordinates of BBox's vertex
00143          bb.extendBy(Y);
00144       }
00145       bbox.extendBy(bb);   
00146    }
00147 //    bbox.scale(1.05);
00148 
00149    return bbox; 
00150 }
00151 
00152 void Ellipsoids::findIntersection(const VEC &P1, const VEC &P2, REAL valp1, REAL valp2, VEC &P, VEC &N) const{
00153    Ray ray(P1, P2-P1);
00154    ray.segment = true;
00155 
00156    if (!intersectedBy(ray))
00157    {
00158       //cout << "Fatal error: no intersection in Ellipsoids::findIntersection\n";
00159            printf( "Fatal error: no intersection in Ellipsoids::findIntersection\n" );
00160       return;
00161    }
00162    P = ray.P;
00163 
00164    static VEC X(3);
00165    for (vector<Quadric>::const_iterator quad=quadlist.begin(); quad!=quadlist.end(); ++quad)
00166    {
00167       // map point into quadric lcs
00168       X = quad->T.fullMult(P);
00169       REAL k =  0.5 - (X[0]*X[0]/quad->a2 + X[1]*X[1]/quad->b2 + X[2]*X[2]/quad->c2);
00170       if (fabs(k) < epsilon)
00171       {
00172          N = P - quad->M.getTranslation();
00173          N.normalize();
00174          break;
00175       }
00176    }
00177    return;
00178 }
00179 
00181 //                 METABALLS                       //
00183 BBox Metaballs::getBoundingBox()
00184 {
00185    bbox.makeEmpty();
00186    VEC X(3), Y(3);
00187 
00188    for (vector<Blob>::const_iterator blob_it = bloblist.begin(); 
00189         blob_it != bloblist.end(); ++blob_it)
00190    {
00191       BBox bb;
00192 
00193       if (blob_it->w>0)
00194       {
00195          X[0] = blob_it->a; X[1] = blob_it->b; X[2] = blob_it->c;
00196          X *= blob_it->w;
00197 
00198          // for each vertex of BBox
00199          for (int p=0; p<8; p++)
00200          {
00201             int sign[3]; 
00202             sign[0] = p&4; 
00203             sign[1] = p&2;
00204             sign[2] = p&1;         
00205  
00206             for (int k=0; k<3; k++) 
00207                Y[k] = (sign[k]==0)? X[k] : -X[k];
00208 
00209             Y = blob_it->M.fullMult(Y);  // point mult
00210             
00211             // Y now contains world coordinates of BBox's vertex
00212             bb.extendBy(Y);
00213          }
00214          bbox.extendBy(bb);
00215       }
00216    }
00217    
00218 //    bbox.scale(1.05);
00219    return bbox;
00220 }
00221 
00222 
00223 
00224 // comparison routine for quicksort of stdlib
00225 int mycompare(const void *aP, const void *bP) 
00226 { 
00227   REAL a=*((float*)aP);
00228   REAL b=*((float*)bP);
00229 
00230   if (a<b)       return -1;
00231   else if (a==b) return  0;
00232   else           return  1;
00233 } 
00234 int (*mycompareP)(const void *, const void *) = mycompare;
00235 
00236 #define LESS(a,b)    ((a) <((b)+epsilon))
00237 #define GREAT(a,b)   ((a) >((b)-epsilon))
00238 
00239 //
00240 // ray tracing MUST be used for Shen's density function as it is zero
00241 // after a certain distance threshold.
00242 //
00243 // Substitute the ray equation into the blob quadric equations,thus t is broken
00244 // into intervals where the ellipsoids of various radii intersect the ray. 
00245 // We are interested only int the outmost intersection point. Suppose 
00246 // [tmin,tmax] is the interval of outmost quadric, we only test the quadrics
00247 // whose interval overlaps this outmost interval. The intervals of those blobs
00248 // are superimposed and broken into new intervals with [tmin,tmax] each of 
00249 // which has a sum of quadratic densities associated with it. We test 
00250 // sebsequently from right to left of new intervals until we find a solution.
00251 // ##Update 1(July 15, 94): k2,k1,k0, s change from float to double type.
00252 // first compute the only the outmost metaball and record its t value.
00253 // then compute additive t value. If the additive t-value < single t-value,
00254 // return the single t-value;
00255 // 
00256 bool 
00257 Metaballs_Shen::intersectedBy(Ray &ray) const
00258 {
00259     int n = bloblist.size();
00260     if (n<=0) return false;
00261     REAL    s, t, t1, t2, tmin, tmax;
00262 
00263     REAL *t_value = new REAL [2*n];
00264     REAL **interval = new REAL* [n]; // t1 and t2  intersction of ray with quardic 
00265     for (int i=0; i<n; i++) interval[i] = new REAL [2];
00266     
00267     REAL k2,k1,k0;
00268     int k;
00269     VEC R,X0; // equivalent ray base and direction vector in blob's lcs
00270 
00271     // 1: find the blobs which have radius of influence to the ray 
00272     for (int j=0; j<n; ++j){
00273        bloblist[j].intersectedBy(ray, interval[j]);
00274     }
00275     
00276     // 2 : find the maximum t
00277     k =0;
00278     for (int ii=0;ii< n;++ii) {
00279         t_value[k] = interval[ii][0];
00280         t_value[k+1] = interval[ii][1];
00281         k +=2;
00282     }
00283     qsort(t_value, k, sizeof(REAL), mycompareP);
00284 
00285     if (t_value[2*n-1] <0.) 
00286     { 
00287        delete [] t_value; 
00288        delete [] interval; 
00289        return(false); 
00290     } 
00291  
00292     bool found = false;
00293     ray.t = -1;
00294 
00295     for (k=1; k<2*n && t_value[k]<0; ++k);
00296     // 3: solve the equation f = iso_value in each interval 
00297     // we exit the loop as soon as an intersection point is found 
00298     // start with the smallest interval to ensure we retrieve the closest point 
00299     for (; k<2*n; ++k){
00300         k2 = k1 = k0 = 0.;
00301         tmin = t_value[k-1]; tmax = t_value[k];// loop through interval
00302 //      if (tmax < 0.) break;  
00303         if (tmin <0.) tmin =0; // intersection point must be along direction
00304         if (fabs(tmax-tmin) < epsilon) continue;
00305         if (ray.segment==true && tmax >1.) break;
00306 
00307         // search the blobs that has density contribution in the interval
00308         int kk=0; 
00309         for (vector<Blob>::const_iterator blob=bloblist.begin();blob!=bloblist.end();blob++,++kk){
00310             if ((LESS(interval[kk][0],tmin))
00311                 &&(GREAT(interval[kk][1],tmax)))
00312             {
00313                 // map ray into blob lcs
00314                 X0 = blob->T.fullMult(ray.O);
00315                 R = blob->T.mult(ray.D);
00316 
00317                 k2 += blob->w*(R[0]*R[0]/blob->a2 +
00318                               R[1]*R[1]/blob->b2 +R[2]*R[2]/blob->c2);
00319                 k1 += 2.0*blob->w*(X0[0]*R[0]/blob->a2+
00320                                   X0[1]*R[1]/blob->b2 +X0[2]*R[2]/blob->c2);
00321                 k0 +=  blob->w*(X0[0]*X0[0]/blob->a2 +
00322                                X0[1]*X0[1]/blob->b2+X0[2]*X0[2]/blob->c2)-blob->w;
00323             }
00324         } // end of for (i=...)
00325         k0 += iso_value;
00326         s = k1*k1 - 4.*k2*k0;
00327         if (s < 0.) continue;
00328         s = sqrt(s);
00329         t1 = 0.5*(-k1 + s)/k2;
00330         t2 = 0.5*(-k1 - s)/k2;
00331         t = max(t1,t2);
00332         if  ( GREAT(t,tmin) && LESS(t,tmax))
00333         {
00334            found = true;
00335            ray.t =t;
00336            break;
00337         }
00338         else {
00339             t = min(t1,t2);
00340             if  ( GREAT(t,tmin) && LESS(t,tmax))
00341             {
00342                found = true;
00343                ray.t =t;
00344                break;
00345             }
00346         }
00347     } // end of for (k= ...) 
00348 
00349     delete [] t_value; 
00350     delete [] interval;
00351 
00352     if (found) ray.P = ray.O + ray.t*ray.D;
00353     return found;
00354 }
00355 
00356 
00357 // return field value at location U 
00358 REAL
00359 Metaballs_Shen::density(const VEC &U) const
00360 {
00361   REAL k, t=0;
00362   static VEC X(3);
00363   
00364   for (vector<Blob>::const_iterator blob=bloblist.begin(); blob!=bloblist.end(); ++blob)
00365   {
00366      // map point into blob lcs
00367      X = blob->T.fullMult(U);
00368 
00369      k =  1.0 - (X[0]*X[0]/blob->a2 + X[1]*X[1]/blob->b2 + X[2]*X[2]/blob->c2);
00370      if ( k>0 ) t += blob->w * k;
00371   }
00372   return t;
00373 }
00374 
00375 /*
00376 // Normally we should use the following code to compute the gradient (which yields the normal)
00377 // But Shen's density function is only C0, so discontinuities exist in the gradient
00378 // As a result, normals will appear "wrong" at places where metaballs blend
00379 VEC
00380 Metaballs_Shen::gradient(const VEC &U) const
00381 {
00382   REAL k;
00383   static VEC X(3);
00384   VEC W(3);
00385 
00386   for (vector<Blob>::const_iterator blob=bloblist.begin(); blob!=bloblist.end(); blob++)
00387   {
00388       X = blob->T.fullMult(U);
00389       k =  1 - (X[0]*X[0]/blob->a2 + X[1]*X[1]/blob->b2 + X[2]*X[2]/blob->c2);
00390       if ( k>0 )
00391       {
00392           W[0] += 2*blob->w*X[0]/blob->a2;
00393           W[1] += 2*blob->w*X[1]/blob->b2;
00394           W[2] += 2*blob->w*X[2]/blob->c2;
00395       }
00396   }  
00397   return W;
00398 }
00399 */
00400 
00401 // We do not use Shen's density function to compute the gradient as it's dicontinuous
00402 // we use instead an exponential function (closely resembles Shen's density function)
00403 // return blob's gradient(U) = normal at point U
00404 VEC Metaballs_Shen::gradient(const VEC &U) const{
00405    REAL k;
00406    static VEC X(3), Y(3);
00407    VEC W(3);
00408    REAL coeff=2;
00409 
00410    for (vector<Blob>::const_iterator blob=bloblist.begin(); blob!=bloblist.end(); ++blob)
00411    {
00412       X = blob->T.fullMult(U);
00413 
00414       k = -2 * blob->w * coeff *
00415          exp(-coeff * (X[0]*X[0]/blob->a2 + X[1]*X[1]/blob->b2 + X[2]*X[2]/blob->c2));
00416 
00417       Y[0] = X[0]*k/blob->a2;
00418       Y[1] = X[1]*k/blob->b2;
00419       Y[2] = X[2]*k/blob->c2;      
00420       
00421       // map back vector into g.c.s.
00422       W += blob->M.mult(Y);
00423    }
00424    return W;
00425 }
00426 
00427 
00429 //  Metaballs with an exponential density function //
00431 REAL Metaballs_exp::density(const VEC &U) const{
00432    REAL t=0;
00433    static VEC X(3);
00434 
00435    for (vector<Blob>::const_iterator blob=bloblist.begin(); blob!=bloblist.end(); ++blob)
00436    {
00437       // map point into blob lcs
00438       X = blob->T.fullMult(U);
00439       t += blob->w *  
00440          exp(-coeff * (X[0]*X[0]/blob->a2 + X[1]*X[1]/blob->b2 + X[2]*X[2]/blob->c2));
00441    }
00442    return t;
00443 }
00444 
00445 
00446 // return blob's gradient(U) = normal at point U
00447 VEC Metaballs_exp::gradient(const VEC &U) const
00448 {
00449    REAL k;
00450    static VEC X(3), Y(3);
00451    VEC W(3);
00452 
00453    for (vector<Blob>::const_iterator blob=bloblist.begin(); blob!=bloblist.end(); ++blob)
00454    {
00455       X = blob->T.fullMult(U);
00456 
00457       k = -2 * blob->w * coeff *
00458          exp(-coeff * (X[0]*X[0]/blob->a2 + X[1]*X[1]/blob->b2 + X[2]*X[2]/blob->c2));
00459 
00460       Y[0] = X[0]*k/blob->a2;
00461       Y[1] = X[1]*k/blob->b2;
00462       Y[2] = X[2]*k/blob->c2;      
00463       
00464       // map back vector into g.c.s.
00465       W += blob->M.mult(Y);
00466    }
00467    return W;
00468 }
00469 
00470 
00471 REAL  MetaballsSphere::density(const VEC &U) const{
00472   REAL r, den, t=0;
00473 #if 0
00474   fprintf(stderr,"MetaballsSphere::density\n");
00475 #endif
00476   for(vector<Sphere>::const_iterator sph=spherelist.begin(); sph!=spherelist.end(); sph++){
00477     r = (U - sph->C).norm();
00478     den=0;
00479     if(r<sph->R)
00480       if(r<sph->ro)
00481         den=sph->k*(sph->ro-r)+1;
00482       else
00483         den=0.25*((sph->k*(r-sph->ro))-2.0)*((sph->k*(r-sph->ro))-2.0);
00484 
00485     t+=den;
00486   }
00487   return t;
00488 }
00489 
00490 VEC   MetaballsSphere::gradient(const VEC& U) const{
00491  REAL r, aux;
00492  VEC grad(3), g(3);
00493 
00494  for(vector<Sphere>::const_iterator sph=spherelist.begin(); sph!=spherelist.end(); sph++){
00495    r = (U - sph->C).norm();
00496    aux = 0;
00497    if (r<sph->R){
00498      if (r<sph->ro){
00499        aux=-sph->k;
00500      }
00501      else{
00502        aux=sph->k*((sph->k*(r-sph->ro))-2.0)/2.0;
00503      }
00504    }
00505 
00506    grad=U-sph->C;
00507    grad*=aux/r;
00508    g+=grad;
00509  }
00510  return g;
00511 }
00512 
00513 
00514 BBox  MetaballsSphere::getBoundingBox(){
00515   VEC UR(3), LL(3);
00516   bbox.makeEmpty();
00517   for(vector<Sphere>::iterator sph=spherelist.begin(); sph!=spherelist.end(); ++sph){
00518      UR[0] = sph->C[0] + sph->R;
00519      UR[1] = sph->C[1] + sph->R;
00520      UR[2] = sph->C[2] + sph->R;
00521 
00522      LL[0] = sph->C[0] - sph->R;
00523      LL[1] = sph->C[1] - sph->R;
00524      LL[2] = sph->C[2] - sph->R; 
00525      
00526      bbox.extendBy(BBox(LL,UR));
00527   }
00528 
00529   return bbox;
00530 
00531 }
00532 
00533 
00534 REAL  MetaballsSphere_exp::density(const VEC &U) const{
00535   REAL r, F;
00536 #if 0
00537   fprintf(stderr,"MetaballsSphere_exp::density\n");
00538 #endif
00539   F=0;
00540   for(vector<Sphere>::const_iterator sph=spherelist.begin(); sph!=spherelist.end(); ++sph){
00541     r = (U - sph->C).norm();
00542     F += exp(-coeff*r);
00543   }
00544   return F;
00545 }
00546 
00547 VEC   MetaballsSphere_exp::gradient(const VEC& U) const{
00548  VEC df_da(3), dF_da(3), r;
00549 
00550  dF_da[0]=dF_da[1]=dF_da[2]=0.0;
00551 
00552  for(vector<Sphere>::const_iterator sph=spherelist.begin(); sph!=spherelist.end(); ++sph){
00553    r = (U - sph->C);
00554    df_da= -2*coeff*exp(-coeff*r.norm())*r;
00555    dF_da+=df_da;
00556  }
00557  return dF_da;
00558 }
00559 
00560 double MetaballsTriangle::EuclidDistFromTriangle(const VEC &P1, const VEC &P2, const VEC &P3,
00561                                                  const VEC &Pt, const double *Plane, VEC &N) const{
00562 
00563   VEC na(3), nb(3), nc(3); // normals of the planes pependicular to the Facet and passing throught the Facet edges
00564   VEC a(3), b(3), c(3);
00565   double Pt_aplane, Pt_bplane, Pt_cplane, dist=0.0, D;
00566   VEC n(3);
00567   n[0]=Plane[0], n[1]=Plane[1], n[2]=Plane[2], D=Plane[3];
00568 
00569   a = P3-P2;
00570   b = P1-P2;
00571   c = P3-P1;
00572   
00573   na =  cross_prod(n,a);
00574   nb = -cross_prod(n,b);
00575   nc = -cross_prod(n,c);
00576 
00577   // chech where is the point
00578   Pt_aplane = dot_prod(Pt-P2,na);
00579   Pt_bplane = dot_prod(Pt-P2,nb);
00580   Pt_cplane = dot_prod(Pt-P1,nc);
00581 
00582 #if 0
00583   cout<<"a="<<a<<endl;
00584   cout<<"b="<<b<<endl;
00585   cout<<"c="<<c<<endl;
00586   
00587   cout<<"na="<<na<<endl;
00588   cout<<"nb="<<nb<<endl;
00589   cout<<"nc="<<nc<<endl;  
00590 
00591   cout<<"Pt in respect to plane na ="<<Pt_aplane<<endl;
00592   cout<<"Pt in respect to plane na ="<<Pt_bplane<<endl;
00593   cout<<"Pt in respect to plane nc ="<<Pt_cplane<<endl;
00594 #endif
00595 
00596   if(Pt_aplane>0.0 && Pt_bplane>0.0 && Pt_cplane>0.0){ // point projects on the Facet
00597     dist = (Pt[0]*n[0] + Pt[1]*n[1] + Pt[2]*n[2] - D)/n.norm();
00598         std::cout<<"Zone 1"<<endl;
00599   }
00600   else if(Pt_aplane<0.0 && Pt_bplane>0.0 && Pt_cplane>0.0){ // point project on the side of P2P3 edge
00601     dist = cross_prod((Pt-P2),a).norm()/a.norm();
00602     VEC Pt_prj = Pt + (D-dot_prod(Pt,n)/n.norm2())*n;
00603     double q = (Pt_prj-P2).norm(), cos_alfa = dot_prod(Pt_prj-P2,a)/((Pt_prj-P2).norm()*a.norm());
00604     double p = q*cos_alfa;
00605     VEC P2P = p*a/a.norm(), N = (Pt-P2) - P2P;
00606     std::cout<<"Zone 2"<<endl;
00607   }
00608   else if(Pt_aplane>0.0 && Pt_bplane>0.0 && Pt_cplane<0.0){ // point project on the side of P1P3 edge
00609     dist = cross_prod((Pt-P1),c).norm()/c.norm();
00610     VEC Pt_prj = Pt + (D-dot_prod(Pt,n)/n.norm2())*n;
00611     double q = (Pt_prj-P1).norm(), cos_alfa = dot_prod(Pt_prj-P1,c)/((Pt_prj-P1).norm()*c.norm());
00612     double p = q*cos_alfa;
00613     VEC P1P = p*c/c.norm(), N = (Pt-P1) - P1P;
00614     std::cout<<"Zone 3"<<endl;
00615   }
00616   else if(Pt_aplane>0.0 && Pt_bplane<0.0 && Pt_cplane>0.0){ // point project on the side of P1P2 edge
00617     dist = cross_prod((Pt-P2),b).norm()/b.norm();
00618     VEC Pt_prj = Pt + (D-dot_prod(Pt,n)/n.norm2())*n;
00619     double q = (Pt_prj-P2).norm(), cos_alfa = dot_prod(Pt_prj-P2,b)/((Pt_prj-P2).norm()*b.norm());
00620     double p = q*cos_alfa;
00621     VEC P2P = p*b/b.norm(), N = (Pt-P2) - P2P;
00622     std::cout<<"Zone 4"<<endl;
00623   }
00624   else if(Pt_aplane<0.0 && Pt_bplane<0.0 && Pt_cplane>0.0){ // point projects on the side of P2 point
00625     dist = (Pt-P2).norm();
00626     std::cout<<"Zone 5"<<endl;
00627   }
00628   else if(Pt_aplane<0.0 && Pt_bplane>0.0 && Pt_cplane<0.0){ // point projects on the side of P3 point
00629     dist = (Pt-P3).norm();
00630     std::cout<<"Zone 6"<<endl;
00631   }
00632   else if(Pt_aplane>0.0 && Pt_bplane<0.0 && Pt_cplane<0.0){ // point projects on the side of P1 point
00633     dist = (Pt-P1).norm();
00634     std::cout<<"Zone 7"<<endl;
00635   } 
00636   return dist;
00637 }
00638 
00639 REAL  MetaballsTriangle::density(const VEC &U) const{
00640   REAL r, den, t=0;
00641   VEC N(3);
00642 #if 0
00643   fprintf(stderr,"MetaballsTriangle::density\n");
00644 #endif
00645    for(vector<TrianglePrimitive>::const_iterator trg=trianglelist.begin(); trg!=trianglelist.end(); ++trg){
00646     r = EuclidDistFromTriangle(trg->P1, trg->P2, trg->P3, U, trg->n, N);
00647     den=0;
00648     if(r<trg->R)
00649       if(r<trg->ro)
00650         den=trg->k*(trg->ro-r)+1;
00651       else
00652         den=0.25*((trg->k*(r-trg->ro))-2.0)*((trg->k*(r-trg->ro))-2.0);
00653     t+=den;
00654   }
00655   return t;
00656 }
00657 
00658 VEC   MetaballsTriangle::gradient(const VEC& U) const{
00659  REAL r, aux;
00660  VEC grad(3), g(3);
00661 
00662  for(vector<TrianglePrimitive>::const_iterator trg=trianglelist.begin(); trg!=trianglelist.end(); ++trg){
00663    r = EuclidDistFromTriangle(trg->P1, trg->P2, trg->P3, U, trg->n, grad);
00664    aux = 0;
00665    if (r<trg->R){
00666      if (r<trg->ro){
00667        aux=-trg->k;
00668      }
00669      else{
00670        aux=trg->k*((trg->k*(r-trg->ro))-2.0)/2.0;
00671      }
00672    }
00673    grad*=aux/r;
00674    g+=grad;
00675  }
00676  return g;
00677 }
00678 
00679 BBox  MetaballsTriangle::getBoundingBox(){
00680   VEC UR(3), LL(3);
00681   int i=0;
00682   bbox.makeEmpty();
00683   for(vector<TrianglePrimitive>::iterator trg=trianglelist.begin(); trg!=trianglelist.end(); ++trg, i++){
00684 #if 0
00685     cout<<"Facet "<<i<<"  :["<<trg->P1[0]<<","<<trg->P1[1]<<","<<trg->P1[2]<<"]"<<endl;
00686     cout<<"         :["<<trg->P2[0]<<","<<trg->P2[1]<<","<<trg->P2[2]<<"]"<<endl;
00687     cout<<"         :["<<trg->P3[0]<<","<<trg->P3[1]<<","<<trg->P3[2]<<"]"<<endl;
00688 #endif
00689     UR[0] = max(max(trg->P1[0],trg->P2[0]),trg->P3[0]) + trg->R;
00690     UR[1] = max(max(trg->P1[1],trg->P2[1]),trg->P3[1]) + trg->R;
00691     UR[2] = max(max(trg->P1[2],trg->P2[2]),trg->P3[2]) + trg->R;
00692 
00693     LL[0] = min(min(trg->P1[0],trg->P2[0]),trg->P3[0]) - trg->R;
00694     LL[1] = min(min(trg->P1[1],trg->P2[1]),trg->P3[1]) - trg->R;
00695     LL[2] = min(min(trg->P1[1],trg->P2[1]),trg->P3[1]) - trg->R;
00696      
00697     bbox.extendBy(BBox(LL,UR));
00698   }
00699 #if 0
00700   cout<<"Bbox is:"<<endl;
00701   cout<<"LL :"<<LL<<endl;
00702   cout<<"UR :"<<UR<<endl;
00703 #endif
00704   return bbox;
00705 }
00706 
00707 
00708 //} // end of the namespace 
00709 
00710 
00711 
00712 
00713 
00714 
00715 
00716 
00717 
00718 
00719 
00720 
00721 
00722 
00723 

Generated on Thu Dec 1 10:13:32 2005 for COME - Biomechanical Joint Model by  doxygen 1.4.5