cgma
|
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 ¢er, 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