cgma
|
00001 #include "CubitFacet.hpp" 00002 #include "CubitPoint.hpp" 00003 #include "CubitVector.hpp" 00004 #include "GeometryDefines.h" 00005 #include "CubitPlane.hpp" 00006 #include "CubitFacetEdge.hpp" 00007 #include "CubitFacetData.hpp" 00008 #include "FacetEvalTool.hpp" 00009 #include "CastTo.hpp" 00010 #include "FacetEntity.hpp" 00011 #include "CubitPointData.hpp" 00012 #include "CubitFacetEdgeData.hpp" 00013 #include "TDFacetBoundaryPoint.hpp" 00014 #include "GfxDebug.hpp" 00015 #include "CubitMessage.hpp" 00016 00017 #ifndef CUBIT_MAX 00018 #define CUBIT_MAX(a,b) (((a) > (b)) ? (a) : (b)) 00019 #endif 00020 #ifndef CUBIT_MIN 00021 #define CUBIT_MIN(a,b) (((a) < (b)) ? (a) : (b)) 00022 #endif 00023 #define min3(a,b,c) CUBIT_MIN((CUBIT_MIN((a),(b))),(c)) 00024 #define max3(a,b,c) CUBIT_MAX((CUBIT_MAX((a),(b))),(c)) 00025 00026 //=========================================================================== 00027 //Function Name: CubitFacet 00028 // 00029 //Member Type: PUBLIC 00030 //Description: constructor 00031 //=========================================================================== 00032 CubitFacet::CubitFacet( ) 00033 : cachedPlane(NULL), facetWeight(0.0), patchCtrlPts(NULL), 00034 markedFlag(0), isFlat(999), isBackwards(0), toolID(0) 00035 00036 { 00037 00038 } 00039 00040 //=========================================================================== 00041 //Function Name: ~CubitFacetData 00042 // 00043 //Member Type: PUBLIC 00044 //Description: destructor 00045 //=========================================================================== 00046 CubitFacet::~CubitFacet() 00047 { 00048 if (cachedPlane ) 00049 delete cachedPlane; 00050 cachedPlane = NULL; 00051 if (patchCtrlPts) 00052 delete [] patchCtrlPts; 00053 } 00054 00055 00056 //=========================================================================== 00057 //Function Name: normal 00058 // 00059 //Member Type: PUBLIC 00060 //Description: return the facet normal 00061 //=========================================================================== 00062 CubitVector CubitFacet::normal() 00063 { 00064 CubitPlane fac_plane = plane(); 00065 CubitVector the_normal = fac_plane.normal(); 00066 if (isBackwards) 00067 the_normal = -the_normal; 00068 return the_normal; 00069 } 00070 00071 //------------------------------------------------------------------------- 00072 // Purpose : set/get the bezier patch internal control points. 00073 // 00074 // Special Notes : Allocate if necessary 00075 // 00076 // Creator : Steve Owen 00077 // 00078 // Creation Date : 06/28/00 00079 //------------------------------------------------------------------------- 00080 void CubitFacet::set_control_points( CubitVector points[6] ) 00081 { 00082 if (!patchCtrlPts) { 00083 patchCtrlPts = new CubitVector [6]; 00084 } 00085 memcpy( patchCtrlPts, points, 6 *sizeof(CubitVector) ); 00086 } 00087 00088 void CubitFacet::set_control_points( const double *pt_array ) 00089 { 00090 if (!patchCtrlPts) { 00091 patchCtrlPts = new CubitVector [6]; 00092 } 00093 int ii; 00094 for (ii=0; ii<6; ii++) 00095 { 00096 patchCtrlPts[ii].x(pt_array[3*ii]); 00097 patchCtrlPts[ii].y(pt_array[3*ii+1]); 00098 patchCtrlPts[ii].z(pt_array[3*ii+2]); 00099 } 00100 } 00101 00102 void CubitFacet::get_control_points( CubitVector points[6] ) 00103 { 00104 assert(patchCtrlPts != 0); 00105 memcpy( points, patchCtrlPts, 6 *sizeof(CubitVector) ); 00106 } 00107 00108 const CubitPlane &CubitFacet::plane() 00109 { 00110 if( ! cachedPlane ) 00111 { 00112 CubitPoint *p0, *p1, *p2; 00113 points(p0, p1, p2); 00114 CubitVector v1 = p1->coordinates() - p0->coordinates(); 00115 CubitVector v2 = p2->coordinates() - p0->coordinates(); 00116 cachedPlane = new CubitPlane( v1 * v2, p0->coordinates() ); 00117 } 00118 return *cachedPlane; 00119 } 00120 00121 void CubitFacet::update_plane() 00122 { 00123 if ( ! cachedPlane ) 00124 return; 00125 00126 CubitPoint *p0, *p1, *p2; 00127 points(p0, p1, p2); 00128 CubitVector v1 = p1->coordinates() - p0->coordinates(); 00129 CubitVector v2 = p2->coordinates() - p0->coordinates(); 00130 CubitVector normal = v1 * v2; 00131 if (is_backwards()) normal = -normal; 00132 cachedPlane->set(normal, p0->coordinates() ); 00133 } 00134 00135 //------------------------------------------------------------------------- 00136 // Purpose : determine if the facet is flat (all normal are the same) 00137 // 00138 // Special Notes : 00139 // 00140 // Creator : Steve Owen 00141 // 00142 // Creation Date : 5/4/01 00143 //------------------------------------------------------------------------- 00144 int CubitFacet::is_flat() 00145 { 00146 if (isFlat != 999) 00147 { 00148 return isFlat; 00149 } 00150 00151 // check the edges first. If on a boundary then assume not flat for now 00152 // This is to account for any in-plane curvature in the boundary edges 00153 00154 int ii; 00155 CubitBoolean on_boundary = CUBIT_FALSE; 00156 for (ii=0; ii<3 && !on_boundary; ii++) 00157 { 00158 CubitPoint *point_ptr = point(ii); 00159 CubitFacetEdge *edge_ptr = edge(ii); 00160 TDFacetBoundaryPoint *td = TDFacetBoundaryPoint::get_facet_boundary_point(point_ptr); 00161 if (td != NULL || (edge_ptr && edge_ptr->num_adj_facets() <= 1)) 00162 { 00163 on_boundary = CUBIT_TRUE; 00164 } 00165 } 00166 if (on_boundary) 00167 { 00168 isFlat = 0; 00169 } 00170 else 00171 { 00172 00173 CubitPoint *p0, *p1, *p2; 00174 points(p0, p1, p2); 00175 00176 CubitVector n0 = p0->normal( this ); 00177 CubitVector n1 = p1->normal( this ); 00178 CubitVector n2 = p2->normal( this ); 00179 double dot0 = n0 % n1; 00180 double dot1 = n1 % n2; 00181 double dot2 = n2 % n0; 00182 00183 double tol = 1.0 - GEOMETRY_RESABS; 00184 if (fabs(dot0) > tol && fabs(dot1) > tol && fabs(dot2) > tol) 00185 isFlat = 1; 00186 else 00187 isFlat = 0; 00188 } 00189 00190 return isFlat; 00191 } 00192 00193 //=========================================================================== 00194 //Function Name: evaluate_position 00195 // 00196 //Member Type: PUBLIC 00197 //Description: evaluate the facet at a position (projects to facet) 00198 // eval_normal is NULL if normal not needed 00199 //=========================================================================== 00200 CubitStatus CubitFacet::evaluate_position( const CubitVector &start_position, 00201 CubitVector *eval_point, 00202 CubitVector *eval_normal) 00203 { 00204 CubitStatus stat = CUBIT_SUCCESS; 00205 00206 if (is_flat()) 00207 { 00208 if (eval_point != NULL) 00209 closest_point(start_position, *eval_point); 00210 if (eval_normal != NULL) 00211 *eval_normal = normal(); 00212 } 00213 else // project to the smooth facet 00214 { 00215 // project the position to the planar facet 00216 CubitVector close_point; 00217 stat = closest_point(start_position, close_point); 00218 00219 // get the area coordinates of this point as a starting guess 00220 CubitVector area_coordinates; 00221 FacetEvalTool::facet_area_coordinate(this, close_point, area_coordinates); 00222 00223 // now evaluate the smooth facet (this may alter the area coords) 00224 CubitVector proj_point; 00225 CubitBoolean outside; 00226 double tol = sqrt(area()) * 1.0e-3; 00227 stat = FacetEvalTool::project_to_facet( this, close_point, area_coordinates, 00228 proj_point, outside, tol ); 00229 00230 if (eval_point != NULL) 00231 { 00232 *eval_point = proj_point; 00233 } 00234 // compute the smooth normal if required 00235 if (eval_normal != NULL) 00236 { 00237 FacetEvalTool::eval_facet_normal(this, area_coordinates, *eval_normal); 00238 } 00239 } 00240 00241 return stat; 00242 } 00243 00244 //=========================================================================== 00245 //Function Name: evaluate 00246 // 00247 //Member Type: PUBLIC 00248 //Description: evaluate the facet at area coordinates 00249 // eval_normal is NULL if normal not needed 00250 //=========================================================================== 00251 CubitStatus CubitFacet::evaluate( CubitVector &areacoord, 00252 CubitVector *eval_point, 00253 CubitVector *eval_normal ) 00254 { 00255 if (isBackwards) 00256 { 00257 double temp = areacoord.y(); 00258 areacoord.y( areacoord.z() ); 00259 areacoord.z( temp ); 00260 } 00261 return FacetEvalTool::eval_facet( this, areacoord, eval_point, eval_normal ); 00262 } 00263 00264 //=========================================================================== 00265 //Function Name: closest_point 00266 // 00267 //Member Type: PUBLIC 00268 //Description: return the closest point on plane defined by the facet 00269 //=========================================================================== 00270 CubitStatus CubitFacet::closest_point(const CubitVector &point, 00271 CubitVector &closest_point ) 00272 { 00273 CubitPlane fac_plane = plane(); 00274 closest_point = fac_plane.project( point ); 00275 return CUBIT_SUCCESS; 00276 } 00277 00278 //=========================================================================== 00279 //Function Name: closest_point_trimmed 00280 // 00281 //Member Type: PUBLIC 00282 //Description: return the closest point on the facet to the point (trimmed 00283 // to its boundary) 00284 //=========================================================================== 00285 CubitStatus CubitFacet::closest_point_trimmed( const CubitVector &mypoint, 00286 CubitVector &closest_point, 00287 CubitPoint *&next_edge_p1, 00288 CubitPoint *&next_edge_p2) 00289 { 00290 CubitVector p1 = point(0)->coordinates(); 00291 CubitVector p2 = point(1)->coordinates(); 00292 CubitVector p3 = point(2)->coordinates(); 00293 //First get the edge vectors. 00294 p1.x(); 00295 p2.x(); 00296 00297 CubitVector y1 = p2 - p1; 00298 CubitVector y2 = p3 - p2; 00299 CubitVector y3 = p1 - p3; 00300 //Now get the vectors from the point to the vertices of the facet. 00301 CubitVector w1 = mypoint - p1; 00302 CubitVector w2 = mypoint - p2; 00303 CubitVector w3 = mypoint - p3; 00304 //Now cross the edge vectors with the vectors to the point. If the point 00305 //in questionis inside the facet then each of these vectors will be in in 00306 //the same direction as the normal of this facet. 00307 CubitVector x1 = y1*w1; 00308 CubitVector x2 = y2*w2; 00309 CubitVector x3 = y3*w3; 00310 00311 //Now take the dot products to help us determine if it is in the triangle. 00312 CubitVector n = normal(); 00313 double d1 = x1%n; 00314 double d2 = x2%n; 00315 double d3 = x3%n; 00316 00317 //If this is true, then we just take the closest point to this facet. 00318 if ( d1 >= -GEOMETRY_RESABS && d2 >= -GEOMETRY_RESABS && d3 >= -GEOMETRY_RESABS ) 00319 { 00320 CubitStatus rv = this->closest_point(mypoint, closest_point); 00321 if ( rv != CUBIT_SUCCESS ) 00322 { 00323 PRINT_ERROR("Closest Point Trimmed Error. Point in facet but can't" 00324 " calc. point.\n"); 00325 return CUBIT_FAILURE; 00326 } 00327 next_edge_p1 = NULL; 00328 next_edge_p2 = NULL; 00329 return CUBIT_SUCCESS; 00330 } 00331 CubitBoolean close_p1 = CUBIT_FALSE; 00332 CubitBoolean close_p2 = CUBIT_FALSE; 00333 CubitBoolean close_p3 = CUBIT_FALSE; 00334 double k1, k2, k3; 00335 //Now with the "d" values, determine which point or edge we 00336 //should project to. We have to go through each of these and 00337 //determine which is the closest. 00338 if ( d1 < 0.0 ) 00339 { 00340 double w1_dot_y1 = w1%y1; 00341 double y1_squared = y1.length_squared(); 00342 if ( y1_squared <= CUBIT_DBL_MIN && y1_squared >= -CUBIT_DBL_MIN ) 00343 { 00344 PRINT_ERROR("Length of facet edge too small.\n"); 00345 return CUBIT_FAILURE; 00346 } 00347 k1 = w1_dot_y1/y1_squared; 00348 if ( k1 < 0.0 ) 00349 close_p1 = CUBIT_TRUE; 00350 else if ( k1 > 1.0 ) 00351 close_p2 = CUBIT_TRUE; 00352 else if ( k1 >= 0.0 && k1 <= 1.0 + GEOMETRY_RESABS ) 00353 { 00354 //So we know that y1, is the closest edge. 00355 closest_point = p1 + k1*y1; 00356 next_edge_p1 = point(0); 00357 next_edge_p2 = point(1); 00358 return CUBIT_SUCCESS; 00359 } 00360 } 00361 if ( d2 < 0.0 ) 00362 { 00363 double w2_dot_y2 = w2%y2; 00364 double y2_squared = y2.length_squared(); 00365 if ( y2_squared <= CUBIT_DBL_MIN && y2_squared >= -CUBIT_DBL_MIN ) 00366 { 00367 PRINT_ERROR("Length of facet edge too small.\n"); 00368 return CUBIT_FAILURE; 00369 } 00370 k2 = w2_dot_y2/y2_squared; 00371 if ( k2 < 0.0 ) 00372 { 00373 close_p2 = CUBIT_TRUE; 00374 } 00375 else if ( k2 > 1.0 ) 00376 { 00377 close_p3 = CUBIT_TRUE; 00378 } 00379 else if ( k2 >= 0.0 && k2 <= 1.0 + GEOMETRY_RESABS ) 00380 { 00381 //So we know that y2, is the closest edge. 00382 closest_point = p2 + k2*y2; 00383 next_edge_p1 = point(1); 00384 next_edge_p2 = point(2); 00385 return CUBIT_SUCCESS; 00386 } 00387 } 00388 if ( d3 < 0.0 ) 00389 { 00390 double w3_dot_y3 = w3%y3; 00391 double y3_squared = y3.length_squared(); 00392 if ( y3_squared <= CUBIT_DBL_MIN && y3_squared >= -CUBIT_DBL_MIN ) 00393 { 00394 PRINT_ERROR("Length of facet edge too small.\n"); 00395 return CUBIT_FAILURE; 00396 } 00397 k3 = w3_dot_y3/y3_squared; 00398 if ( k3 < 0.0 ) 00399 { 00400 close_p3 = CUBIT_TRUE; 00401 } 00402 else if ( k3 > 1.0 ) 00403 { 00404 close_p1 = CUBIT_TRUE; 00405 } 00406 else if ( k3 >= 0.0 && k3 <= 1.0 + GEOMETRY_RESABS ) 00407 { 00408 //So we know that y3, is the closest edge. 00409 closest_point = p3 + k3*y3; 00410 next_edge_p1 = point(2); 00411 next_edge_p2 = point(0); 00412 return CUBIT_SUCCESS; 00413 } 00414 } 00415 //Now we have the distances, and which edges the point is closest to. 00416 if ( close_p1 && !close_p2 && !close_p3 ) 00417 { 00418 closest_point = p1 ; 00419 next_edge_p1 = point(0); 00420 next_edge_p2 = NULL; 00421 return CUBIT_SUCCESS; 00422 } 00423 else if ( close_p2 && !close_p1 && !close_p3 ) 00424 { 00425 closest_point = p2; 00426 next_edge_p1 = point(1); 00427 next_edge_p2 = NULL; 00428 return CUBIT_SUCCESS; 00429 } 00430 else if ( close_p3 && !close_p1 && !close_p2 ) 00431 { 00432 closest_point = p3; 00433 next_edge_p1 = point(2); 00434 next_edge_p2 = NULL; 00435 return CUBIT_SUCCESS; 00436 } 00437 else if( close_p1 && close_p2 && !close_p3 ) 00438 { 00439 if( w1.length_squared() < w2.length_squared() ) 00440 closest_point = p1; 00441 else 00442 closest_point = p2; 00443 return CUBIT_SUCCESS; 00444 } 00445 else if( close_p2 && close_p3 && !close_p1 ) 00446 { 00447 if( w2.length_squared() < w3.length_squared() ) 00448 closest_point = p2; 00449 else 00450 closest_point = p3; 00451 return CUBIT_SUCCESS; 00452 } 00453 else if( close_p1 && close_p3 && !close_p2 ) 00454 { 00455 if( w1.length_squared() < w3.length_squared() ) 00456 closest_point = p1; 00457 else 00458 closest_point = p3; 00459 return CUBIT_SUCCESS; 00460 } 00461 00462 PRINT_ERROR("Problems finding the closest point to a facet.\n"); 00463 return CUBIT_FAILURE; 00464 } 00465 00466 //=========================================================================== 00467 //Function Name: contains 00468 // 00469 //Member Type: PUBLIC 00470 //Description: determine if point is contained in facet 00471 //=========================================================================== 00472 CubitBoolean CubitFacet::contains( CubitPoint *p1 ) 00473 { 00474 for ( int i = 0; i < 3; i++ ) 00475 if ( point(i) == p1 ) 00476 return CUBIT_TRUE; 00477 return CUBIT_FALSE; 00478 } 00479 00480 //=========================================================================== 00481 //Function Name: shared_facet 00482 // 00483 //Member Type: PUBLIC 00484 //Description: Find the other facet that shares these two points. 00485 // Note: assumes max two facets per edge 00486 //=========================================================================== 00487 CubitFacet* CubitFacet::shared_facet( CubitPoint *p1, CubitPoint *p2 ) 00488 { 00489 //Find the other facet that shares these two points. 00490 int ii; 00491 DLIList<CubitFacet*> facet_list; 00492 p1->facets(facet_list); 00493 00494 for ( ii = facet_list.size(); ii > 0; ii-- ) 00495 { 00496 CubitFacet *t_facet = facet_list.get_and_step(); 00497 if ( t_facet == this ) 00498 continue; 00499 if ( t_facet->contains(p2) ) 00500 { 00501 assert( t_facet->contains(p1) ); 00502 return t_facet; 00503 } 00504 } 00505 return (CubitFacet*)NULL; 00506 } 00507 00508 //=========================================================================== 00509 //Function Name: shared_facets 00510 // 00511 //Member Type: PUBLIC 00512 //Description: Make a list of all facets adjacent this facet at the edge 00513 // defined by p1, p2 00514 //=========================================================================== 00515 void CubitFacet::shared_facets( CubitPoint *p1, CubitPoint *p2, 00516 DLIList <CubitFacet *> &adj_facet_list) 00517 { 00518 //Find the other facets that share these two points. 00519 int ii; 00520 DLIList<CubitFacet*> facet_list; 00521 p1->facets(facet_list); 00522 00523 for ( ii = facet_list.size(); ii > 0; ii-- ) 00524 { 00525 CubitFacet *t_facet = facet_list.get_and_step(); 00526 if ( t_facet == this ) 00527 continue; 00528 if ( t_facet->contains(p2) ) 00529 { 00530 assert( t_facet->contains(p1) ); 00531 adj_facet_list.append( t_facet ); 00532 } 00533 } 00534 } 00535 00536 00537 //=========================================================================== 00538 //Function Name: shared_facet_on_surf 00539 // 00540 //Member Type: PUBLIC 00541 //Description: Find the other facet that shares these two points and that 00542 // is has the same tool id. 00543 // Note: assumes max two facets per edge 00544 //=========================================================================== 00545 CubitFacet* CubitFacet::shared_facet_on_surf( CubitPoint *p1, CubitPoint *p2, 00546 int tool_id ) 00547 { 00548 //Find the other facet that shares these two points and that 00549 // is marked with flag. 00550 int ii; 00551 DLIList<CubitFacet*> facet_list; 00552 p1->facets(facet_list); 00553 00554 for ( ii = facet_list.size(); ii > 0; ii-- ) 00555 { 00556 CubitFacet *t_facet = facet_list.get_and_step(); 00557 if ( t_facet == this ) 00558 continue; 00559 if ( t_facet->contains(p2) ) 00560 { 00561 if (tool_id == t_facet->tool_id()) 00562 { 00563 assert( t_facet->contains(p1) ); 00564 return t_facet; 00565 } 00566 } 00567 } 00568 return (CubitFacet*)NULL; 00569 } 00570 00571 //=========================================================================== 00572 //Function Name: center 00573 // 00574 //Member Type: PUBLIC 00575 //Description: return the centroid of this facet 00576 //=========================================================================== 00577 CubitVector CubitFacet::center() 00578 { 00579 CubitVector vec( point(0)->coordinates() ); 00580 vec += point(1)->coordinates(); 00581 vec += point(2)->coordinates(); 00582 vec /= 3.0; 00583 return vec; 00584 } 00585 00586 //=========================================================================== 00587 //Function Name: draw 00588 // 00589 //Member Type: PUBLIC 00590 //Description: draw the facet 00591 //=========================================================================== 00592 void CubitFacet::debug_draw(int color, int flush_it, int draw_uv ) 00593 { 00594 if ( color == -1 ) 00595 color = CUBIT_RED_INDEX; 00596 GfxDebug::draw_facet(this, color, draw_uv); 00597 if ( flush_it ) 00598 GfxDebug::flush(); 00599 } 00600 00601 const int CubitFacet::point_edge_conn[30][2] = { {4, 8}, {8, 11}, {11, 13}, {13, 14}, 00602 {3, 7}, {7, 10}, {10, 12}, 00603 {2, 6}, {6, 9}, 00604 {1, 5}, 00605 {14, 12}, {12, 9}, {9, 5}, {5, 0}, 00606 {13, 10}, {10, 6}, {6, 1}, 00607 {11, 7}, {7, 2}, 00608 {8, 3}, 00609 {0, 1}, {1, 2}, {2, 3}, {3, 4}, 00610 {5, 6}, {6, 7}, {7, 8}, 00611 {9, 10}, {10, 11}, 00612 {12, 13} }; 00613 const int CubitFacet::point_facet_conn[16][3] = { 00614 {0, 1, 5}, {1, 6, 5}, {1, 2, 6}, {2, 7, 6}, {2, 3, 7}, {3, 8, 7}, {3, 4, 8}, 00615 {5, 6, 9}, {6, 10, 9}, {6, 7, 10}, {7, 11, 10}, {7, 8, 11}, 00616 {9, 10, 12}, {10, 13, 12}, {10, 11, 13}, 00617 {12, 13, 14} }; 00618 const double CubitFacet::my_points[15][3] = { 00619 {1.00, 0.00, 0.00},{0.75, 0.25, 0.00},{0.50, 0.50, 0.00}, 00620 {0.25, 0.75, 0.00},{0.00, 1.00, 0.00},{0.75, 0.00, 0.25}, 00621 {0.50, 0.25, 0.25},{0.25, 0.50, 0.25},{0.00, 0.75, 0.25}, 00622 {0.50, 0.00, 0.50},{0.25, 0.25, 0.50},{0.00, 0.50, 0.50}, 00623 {0.25, 0.00, 0.75},{0.00, 0.25, 0.75},{0.00, 0.00, 1.00} }; 00624 00625 00626 00627 //=========================================================================== 00628 //Function Name: min_diagonal 00629 // 00630 //Member Type: PUBLIC 00631 //Description: from the three points find the minimum diagonal. 00632 //=========================================================================== 00633 double CubitFacet::min_diagonal() 00634 { 00635 //from the three points find the minimum diagonal. 00636 CubitVector p1 = point(0)->coordinates(); 00637 CubitVector p2 = point(1)->coordinates(); 00638 CubitVector p3 = point(2)->coordinates(); 00639 CubitVector temp1 = p2-p1; 00640 CubitVector mid_side_1 = p1 + temp1/2.0; 00641 CubitVector temp2 = p3-p2; 00642 CubitVector mid_side_2 = p2 + temp2/2.0; 00643 CubitVector temp3 = p1-p3; 00644 CubitVector mid_side_3 = p3 + temp3/2.0; 00645 CubitVector diagv_1 = p3 - mid_side_1; 00646 CubitVector diagv_2 = p2 - mid_side_3; 00647 CubitVector diagv_3 = p1 - mid_side_2; 00648 00649 double diag_1 = diagv_1.length(); 00650 double diag_2 = diagv_2.length(); 00651 double diag_3 = diagv_3.length(); 00652 if ( diag_1 >= diag_2 && diag_1 >= diag_3 ) 00653 return diag_1; 00654 else if ( diag_2 > diag_1 && diag_2 > diag_3 ) 00655 return diag_2; 00656 return diag_3; 00657 } 00658 00659 //------------------------------------------------------------------------- 00660 // Purpose : Get the two points of the edge opposite the 00661 // passed point. 00662 // 00663 // Special Notes : 00664 // 00665 // Creator : Jason Kraftcheck 00666 // 00667 // Creation Date : 03/07/00 00668 //------------------------------------------------------------------------- 00669 void CubitFacet::opposite_edge( CubitPoint* thepoint, 00670 CubitPoint*& p1, CubitPoint *& p2 ) 00671 { 00672 p1 = p2 = 0; 00673 int i; 00674 00675 for( i = 0; i < 3; i++ ) 00676 if( point(i) == thepoint ) 00677 break; 00678 00679 if( i < 3 ) //point is on this triangle 00680 { 00681 p1 = point((i+1)%3); 00682 p2 = point((i+2)%3); 00683 } 00684 } 00685 00686 //------------------------------------------------------------------------- 00687 // Purpose : Local modification functions. 00688 // 00689 // Special Notes : 00690 // 00691 // Creator : 00692 // 00693 // Creation Date : 03/25/00 00694 //------------------------------------------------------------------------- 00695 CubitPoint* CubitFacet::split_edge( CubitPoint* /* edge_pt1 */, 00696 CubitPoint* /* edge_pt2 */, 00697 const CubitVector& /* position */ ) 00698 { 00699 // this function should be implemented in child class since it creates 00700 // new facet and point entities 00701 assert(1); 00702 CubitPoint* new_point = NULL; 00703 return new_point; 00704 } 00705 00706 //------------------------------------------------------------------------- 00707 // Purpose : insert a point into the facet 00708 // 00709 // Special Notes : create two new facets and return them 00710 // 00711 // Creator : 00712 // 00713 // Creation Date : 00714 //------------------------------------------------------------------------- 00715 CubitPoint* CubitFacet::insert_point( const CubitVector& /* position */, 00716 CubitFacet*& /* new_tri1 */, 00717 CubitFacet*& /* new_tri2 */) 00718 { 00719 // this function should be implemented in child class since it creates 00720 // new facet and point entities 00721 assert(1); 00722 CubitPoint* new_point = NULL; 00723 return new_point; 00724 } 00725 00726 00727 //------------------------------------------------------------------------- 00728 // Purpose : return the index of the other index not used by 00729 // points p1 and p2 00730 // 00731 // Special Notes : 00732 // 00733 // Creator : 00734 // 00735 // Creation Date : 00736 //------------------------------------------------------------------------- 00737 int CubitFacet::other_index( CubitPoint* pt1, CubitPoint* pt2 ) 00738 { 00739 int i; 00740 for( i = 0; (point(i) != pt1) && (i < 3); i++ ); 00741 if( i == 3 ) return -1; 00742 00743 int i1 = (i+1)%3; 00744 int i2 = (i+2)%3; 00745 00746 if( point(i1) == pt2 ) return i2; 00747 else if( point(i2) == pt2 ) return i1; 00748 else return -1; 00749 } 00750 00751 //------------------------------------------------------------------------- 00752 // Purpose : compute the angle at one of the points on the facet 00753 // 00754 // Special Notes : angle is in radians 00755 // 00756 // Creator : Steve Owen 00757 // 00758 // Creation Date : 06/28/00 00759 //------------------------------------------------------------------------- 00760 double CubitFacet::angle( CubitPoint *pt ) 00761 { 00762 int ii, index = -1; 00763 CubitBoolean found=CUBIT_FALSE; 00764 for (ii=0; ii<3 && !found; ii++) { 00765 if (pt==this->point(ii)) { 00766 index = ii; 00767 found = CUBIT_TRUE; 00768 } 00769 } 00770 if (!found) { 00771 return 0.0e0; 00772 } 00773 CubitVector e0 = this->point((index+1)%3)->coordinates() - pt->coordinates(); 00774 CubitVector e1 = this->point((index+2)%3)->coordinates() - pt->coordinates(); 00775 e0.normalize(); 00776 e1.normalize(); 00777 double myangle; 00778 double cosangle = e0%e1; 00779 if (cosangle >= 1.0) { 00780 myangle = 0.0e0; 00781 } 00782 else if( cosangle <= -1.0 ) { 00783 myangle = CUBIT_PI; 00784 } 00785 else { 00786 myangle = acos(cosangle); 00787 } 00788 return myangle; 00789 } 00790 00791 //------------------------------------------------------------------------- 00792 // Purpose : return the edge on a facet and its corresponding index. 00793 // 00794 // Special Notes : The index of the edge corresponds to the point index on 00795 // the facet opposite the edge. 00796 // 00797 // Creator : Steve Owen 00798 // 00799 // Creation Date : 06/28/00 00800 //------------------------------------------------------------------------- 00801 CubitFacetEdge *CubitFacet::edge_from_pts( CubitPoint *p1, 00802 CubitPoint *p2, 00803 int &edge_index ) 00804 { 00805 if ((point(0) == p1 && point(1) == p2) || 00806 (point(0) == p2 && point(1) == p1)) { 00807 edge_index = 2; 00808 return edge(2); 00809 } 00810 if ((point(1) == p1 && point(2) == p2) || 00811 (point(1) == p2 && point(2) == p1)) { 00812 edge_index = 0; 00813 return edge(0); 00814 } 00815 if ((point(2) == p1 && point(0) == p2) || 00816 (point(2) == p2 && point(0) == p1)) { 00817 edge_index = 1; 00818 return edge(1); 00819 } 00820 edge_index = -1; 00821 return NULL; 00822 } 00823 00824 //------------------------------------------------------------------------- 00825 // Purpose : return the index of an edge on a facet given two 00826 // points on the facet 00827 // 00828 // Special Notes : The index of the edge corresponds to the point index on 00829 // the facet opposite the edge. 00830 // 00831 // Creator : Steve Owen 00832 // 00833 // Creation Date : 06/28/00 00834 //------------------------------------------------------------------------- 00835 int CubitFacet::edge_index( CubitPoint *p1, CubitPoint *p2, int &sense ) 00836 { 00837 if (point(0) == p1 && point(1) == p2) 00838 { 00839 sense = 1; 00840 return 2; 00841 } 00842 if (point(0) == p2 && point(1) == p1) 00843 { 00844 sense = -1; 00845 return 2; 00846 } 00847 if (point(1) == p1 && point(2) == p2) 00848 { 00849 sense = 1; 00850 return 0; 00851 } 00852 if (point(1) == p2 && point(2) == p1) 00853 { 00854 sense = -1; 00855 return 0; 00856 } 00857 if (point(2) == p1 && point(0) == p2) 00858 { 00859 sense = 1; 00860 return 1; 00861 } 00862 if (point(2) == p2 && point(0) == p1) 00863 { 00864 sense = -1; 00865 return 1; 00866 } 00867 sense = 0; 00868 return -1; 00869 } 00870 00871 // overloaded function - based on edge pointer 00872 int CubitFacet::edge_index( CubitFacetEdge *theedge ) 00873 { 00874 if (edge(0) == theedge) return 0; 00875 if (edge(1) == theedge) return 1; 00876 if (edge(2) == theedge) return 2; 00877 return -1; 00878 } 00879 00880 00881 //------------------------------------------------------------------------- 00882 // Purpose : return the index of a point on a facet 00883 // 00884 // Creator : Steve Owen 00885 // 00886 // Creation Date : 06/28/00 00887 //------------------------------------------------------------------------- 00888 int CubitFacet::point_index( CubitPoint *pt ) 00889 { 00890 if (point(0) == pt) return 0; 00891 if (point(1) == pt) return 1; 00892 if (point(2) == pt) return 2; 00893 return -1; 00894 } 00895 00896 //------------------------------------------------------------------------- 00897 // Purpose : get the points that define an edge of a facet. 00898 // 00899 // Special Notes : The index of the edge corresponds to the point index on 00900 // the facet opposite the edge. The points are returned 00901 // based on the edgeUse order 00902 // 00903 // Creator : Steve Owen 00904 // 00905 // Creation Date : 06/28/00 00906 //------------------------------------------------------------------------- 00907 void CubitFacet::get_edge_pts( int index, CubitPoint *&p1, CubitPoint *&p2 ) 00908 { 00909 assert(index >=0 && index <=2); 00910 00911 p1 = point((index+1)%3); 00912 p2 = point((index+2)%3); 00913 } 00914 00915 //------------------------------------------------------------------------- 00916 // Purpose : update the bounding box of the facet based on the control 00917 // polygon of the facet. 00918 // 00919 // Creator : Steve Owen 00920 // 00921 // Creation Date : 06/28/00 00922 //------------------------------------------------------------------------- 00923 void CubitFacet::update_bezier_bounding_box( ) 00924 { 00925 int i,j; 00926 CubitVector ctrl_pts[5], min, max; 00927 CubitFacetEdge *myedge; 00928 CubitBox bbox = bounding_box(); 00929 min = bbox.minimum(); 00930 max = bbox.maximum(); 00931 for (i=0; i<3; i++) { 00932 myedge = edge(i); 00933 assert(myedge != 0); 00934 myedge->control_points( this, ctrl_pts ); 00935 for (j=1; j<4; j++) { 00936 if (ctrl_pts[j].x() < min.x()) min.x( ctrl_pts[j].x() ); 00937 if (ctrl_pts[j].y() < min.y()) min.y( ctrl_pts[j].y() ); 00938 if (ctrl_pts[j].z() < min.z()) min.z( ctrl_pts[j].z() ); 00939 if (ctrl_pts[j].x() > max.x()) max.x( ctrl_pts[j].x() ); 00940 if (ctrl_pts[j].y() > max.y()) max.y( ctrl_pts[j].y() ); 00941 if (ctrl_pts[j].z() > max.z()) max.z( ctrl_pts[j].z() ); 00942 } 00943 } 00944 CubitVector patch_ctrl_pts[6]; 00945 get_control_points( patch_ctrl_pts ); 00946 assert(patch_ctrl_pts != 0); 00947 for (j=0; j<6; j++) { 00948 if (patch_ctrl_pts[j].x() < min.x()) min.x( patch_ctrl_pts[j].x() ); 00949 if (patch_ctrl_pts[j].y() < min.y()) min.y( patch_ctrl_pts[j].y() ); 00950 if (patch_ctrl_pts[j].z() < min.z()) min.z( patch_ctrl_pts[j].z() ); 00951 if (patch_ctrl_pts[j].x() > max.x()) max.x( patch_ctrl_pts[j].x() ); 00952 if (patch_ctrl_pts[j].y() > max.y()) max.y( patch_ctrl_pts[j].y() ); 00953 if (patch_ctrl_pts[j].z() > max.z()) max.z( patch_ctrl_pts[j].z() ); 00954 } 00955 bBox.reset(min,max); 00956 } 00957 00958 //------------------------------------------------------------------------- 00959 // Purpose : reset the bounding box of the facet based on the control 00960 // polygon of the facet. 00961 // 00962 // Creator : Steve Owen 00963 // 00964 // Creation Date : 3/14/02 00965 //------------------------------------------------------------------------- 00966 void CubitFacet::reset_bounding_box( ) 00967 { 00968 00969 CubitPoint *p1 = point (0); 00970 CubitPoint *p2 = point (1); 00971 CubitPoint *p3 = point (2); 00972 00973 // define the bounding box 00974 00975 if (!patchCtrlPts || is_flat()) 00976 { 00977 CubitVector bbox_min, bbox_max; 00978 bbox_min.x(min3(p1->x(),p2->x(),p3->x())); 00979 bbox_min.y(min3(p1->y(),p2->y(),p3->y())); 00980 bbox_min.z(min3(p1->z(),p2->z(),p3->z())); 00981 bbox_max.x(max3(p1->x(),p2->x(),p3->x())); 00982 bbox_max.y(max3(p1->y(),p2->y(),p3->y())); 00983 bbox_max.z(max3(p1->z(),p2->z(),p3->z())); 00984 bBox.reset(bbox_min,bbox_max); 00985 } 00986 else 00987 { 00988 update_bezier_bounding_box( ); 00989 } 00990 } 00991 00992 //------------------------------------------------------------------------- 00993 // Purpose : get the next CCW (rhr) facetedge on the facet 00994 // 00995 // Special Notes : 00996 // 00997 // Creator : Steve Owen 00998 // 00999 // Creation Date : 06/28/00 01000 //------------------------------------------------------------------------- 01001 CubitFacetEdge *CubitFacet::next_edge( CubitFacetEdge *theedge ) 01002 { 01003 int i; 01004 for (i=0; i<3; i++) { 01005 if (theedge == edge(i)) { 01006 return edge((i+1)%3); 01007 } 01008 } 01009 return NULL; 01010 } 01011 01012 //------------------------------------------------------------------------- 01013 // Purpose : get the prev CCW (rhr) facetedge on the facet 01014 // 01015 // Special Notes : 01016 // 01017 // Creator : Steve Owen 01018 // 01019 // Creation Date : 06/28/00 01020 //------------------------------------------------------------------------- 01021 CubitFacetEdge *CubitFacet::prev_edge( CubitFacetEdge *theedge ) 01022 { 01023 int i; 01024 for (i=0; i<3; i++) { 01025 if (theedge == edge(i)) { 01026 return edge((i+2)%3); 01027 } 01028 } 01029 return NULL; 01030 } 01031 01032 //------------------------------------------------------------------------- 01033 // Purpose : reorient the facet 01034 // 01035 // Special Notes : 01036 // 01037 // Creator : Steve Owen 01038 // 01039 // Creation Date : 06/28/00 01040 //------------------------------------------------------------------------- 01041 void CubitFacet::flip() 01042 { 01043 // must be implemented in child class 01044 assert(0); 01045 01046 } 01047 01048 //------------------------------------------------------------------------- 01049 // Purpose : return the next edge on the triangle at the point 01050 // 01051 // Special Notes : 01052 // 01053 // Creator : Steve Owen 01054 // 01055 // Creation Date : 4/31/01 01056 //------------------------------------------------------------------------- 01057 CubitFacetEdge *CubitFacet::next_edge_at_point( CubitFacetEdge *edge_ptr, 01058 CubitPoint *point_ptr ) 01059 { 01060 int eidx = edge_index( edge_ptr ); 01061 int pidx = point_index( point_ptr ); 01062 switch(eidx) 01063 { 01064 case 0: 01065 switch(pidx) 01066 { 01067 case 1: eidx = 2; break; 01068 case 2: eidx = 1; break; 01069 default: eidx = -1; break; 01070 } 01071 break; 01072 case 1: 01073 switch(pidx) 01074 { 01075 case 0: eidx = 2; break; 01076 case 2: eidx = 0; break; 01077 default: eidx = -1; break; 01078 } 01079 break; 01080 case 2: 01081 switch(pidx) 01082 { 01083 case 0: eidx = 1; break; 01084 case 1: eidx = 0; break; 01085 default: eidx = -1; break; 01086 } 01087 break; 01088 default: 01089 eidx = -1; 01090 break; 01091 } 01092 if (eidx == -1) 01093 return (CubitFacetEdge *)NULL; 01094 01095 return edge( eidx ); 01096 } 01097 01098 //====================================================================== 01099 // Function: get_edge control_points (PUBLIC) 01100 // Description: return the control points on the facet edges based 01101 // on its edge use directions 01102 // Author: sjowen 01103 // Date: 5/01 01104 //====================================================================== 01105 CubitStatus CubitFacet::get_edge_control_points( CubitVector P[3][5] ) 01106 { 01107 CubitStatus stat; 01108 CubitFacetEdge *edge_ptr; 01109 CubitVector ctrl_pts[5]; 01110 int ii, jj; 01111 for (ii=0; ii<3; ii++) { 01112 edge_ptr = edge(ii); 01113 stat = edge_ptr->control_points(this, ctrl_pts); 01114 if (stat!= CUBIT_SUCCESS) 01115 return stat; 01116 for (jj=0; jj<5; jj++) 01117 { 01118 P[ii][jj] = ctrl_pts[jj]; 01119 } 01120 } 01121 return stat; 01122 } 01123 01124 //====================================================================== 01125 // Function: area (PUBLIC) 01126 // Description: compute the area of the facet 01127 // Author: sjowen 01128 // Date: 3/02 01129 //====================================================================== 01130 double CubitFacet::area( ) 01131 { 01132 CubitVector e0(point(0)->coordinates(), point(1)->coordinates()); 01133 CubitVector e1(point(0)->coordinates(), point(2)->coordinates()); 01134 double area = (e0 * e1).length() * 0.5; 01135 return area; 01136 } 01137 01138 double CubitFacet::aspect_ratio() 01139 { 01140 static const double normal_coeff = sqrt( 3. ) / 6.; 01141 01142 // three vectors for each side 01143 CubitVector a = point(1)->coordinates() - point(0)->coordinates(); 01144 CubitVector b = point(2)->coordinates() - point(1)->coordinates(); 01145 CubitVector c = point(0)->coordinates() - point(2)->coordinates(); 01146 01147 double a1 = a.length(); 01148 double b1 = b.length(); 01149 double c1 = c.length(); 01150 01151 double hm = a1 > b1 ? a1 : b1; 01152 hm = hm > c1 ? hm : c1; 01153 01154 CubitVector ab = a * b; 01155 double denominator = ab.length(); 01156 01157 if( denominator < CUBIT_DBL_MIN ) 01158 return (double)CUBIT_DBL_MAX; 01159 else 01160 { 01161 double aspect_ratio; 01162 aspect_ratio = normal_coeff * hm * (a1 + b1 + c1) / denominator; 01163 01164 if( aspect_ratio > 0 ) 01165 return (double) CUBIT_MIN( aspect_ratio, CUBIT_DBL_MAX ); 01166 return (double) CUBIT_MAX( aspect_ratio, -CUBIT_DBL_MAX ); 01167 } 01168 } 01169 01170 01171 //====================================================================== 01172 // Function: init_patch (PUBLIC) 01173 // Description: computes the interior control points for the facet and 01174 // stores them with the facet. Assumes edge control points 01175 // have already been computed 01176 // Author: sjowen 01177 // Date: 10/03 01178 //====================================================================== 01179 CubitStatus CubitFacet::init_patch( ) 01180 { 01181 return FacetEvalTool::init_bezier_facet( this ); 01182 } 01183 01184 //=========================================================================== 01185 //Function Name: add_edge 01186 // 01187 //Member Type: PUBLIC 01188 //Description: add an existing edge to a facet. The edge must contain 01189 // points that are already part of this facet 01190 //=========================================================================== 01191 void CubitFacet::add_edge(CubitFacetEdge *edge) 01192 { 01193 CubitPoint *p0 = edge->point(0); 01194 CubitPoint *p1 = edge->point(1); 01195 01196 // find the points on this facet 01197 01198 int p0_index = point_index( p0 ); 01199 int p1_index = point_index( p1 ); 01200 assert(p0_index >=0 && p1_index >= 0); 01201 assert(p0_index != p1_index); 01202 01203 // add the edge based on the relative index of the points 01204 // set the edge use based on their order 01205 01206 int edge_index; 01207 if ((p0_index+1)%3 == p1_index) 01208 { 01209 edge_index = (p1_index + 1)%3; 01210 assert(this->edge(edge_index) == NULL); 01211 this->edge( edge, edge_index ); 01212 this->edge_use(1, edge_index); 01213 } 01214 else if((p0_index+2)%3 == p1_index) 01215 { 01216 edge_index = (p0_index + 1)%3; 01217 assert(this->edge(edge_index) == NULL); 01218 this->edge( edge, edge_index ); 01219 this->edge_use(-1, edge_index); 01220 } 01221 else 01222 { 01223 assert(0); // shouldn't happen 01224 } 01225 01226 // add the facet to the edge 01227 01228 edge->add_facet( this ); 01229 } 01230 01231 01232 CubitPoint *CubitFacet::opposite_point( CubitFacetEdge *edge ) 01233 { 01234 int i; 01235 for( i = 0; i < 3; i++ ) 01236 if( point(i) != edge->point(0) && point(i) != edge->point(1) ) 01237 return point(i); 01238 01239 return NULL; 01240 } 01241 01242 CubitVector CubitFacet::update_normal( void ) 01243 { 01244 this->update_plane(); 01245 return normal(); 01246 } 01247 01248 void CubitFacet::unlink_from_children( void ) 01249 { 01250 01251 this->point(0)->remove_facet(this); 01252 this->point(1)->remove_facet(this); 01253 this->point(2)->remove_facet(this); 01254 this->edge(0)->remove_facet(this); 01255 this->edge(1)->remove_facet(this); 01256 this->edge(2)->remove_facet(this); 01257 01258 } 01259 01260 CubitFacetEdge* CubitFacet::shared_edge( CubitFacet *cubit_facet ) 01261 { 01262 for( int i=0; i<3; i++ ) 01263 for( int j=0; j<3; j++ ) 01264 if( edge(i) == cubit_facet->edge(j) ) 01265 return edge(i); 01266 01267 return NULL; 01268 }