cgma
TDDelaunay.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // File:        TDDelaunay.cpp
00003 // Description: Support for FacetorTool.  Maintains circumcircle
00004 //              info at the triangles.  Do it up template style.
00005 // Author:      chynes
00006 // Date:        6/3/2002
00007 //-------------------------------------------------------------------------
00008 #ifdef INLINE_TEMPLATES
00009 #define MY_INLINE inline
00010 #else
00011 #define MY_INLINE
00012 #endif
00013 
00014 #include "TDDelaunay.hpp"
00015 #include "CubitMessage.hpp"
00016 #ifndef SQR
00017 #define SQR(x) ((x) * (x))
00018 #endif
00019 
00020 template< class TRIA, class NODE > MY_INLINE
00021 TDDelaunay< TRIA, NODE >::TDDelaunay()
00022 {
00023   mRadius = -1.0;
00024   visitFlag = INT_MIN;
00025   sortIndex = -1;
00026 }
00027 
00028 template< class TRIA, class NODE > MY_INLINE
00029 TDDelaunay< TRIA, NODE >::~TDDelaunay()
00030 {
00031 }
00032 
00033 //-------------------------------------------------------------------------
00034 // Function:    reset
00035 // Description: reset the circumradius stuff
00036 // Note:        
00037 // Author:      sjowen
00038 // Date:        9/19/2003
00039 //-------------------------------------------------------------------------
00040 template< class TRIA, class NODE > MY_INLINE
00041 void TDDelaunay< TRIA, NODE >::reset( )
00042 {
00043   mRadius = -1.0;
00044   visitFlag = INT_MIN;
00045   sortIndex = -1;
00046 }
00047 
00048 //-------------------------------------------------------------------------
00049 // Function:    circumcenter
00050 // Description: return the circumcenter of a triangle in 3D.
00051 //              computes and stores with the tooldata if it has not
00052 //              yet been initialized
00053 // Note:        This function was copied from NodeTri.cpp
00054 // Author:      chynes
00055 // Date:        6/3/2002
00056 //-------------------------------------------------------------------------
00057 template< class TRIA, class NODE > MY_INLINE
00058 CubitVector& TDDelaunay< TRIA, NODE >::circumcenter( TRIA *tri_ptr )
00059 {
00060   if (mRadius < 0.0) {
00061 
00062     NODE *corner[3];
00063     tri_ptr->tri_nodes( corner[0], corner[1], corner[2] );
00064 
00065       // Use coordinates relative to point `a' of the triangle. 
00066     CubitVector vec_ba(corner[0]->coordinates(), 
00067                        corner[1]->coordinates());
00068     CubitVector vec_ca(corner[0]->coordinates(), 
00069                        corner[2]->coordinates());
00070 
00071       // Squares of lengths of the edges incident to `a'. 
00072     double ba_length = vec_ba.length_squared();
00073     double ca_length = vec_ca.length_squared();
00074   
00075       // Cross product of these edges. 
00076       // (Take your chances with floating-point roundoff.)
00077     CubitVector cross_bc = vec_ba * vec_ca;
00078 
00079       // Calculate the denominator of the formulae. 
00080     double denominator = 0.5 / (cross_bc % cross_bc);
00081     assert(denominator != 0.0);
00082 
00083       // Calculate offset (from `a') of circumcenter. 
00084     mCenter  = (ba_length * vec_ca - ca_length * vec_ba) * cross_bc;
00085     mCenter *= denominator;
00086 
00087       // radius is length from point `a' to center
00088     mRadius = mCenter.length();
00089 
00090       // Add point `a' to get global coordinate of center
00091     mCenter += corner[0]->coordinates();
00092   }
00093   return mCenter;
00094 }
00095 
00096 //-------------------------------------------------------------------------
00097 // Function:    circumcenter2d
00098 // Description: same as circumcenter, but assumes 2d triangle (x,y,0)
00099 // Author:      chynes
00100 // Date:        6/3/2002
00101 //-------------------------------------------------------------------------
00102 template< class TRIA, class NODE > MY_INLINE
00103 CubitVector& TDDelaunay< TRIA, NODE >::circumcenter2d( TRIA *tri_ptr )
00104 {
00105   if (mRadius < 0.0) {
00106 
00107     NODE *corner[3];
00108     tri_ptr->tri_nodes( corner[0], corner[1], corner[2] );
00109 
00110     double A11 = corner[1]->coordinates().x() - 
00111                  corner[0]->coordinates().x();
00112     double A12 = corner[1]->coordinates().y() - 
00113                  corner[0]->coordinates().y();
00114     double A21 = corner[2]->coordinates().x() - 
00115                  corner[0]->coordinates().x();
00116     double A22 = corner[2]->coordinates().y() - 
00117                  corner[0]->coordinates().y();
00118     double det = A11*A22 - A21*A12;
00119     if(det == 0.0)
00120     {
00121       PRINT_ERROR("Co-linear points can not be used to determine circle.\n");
00122       mCenter.x(0.0);//assert(0);
00123       mCenter.y(0.0);
00124       mCenter.z(0.0);
00125       return mCenter;
00126     }
00127     
00128     double B1 = (A11*A11) + (A12*A12);
00129     double B2 = (A21*A21) + (A22*A22);
00130     det += det;
00131     double xc = (B1*A22 - B2*A12)/det;
00132     double yc = (B2*A11 - B1*A21)/det;
00133     mRadius = xc * xc + yc * yc;
00134     mCenter.x( corner[0]->coordinates().x() + xc );
00135     mCenter.y( corner[0]->coordinates().y() + yc );
00136   }
00137   return mCenter;
00138 }
00139 
00140 //-------------------------------------------------------------------------
00141 // Function:    radius
00142 // Description: return radius of circumcircle for 3D triangle.  Computes
00143 //              and stores value if necessary 
00144 // Author:      chynes
00145 // Date:        6/3/2002
00146 //-------------------------------------------------------------------------
00147 template< class TRIA, class NODE > MY_INLINE
00148 double TDDelaunay< TRIA, NODE >::radius( TRIA *tri_ptr )
00149 {
00150   if (mRadius < 0.0) {
00151     this->circumcenter( tri_ptr );
00152   }
00153   return mRadius;
00154 }
00155 
00156 //-------------------------------------------------------------------------
00157 // Function:    radius2d
00158 // Description: same as radius, but assumes 2d triangle (x,y,0)
00159 // Author:      chynes
00160 // Date:        6/3/2002
00161 //-------------------------------------------------------------------------
00162 template< class TRIA, class NODE > MY_INLINE
00163 double TDDelaunay< TRIA, NODE >::radius2d( TRIA *tri_ptr )
00164 {
00165   if (mRadius < 0.0) {
00166     this->circumcenter2d( tri_ptr );
00167   }
00168   return mRadius;
00169 }
00170 
00171 //-------------------------------------------------------------------------
00172 // Function:    circumsphere
00173 // Description: define radius (squared) and circumsphere center for a tet
00174 // Author:      sjowen
00175 // Date:        8/4/2003
00176 //-------------------------------------------------------------------------
00177 template< class TRIA, class NODE > MY_INLINE 
00178 int TDDelaunay< TRIA, NODE >:: 
00179 circumsphere( TRIA *tet_ptr, CubitVector &center, double &radsq )
00180 {
00181   if (mRadius != -1)
00182   {
00183     radsq = mRadius;
00184     center = mCenter;
00185     return CUBIT_SUCCESS;
00186   }
00187   double reltol = DBL_EPSILON * 100.0;
00188 
00189   NODE *na, *nb, *nc, *nd;
00190   tet_ptr->tet_nodes(nc, nb, na, nd);
00191   CubitVector a = na->coordinates();
00192   CubitVector b = nb->coordinates();
00193   CubitVector c = nc->coordinates();
00194   CubitVector d = nd->coordinates();
00195 
00196   CubitVector da = a - d;
00197   CubitVector db = b - d;
00198   CubitVector dc = c - d;
00199 
00200   double rhsa = 0.5*(SQR(da.x()) + SQR(da.y()) + SQR(da.z()));
00201   double rhsb = 0.5*(SQR(db.x()) + SQR(db.y()) + SQR(db.z()));
00202   double rhsc = 0.5*(SQR(dc.x()) + SQR(dc.y()) + SQR(dc.z()));
00203 
00204   double cpa = db.y()*dc.z() - dc.y()*db.z();
00205   double cpb = dc.y()*da.z() - da.y()*dc.z();
00206   double cpc = da.y()*db.z() - db.y()*da.z();
00207 
00208   double det = da.x()*cpa + db.x()*cpb + dc.x()*cpc;
00209 
00210   double xmax = CUBIT_MAX(fabs(a.x()),fabs(b.x()));
00211          xmax = CUBIT_MAX(xmax,fabs(c.x())); 
00212          xmax = CUBIT_MAX(xmax,fabs(d.x()));
00213   double ymax = CUBIT_MAX(fabs(a.y()),fabs(b.y()));
00214          ymax = CUBIT_MAX(ymax,fabs(c.y())); 
00215          ymax = CUBIT_MAX(ymax,fabs(d.y()));
00216   double zmax = CUBIT_MAX(fabs(a.z()),fabs(b.z()));
00217          zmax = CUBIT_MAX(zmax,fabs(c.z())); 
00218          zmax = CUBIT_MAX(zmax,fabs(d.z()));
00219   double tolabs = reltol*xmax*ymax*zmax;
00220   if (fabs(det) <= tolabs) {
00221     radsq = mRadius = -1.0; 
00222     return CUBIT_FAILURE;
00223   }
00224   center.x( (rhsa*cpa + rhsb*cpb + rhsc*cpc)/det );
00225   cpa = db.x()*rhsc - dc.x()*rhsb;
00226   cpb = dc.x()*rhsa - da.x()*rhsc;
00227   cpc = da.x()*rhsb - db.x()*rhsa;
00228   center.y( (da.z()*cpa + db.z()*cpb + dc.z()*cpc)/det );
00229   center.z( -(da.y()*cpa + db.y()*cpb + dc.y()*cpc)/det );
00230   radsq = SQR(center.x()) + SQR(center.y()) + SQR(center.z());
00231   center += d;
00232 
00233   mRadius = radsq;
00234   mCenter = center;
00235 
00236   return CUBIT_SUCCESS;
00237 }
00238 
00239 
00240 
00241 
00242 
00243 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines