cgma
|
00001 //- Class: FacetEvalTool 00002 //- Description: The FacetEvalTool is a tool to perform generic geometric 00003 //- operations on a set of facets. 00004 //- Assumptions: All of the facets are connected topologically correct. 00005 //- 00006 //- Owner: Steve J. Owen 00007 //- Checked by: 00008 00009 #include <float.h> 00010 #include "CastTo.hpp" 00011 #include "CubitVector.hpp" 00012 #include "CubitPoint.hpp" 00013 #include "CubitFacet.hpp" 00014 #include "CubitFacetEdge.hpp" 00015 #include "CubitFacetEdgeData.hpp" 00016 #include "CpuTimer.hpp" 00017 #include "CubitMessage.hpp" 00018 #include "CubitBox.hpp" 00019 #include "DLIList.hpp" 00020 #include "FacetEvalTool.hpp" 00021 #include "GeometryDefines.h" 00022 #include "CubitTransformMatrix.hpp" 00023 #include "ChollaDebug.hpp" 00024 #include "TDFacetBoundaryEdge.hpp" 00025 #include "TDFacetBoundaryPoint.hpp" 00026 #include "GfxDebug.hpp" 00027 //#include "FacetParamTool.hpp" 00028 #include "KDDTree.hpp" 00029 #include "AbstractTree.hpp" 00030 #include "CubitFileIOWrapper.hpp" 00031 #include "FacetDataUtil.hpp" 00032 00033 double FacetEvalTool::timeGridSearch = 0.0; 00034 double FacetEvalTool::timeFacetProject = 0.0; 00035 int FacetEvalTool::numEvals = 0; 00036 #define GRID_SEARCH_THRESHOLD 20 00037 00038 //=========================================================================== 00039 //Function Name: FacetEvalTool 00040 // 00041 //Member Type: PUBLIC 00042 //Description: constructor 00043 //=========================================================================== 00044 CubitStatus FacetEvalTool::initialize( 00045 DLIList<CubitFacet*> &facet_list, 00046 DLIList<CubitPoint*> &point_list, // if this isn't filled in, I'll do it here 00047 int interp_order, // 0 = linear or 4 = Bezier only for now 00048 double min_dot ) // from feature angle 00049 { 00050 myFacetList = facet_list; 00051 myPointList = point_list; 00052 isParameterized = CUBIT_FALSE; 00053 minDot = min_dot; 00054 output_id = -1; 00055 00056 // mark all of the facets on this surface with the toolID 00057 00058 int i; 00059 for (i = 0; i< myFacetList.size(); i++) 00060 myFacetList.get_and_step()->set_tool_id( toolID ); 00061 00062 // generate the list of points, if not already defined 00063 00064 if (myPointList.size() == 0) 00065 { 00066 get_points_from_facets( facet_list, myPointList ); 00067 } 00068 interpOrder = 0; // default to project to linear facet 00069 00070 // set the bounding box and compareTol and setup grid search 00071 myBBox = NULL; 00072 aTree = NULL; 00073 00074 reset_bounding_box(); 00075 00076 00077 lastFacet = NULL; 00078 isFlat = -999; 00079 isFlat = is_flat(); 00080 00081 if (interp_order == -1) { 00082 interpOrder = 0; // use linear as default interp order 00083 } 00084 else { 00085 interpOrder = interp_order; 00086 } 00087 00088 // generate edges 00089 00090 if ( CUBIT_SUCCESS != get_edges_from_facets( facet_list, myEdgeList ) || 00091 CUBIT_SUCCESS != get_loops_from_facets( myEdgeList, myLoopList ) ) 00092 { 00093 PRINT_ERROR("Unable to initialize Facet Evaluation Tool.\n"); 00094 return CUBIT_FAILURE; 00095 } 00096 00097 if (interpOrder > 0) { 00098 init_gradient(); 00099 if (interpOrder == 3) { // least_squares 00100 init_quadrics(); 00101 } 00102 else if(interpOrder == 4) { // spline 00103 init_bezier_surface(); 00104 } 00105 } 00106 00107 // compute the area of all facets 00108 00109 myArea = -1.0; 00110 myArea = area(); 00111 00112 00113 int mydebug = 0; 00114 if (mydebug) 00115 { 00116 debug_draw_eval_bezier_facet( myFacetList.get_and_step() ); 00117 debug_draw_facets(); 00118 debug_draw_facet_normals(); 00119 if (interpOrder > 0) debug_draw_point_normals(); 00120 GfxDebug::flush(); 00121 GfxDebug::mouse_xforms(); 00122 } 00123 00124 //parameterize(); 00125 return CUBIT_SUCCESS; 00126 } 00127 00128 //=========================================================================== 00129 //Function Name: FacetEvalTool 00130 //Member Type: PUBLIC 00131 //Descriptoin: constructor. This one is an empty constructor 00132 // sed with restore method 00133 //=========================================================================== 00134 FacetEvalTool::FacetEvalTool() 00135 { 00136 static int counter = 1; 00137 toolID = counter++; 00138 myBBox = NULL; 00139 aTree = NULL; 00140 lastFacet = NULL; 00141 isFlat = -999; 00142 myArea = -1.0; 00143 interpOrder = 0; 00144 minDot = 0; 00145 isParameterized = CUBIT_FALSE; 00146 } 00147 00148 //=========================================================================== 00149 //Function Name: ~FacetEvalTool 00150 // 00151 //Member Type: PUBLIC 00152 //Descriptoin: destructor 00153 //=========================================================================== 00154 FacetEvalTool::~FacetEvalTool() 00155 { 00156 if ( DEBUG_FLAG(110) ) 00157 { 00158 PRINT_INFO("num facets = %d\n",myFacetList.size()); 00159 PRINT_INFO("numEvals = %d\n",numEvals); 00160 PRINT_INFO("timeFacetProject = %f\n",timeFacetProject); 00161 PRINT_INFO("timeGridSearch = %f\n",timeGridSearch); 00162 } 00163 00164 if (aTree != NULL) 00165 delete aTree; 00166 00167 if (myBBox) delete myBBox; 00168 destroy_facets(); 00169 00170 myLoopList.reset(); 00171 int i; 00172 for (i=myLoopList.size(); i>0; i--) 00173 { 00174 delete myLoopList.get_and_step(); 00175 } 00176 myLoopList.clean_out(); 00177 } 00178 00179 void FacetEvalTool::remove_facets( DLIList<CubitFacet*>& facets ) 00180 { 00181 facets = myFacetList; 00182 for ( int i = facets.size(); i--; ) 00183 facets.step_and_get()->set_tool_id(0); 00184 myFacetList.clean_out(); 00185 myEdgeList.clean_out(); 00186 myPointList.clean_out(); 00187 } 00188 00189 CubitStatus FacetEvalTool::reverse_facets( ) 00190 { 00191 int i; 00192 CubitFacet* temp_facet; 00193 00194 for(i=0; i<myFacetList.size(); i++){ 00195 temp_facet=myFacetList.get_and_step(); 00196 if(!temp_facet){ 00197 PRINT_ERROR("Unexpected NULL pointer for facet.\n"); 00198 return CUBIT_FAILURE; 00199 } 00200 temp_facet->flip(); 00201 } 00202 00203 return CUBIT_SUCCESS; 00204 } 00205 00206 CubitStatus FacetEvalTool::reverse_facets( DLIList<CubitFacet *> &facets ) 00207 { 00208 int i; 00209 CubitFacet* temp_facet; 00210 00211 for(i=0; i<facets.size(); i++){ 00212 temp_facet=facets.get_and_step(); 00213 if(!temp_facet){ 00214 PRINT_ERROR("Unexpected NULL pointer for facet.\n"); 00215 return CUBIT_FAILURE; 00216 } 00217 temp_facet->flip(); 00218 } 00219 00220 return CUBIT_SUCCESS; 00221 } 00222 00223 00224 void FacetEvalTool::replace_facets( DLIList<CubitFacet *> &facet_list ) 00225 { 00226 myFacetList.clean_out(); 00227 myEdgeList.clean_out(); 00228 myPointList.clean_out(); 00229 FacetDataUtil::get_points( facet_list, myPointList ); 00230 FacetDataUtil::get_edges( facet_list, myEdgeList ); 00231 myFacetList = facet_list; 00232 for ( int i = myFacetList.size(); i--; ) 00233 myFacetList.step_and_get()->set_tool_id(toolID); 00234 reset_bounding_box(); 00235 } 00236 00237 00238 //=========================================================================== 00239 //Function Name: set_up_grid_search 00240 // 00241 //Member Type: PUBLIC 00242 //Descriptoin: set up grid search if we have a lot of facets 00243 //=========================================================================== 00244 void FacetEvalTool::set_up_grid_search( 00245 double geom_factor ) 00246 { 00247 if(aTree) 00248 delete aTree; 00249 00250 if (myFacetList.size() < GRID_SEARCH_THRESHOLD) 00251 { 00252 aTree = NULL; 00253 } 00254 else 00255 { 00256 aTree = new KDDTree<CubitFacet*> (GEOMETRY_RESABS*geom_factor, false/*self-balancing off*/); 00257 for ( int ii = myFacetList.size(); ii > 0; ii-- ) 00258 { 00259 aTree->add(myFacetList.get_and_step()); 00260 } 00261 aTree->balance(); 00262 } 00263 } 00264 00265 //=========================================================================== 00266 //Function Name: is_flat 00267 // 00268 //Member Type: PUBLIC 00269 //Descriptoin: Determine if the facets are all in the same plane 00270 //=========================================================================== 00271 int FacetEvalTool::is_flat() 00272 { 00273 int ii; 00274 if (isFlat != -999) { 00275 return isFlat; 00276 } 00277 else { 00278 isFlat = CUBIT_TRUE; 00279 CubitVector firstnormal = myFacetList.get_and_step()->normal(); 00280 firstnormal.normalize(); 00281 CubitVector normal; 00282 for ( ii = myFacetList.size(); ii > 1 &&isFlat; ii-- ){ 00283 normal = myFacetList.get_and_step()->normal(); 00284 normal.normalize(); 00285 if (fabs(normal%firstnormal) < 0.9987654321) { 00286 isFlat = CUBIT_FALSE; 00287 } 00288 } 00289 } 00290 return isFlat; 00291 } 00292 00293 //=========================================================================== 00294 //Function Name: init_gradient 00295 // 00296 //Member Type: PRIVATE 00297 //Descriptoin: initialize the gradients for order 1 interpolation 00298 //=========================================================================== 00299 CubitStatus FacetEvalTool::init_gradient() 00300 { 00301 int i,j; 00302 00303 // retrieve all faces attached to the points in point_list 00304 00305 for (i = 0; i < myPointList.size(); i++) 00306 { 00307 CubitPoint* point = myPointList.get_and_step(); 00308 00309 DLIList<CubitFacet*> adj_facet_list; 00310 point->facets(adj_facet_list); 00311 if (adj_facet_list.size() > 0) { 00312 CubitVector avg_normal(0.0e0, 0.0e0, 0.0e0); 00313 double totangle = 0.0e0; 00314 00315 // weight the normal by the spanning angle at the point 00316 00317 for (j = 0; j < adj_facet_list.size(); j++) 00318 { 00319 CubitFacet* facet = adj_facet_list.get_and_step(); 00320 double angle = facet->angle( point ); 00321 facet->weight( angle ); 00322 totangle += angle; 00323 } 00324 for (j = 0; j < adj_facet_list.size(); j++) 00325 { 00326 CubitFacet* facet = adj_facet_list.get_and_step(); 00327 CubitVector normal = facet->normal(); 00328 normal.normalize(); 00329 avg_normal += (facet->weight() / totangle) * normal; 00330 } 00331 avg_normal.normalize(); 00332 point->normal(avg_normal); 00333 double coefd = -(point->coordinates()%avg_normal); 00334 point->d_coef( coefd ); 00335 } 00336 } 00337 return CUBIT_SUCCESS; 00338 } 00339 00340 //=========================================================================== 00341 //Function Name: init_quadrics 00342 // NOTE: I (Roshan) fixed couple of bugs on Aug 02, 2010. See BUGFIX comments below. I didn't test this function; however, I have tested CMLSmoothTool::init_quadric(). 00343 //Member Type: PRIVATE 00344 //Descriptoin: initialize the quadrics at the facet vertices for order 2 00345 // interpolation 00346 //=========================================================================== 00347 CubitStatus FacetEvalTool::init_quadrics() 00348 { 00349 // use the normal at the vertices as a local space with which to do 00350 // interpolation. A quadric will be approximated from the surrounding 00351 // vertices. Interpolation will provide a "z" deviation from the tangent 00352 // plane at the vertex 00353 00354 // define a basis set of vectors at each point (assumes the gradients 00355 // have already been approximated 00356 00357 int i,j; 00358 CubitPoint* point; 00359 for (i = 0; i < myPointList.size(); i++) 00360 { 00361 point = myPointList.get_and_step(); 00362 point->define_tangent_vectors(); 00363 } 00364 00365 // set up for least squares 00366 00367 CubitStatus status; 00368 #define MAX_CLOSE_POINTS 100 00369 CubitPoint *close_points[MAX_CLOSE_POINTS]; 00370 CubitVector coords[MAX_CLOSE_POINTS], cp; 00371 double weight[MAX_CLOSE_POINTS]; 00372 int num_close; 00373 CubitMatrix lhs(5,5); 00374 CubitMatrix rhs(5,1); 00375 CubitMatrix coef(5,1); 00376 for (i = 0; i < myPointList.size(); i++) 00377 { 00378 point = myPointList.get_and_step(); 00379 status = get_close_points( point, close_points, num_close, 00380 MAX_CLOSE_POINTS, 5 ); 00381 if (status != CUBIT_SUCCESS) { 00382 return status; 00383 } 00384 00385 // transform to local system in x-y 00386 // determine weights based on inverse distance 00387 00388 weight[0] = 0.0e0; 00389 double maxdist = -1e100; 00390 double totweight = 0.0e0; 00391 for(j=0; j<num_close; j++) { 00392 cp = close_points[j]->coordinates(); 00393 point->transform_to_local( cp, coords[j] ); 00394 weight[j] = sqrt( FacetEvalToolUtils::sqr(coords[j].x()) + FacetEvalToolUtils::sqr(coords[j].y()) ); 00395 if (weight[j] > maxdist) maxdist = weight[j]; 00396 } 00397 maxdist *= 1.1e0; 00398 for (j=0; j<num_close; j++) { 00399 weight[j] = FacetEvalToolUtils::sqr((maxdist-weight[j])/(maxdist*weight[j])); 00400 totweight += weight[j]; 00401 } 00402 00403 // fill up the matrices 00404 00405 //lhs.set_to_identity(); 00406 //rhs.set_to_identity(); 00407 //coef.set_to_identity(); 00408 00409 double dx, dy, wjdx, wjdy, dx2, dy2, dxdy, dz; 00410 for (j=0; j<num_close; j++) { 00411 weight[j] /= totweight; 00412 weight[j] = 1; // BUGFIX: ignore weights for now and reset weights to 1 00413 dx = /*-*/ coords[j].x(); //BUGFIX: Why we need -ve coords? 00414 dy = /*-*/ coords[j].y(); //BUGFIX: Why we need -ve coords? 00415 wjdx = weight[j] * dx; 00416 wjdy = weight[j] * dy; 00417 dx2 = FacetEvalToolUtils::sqr( dx ); 00418 dy2 = FacetEvalToolUtils::sqr( dy ); 00419 dxdy = dx * dy; 00420 dz = coords[j].z(); 00421 00422 lhs.add( 0, 0, wjdx * dx ); 00423 lhs.add( 0, 1, wjdx * dy ); 00424 lhs.add( 0, 2, wjdx * dx2 ); 00425 lhs.add( 0, 3, wjdx * dxdy ); 00426 lhs.add( 0, 4, wjdx * dy2 ); 00427 rhs.add( 0, 0, wjdx * dz ); // BUGFIX: dz was missing 00428 00429 lhs.add( 1, 1, wjdy * dy ); 00430 lhs.add( 1, 2, wjdy * dx2 ); 00431 lhs.add( 1, 3, wjdy * dxdy ); 00432 lhs.add( 1, 4, wjdy * dx * dy2 ); 00433 rhs.add( 1, 0, wjdy * dz ); // BUGFIX: dz was missing 00434 00435 lhs.add( 2, 2, wjdx * dx2 * dx ); 00436 lhs.add( 2, 3, wjdx * dx2 * dy ); 00437 lhs.add( 2, 4, wjdx * dx * dy2 ); 00438 rhs.add( 2, 0, wjdx * dx * dz );// BUGFIX: dz was missing 00439 00440 lhs.add( 3, 3, wjdx * dx * dy2 ); 00441 lhs.add( 3, 4, wjdx * dy * dy2 ); 00442 rhs.add( 3, 0, wjdx * dy * dz ); // BUGFIX: dz was missing 00443 00444 lhs.add( 4, 4, wjdy * dy * dy2 ); 00445 rhs.add( 4, 0, wjdy * dy * dz ); // BUGFIX: dz was missing 00446 } 00447 lhs.set( 1, 0, lhs.get(0,1) ); 00448 lhs.set( 2, 0, lhs.get(0,2) ); 00449 lhs.set( 2, 1, lhs.get(1,2) ); 00450 lhs.set( 3, 0, lhs.get(0,3) ); 00451 lhs.set( 3, 1, lhs.get(1,3) ); 00452 lhs.set( 3, 2, lhs.get(2,3) ); 00453 lhs.set( 4, 0, lhs.get(0,4) ); 00454 lhs.set( 4, 1, lhs.get(1,4) ); 00455 lhs.set( 4, 2, lhs.get(2,4) ); 00456 lhs.set( 4, 3, lhs.get(3,4) ); 00457 00458 // solve the system 00459 00460 status = lhs.solveNxN( rhs, coef ); 00461 if (status != CUBIT_SUCCESS) { 00462 return status; 00463 } 00464 00465 // store the quadric coefficents with the point 00466 00467 point->coef_vector( coef ); 00468 } 00469 return CUBIT_SUCCESS; 00470 } 00471 00472 //=========================================================================== 00473 //Function Name: get_close_points 00474 // 00475 //Member Type: PRIVATE 00476 //Descriptoin: get a list of points close to the current point on the facets 00477 // return a minimum of min_close and a maximum of max_close points 00478 //=========================================================================== 00479 CubitStatus FacetEvalTool::get_close_points( 00480 CubitPoint *point, 00481 CubitPoint **close_point, 00482 int &num_close, 00483 int max_close, 00484 int min_close ) 00485 { 00486 00487 // get the points immediately adjacent 00488 00489 DLIList<CubitFacet*> adj_facet_list; 00490 point->facets(adj_facet_list); 00491 if (adj_facet_list.size() > max_close) { 00492 return CUBIT_FAILURE; 00493 } 00494 point->adjacent_points(close_point, num_close); 00495 00496 // if we don't have enough yet, then go to the next level 00497 00498 if (num_close < min_close) { 00499 CubitPoint *cpoint[100]; 00500 CubitPoint *cur_point; 00501 CubitBoolean found; 00502 int nclose, cnclose; 00503 nclose = num_close; 00504 for(int i=0; i<num_close; i++) { 00505 cur_point = close_point[i]; 00506 DLIList<CubitFacet*> cadj_facet_list; 00507 cur_point->facets(cadj_facet_list); 00508 if (cadj_facet_list.size() + nclose > max_close) { 00509 return CUBIT_FAILURE; 00510 } 00511 cur_point->adjacent_points(cpoint,cnclose); 00512 for(int k=0; k<cnclose; k++) { 00513 00514 // check that it is not already on the list 00515 00516 found = CUBIT_FALSE; 00517 for(int l=0; l<nclose && !found; l++) { 00518 if (close_point[l] == cpoint[k] || 00519 cpoint[k] == point) { 00520 found = CUBIT_TRUE; 00521 } 00522 } 00523 if (!found) { 00524 00525 // make sure the normal at this point is not more than 90 degrees 00526 // from the normal at the point 00527 00528 double dot = cpoint[k]->normal() % point->normal(); 00529 if (dot > GEOMETRY_RESABS) { 00530 00531 // add the point to the list 00532 00533 close_point[nclose++] = cpoint[k]; 00534 } 00535 } 00536 } 00537 } 00538 num_close = nclose; 00539 if (num_close < min_close) { 00540 return CUBIT_FAILURE; 00541 } 00542 } 00543 return CUBIT_SUCCESS; 00544 } 00545 00546 //=========================================================================== 00547 //Function Name: mark edge pairs 00548 // 00549 //Member Type: PRIVATE 00550 //Descriptoin: For the given point, we loop over the attached boundary 00551 // edges and figure out which pairs should be C1 continuous. 00552 // A given edge is paired with at most two other edges. The 00553 // other edges (or the other edge) is stored on a tool data 00554 // to be used later. 00555 //=========================================================================== 00556 CubitStatus FacetEvalTool::mark_edge_pairs(CubitPoint* point) 00557 { 00558 int i,j; 00559 DLIList<CubitFacetEdge*> edge_list; 00560 DLIList<CubitFacetEdge*> edge_list_init; 00561 CubitPoint* prev_point = NULL; 00562 CubitPoint* next_point = NULL; 00563 CubitFacetEdge* prev_edge = NULL; 00564 CubitFacetEdge* next_edge = NULL; 00565 CubitVector e0, e1; 00566 double current_dot; 00567 point->edges(edge_list_init); 00568 TDFacetBoundaryEdge *td_fbe = NULL; 00569 00570 // make a list with only the boundary edges 00571 for(i=0; i< edge_list_init.size(); i++){ 00572 prev_edge = edge_list_init.get_and_step(); 00573 td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge(prev_edge); 00574 if(td_fbe) 00575 edge_list.append(prev_edge); 00576 } 00577 prev_edge=NULL; 00578 //if there is one or none, we don't need to bother looking 00579 // for pairs. 00580 if(edge_list.size() < 2) 00581 return CUBIT_SUCCESS; 00582 int num_edges=edge_list.size(); 00583 std::vector<int> other_index(num_edges); 00584 std::vector<double> dot_array(num_edges); 00585 bool pair_exists = false; 00586 // loop over the edges. For each edge, find the edge that would 00587 // make the best other edge to pair this one with 00588 for(i = 0; i<num_edges; i++){ 00589 other_index[i]=-1; 00590 dot_array[i]=-1.0; 00591 00592 prev_edge=edge_list[i]; 00593 prev_point = prev_edge->other_point(point); 00594 // now figure out which other edge would be the best pair with 00595 // this one. This could be sped up by only looking at the edges 00596 // i+1 to num_edges, but ever this more exhaustive search is not 00597 // guaranteed to make an optimal pairing... we take the longer 00598 // approach hoping it will give slightly better results for 00599 // hard problems... 00600 for(j = 0; j<num_edges; j++){ 00601 if(j!=i){ 00602 next_edge = edge_list[j]; 00603 next_point = next_edge->other_point(point); 00604 e0 = point->coordinates() - next_point->coordinates(); 00605 e1 = prev_point->coordinates() - point->coordinates(); 00606 e0.normalize(); 00607 e1.normalize(); 00608 current_dot = e0%e1; 00609 //if the current dot satisfies the feature angle criterion 00610 // and is better than any other we've seen so far for this 00611 // given edge, save it. 00612 if(current_dot >= minDot && current_dot > dot_array[i]){ 00613 dot_array[i]=current_dot; 00614 other_index[i]=j; 00615 pair_exists=true;//keep track of whether a pair has been saved 00616 } 00617 } 00618 } 00619 } 00620 //if there aren't any pairs, don't bother moving forward. 00621 if(!pair_exists) 00622 return CUBIT_SUCCESS; 00623 //now find the best pair. That is the pair with biggest 00624 // dot product. Then find the next, and so on until we 00625 // are done. 00626 double best_this_time = CUBIT_DBL_MAX; 00627 int best_index=-1; 00628 // given num_edges > 2 and each edge is paired with at most 00629 // one other edge at this node, there can't be more than 00630 // num_edges - 1 pairs. Actually, num_edges / 2, but 00631 // it is just a safety check anyway, so num_edges-1 will work. 00632 for(i=0;i<num_edges-1 && best_this_time >= minDot; i++){ 00633 best_this_time = -1.0; 00634 best_index = -1; 00635 //loop over and find the biggest dot 00636 for(j=0;j<num_edges; j++){ 00637 if(dot_array[j] > best_this_time){ 00638 best_this_time = dot_array[j]; 00639 best_index = j; 00640 } 00641 } 00642 //if we found a pair that we can make C1 00643 if(best_index >= 0){ 00644 //Don't let the above loop find either of these again 00645 // (unless they are the 'other' in the pair). 00646 dot_array[best_index] = -1.0; 00647 dot_array[other_index[best_index]] = -1.0; 00648 00649 //First, make sure the other in the pair hasn't already 00650 // been used. 00651 CubitFacetEdge* edge_1 = edge_list[best_index]; 00652 CubitFacetEdge* edge_2 = edge_list[other_index[best_index]]; 00653 td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge( edge_2 ); 00654 if(!td_fbe){ 00655 PRINT_ERROR("Expected a tool data.\n"); 00656 return CUBIT_FAILURE; 00657 } 00658 //figure out whether it should be stored as prev or next 00659 if(point == edge_2->point(0)){ 00660 //if something has already been stored here, then 00661 // need to skip this pair 00662 if(td_fbe->get_prev_edge()) 00663 edge_1 = NULL; 00664 else 00665 td_fbe->set_prev_edge(edge_1); 00666 } 00667 else{ 00668 if(td_fbe->get_next_edge()) 00669 edge_1 = NULL; 00670 else 00671 td_fbe->set_next_edge(edge_1); 00672 } 00673 //edge_1 will be NULL if we decided above to skip this pair 00674 if(edge_1){//otherwise save edge_2 in the appropriate spot 00675 // for edge_1's tool data. 00676 td_fbe = TDFacetBoundaryEdge::get_facet_boundary_edge( edge_1 ); 00677 if(!td_fbe){ 00678 PRINT_ERROR("Expected another tool data.\n"); 00679 return CUBIT_FAILURE; 00680 } 00681 00682 if(point == edge_1->point(0)) 00683 td_fbe->set_prev_edge(edge_2); 00684 else 00685 td_fbe->set_next_edge(edge_2); 00686 } 00687 } 00688 00689 } 00690 return CUBIT_SUCCESS; 00691 } 00692 00693 00694 00695 //=========================================================================== 00696 //Function Name: pair_edges 00697 // 00698 //Member Type: PRIVATE 00699 //Descriptoin: Basically, loops over the points and calls 00700 // mark_edge_pairs 00701 //=========================================================================== 00702 CubitStatus FacetEvalTool::pair_edges() 00703 { 00704 CubitStatus status = CUBIT_SUCCESS; 00705 int i; 00706 CubitPoint* point = NULL; 00707 for( i=0;i<myPointList.size(); i++){ 00708 point = myPointList.get_and_step(); 00709 status = mark_edge_pairs(point); 00710 if(status!=CUBIT_SUCCESS) 00711 return status; 00712 } 00713 return status; 00714 } 00715 00716 //=========================================================================== 00717 //Function Name: init_bezier_surface 00718 // 00719 //Member Type: PRIVATE 00720 //Descriptoin: compute the surface control points 00721 //=========================================================================== 00722 CubitStatus FacetEvalTool::init_bezier_surface() 00723 { 00724 // initialize the edges 00725 00726 int i; 00727 CubitStatus status = CUBIT_SUCCESS; 00728 CubitFacetEdge *edge; 00729 // figure out which edges should be paired for C1 continuity. 00730 status = pair_edges(); 00731 if(status!=CUBIT_SUCCESS) 00732 return status; 00733 00734 for (i=0; i<myEdgeList.size() && status == CUBIT_SUCCESS; i++) { 00735 edge = myEdgeList.get_and_step(); 00736 status = init_bezier_edge( edge, minDot ); 00737 if (status != CUBIT_SUCCESS) 00738 return status; 00739 } 00740 int mydebug = 0; 00741 if (mydebug) 00742 { 00743 debug_draw_bezier_edges(); 00744 dview(); 00745 } 00746 00747 // initialize the facets 00748 00749 if (status == CUBIT_SUCCESS) { 00750 CubitFacet *facet; 00751 for (i=0; i<myFacetList.size() && status == CUBIT_SUCCESS; i++) { 00752 facet = myFacetList.get_and_step(); 00753 status = init_bezier_facet( facet ); 00754 } 00755 } 00756 if(status != CUBIT_SUCCESS){ 00757 PRINT_ERROR("Problem initializing bezier facet.\n"); 00758 return status; 00759 } 00760 00761 // reset the bounding box to account for new control points 00762 00763 reset_bounding_box(); 00764 00765 //draw_eval_bezier_facet( myFacetList.get_and_step() ); 00766 // draw_bezier_facet( myFacetList.get_and_step() ); 00767 00768 return status; 00769 } 00770 00771 //=========================================================================== 00772 //Function Name: init_bezier_edge 00773 // 00774 //Member Type: PRIVATE 00775 //Descriptoin: compute the control points for an edge 00776 //=========================================================================== 00777 CubitStatus FacetEvalTool::init_bezier_edge( CubitFacetEdge *edge, 00778 double min_dot ) 00779 { 00780 CubitStatus stat = CUBIT_SUCCESS; 00781 00782 TDFacetBoundaryEdge *td_bfe = 00783 TDFacetBoundaryEdge::get_facet_boundary_edge( edge ); 00784 if (td_bfe) 00785 { 00786 stat = td_bfe->init_control_points( min_dot ); 00787 if (stat != CUBIT_SUCCESS) 00788 return stat; 00789 stat = td_bfe->merge_control_points(); 00790 } 00791 else 00792 { 00793 CubitVector ctrl_pts[3]; 00794 CubitVector P0 = edge->point(0)->coordinates(); 00795 CubitVector P3 = edge->point(1)->coordinates(); 00796 CubitVector N0 = edge->point(0)->normal( edge ); 00797 CubitVector N3 = edge->point(1)->normal( edge ); 00798 CubitVector T0, T3; 00799 if (edge->num_adj_facets() <= 1) 00800 { 00801 stat = compute_curve_tangent( edge, min_dot, T0, T3 ); 00802 if (stat != CUBIT_SUCCESS) 00803 return stat; 00804 } 00805 else 00806 { 00807 T0 = P3 - P0; 00808 T0.normalize(); 00809 T3 = T0; 00810 } 00811 stat = init_edge_control_points( P0, P3, N0, N3, T0, T3, ctrl_pts ); 00812 if (stat != CUBIT_SUCCESS) 00813 return stat; 00814 edge->control_points( ctrl_pts, 4 ); 00815 } 00816 return stat; 00817 } 00818 00819 00820 //=========================================================================== 00821 //Function Name: init_edge_control_points 00822 // 00823 //Member Type: PRIVATE 00824 //Descriptoin: compute the control points for an edge 00825 //=========================================================================== 00826 CubitStatus FacetEvalTool::init_edge_control_points( CubitVector &P0, 00827 CubitVector &P3, 00828 CubitVector &N0, 00829 CubitVector &N3, 00830 CubitVector &T0, 00831 CubitVector &T3, 00832 CubitVector Pi[3] ) 00833 { 00834 CubitVector Vi[4]; 00835 Vi[0] = P0; 00836 Vi[3] = P3; 00837 double di = P0.distance_between( P3 ); 00838 double ai = N0 % N3; 00839 double ai0 = N0 % T0; 00840 double ai3 = N3 % T3; 00841 double denom = 4 - FacetEvalToolUtils::sqr(ai); 00842 if (fabs(denom) < 1e-20) { 00843 return CUBIT_FAILURE; 00844 } 00845 double row = 6.0e0 * (2.0e0 * ai0 + ai * ai3) / denom; 00846 double omega = 6.0e0 * (2.0e0 * ai3 + ai * ai0) / denom; 00847 Vi[1] = Vi[0] + (di * (((6.0e0 * T0) - ((2.0e0 * row) * N0) + (omega * N3)) / 18.0e0)); 00848 Vi[2] = Vi[3] - (di * (((6.0e0 * T3) + (row * N0) - ((2.0e0 * omega) * N3)) / 18.0e0)); 00849 CubitVector Wi[3]; 00850 Wi[0] = Vi[1] - Vi[0]; 00851 Wi[1] = Vi[2] - Vi[1]; 00852 Wi[2] = Vi[3] - Vi[2]; 00853 00854 Pi[0] = 0.25 * Vi[0] + 0.75 * Vi[1]; 00855 Pi[1] = 0.50 * Vi[1] + 0.50 * Vi[2]; 00856 Pi[2] = 0.75 * Vi[2] + 0.25 * Vi[3]; 00857 00858 return CUBIT_SUCCESS; 00859 } 00860 00861 //=========================================================================== 00862 //Function Name: init_edge_control_points_single 00863 // 00864 //Member Type: PRIVATE 00865 //Descriptoin: compute the control points for an edge without normals 00866 //=========================================================================== 00867 CubitStatus FacetEvalTool::init_edge_control_points_single( 00868 CubitVector &P0, 00869 CubitVector &P3, 00870 CubitVector &T0, 00871 CubitVector &T3, 00872 CubitVector Pi[3] ) 00873 { 00874 CubitVector Vi[4]; 00875 Vi[0] = P0; 00876 Vi[3] = P3; 00877 double di = P0.distance_between( P3 ); 00878 double ai = T0 % T3; 00879 double denom = 4 - FacetEvalToolUtils::sqr(ai); 00880 if (fabs(denom) < 1e-20) { 00881 return CUBIT_FAILURE; 00882 } 00883 Vi[1] = Vi[0] + (di * (((6.0e0 * T0)) / 18.0e0)); 00884 Vi[2] = Vi[3] - (di * (((6.0e0 * T3)) / 18.0e0)); 00885 00886 Pi[0] = 0.25 * Vi[0] + 0.75 * Vi[1]; 00887 Pi[1] = 0.50 * Vi[1] + 0.50 * Vi[2]; 00888 Pi[2] = 0.75 * Vi[2] + 0.25 * Vi[3]; 00889 00890 return CUBIT_SUCCESS; 00891 } 00892 00893 //=========================================================================== 00894 //Function Name: init_bezier_facet 00895 // 00896 //Member Type: PRIVATE 00897 //Descriptoin: compute the control points for a facet 00898 //=========================================================================== 00899 CubitStatus FacetEvalTool::init_bezier_facet( CubitFacet *facet ) 00900 { 00901 00902 CubitStatus stat = CUBIT_SUCCESS; 00903 CubitVector P[3][5]; 00904 CubitVector N[6], G[6]; 00905 stat = facet->get_edge_control_points( P ); 00906 if (stat != CUBIT_SUCCESS) 00907 return stat; 00908 00909 // retreive the normals from the edge points. Note we duplicate the 00910 // pointer data here only because of the edge_use 00911 00912 int mydebug = 0; 00913 if (mydebug) 00914 { 00915 dcolor(CUBIT_RED_INDEX); 00916 dfdraw(facet); 00917 dview(); 00918 } 00919 for (int i=0; i<3; i++) { 00920 CubitFacetEdge *edge = facet->edge(i); 00921 if (facet->edge_use(i) == 1) { 00922 N[i*2] = edge->point(0)->normal( facet ); 00923 N[i*2+1] = edge->point(1)->normal( facet ); 00924 } 00925 else { 00926 N[i*2] = edge->point(1)->normal( facet ); 00927 N[i*2+1] = edge->point(0)->normal( facet ); 00928 } 00929 } 00930 00931 // init the facet control points. 00932 00933 stat = init_facet_control_points( N, P, G ); 00934 if (stat != CUBIT_SUCCESS) 00935 return stat; 00936 facet->set_control_points ( G ); 00937 facet->update_bezier_bounding_box(); 00938 return stat; 00939 } 00940 00941 //=========================================================================== 00942 //Function Name: init_facet_control_points 00943 // 00944 //Member Type: PRIVATE 00945 //Descriptoin: compute the control points for a facet 00946 //=========================================================================== 00947 CubitStatus FacetEvalTool::init_facet_control_points( 00948 CubitVector N[6], // vertex normals (per edge) 00949 CubitVector P[3][5], // edge control points 00950 CubitVector G[6] ) // return internal control points 00951 { 00952 CubitVector Di[4], Ai[3], N0, N3, Vi[4], Wi[3]; 00953 double denom; 00954 double lambda[2], mu[2]; 00955 00956 CubitStatus stat = CUBIT_SUCCESS; 00957 00958 for (int i=0; i<3; i++) { 00959 N0 = N[i*2]; 00960 N3 = N[i*2+1]; 00961 Vi[0] = P[i][0]; 00962 Vi[1] = (P[i][1] - 0.25 * P[i][0]) / 0.75; 00963 Vi[2] = (P[i][3] - 0.25 * P[i][4]) / 0.75; 00964 Vi[3] = P[i][4]; 00965 Wi[0] = Vi[1] - Vi[0]; 00966 Wi[1] = Vi[2] - Vi[1]; 00967 Wi[2] = Vi[3] - Vi[2]; 00968 Di[0] = P[(i+2)%3][3] - 0.5*(P[i][1] + P[i][0]); 00969 Di[3] = P[(i+1)%3][1] - 0.5*(P[i][4] + P[i][3]); 00970 if(Wi[0].length() == 0.0) 00971 { 00972 Ai[0] = N0 * Wi[0]; 00973 lambda[0] = Di[0] % Wi[0]; 00974 } 00975 else 00976 { 00977 Ai[0] = (N0 * Wi[0]) / Wi[0].length(); 00978 lambda[0] = (Di[0] % Wi[0]) / (Wi[0] % Wi[0]); 00979 } 00980 00981 if(Wi[2].length() == 0.0) 00982 { 00983 Ai[2] = N3 * Wi[2]; 00984 lambda[1] = Di[3] % Wi[2]; 00985 } 00986 else 00987 { 00988 Ai[2] = (N3 * Wi[2]) / Wi[2].length(); 00989 lambda[1] = (Di[3] % Wi[2]) / (Wi[2] % Wi[2]); 00990 } 00991 Ai[1] = Ai[0] + Ai[2]; 00992 denom = Ai[1].length(); 00993 if (denom > 0) 00994 Ai[1] /= denom; 00995 mu[0] = (Di[0] % Ai[0]); 00996 mu[1] = (Di[3] % Ai[2]); 00997 G[i*2] = 0.5 * (P[i][1] + P[i][2]) + 00998 0.66666666666666 * lambda[0] * Wi[1] + 00999 0.33333333333333 * lambda[1] * Wi[0] + 01000 0.66666666666666 * mu[0] * Ai[1] + 01001 0.33333333333333 * mu[1] * Ai[0]; 01002 G[i*2+1] = 0.5 * (P[i][2] + P[i][3]) + 01003 0.33333333333333 * lambda[0] * Wi[2] + 01004 0.66666666666666 * lambda[1] * Wi[1] + 01005 0.33333333333333 * mu[0] * Ai[2] + 01006 0.66666666666666 * mu[1] * Ai[1]; 01007 } 01008 return stat; 01009 } 01010 01011 //=========================================================================== 01012 //Function Name: eval_bezier_patch 01013 // 01014 //Member Type: PRIVATE 01015 //Descriptoin: evaluate the bezier patch defined at a facet 01016 //=========================================================================== 01017 CubitStatus FacetEvalTool::eval_bezier_patch( CubitFacet *facet, 01018 CubitVector &areacoord, 01019 CubitVector &pt) 01020 { 01021 // interpolate internal control points 01022 01023 CubitVector gctrl_pts[6]; 01024 facet->get_control_points( gctrl_pts ); 01025 CubitVector P_facet[3]; 01026 if (fabs(areacoord.y() + areacoord.z()) < 1.0e-6) { 01027 pt = facet->point(0)->coordinates(); 01028 return CUBIT_SUCCESS; 01029 } 01030 if (fabs(areacoord.x() + areacoord.z()) < 1.0e-6) { 01031 pt = facet->point(1)->coordinates(); 01032 return CUBIT_SUCCESS; 01033 } 01034 if (fabs(areacoord.x() + areacoord.y()) < 1.0e-6) { 01035 pt = facet->point(2)->coordinates(); 01036 return CUBIT_SUCCESS; 01037 } 01038 01039 //2,1,1 01040 P_facet[0] = (1.0e0 / (areacoord.y() + areacoord.z())) * 01041 (areacoord.y() * gctrl_pts[3] + 01042 areacoord.z() * gctrl_pts[4]); 01043 //1,2,1 01044 P_facet[1] = (1.0e0 / (areacoord.x() + areacoord.z())) * 01045 (areacoord.x() * gctrl_pts[0] + 01046 areacoord.z() * gctrl_pts[5]); 01047 //1,1,2 01048 P_facet[2] = (1.0e0 / (areacoord.x() + areacoord.y())) * 01049 (areacoord.x() * gctrl_pts[1] + 01050 areacoord.y() * gctrl_pts[2]); 01051 01052 // sum the contribution from each of the control points 01053 01054 pt.set(0.0e0, 0.0e0, 0.0e0); 01055 CubitFacetEdge *edge; 01056 edge = facet->edge( 2 ); 01057 CubitVector ctrl_pts[5]; 01058 edge->control_points(facet, ctrl_pts); 01059 01060 //i=4; j=0; k=0; 01061 double B = FacetEvalToolUtils::quart(areacoord.x()); 01062 pt += B * ctrl_pts[0]; 01063 01064 //i=3; j=1; k=0; 01065 B = 4.0 * FacetEvalToolUtils::cube(areacoord.x()) * areacoord.y(); 01066 pt += B * ctrl_pts[1]; 01067 01068 //i=2; j=2; k=0; 01069 B = 6.0 * FacetEvalToolUtils::sqr(areacoord.x()) * FacetEvalToolUtils::sqr(areacoord.y()); 01070 pt += B * ctrl_pts[2]; 01071 01072 //i=1; j=3; k=0; 01073 B = 4.0 * areacoord.x() * FacetEvalToolUtils::cube(areacoord.y()); 01074 pt += B * ctrl_pts[3]; 01075 01076 edge = facet->edge( 0 ); 01077 edge->control_points(facet, ctrl_pts); 01078 01079 //i=0; j=4; k=0; 01080 B = FacetEvalToolUtils::quart(areacoord.y()); 01081 pt += B * ctrl_pts[0]; 01082 01083 //i=0; j=3; k=1; 01084 B = 4.0 * FacetEvalToolUtils::cube(areacoord.y()) * areacoord.z(); 01085 pt += B * ctrl_pts[1]; 01086 01087 //i=0; j=2; k=2; 01088 B = 6.0 * FacetEvalToolUtils::sqr(areacoord.y()) * FacetEvalToolUtils::sqr(areacoord.z()); 01089 pt += B * ctrl_pts[2]; 01090 01091 //i=0; j=1; k=3; 01092 B = 4.0 * areacoord.y() * FacetEvalToolUtils::cube(areacoord.z()); 01093 pt += B * ctrl_pts[3]; 01094 01095 edge = facet->edge( 1 ); 01096 edge->control_points(facet, ctrl_pts); 01097 01098 //i=0; j=0; k=4; 01099 B = FacetEvalToolUtils::quart(areacoord.z()); 01100 pt += B * ctrl_pts[0]; 01101 01102 //i=1; j=0; k=3; 01103 B = 4.0 * areacoord.x() * FacetEvalToolUtils::cube(areacoord.z()); 01104 pt += B * ctrl_pts[1]; 01105 01106 //i=2; j=0; k=2; 01107 B = 6.0 * FacetEvalToolUtils::sqr(areacoord.x()) * FacetEvalToolUtils::sqr(areacoord.z()); 01108 pt += B * ctrl_pts[2]; 01109 01110 //i=3; j=0; k=1; 01111 B = 4.0 * FacetEvalToolUtils::cube(areacoord.x()) * areacoord.z(); 01112 pt += B * ctrl_pts[3]; 01113 01114 //i=2; j=1; k=1; 01115 B = 12.0 * FacetEvalToolUtils::sqr(areacoord.x()) * areacoord.y() * areacoord.z(); 01116 pt += B * P_facet[0]; 01117 01118 //i=1; j=2; k=1; 01119 B = 12.0 * areacoord.x() * FacetEvalToolUtils::sqr(areacoord.y()) * areacoord.z(); 01120 pt += B * P_facet[1]; 01121 01122 //i=1; j=1; k=2; 01123 B = 12.0 * areacoord.x() * areacoord.y() * FacetEvalToolUtils::sqr(areacoord.z()); 01124 pt += B * P_facet[2]; 01125 01126 return CUBIT_SUCCESS; 01127 } 01128 01129 //=========================================================================== 01130 //Function Name: eval_bezier_patch_normal 01131 // 01132 //Member Type: PRIVATE 01133 //Descriptoin: evaluate the bezier patch defined at a facet 01134 //=========================================================================== 01135 CubitStatus FacetEvalTool::eval_bezier_patch_normal( CubitFacet *facet, 01136 CubitVector &areacoord, 01137 CubitVector &normal ) 01138 { 01139 // interpolate internal control points 01140 01141 CubitVector gctrl_pts[6]; 01142 facet->get_control_points( gctrl_pts ); 01143 if (fabs(areacoord.y() + areacoord.z()) < 1.0e-6) { 01144 normal = facet->point(0)->normal(facet); 01145 return CUBIT_SUCCESS; 01146 } 01147 if (fabs(areacoord.x() + areacoord.z()) < 1.0e-6) { 01148 normal = facet->point(1)->normal(facet); 01149 return CUBIT_SUCCESS; 01150 } 01151 if (fabs(areacoord.x() + areacoord.y()) < 1.0e-6) { 01152 normal = facet->point(2)->normal(facet); 01153 return CUBIT_SUCCESS; 01154 } 01155 01156 // compute the hodograph of the quartic Gregory patch 01157 01158 CubitVector Nijk[10]; 01159 hodograph(facet,areacoord,Nijk); 01160 01161 // sum the contribution from each of the control points 01162 01163 normal.set(0.0e0, 0.0e0, 0.0e0); 01164 01165 //i=3; j=0; k=0; 01166 double Bsum = 0.0; 01167 double B = FacetEvalToolUtils::cube(areacoord.x()); 01168 Bsum += B; 01169 normal += B * Nijk[0]; 01170 01171 //i=2; j=1; k=0; 01172 B = 3.0 * FacetEvalToolUtils::sqr(areacoord.x()) * areacoord.y(); 01173 Bsum += B; 01174 normal += B * Nijk[1]; 01175 01176 //i=1; j=2; k=0; 01177 B = 3.0 * areacoord.x() * FacetEvalToolUtils::sqr(areacoord.y()); 01178 Bsum += B; 01179 normal += B * Nijk[2]; 01180 01181 //i=0; j=3; k=0; 01182 B = FacetEvalToolUtils::cube(areacoord.y()); 01183 Bsum += B; 01184 normal += B * Nijk[3]; 01185 01186 //i=2; j=0; k=1; 01187 B = 3.0 * FacetEvalToolUtils::sqr(areacoord.x()) * areacoord.z(); 01188 Bsum += B; 01189 normal += B * Nijk[4]; 01190 01191 //i=1; j=1; k=1; 01192 B = 6.0 * areacoord.x() * areacoord.y() * areacoord.z(); 01193 Bsum += B; 01194 normal += B * Nijk[5]; 01195 01196 //i=0; j=2; k=1; 01197 B = 3.0 * FacetEvalToolUtils::sqr(areacoord.y()) * areacoord.z(); 01198 Bsum += B; 01199 normal += B * Nijk[6]; 01200 01201 //i=1; j=0; k=2; 01202 B = 3.0 * areacoord.x() * FacetEvalToolUtils::sqr(areacoord.z()); 01203 Bsum += B; 01204 normal += B * Nijk[7]; 01205 01206 //i=0; j=1; k=2; 01207 B = 3.0 * areacoord.y() * FacetEvalToolUtils::sqr(areacoord.z()); 01208 Bsum += B; 01209 normal += B * Nijk[8]; 01210 01211 //i=0; j=0; k=3; 01212 B = FacetEvalToolUtils::cube(areacoord.z()); 01213 Bsum += B; 01214 normal += B * Nijk[9]; 01215 01216 assert(fabs(Bsum - 1.0) < 1e-9); 01217 01218 normal.normalize(); 01219 01220 return CUBIT_SUCCESS; 01221 } 01222 01223 //=========================================================================== 01224 //Function Name: hodograph 01225 // 01226 //Member Type: PUBLIC 01227 //Description: get the hodograph control points for the facet 01228 //Note: This is a triangle cubic patch that is defined by the 01229 // normals of quartic facet control point lattice. Returned coordinates 01230 // in Nijk are defined by the following diagram 01231 // 01232 // 01233 // *9 index polar 01234 // / \ 0 300 point(0) 01235 // / \ 1 210 01236 // 7*-----*8 2 120 01237 // / \ / \ 3 030 point(1) 01238 // / \ / \ 4 201 01239 // 4*----5*-----*6 5 111 01240 // / \ / \ / \ 6 021 01241 // / \ / \ / \ 7 102 01242 // *-----*-----*-----* 8 012 01243 // 0 1 2 3 9 003 point(2) 01244 // 01245 //=========================================================================== 01246 CubitStatus FacetEvalTool::hodograph( CubitFacet *facet, 01247 CubitVector &areacoord, 01248 CubitVector Nijk[10] ) 01249 { 01250 01251 // compute the control points on the interior of the patch based on areacoord 01252 01253 CubitVector gctrl_pts[6]; 01254 facet->get_control_points( gctrl_pts ); 01255 CubitVector P_facet[3]; 01256 01257 //2,1,1 01258 P_facet[0] = (1.0e0 / (areacoord.y() + areacoord.z())) * 01259 (areacoord.y() * gctrl_pts[3] + 01260 areacoord.z() * gctrl_pts[4]); 01261 //1,2,1 01262 P_facet[1] = (1.0e0 / (areacoord.x() + areacoord.z())) * 01263 (areacoord.x() * gctrl_pts[0] + 01264 areacoord.z() * gctrl_pts[5]); 01265 //1,1,2 01266 P_facet[2] = (1.0e0 / (areacoord.x() + areacoord.y())) * 01267 (areacoord.x() * gctrl_pts[1] + 01268 areacoord.y() * gctrl_pts[2]); 01269 01270 // corner control points are just the normals at the points 01271 01272 //3, 0, 0 01273 Nijk[0] = facet->point(0)->normal(facet); 01274 //0, 3, 0 01275 Nijk[3] = facet->point(1)->normal(facet); 01276 //0, 0, 3 01277 Nijk[9] = facet->point(2)->normal(facet); 01278 01279 // fill in the boundary control points. Define as the normal to the local 01280 // triangle formed by the quartic control point lattice 01281 01282 CubitFacetEdge *edge; 01283 edge = facet->edge( 2 ); 01284 CubitVector ctrl_pts[5]; 01285 edge->control_points(facet, ctrl_pts); 01286 01287 //2, 1, 0 01288 Nijk[1] = (ctrl_pts[2] - ctrl_pts[1]) * (P_facet[0] - ctrl_pts[1]); 01289 Nijk[1].normalize(); 01290 01291 //1, 2, 0 01292 Nijk[2] = (ctrl_pts[3] - ctrl_pts[2]) * (P_facet[1] - ctrl_pts[2]); 01293 Nijk[2].normalize(); 01294 01295 edge = facet->edge( 0 ); 01296 edge->control_points(facet, ctrl_pts); 01297 01298 //0, 2, 1 01299 Nijk[6] = (ctrl_pts[1] - P_facet[1]) * (ctrl_pts[2] - P_facet[1]); 01300 Nijk[6].normalize(); 01301 01302 //0, 1, 2 01303 Nijk[8] = (ctrl_pts[2] - P_facet[2]) * (ctrl_pts[3] - P_facet[2]); 01304 Nijk[8].normalize(); 01305 01306 edge = facet->edge( 1 ); 01307 edge->control_points(facet, ctrl_pts); 01308 01309 //1, 0, 2 01310 Nijk[7] = (P_facet[2] - ctrl_pts[2]) * (ctrl_pts[1] - ctrl_pts[2]); 01311 Nijk[7].normalize(); 01312 01313 //2, 0, 1 01314 Nijk[4] = (P_facet[0] - ctrl_pts[3]) * (ctrl_pts[2] - ctrl_pts[3]); 01315 Nijk[4].normalize(); 01316 01317 //1, 1, 1 01318 Nijk[5] = (P_facet[1] - P_facet[0]) * (P_facet[2] - P_facet[0]); 01319 Nijk[5].normalize(); 01320 01321 int mydebug = 0; 01322 if (mydebug) 01323 { 01324 #define ONE_THIRD 0.33333333333333333333333333333333333 01325 #define TWO_THIRDS .666666666666666666666666666666666666667 01326 int ii; 01327 CubitVector ac, pt; 01328 for(ii=0; ii<10; ii++) 01329 { 01330 switch(ii) 01331 { 01332 case 0: ac.set(1.0, 0.0, 0.0 ); break; 01333 case 1: ac.set(TWO_THIRDS, ONE_THIRD, 0.0 ); break; 01334 case 2: ac.set(ONE_THIRD, TWO_THIRDS, 0.0 ); break; 01335 case 3: ac.set(0.0, 1.0, 0.0 ); break; 01336 case 4: ac.set(TWO_THIRDS, 0.0, ONE_THIRD ); break; 01337 case 5: ac.set(ONE_THIRD, ONE_THIRD, ONE_THIRD ); break; 01338 case 6: ac.set(0.0, TWO_THIRDS, ONE_THIRD ); break; 01339 case 7: ac.set(ONE_THIRD, 0.0, TWO_THIRDS); break; 01340 case 8: ac.set(0.0, ONE_THIRD, TWO_THIRDS); break; 01341 case 9: ac.set(0.0, 0.0, 1.0 ); break; 01342 } 01343 eval_bezier_patch(facet, ac, pt); 01344 dray(pt,Nijk[ii],1.0); 01345 } 01346 dview(); 01347 } 01348 01349 return CUBIT_SUCCESS; 01350 } 01351 01352 01353 //=========================================================================== 01354 //Function Name: project_to_patch 01355 // 01356 //Member Type: PUBLIC 01357 //Descriptoin: Project a point to a bezier patch. Pass in the area 01358 // of the point projected to the linear facet. Function 01359 // assumes that the point is contained within the patch - 01360 // if not, it will project to one of its edges. 01361 //=========================================================================== 01362 CubitStatus FacetEvalTool::project_to_patch( 01363 CubitFacet *facet, // (IN) the facet where the patch is defined 01364 CubitVector &ac, // (IN) area coordinate initial guess (from linear facet) 01365 const CubitVector &pt, // (IN) point we are projecting to patch 01366 CubitVector &eval_pt, // (OUT) The projected point 01367 CubitVector *eval_norm, // (OUT) normal at evaluated point 01368 CubitBoolean &outside, // (OUT) the closest point on patch to pt is on an edge 01369 double compare_tol, // (IN) comparison tolerance 01370 int edge_id ) // (IN) only used if this is to be projected to one 01371 // of the edges. Otherwise, should be -1 01372 { 01373 CubitStatus status = CUBIT_SUCCESS; 01374 01375 // see if we are at a vertex 01376 01377 #define INCR 0.01 01378 const double tol = compare_tol; 01379 01380 if (is_at_vertex( facet, pt, ac, compare_tol, eval_pt, eval_norm )) 01381 { 01382 outside = CUBIT_FALSE; 01383 return CUBIT_SUCCESS; 01384 } 01385 01386 // check if the start ac is inside the patch -if not, then move it there 01387 01388 int nout = 0; 01389 const double atol = 0.001; 01390 if(move_ac_inside( ac, atol )) 01391 nout++; 01392 01393 int diverge = 0; 01394 int iter = 0; 01395 CubitVector newpt; 01396 eval_bezier_patch(facet, ac, newpt); 01397 CubitVector move = pt - newpt; 01398 double lastdist = move.length(); 01399 double bestdist = lastdist; 01400 CubitVector bestac = ac; 01401 CubitVector bestpt = newpt; 01402 CubitVector bestnorm; 01403 01404 // If we are already close enough, then return now 01405 01406 if (lastdist <= tol && !eval_norm && nout == 0) { 01407 eval_pt = pt; 01408 outside = CUBIT_FALSE; 01409 return status; 01410 } 01411 01412 double ratio, mag, umove, vmove, det, distnew, movedist; 01413 CubitVector lastpt = newpt; 01414 CubitVector lastac = ac; 01415 CubitVector norm; 01416 CubitVector xpt, ypt, zpt, xac, yac, zac, xvec, yvec, zvec; 01417 CubitVector du, dv, newac; 01418 CubitBoolean done = CUBIT_FALSE; 01419 while (!done) { 01420 01421 // We will be locating the projected point within the u,v,w coordinate 01422 // system of the triangular bezier patch. Since u+v+w=1, the components 01423 // are not linearly independant. We will choose only two of the 01424 // coordinates to use and compute the third. 01425 01426 int system; 01427 if (lastac.x() >= lastac.y() && lastac.x() >= lastac.z()) { 01428 system = 0; 01429 } 01430 else if (lastac.y() >= lastac.z()) { 01431 system = 1; 01432 } 01433 else { 01434 system = 2; 01435 } 01436 01437 // compute the surface derivatives with respect to each 01438 // of the barycentric coordinates 01439 01440 01441 if (system == 1 || system == 2) { 01442 xac.x( lastac.x() + INCR ); 01443 if (lastac.y() + lastac.z() == 0.0) 01444 return CUBIT_FAILURE; 01445 ratio = lastac.z() / (lastac.y() + lastac.z()); 01446 xac.y( (1.0 - xac.x()) * (1.0 - ratio) ); 01447 xac.z( 1.0 - xac.x() - xac.y() ); 01448 eval_bezier_patch(facet, xac, xpt); 01449 xvec = xpt - lastpt; 01450 xvec /= INCR; 01451 } 01452 if (system == 0 || system == 2) { 01453 yac.y( lastac.y() + INCR ); 01454 if (lastac.x() + lastac.z() == 0.0) 01455 return CUBIT_FAILURE; 01456 ratio = lastac.z() / (lastac.x() + lastac.z()); 01457 yac.x( (1.0 - yac.y()) * (1.0 - ratio) ); 01458 yac.z( 1.0 - yac.x() - yac.y() ); 01459 eval_bezier_patch(facet, yac, ypt); 01460 yvec = ypt - lastpt; 01461 yvec /= INCR; 01462 } 01463 if (system == 0 || system == 1) { 01464 zac.z( lastac.z() + INCR ); 01465 if (lastac.x() + lastac.y() == 0.0) 01466 return CUBIT_FAILURE; 01467 ratio = lastac.y() / (lastac.x() + lastac.y()); 01468 zac.x( (1.0 - zac.z()) * (1.0 - ratio) ); 01469 zac.y( 1.0 - zac.x() - zac.z() ); 01470 eval_bezier_patch(facet, zac, zpt); 01471 zvec = zpt - lastpt; 01472 zvec /= INCR; 01473 } 01474 01475 // compute the surface normal 01476 01477 switch (system) { 01478 case 0: 01479 du = yvec; 01480 dv = zvec; 01481 break; 01482 case 1: 01483 du = zvec; 01484 dv = xvec; 01485 break; 01486 case 2: 01487 du = xvec; 01488 dv = yvec; 01489 break; 01490 } 01491 norm = du * dv; 01492 mag = norm.length(); 01493 if (mag < DBL_EPSILON) { 01494 return CUBIT_FAILURE; 01495 // do something else here (it is likely a flat triangle - 01496 // so try evaluating just an edge of the bezier patch) 01497 } 01498 norm /= mag; 01499 if (iter == 0) 01500 bestnorm = norm; 01501 01502 // project the move vector to the tangent plane 01503 01504 move = (norm * move) * norm; 01505 01506 // compute an equivalent u-v-w vector 01507 01508 CubitVector absnorm( fabs(norm.x()), fabs(norm.y()), fabs(norm.z()) ); 01509 if (absnorm.z() >= absnorm.y() && absnorm.z() >= absnorm.x()) { 01510 det = du.x() * dv.y() - dv.x() * du.y(); 01511 if (fabs(det) <= DBL_EPSILON) { 01512 return CUBIT_FAILURE; // do something else here 01513 } 01514 umove = (move.x() * dv.y() - dv.x() * move.y()) / det; 01515 vmove = (du.x() * move.y() - move.x() * du.y()) / det; 01516 } 01517 else if (absnorm.y() >= absnorm.z() && absnorm.y() >= absnorm.x()) { 01518 det = du.x() * dv.z() - dv.x() * du.z(); 01519 if (fabs(det) <= DBL_EPSILON) { 01520 return CUBIT_FAILURE; 01521 } 01522 umove = (move.x() * dv.z() - dv.x() * move.z()) / det; 01523 vmove = (du.x() * move.z() - move.x() * du.z()) / det; 01524 } 01525 else { 01526 det = du.y() * dv.z() - dv.y() * du.z(); 01527 if (fabs(det) <= DBL_EPSILON) { 01528 return CUBIT_FAILURE; 01529 } 01530 umove = (move.y() * dv.z() - dv.y() * move.z()) / det; 01531 vmove = (du.y() * move.z() - move.y() * du.z()) / det; 01532 } 01533 01534 /* === compute the new u-v coords and evaluate surface at new location */ 01535 01536 switch (system) { 01537 case 0: 01538 newac.y( lastac.y() + umove ); 01539 newac.z( lastac.z() + vmove ); 01540 newac.x( 1.0 - newac.y() - newac.z() ); 01541 break; 01542 case 1: 01543 newac.z( lastac.z() + umove ); 01544 newac.x( lastac.x() + vmove ); 01545 newac.y( 1.0 - newac.z() - newac.x() ); 01546 break; 01547 case 2: 01548 newac.x( lastac.x() + umove ); 01549 newac.y( lastac.y() + vmove ); 01550 newac.z( 1.0 - newac.x() - newac.y() ); 01551 break; 01552 } 01553 01554 // Keep it inside the patch 01555 01556 if ( newac.x() >= -atol && 01557 newac.y() >= -atol && 01558 newac.z() >= -atol) { 01559 nout = 0; 01560 } 01561 else { 01562 if (move_ac_inside( newac, atol ) == CUBIT_TRUE) 01563 nout++; 01564 } 01565 01566 // Evaluate at the new location 01567 01568 if (edge_id != -1) 01569 ac_at_edge( newac, newac, edge_id ); // move to edge first 01570 eval_bezier_patch(facet, newac, newpt); 01571 01572 // Check for convergence 01573 01574 distnew = pt.distance_between(newpt); 01575 move = newpt - lastpt; 01576 movedist = move.length(); 01577 if (movedist < tol || 01578 distnew < tol ) { 01579 done = CUBIT_TRUE; 01580 if (distnew < bestdist) 01581 { 01582 bestdist = distnew; 01583 bestac = newac; 01584 bestpt = newpt; 01585 bestnorm = norm; 01586 } 01587 } 01588 else { 01589 01590 // don't allow more than 30 iterations 01591 01592 iter++; 01593 if (iter > 30) { 01594 //if (movedist > tol * 100.0) nout=1; 01595 done = CUBIT_TRUE; 01596 } 01597 01598 // Check for divergence - don't allow more than 5 divergent 01599 // iterations 01600 01601 if (distnew > lastdist) { 01602 diverge++; 01603 if (diverge > 10) { 01604 done = CUBIT_TRUE; 01605 //if (movedist > tol * 100.0) nout=1; 01606 } 01607 } 01608 01609 // Check if we are continuing to project outside the facet. 01610 // If so, then stop now 01611 01612 if (nout > 3) { 01613 done = CUBIT_TRUE; 01614 } 01615 01616 // set up for next iteration 01617 01618 if (!done) { 01619 if (distnew < bestdist) 01620 { 01621 bestdist = distnew; 01622 bestac = newac; 01623 bestpt = newpt; 01624 bestnorm = norm; 01625 } 01626 lastdist = distnew; 01627 lastpt = newpt; 01628 lastac = newac; 01629 move = pt - lastpt; 01630 } 01631 } 01632 } 01633 01634 eval_pt = bestpt; 01635 if (eval_norm) { 01636 *eval_norm = bestnorm; 01637 } 01638 outside = (nout > 0) ? CUBIT_TRUE : CUBIT_FALSE; 01639 ac = bestac; 01640 01641 return status; 01642 } 01643 01644 //=========================================================================== 01645 //Function Name: is_at_vertex 01646 // 01647 //Member Type: PRIVATE 01648 //Description: determine if the point is at one of the facet's vertices 01649 //=========================================================================== 01650 CubitBoolean FacetEvalTool::is_at_vertex( 01651 CubitFacet *facet, // (IN) facet we are evaluating 01652 const CubitVector &pt, // (IN) the point 01653 CubitVector &ac, // (IN) the ac of the point on the facet plane 01654 double compare_tol, // (IN) return TRUE of closer than this 01655 CubitVector &eval_pt, // (OUT) location at vertex if TRUE 01656 CubitVector *eval_norm_ptr ) // (OUT) normal at vertex if TRUE 01657 { 01658 double dist; 01659 CubitVector vert_loc; 01660 const double actol = 0.1; 01661 if (fabs(ac.x()) < actol && fabs(ac.y()) < actol) { 01662 vert_loc = facet->point(2)->coordinates(); 01663 dist = pt.distance_between( vert_loc ); 01664 if (dist <= compare_tol) 01665 { 01666 eval_pt = vert_loc; 01667 if (eval_norm_ptr) 01668 { 01669 *eval_norm_ptr = facet->point(2)->normal( facet ); 01670 } 01671 return CUBIT_TRUE; 01672 } 01673 } 01674 01675 if (fabs(ac.x()) < actol && fabs(ac.z()) < actol) { 01676 vert_loc = facet->point(1)->coordinates(); 01677 dist = pt.distance_between( vert_loc ); 01678 if (dist <= compare_tol) 01679 { 01680 eval_pt = vert_loc; 01681 if (eval_norm_ptr) 01682 { 01683 *eval_norm_ptr = facet->point(1)->normal( facet ); 01684 } 01685 return CUBIT_TRUE; 01686 } 01687 } 01688 01689 if (fabs(ac.y()) < actol && fabs(ac.z()) < actol) { 01690 vert_loc = facet->point(0)->coordinates(); 01691 dist = pt.distance_between( vert_loc ); 01692 if (dist <= compare_tol) 01693 { 01694 eval_pt = vert_loc; 01695 if (eval_norm_ptr) 01696 { 01697 *eval_norm_ptr = facet->point(0)->normal( facet ); 01698 } 01699 return CUBIT_TRUE; 01700 } 01701 } 01702 01703 return CUBIT_FALSE; 01704 } 01705 01706 //=========================================================================== 01707 //Function Name: ac_at_edge 01708 // 01709 //Member Type: PRIVATE 01710 //Description: determine the area coordinate of the facet at the edge 01711 //=========================================================================== 01712 void FacetEvalTool::ac_at_edge( CubitVector &fac, // facet area coordinate 01713 CubitVector &eac, // edge area coordinate 01714 int edge_id ) // id of edge 01715 { 01716 double u = 0.0, v = 0.0, w = 0.0; 01717 switch (edge_id) 01718 { 01719 case 0: 01720 u = 0.0; 01721 v = fac.y() / (fac.y() + fac.z()); 01722 w = 1.0 - v; 01723 break; 01724 case 1: 01725 u = fac.x() / (fac.x() + fac.z()); 01726 v = 0.0; 01727 w = 1.0 - u; 01728 break; 01729 case 2: 01730 u = fac.x() / (fac.x() + fac.y()); 01731 v = 1.0 - u; 01732 w = 0.0; 01733 break; 01734 default: 01735 assert(0); 01736 break; 01737 } 01738 eac.set(u, v, w); 01739 } 01740 01741 //=========================================================================== 01742 //Function Name: move_ac_inside 01743 // 01744 //Member Type: PRIVATE 01745 //Description: find the closest area coordinate to the boundary of the 01746 // patch if any of its components are < 0 01747 // Return if the ac was modified. 01748 //=========================================================================== 01749 CubitBoolean FacetEvalTool::move_ac_inside( CubitVector &ac, double tol ) 01750 { 01751 int nout = 0; 01752 if (ac.x() < -tol) { 01753 ac.x( 0.0 ); 01754 ac.y( ac.y() / (ac.y() + ac.z()) ); 01755 ac.z( 1.0 - ac.y() ); 01756 nout++; 01757 } 01758 if (ac.y() < -tol) { 01759 ac.y( 0.0 ); 01760 ac.x( ac.x() / (ac.x() + ac.z()) ); 01761 ac.z( 1.0 - ac.x() ); 01762 nout++; 01763 } 01764 if (ac.z() < -tol) { 01765 ac.z( 0.0 ); 01766 ac.x( ac.x() / (ac.x() + ac.y()) ); 01767 ac.y( 1.0 - ac.x() ); 01768 nout++; 01769 } 01770 return (nout > 0) ? CUBIT_TRUE : CUBIT_FALSE; 01771 } 01772 01773 bool FacetEvalTool::have_data_to_calculate_bbox(void) 01774 { 01775 if(myPointList.size() > 0 || 01776 (interpOrder == 4 && 01777 (myEdgeList.size() > 0 || 01778 myFacetList.size() > 0))) 01779 { 01780 return true; 01781 } 01782 return false; 01783 } 01784 01785 //=========================================================================== 01786 //Function Name: reset_bounding_box 01787 // 01788 //Member Type: PUBLIC 01789 //Description: Calculates the bounding box of the surface (also sets 01790 // the compareTol and grid search). 01791 //=========================================================================== 01792 void FacetEvalTool::reset_bounding_box() 01793 { 01794 if(have_data_to_calculate_bbox()) 01795 { 01796 if (myBBox != NULL) 01797 { 01798 delete myBBox; 01799 myBBox = NULL; 01800 } 01801 01802 bounding_box(); 01803 01804 double diag = sqrt(FacetEvalToolUtils::sqr(myBBox->x_range()) + 01805 FacetEvalToolUtils::sqr(myBBox->y_range()) + 01806 FacetEvalToolUtils::sqr(myBBox->z_range())); 01807 compareTol = 1.0e-3 * diag; 01808 01809 set_up_grid_search( diag ); 01810 } 01811 } 01812 01813 01814 //=========================================================================== 01815 //Function Name: bounding_box 01816 // 01817 //Member Type: PUBLIC 01818 //Descriptoin: Calculates the bounding box of the surface. 01819 //=========================================================================== 01820 CubitBox FacetEvalTool::bounding_box() 01821 { 01822 if ( !myBBox ) 01823 { 01824 int ii; 01825 CubitPoint *point_ptr; 01826 double x, y, z; 01827 double x_min = CUBIT_DBL_MAX, x_max = -CUBIT_DBL_MAX; 01828 double y_min = CUBIT_DBL_MAX, y_max = -CUBIT_DBL_MAX; 01829 double z_min = CUBIT_DBL_MAX, z_max = -CUBIT_DBL_MAX; 01830 for ( ii = myPointList.size(); ii > 0; ii-- ) 01831 { 01832 point_ptr = myPointList.get_and_step(); 01833 x = point_ptr->x(); 01834 y = point_ptr->y(); 01835 z = point_ptr->z(); 01836 if ( x < x_min ) 01837 x_min = x; 01838 if ( y < y_min ) 01839 y_min = y; 01840 if ( z < z_min ) 01841 z_min = z; 01842 if ( x > x_max ) 01843 x_max = x; 01844 if ( y > y_max ) 01845 y_max = y; 01846 if ( z > z_max ) 01847 z_max = z; 01848 } 01849 if (interpOrder == 4) 01850 { 01851 CubitFacetEdge *edge_ptr; 01852 CubitVector ctrl_pts[6]; 01853 int jj; 01854 for ( ii = myEdgeList.size(); ii > 0; ii-- ) 01855 { 01856 edge_ptr = myEdgeList.get_and_step(); 01857 edge_ptr->control_points(ctrl_pts); 01858 for (jj=1; jj<4; jj++) 01859 { 01860 x = ctrl_pts[jj].x(); 01861 y = ctrl_pts[jj].y(); 01862 z = ctrl_pts[jj].z(); 01863 if ( x < x_min ) 01864 x_min = x; 01865 if ( y < y_min ) 01866 y_min = y; 01867 if ( z < z_min ) 01868 z_min = z; 01869 if ( x > x_max ) 01870 x_max = x; 01871 if ( y > y_max ) 01872 y_max = y; 01873 if ( z > z_max ) 01874 z_max = z; 01875 } 01876 } 01877 CubitFacet *facet_ptr; 01878 for ( ii = myFacetList.size(); ii > 0; ii-- ) 01879 { 01880 facet_ptr = myFacetList.get_and_step(); 01881 facet_ptr->get_control_points(ctrl_pts); 01882 for (jj=0; jj<6; jj++) 01883 { 01884 x = ctrl_pts[jj].x(); 01885 y = ctrl_pts[jj].y(); 01886 z = ctrl_pts[jj].z(); 01887 if ( x < x_min ) 01888 x_min = x; 01889 if ( y < y_min ) 01890 y_min = y; 01891 if ( z < z_min ) 01892 z_min = z; 01893 if ( x > x_max ) 01894 x_max = x; 01895 if ( y > y_max ) 01896 y_max = y; 01897 if ( z > z_max ) 01898 z_max = z; 01899 } 01900 } 01901 } 01902 CubitVector min_v(x_min, y_min, z_min ); 01903 CubitVector max_v(x_max, y_max, z_max ); 01904 myBBox = new CubitBox( min_v, max_v ); 01905 } 01906 return *(myBBox); 01907 } 01908 01909 //=========================================================================== 01910 //Function Name: closest_point 01911 // 01912 //Member Type: PUBLIC 01913 //Description: Finds the closest point from the vector (this_point) to the 01914 // set of facets that lies on the set of facets. If the point 01915 // lies outside this set, the closest point will be on the plane 01916 // of the closest facet. The closest_point is set to be that point. 01917 //=========================================================================== 01918 CubitStatus FacetEvalTool::closest_point(CubitVector &this_point, 01919 CubitVector *closest_point_ptr, 01920 CubitVector *normal_ptr) 01921 { 01922 CubitBoolean trim = CUBIT_FALSE; 01923 CubitBoolean outside; 01924 CubitStatus rv = CUBIT_SUCCESS; 01925 static int count = 0; count++; 01926 01927 int mydebug = 0; 01928 if (mydebug) 01929 { 01930 debug_draw_vec( this_point, CUBIT_RED_INDEX ); 01931 } 01932 01933 rv = project_to_facets( this_point, trim, &outside, 01934 closest_point_ptr, normal_ptr ); 01935 01936 if (DEBUG_FLAG(49)) 01937 { 01938 if (closest_point_ptr) 01939 { 01940 double dist = closest_point_ptr->distance_between( this_point ); 01941 if (dist > 1.0) 01942 { 01943 PRINT_ERROR("Appears to be bad projection in FacetEvalTool::project_to_facets\n"); 01944 } 01945 } 01946 } 01947 01948 if (mydebug && closest_point_ptr) 01949 { 01950 debug_draw_vec( *closest_point_ptr, CUBIT_GREEN_INDEX ); 01951 } 01952 return rv; 01953 } 01954 01955 01956 CubitFacet* FacetEvalTool::closest_facet( const CubitVector& point ) 01957 { 01958 CubitVector non_const(point); 01959 CubitBoolean junk; 01960 CubitStatus result = project_to_facets( non_const, true, &junk, 0, 0 ); 01961 return result ? lastFacet : 0; 01962 } 01963 01964 //=========================================================================== 01965 //Function Name: facets_from_search_grid 01966 // 01967 //Member Type: PRIVATE 01968 //Description: find the closest facets to the point in the search grid 01969 // by starting with a default tolerance and expanding until facets are found 01970 //=========================================================================== 01971 void FacetEvalTool::facets_from_search_grid( 01972 CubitVector &this_point, 01973 DLIList<CubitFacet *> &facet_list, 01974 double &tol_used) 01975 { 01976 double tol = compareTol * 10; 01977 while (facet_list.size() == 0) 01978 { 01979 CubitVector ptmin( this_point.x() - tol, 01980 this_point.y() - tol, 01981 this_point.z() - tol ); 01982 CubitVector ptmax( this_point.x() + tol, 01983 this_point.y() + tol, 01984 this_point.z() + tol ); 01985 CubitBox ptbox(ptmin,ptmax); 01986 aTree->find(ptbox,facet_list); 01987 01988 if (0 == facet_list.size()) 01989 tol *= 2.0; 01990 } 01991 01992 tol_used = tol; 01993 } 01994 01995 //=========================================================================== 01996 //Function Name: facets_from_search_grid 01997 // 01998 //Member Type: PRIVATE 01999 //Description: find the closest facets to the point in the search grid 02000 // for a given tolerance 02001 //=========================================================================== 02002 void FacetEvalTool::facets_from_search_grid( 02003 CubitVector &this_point, 02004 double compare_tol, 02005 DLIList<CubitFacet *> &facet_list ) 02006 { 02007 double tol = compare_tol; 02008 02009 CubitVector ptmin( this_point.x() - tol, 02010 this_point.y() - tol, 02011 this_point.z() - tol ); 02012 CubitVector ptmax( this_point.x() + tol, 02013 this_point.y() + tol, 02014 this_point.z() + tol ); 02015 CubitBox ptbox(ptmin,ptmax); 02016 aTree->find(ptbox,facet_list); 02017 } 02018 02019 //=========================================================================== 02020 //Function Name: project_to_facets 02021 // 02022 //Member Type: PRIVATE 02023 //Description: Project a point to the facets. Use the interpOrder. 02024 // if trim is set, then trim the point to the boundary. 02025 // This is a non-static version. it uses the facets 02026 // in the evaltool 02027 //=========================================================================== 02028 CubitStatus 02029 FacetEvalTool::project_to_facets(CubitVector &this_point, 02030 CubitBoolean trim, 02031 CubitBoolean *outside, 02032 CubitVector *closest_point_ptr, 02033 CubitVector *normal_ptr) 02034 { 02035 CpuTimer function_time; 02036 if (DEBUG_FLAG(110)) 02037 { 02038 function_time.cpu_secs(); 02039 numEvals++; 02040 } 02041 02042 CubitStatus rv = CUBIT_SUCCESS; 02043 02044 // if there are a lot of facets on this surface - use the grid search first 02045 // to narrow the selection 02046 02047 if (aTree != NULL) 02048 { 02049 DLIList<CubitFacet *> facet_list; 02050 double search_tol = DBL_MAX; 02051 facets_from_search_grid( this_point, facet_list, search_tol ); 02052 if ( DEBUG_FLAG(110) ) 02053 timeGridSearch += function_time.cpu_secs(); 02054 02055 if (facet_list.size()) 02056 { 02057 CubitVector grid_close_pt; 02058 rv = project_to_facets(facet_list,lastFacet,interpOrder,compareTol, 02059 this_point,trim,outside, &grid_close_pt, 02060 normal_ptr); 02061 02062 if (CUBIT_SUCCESS == rv) 02063 { 02064 if (closest_point_ptr) 02065 { 02066 *closest_point_ptr = grid_close_pt; 02067 } 02068 02069 // when we do the projection, if we end up with the closest point being farther 02070 // away than the grid search tolerance, we may have missed a closer facet 02071 // so redo the grid search using the distance as a tolerance 02072 double distance = grid_close_pt.distance_between( this_point ); 02073 if (distance > search_tol) 02074 { 02075 DLIList<CubitFacet*> facets_within_distance; 02076 CubitVector grid_close_pt2; 02077 facets_from_search_grid(this_point, distance, facets_within_distance); 02078 if (facets_within_distance.size() && 02079 (facets_within_distance != facet_list) ) 02080 { 02081 rv = project_to_facets(facets_within_distance, lastFacet, interpOrder, compareTol, 02082 this_point, trim, outside, &grid_close_pt2, 02083 normal_ptr); 02084 if (CUBIT_SUCCESS == rv) 02085 { 02086 double distance2 = grid_close_pt2.distance_between( this_point ); 02087 if (distance2 < distance) 02088 { 02089 if (closest_point_ptr) 02090 { 02091 *closest_point_ptr = grid_close_pt2; 02092 } 02093 } 02094 } 02095 } 02096 } 02097 } 02098 02099 if ( DEBUG_FLAG(110) ) 02100 { 02101 timeFacetProject += function_time.cpu_secs(); 02102 if (closest_point_ptr) 02103 { 02104 double dist = closest_point_ptr->distance_between( this_point ); 02105 if (dist > compareTol * 100) 02106 { 02107 PRINT_ERROR("Appears to be bad projection in FacetEvalTool::project_to_facets\n"); 02108 dcolor(CUBIT_GREEN_INDEX); 02109 dpoint(this_point); 02110 dcolor(CUBIT_RED_INDEX); 02111 dpoint(*closest_point_ptr); 02112 dcolor(CUBIT_YELLOW_INDEX); 02113 dfldraw(facet_list); 02114 dview(); 02115 rv = CUBIT_FAILURE; 02116 } 02117 } 02118 } 02119 } 02120 } 02121 02122 // otherwise just use the complete list of facets 02123 02124 else 02125 { 02126 rv = project_to_facets(myFacetList,lastFacet,interpOrder,compareTol, 02127 this_point,trim,outside,closest_point_ptr, 02128 normal_ptr); 02129 if ( DEBUG_FLAG(110) ) 02130 timeFacetProject += function_time.cpu_secs(); 02131 } 02132 02133 return rv; 02134 } 02135 02136 //=========================================================================== 02137 //Function Name: project_to_facets 02138 // 02139 //Member Type: PRIVATE 02140 //Description: Project a point to the facets. Use the interpOrder. 02141 // if trim is set, then trim the point to the boundary. 02142 // This is a static version of the above. Any list of facets 02143 // can be passed to this function 02144 //=========================================================================== 02145 CubitStatus 02146 FacetEvalTool::project_to_facets( 02147 DLIList <CubitFacet *> &facet_list, // (IN) facets that we can project to 02148 CubitFacet *&last_facet, // (IN/OUT) last facet projected to - 02149 // it will try this one first 02150 int interp_order, // (IN) 0 = linear facets, 02151 // 4 = b-spline patches 02152 double compare_tol, // (IN) tolerance for projection - 02153 // should be about 1e-3*edge 02154 const CubitVector &this_point, // (IN) point we are projecting 02155 CubitBoolean trim, // (IN) trim to facet (always trimmed 02156 // if b-spline patch) 02157 CubitBoolean *outside, // (OUT) TRUE if projected outside 02158 // the facet 02159 CubitVector *closest_point_ptr, // (OUT) resulting projection point 02160 // (NULL if only want normal) 02161 CubitVector *normal_ptr) // (OUT) resulting normal at projected 02162 // point (NULL if not required) 02163 { 02164 int ncheck, ii, nincr=0; 02165 static int calls=0; 02166 static int nncheck=0; 02167 static int ntol=0; 02168 static int mydebug=0; 02169 CubitBoolean outside_facet, best_outside_facet; 02170 CubitVector close_point, best_point, best_areacoord; 02171 CubitFacet *best_facet = NULL; 02172 CubitFacet *facet; 02173 assert (facet_list.size() > 0); 02174 double big_dist = compare_tol * 1.0e3; 02175 02176 // set the first facet to be checked as the last one located 02177 02178 if (last_facet) { 02179 if (!facet_list.move_to(last_facet)) { 02180 facet_list.reset(); 02181 } 02182 } 02183 else { 02184 facet_list.reset(); 02185 } 02186 02187 // so we don't evaluate a facet more than once - mark the facets 02188 // as we evaluate them. Put the evaluated facets on a used_facet_list 02189 // so we clear the marks off when we are done. Note: this assumes 02190 // theat marks are initially cleared. 02191 02192 DLIList<CubitFacet *>used_facet_list; 02193 for(ii=0; ii<facet_list.size(); ii++) 02194 facet_list.get_and_step()->marked(0); 02195 02196 int nfacets = facet_list.size(); 02197 int nevald = 0; 02198 double tol = compare_tol * 10; 02199 const double atol = 0.001; 02200 double mindist = CUBIT_DBL_MAX; 02201 CubitBoolean eval_all = CUBIT_FALSE; 02202 CubitBoolean done = CUBIT_FALSE; 02203 best_outside_facet = CUBIT_TRUE; 02204 02205 while(!done) { 02206 02207 // define a bounding box around the point 02208 02209 double ptmin_x = this_point.x() - tol; 02210 double ptmin_y = this_point.y() - tol; 02211 double ptmin_z = this_point.z() - tol; 02212 double ptmax_x = this_point.x() + tol; 02213 double ptmax_y = this_point.y() + tol; 02214 double ptmax_z = this_point.z() + tol; 02215 02216 bool debug = false; 02217 02218 if( debug ) 02219 { 02220 GfxDebug::clear(); 02221 for( int i=used_facet_list.size(); i--; ) 02222 used_facet_list.get_and_step()->debug_draw(CUBIT_GREEN_INDEX, 0 ); 02223 } 02224 02225 ncheck = 0; 02226 for ( ii = facet_list.size(); ii > 0 && !done; ii-- ) 02227 { 02228 facet = facet_list.get_and_step(); 02229 if (facet->marked()) 02230 continue; 02231 02232 // Try to trivially reject this facet with a bounding box test 02233 // (Does the bounding box of the facet intersect with the 02234 // bounding box of the point) 02235 02236 if( debug ) 02237 { 02238 facet->debug_draw( CUBIT_RED_INDEX ); 02239 GfxDebug::flush(); 02240 GfxDebug::mouse_xforms(); 02241 } 02242 02243 02244 if (!eval_all) 02245 { 02246 const CubitBox &bbox = facet->bounding_box(); 02247 if (ptmax_x < bbox.min_x() || 02248 ptmin_x > bbox.max_x()) { 02249 continue; 02250 } 02251 if (ptmax_y < bbox.min_y() || 02252 ptmin_y > bbox.max_y()) { 02253 continue; 02254 } 02255 if (ptmax_z < bbox.min_z() || 02256 ptmin_z > bbox.max_z()) { 02257 continue; 02258 } 02259 } 02260 02261 // skip zero area facets 02262 if(facet->area() <= 0.0) 02263 { 02264 facet->marked(1); 02265 nfacets--; 02266 continue; 02267 } 02268 02269 // Only facets that pass the bounding box test will get past here! 02270 02271 // Project point to plane of the facet and determine its area coordinates 02272 02273 ncheck++; nevald++; 02274 CubitVector pt_on_plane; 02275 double dist_to_plane; 02276 project_to_facet_plane( facet, this_point, pt_on_plane, dist_to_plane ); 02277 02278 CubitVector areacoord; 02279 facet_area_coordinate( facet, pt_on_plane, areacoord ); 02280 if (interp_order != 0) 02281 { 02282 02283 // modify the areacoord - project to the bezier patch- snaps to the 02284 // edge of the patch if necessary 02285 02286 if (project_to_facet( facet, this_point, areacoord, 02287 close_point, outside_facet, compare_tol ) != CUBIT_SUCCESS) 02288 { 02289 return CUBIT_FAILURE; 02290 } 02291 } 02292 else 02293 { 02294 02295 // If sign of areacoords are all positive then its inside the triangle 02296 // and we are done - go interpolate the point. (use an absolute 02297 // tolerance since the coordinates arenormalized) 02298 if (areacoord.x() > -atol && 02299 areacoord.y() > -atol && 02300 areacoord.z() > -atol) { 02301 if (dist_to_plane < compare_tol && !trim) 02302 { 02303 close_point = this_point; 02304 } 02305 else 02306 { 02307 close_point = pt_on_plane; 02308 } 02309 outside_facet = CUBIT_FALSE; 02310 } 02311 02312 // otherwise find the closest vertex or edge to the projected point 02313 02314 else if (areacoord.x() < atol) 02315 { 02316 outside_facet = CUBIT_TRUE; 02317 if (areacoord.y() < atol) 02318 { 02319 if (eval_point( facet, 2, close_point ) != CUBIT_SUCCESS) 02320 { 02321 return CUBIT_FAILURE; 02322 } 02323 } 02324 else if(areacoord.z() < atol) 02325 { 02326 if (eval_point( facet, 1, close_point ) != CUBIT_SUCCESS) 02327 { 02328 return CUBIT_FAILURE; 02329 } 02330 } 02331 else 02332 { 02333 if(project_to_facetedge( facet, 1, 2, this_point, pt_on_plane, 02334 close_point, outside_facet, trim ) !=CUBIT_SUCCESS) 02335 { 02336 return CUBIT_FAILURE; 02337 } 02338 } 02339 } 02340 else if (areacoord.y() < atol) 02341 { 02342 outside_facet = CUBIT_TRUE; 02343 if (areacoord.z() < atol) 02344 { 02345 if (eval_point( facet, 0, close_point )!= CUBIT_SUCCESS) 02346 { 02347 return CUBIT_FAILURE; 02348 } 02349 } 02350 else 02351 { 02352 if(project_to_facetedge( facet, 2, 0, this_point, pt_on_plane, 02353 close_point, outside_facet, trim ) !=CUBIT_SUCCESS) 02354 { 02355 return CUBIT_FAILURE; 02356 } 02357 } 02358 } 02359 else 02360 { 02361 outside_facet = CUBIT_TRUE; 02362 if(project_to_facetedge( facet, 0, 1, this_point, pt_on_plane, 02363 close_point, outside_facet, trim ) !=CUBIT_SUCCESS) 02364 { 02365 return CUBIT_FAILURE; 02366 } 02367 } 02368 } 02369 02370 // keep track of the minimum distance 02371 double dist = close_point.distance_between( this_point ); 02372 02373 if( trim ) 02374 { 02375 if( dist < mindist ) 02376 { 02377 mindist = dist; 02378 best_point = close_point; 02379 best_facet = facet; 02380 best_areacoord = areacoord; 02381 best_outside_facet = outside_facet; 02382 } 02383 } 02384 else if ( (best_outside_facet == outside_facet && dist < mindist) || 02385 (best_outside_facet && !outside_facet && (dist < big_dist || !best_facet)) ) 02386 { 02387 mindist = dist; 02388 best_point = close_point; 02389 best_facet = facet; 02390 best_areacoord = areacoord; 02391 best_outside_facet = outside_facet; 02392 02393 if (dist < compare_tol && !trim) { 02394 done = CUBIT_TRUE; 02395 } 02396 big_dist = 10.0 * mindist; 02397 } 02398 facet->marked(1); 02399 used_facet_list.append(facet); 02400 } 02401 02402 // We are done if we found at least one triangle. Otherwise 02403 // increase the tolerance and try again 02404 02405 if (!done) 02406 { 02407 if (nevald == nfacets) 02408 { 02409 done = CUBIT_TRUE; 02410 } 02411 else 02412 { 02413 nincr++; 02414 if (ncheck > 0) { 02415 if (best_outside_facet) { 02416 if (nincr < 10) 02417 { 02418 tol *= 2.0; 02419 ntol++; 02420 } 02421 else 02422 // getting here means that the compare_tol probably is too small 02423 // just try all the remaining facets 02424 { 02425 eval_all = CUBIT_TRUE; 02426 } 02427 } 02428 else 02429 { 02430 done = CUBIT_TRUE; 02431 } 02432 } 02433 else { 02434 if (nincr >= 10) 02435 { 02436 eval_all = CUBIT_TRUE; 02437 } 02438 else 02439 { 02440 tol *= 2.0e0; 02441 ntol++; 02442 } 02443 } 02444 } 02445 } 02446 } // while(!done) 02447 if(best_facet == NULL){ 02448 PRINT_ERROR("Unable to determine facet correctly.\n"); 02449 return CUBIT_FAILURE; 02450 } 02451 // make sure we actually got something 02452 assert(best_facet != NULL); 02453 02454 // if the closest point is outside of a facet, then evaluate the point 02455 // on the facet using its area coordinates (otherwise it would be 02456 // trimmed to an edge or point) 02457 02458 02459 if ( !trim && best_outside_facet && interp_order != 4) { 02460 if (project_to_facet( best_facet, this_point, best_areacoord, 02461 best_point, best_outside_facet, compare_tol ) 02462 != CUBIT_SUCCESS) { 02463 return CUBIT_FAILURE; 02464 } 02465 02466 // see if its really outside (it could just be on an edge where the 02467 // curvature is convex) 02468 02469 best_outside_facet = is_outside( best_facet, best_areacoord ); 02470 } 02471 02472 // evaluate the normal if required 02473 02474 if (normal_ptr) { 02475 CubitVector normal; 02476 if (eval_facet_normal( best_facet, best_areacoord, normal ) 02477 != CUBIT_SUCCESS) { 02478 return CUBIT_FAILURE; 02479 } 02480 *normal_ptr = normal; 02481 } 02482 02483 if (closest_point_ptr) { 02484 *closest_point_ptr = best_point; 02485 } 02486 02487 *outside = best_outside_facet; 02488 last_facet = best_facet; 02489 02490 02491 // clear the marks from the used facets 02492 02493 for (ii=0; ii<used_facet_list.size(); ii++) 02494 { 02495 facet = used_facet_list.get_and_step(); 02496 facet->marked( 0 ); 02497 } 02498 02499 if (mydebug) { 02500 nncheck+= ncheck; 02501 calls++; 02502 if (calls%100==0){ 02503 PRINT_INFO("calls = %d, ckecks = %d, ntol = %d\n",calls,nncheck,ntol); 02504 } 02505 } 02506 02507 return CUBIT_SUCCESS; 02508 } 02509 02510 02511 //=========================================================================== 02512 //Function Name: eval_facet 02513 // 02514 //Member Type: PUBLIC 02515 //Descriptoin: Evaluate the location and normal of a set of area coordinates 02516 // on a facet. Use the interpOrder to evaluate. 02517 // Static function 02518 //=========================================================================== 02519 CubitStatus FacetEvalTool::eval_facet( CubitFacet *facet, 02520 CubitVector &areacoord, 02521 CubitVector *eval_point, 02522 CubitVector *eval_normal ) 02523 { 02524 CubitStatus rv = CUBIT_SUCCESS; 02525 int mydebug = 0; 02526 if (mydebug) 02527 { 02528 dcolor( CUBIT_RED_INDEX ); 02529 dfdraw( facet ); 02530 dview(); 02531 dcolor( CUBIT_YELLOW_INDEX ); 02532 } 02533 02534 CubitPoint *pt0 = facet->point(0); 02535 CubitPoint *pt1 = facet->point(1); 02536 CubitPoint *pt2 = facet->point(2); 02537 CubitVector close_point; 02538 02539 CubitVector this_point; 02540 this_point.x( areacoord.x() * pt0->x() + 02541 areacoord.y() * pt1->x() + 02542 areacoord.z() * pt2->x() ); 02543 this_point.y( areacoord.x() * pt0->y() + 02544 areacoord.y() * pt1->y() + 02545 areacoord.z() * pt2->y() ); 02546 this_point.z( areacoord.x() * pt0->z() + 02547 areacoord.y() * pt1->z() + 02548 areacoord.z() * pt2->z() ); 02549 02550 int eval_order = facet->eval_order(); 02551 if (eval_order != 0) 02552 { 02553 if (facet->is_flat()) 02554 eval_order = 0; 02555 } 02556 02557 switch(eval_order) { 02558 case 0: 02559 if (eval_point) 02560 *eval_point = this_point; 02561 if (eval_normal) 02562 eval_facet_normal(facet, areacoord, *eval_normal); 02563 break; 02564 02565 case 4: 02566 eval_bezier_patch( facet, 02567 areacoord, 02568 close_point ); 02569 //project_to_patch(facet, areacoord, this_point, close_point, 02570 // eval_normal, outside ); 02571 02572 //for now over-ride the normal from project_to_patch -- it is bogus 02573 if (eval_normal) 02574 eval_facet_normal(facet, areacoord, *eval_normal); 02575 if (eval_point) 02576 *eval_point = close_point; 02577 02578 break; 02579 default: 02580 // the interpolation order for now is limited to 0 and 4 02581 // something other than that is being attempted (or eval_order is not 02582 // returning the correct value) 02583 assert(0); 02584 break; 02585 } 02586 02587 return rv; 02588 } 02589 02590 //=========================================================================== 02591 //Function Name: eval_facet 02592 // 02593 //Member Type: PUBLIC 02594 //Descriptoin: Evaluate the location of a set of area coordinates 02595 // on a facet. Use the interpOrder to evaluate. 02596 //=========================================================================== 02597 CubitStatus FacetEvalTool::eval_facet( CubitFacet *facet, 02598 CubitVector &pt, 02599 CubitVector &areacoord, 02600 CubitVector &close_point, 02601 CubitBoolean &outside_facet ) 02602 { 02603 02604 CubitPoint *pt0 = facet->point(0); 02605 CubitPoint *pt1 = facet->point(1); 02606 CubitPoint *pt2 = facet->point(2); 02607 02608 int interp_order = facet->eval_order(); 02609 if (interp_order != 0 && facet->is_flat()) 02610 { 02611 interp_order = 0; 02612 } 02613 02614 switch(interp_order) { 02615 case 0: 02616 close_point.x( areacoord.x() * pt0->x() + 02617 areacoord.y() * pt1->x() + 02618 areacoord.z() * pt2->x() ); 02619 close_point.y( areacoord.x() * pt0->y() + 02620 areacoord.y() * pt1->y() + 02621 areacoord.z() * pt2->y() ); 02622 close_point.z( areacoord.x() * pt0->z() + 02623 areacoord.y() * pt1->z() + 02624 areacoord.z() * pt2->z() ); 02625 outside_facet = CUBIT_FALSE; 02626 break; 02627 case 1: 02628 { 02629 CubitVector tp0 = pt0->project_to_tangent_plane( pt ); 02630 CubitVector tp1 = pt1->project_to_tangent_plane( pt ); 02631 CubitVector tp2 = pt2->project_to_tangent_plane( pt ); 02632 close_point.x( areacoord.x() * tp0.x() + 02633 areacoord.y() * tp1.x() + 02634 areacoord.z() * tp2.x() ); 02635 close_point.y( areacoord.x() * tp0.y() + 02636 areacoord.y() * tp1.y() + 02637 areacoord.z() * tp2.y() ); 02638 close_point.z( areacoord.x() * tp0.z() + 02639 areacoord.y() * tp1.z() + 02640 areacoord.z() * tp2.z() ); 02641 outside_facet = CUBIT_FALSE; 02642 } 02643 break; 02644 case 2: 02645 { 02646 CubitVector qp0, qp1, qp2, qn0, qn1, qn2; 02647 eval_quadratic( facet, 0, pt, qp0, qn0 ); 02648 eval_quadratic( facet, 1, pt, qp1, qn1 ); 02649 eval_quadratic( facet, 2, pt, qp2, qn2 ); 02650 02651 close_point.x( areacoord.x() * qp0.x() + 02652 areacoord.y() * qp1.x() + 02653 areacoord.z() * qp2.x() ); 02654 close_point.y( areacoord.x() * qp0.y() + 02655 areacoord.y() * qp1.y() + 02656 areacoord.z() * qp2.y() ); 02657 close_point.z( areacoord.x() * qp0.z() + 02658 areacoord.y() * qp1.z() + 02659 areacoord.z() * qp2.z() ); 02660 outside_facet = CUBIT_FALSE; 02661 } 02662 break; 02663 case 3: 02664 { 02665 CubitVector qp0, qp1, qp2; 02666 eval_quadric( facet, 0, pt, qp0 ); 02667 eval_quadric( facet, 1, pt, qp1 ); 02668 eval_quadric( facet, 2, pt, qp2 ); 02669 02670 close_point.x( areacoord.x() * qp0.x() + 02671 areacoord.y() * qp1.x() + 02672 areacoord.z() * qp2.x() ); 02673 close_point.y( areacoord.x() * qp0.y() + 02674 areacoord.y() * qp1.y() + 02675 areacoord.z() * qp2.y() ); 02676 close_point.z( areacoord.x() * qp0.z() + 02677 areacoord.y() * qp1.z() + 02678 areacoord.z() * qp2.z() ); 02679 outside_facet = CUBIT_FALSE; 02680 } 02681 break; 02682 case 4: 02683 { 02684 //CubitStatus stat = eval_bezier_patch( facet, areacoord, pt ); 02685 //close_point = pt; 02686 //outside_facet = CUBIT_FALSE; 02687 double compare_tol = /*sqrt(facet->area()) **/ 1.0e-3; 02688 int edge_id = -1; 02689 project_to_patch(facet, areacoord, pt, close_point, NULL, 02690 outside_facet, compare_tol, edge_id ); 02691 } 02692 break; 02693 } 02694 02695 return CUBIT_SUCCESS; 02696 } 02697 02698 //=========================================================================== 02699 //Function Name: project_to_facet 02700 // 02701 //Member Type: PUBLIC 02702 //Description: project to a single facet. Uses the input areacoord as 02703 // a starting guess. 02704 //=========================================================================== 02705 CubitStatus FacetEvalTool::project_to_facet( CubitFacet *facet, 02706 const CubitVector &pt, 02707 CubitVector &areacoord, 02708 CubitVector &close_point, 02709 CubitBoolean &outside_facet, 02710 double compare_tol) 02711 { 02712 02713 CubitStatus stat = CUBIT_SUCCESS; 02714 CubitPoint *pt0 = facet->point(0); 02715 CubitPoint *pt1 = facet->point(1); 02716 CubitPoint *pt2 = facet->point(2); 02717 02718 int interp_order = facet->eval_order(); 02719 if (facet->is_flat()) 02720 { 02721 interp_order = 0; 02722 } 02723 02724 switch(interp_order) { 02725 case 0: 02726 close_point.x( areacoord.x() * pt0->x() + 02727 areacoord.y() * pt1->x() + 02728 areacoord.z() * pt2->x() ); 02729 close_point.y( areacoord.x() * pt0->y() + 02730 areacoord.y() * pt1->y() + 02731 areacoord.z() * pt2->y() ); 02732 close_point.z( areacoord.x() * pt0->z() + 02733 areacoord.y() * pt1->z() + 02734 areacoord.z() * pt2->z() ); 02735 outside_facet = CUBIT_FALSE; 02736 break; 02737 case 1: 02738 case 2: 02739 case 3: 02740 assert(0); // not available from this function 02741 break; 02742 case 4: 02743 { 02744 int edge_id = -1; 02745 stat = project_to_patch(facet, areacoord, pt, close_point, NULL, 02746 outside_facet, compare_tol, edge_id ); 02747 } 02748 break; 02749 } 02750 02751 return stat; 02752 } 02753 02754 //=========================================================================== 02755 //Function Name: project_to_facetedge 02756 // 02757 //Member Type: PUBLIC 02758 //Description: Project a point to the facet edge. 02759 // Use the interpOrder to evaluate. 02760 //=========================================================================== 02761 CubitStatus FacetEvalTool::project_to_facetedge( CubitFacet *facet, 02762 int vert0, int vert1, 02763 const CubitVector &the_point, 02764 CubitVector &pt_on_plane, 02765 CubitVector &close_point, 02766 CubitBoolean &outside_facet, 02767 CubitBoolean must_be_on_edge) 02768 { 02769 CubitPoint *pt0 = facet->point(vert0); 02770 CubitPoint *pt1 = facet->point(vert1); 02771 02772 // the edge vector 02773 02774 CubitVector e0 ( pt1->x() - pt0->x(), 02775 pt1->y() - pt0->y(), 02776 pt1->z() - pt0->z() ); 02777 e0.normalize(); 02778 02779 // vector from vert0 to point 02780 02781 CubitVector v0 ( pt_on_plane.x() - pt0->x(), 02782 pt_on_plane.y() - pt0->y(), 02783 pt_on_plane.z() - pt0->z() ); 02784 02785 CubitVector v1 ( pt_on_plane.x() - pt1->x(), 02786 pt_on_plane.y() - pt1->y(), 02787 pt_on_plane.z() - pt1->z() ); 02788 02789 // project to edge 02790 02791 double projection1 = v0%e0; 02792 double projection2 = v1%(-e0); 02793 02794 if( !must_be_on_edge || (projection1 > 0 && projection2 > 0 )) 02795 { 02796 close_point.x ( pt0->x() + e0.x() * projection1 ); 02797 close_point.y ( pt0->y() + e0.y() * projection1 ); 02798 close_point.z ( pt0->z() + e0.z() * projection1 ); 02799 } 02800 else //we are closer to one a facet vertex than to the edge 02801 { 02802 if( the_point.distance_between( pt0->coordinates() ) 02803 < the_point.distance_between( pt1->coordinates())) 02804 close_point = pt0->coordinates(); 02805 else 02806 close_point = pt1->coordinates(); 02807 } 02808 02809 // project the point on the facet (if the order is higher than 0) 02810 02811 outside_facet = CUBIT_TRUE; 02812 if (facet->eval_order() > 0 && !facet->is_flat()) { 02813 CubitVector areacoord; 02814 facet_area_coordinate( facet, close_point, areacoord ); 02815 int edge_id = -1; 02816 if ((vert0 == 0 && vert1 == 1) || 02817 (vert0 == 1 && vert1 == 0)) 02818 { 02819 edge_id = 2; 02820 } 02821 else if ((vert0 == 1 && vert1 == 2) || 02822 (vert0 == 2 && vert1 == 1)) 02823 { 02824 edge_id = 0; 02825 } 02826 else if ((vert0 == 2 && vert1 == 0) || 02827 (vert0 == 0 && vert1 == 2)) 02828 { 02829 edge_id = 1; 02830 } 02831 else 02832 { 02833 assert(0); //edge_id wasn't set 02834 } 02835 02836 double compare_tol = projection1 * 1.0e-3; 02837 if (project_to_patch( facet, areacoord, the_point, close_point, 02838 NULL, outside_facet, compare_tol, edge_id )!= CUBIT_SUCCESS) { 02839 return CUBIT_FAILURE; 02840 } 02841 } 02842 02843 return CUBIT_SUCCESS; 02844 } 02845 02846 //=========================================================================== 02847 //Function Name: eval_edge 02848 // 02849 //Member Type: PUBLIC 02850 //Description: Evaluate the location of a point projected to a 02851 // linear edge. 02852 //=========================================================================== 02853 CubitStatus FacetEvalTool::eval_edge( CubitFacet *facet, 02854 int vert0, int vert1, 02855 CubitVector &pt_on_plane, 02856 CubitVector &close_point ) 02857 { 02858 CubitPoint *pt0 = facet->point(vert0); 02859 CubitPoint *pt1 = facet->point(vert1); 02860 02861 // the edge vector 02862 02863 CubitVector e0 ( pt1->x() - pt0->x(), 02864 pt1->y() - pt0->y(), 02865 pt1->z() - pt0->z() ); 02866 e0.normalize(); 02867 02868 // vector from vert0 to point 02869 02870 CubitVector v0 ( pt_on_plane.x() - pt0->x(), 02871 pt_on_plane.y() - pt0->y(), 02872 pt_on_plane.z() - pt0->z() ); 02873 02874 // project to edge 02875 02876 double len = v0%e0; 02877 close_point.x ( pt0->x() + e0.x() * len ); 02878 close_point.y ( pt0->y() + e0.y() * len ); 02879 close_point.z ( pt0->z() + e0.z() * len ); 02880 02881 return CUBIT_SUCCESS; 02882 } 02883 02884 //=========================================================================== 02885 //Function Name: eval_point 02886 // 02887 //Member Type: PUBLIC 02888 //Descriptoin: Evaluate the location and normal of a set of area coordinates 02889 // on a facet. 02890 //=========================================================================== 02891 CubitStatus FacetEvalTool::eval_point( CubitFacet *facet, 02892 int vertex_id, 02893 CubitVector &close_point ) 02894 { 02895 close_point.x (facet->point(vertex_id)->x()); 02896 close_point.y (facet->point(vertex_id)->y()); 02897 close_point.z (facet->point(vertex_id)->z()); 02898 02899 return CUBIT_SUCCESS; 02900 } 02901 02902 //=========================================================================== 02903 //Function Name: eval_facet_normal 02904 // 02905 //Member Type: PUBLIC 02906 //Descriptoin: Evaluate the normal of the facet (use the interpOrder) 02907 // return normalized normal 02908 //=========================================================================== 02909 CubitStatus FacetEvalTool::eval_facet_normal( CubitFacet *facet, 02910 CubitVector &areacoord, 02911 CubitVector &normal ) 02912 { 02913 switch(facet->eval_order()) { 02914 case 0: 02915 normal = facet->normal(); 02916 break; 02917 case 1: case 2: case 3: 02918 { 02919 CubitVector norm0 = facet->point(0)->normal( facet ); 02920 CubitVector norm1 = facet->point(1)->normal( facet ); 02921 CubitVector norm2 = facet->point(2)->normal( facet ); 02922 normal.x( areacoord.x() * norm0.x() + 02923 areacoord.y() * norm1.x() + 02924 areacoord.z() * norm2.x() ); 02925 normal.y( areacoord.x() * norm0.y() + 02926 areacoord.y() * norm1.y() + 02927 areacoord.z() * norm2.y() ); 02928 normal.z( areacoord.x() * norm0.z() + 02929 areacoord.y() * norm1.z() + 02930 areacoord.z() * norm2.z() ); 02931 normal.normalize(); 02932 } 02933 break; 02934 case 4: 02935 if(facet->is_flat()) 02936 { 02937 normal = facet->normal(); 02938 } 02939 else 02940 { 02941 eval_bezier_patch_normal(facet, areacoord, normal); 02942 02943 // check for reasonableness of the normal 02944 02945 #if 0 02946 if (DEBUG_FLAG(110)) 02947 { 02948 CubitVector norm0 = facet->point(0)->normal( facet ); 02949 CubitVector norm1 = facet->point(1)->normal( facet ); 02950 CubitVector norm2 = facet->point(2)->normal( facet ); 02951 CubitVector lin_normal; 02952 lin_normal.x( areacoord.x() * norm0.x() + 02953 areacoord.y() * norm1.x() + 02954 areacoord.z() * norm2.x() ); 02955 lin_normal.y( areacoord.x() * norm0.y() + 02956 areacoord.y() * norm1.y() + 02957 areacoord.z() * norm2.y() ); 02958 lin_normal.z( areacoord.x() * norm0.z() + 02959 areacoord.y() * norm1.z() + 02960 areacoord.z() * norm2.z() ); 02961 lin_normal.normalize(); 02962 02963 PRINT_INFO("(facet %4d) ac=%7.5lf %7.5lf %7.5lf\n", 02964 facet->id(), areacoord.x(), areacoord.y(), areacoord.z()); 02965 PRINT_INFO(" bn=%7.5lf %7.5lf %7.5lf\n", 02966 normal.x(), normal.y(), normal.z()); 02967 PRINT_INFO(" ln=%7.5lf %7.5lf %7.5lf\n", 02968 lin_normal.x(), lin_normal.y(), lin_normal.z()); 02969 02970 const double tol = 1e-2; 02971 if (fabs(lin_normal.x() - normal.x()) > tol || 02972 fabs(lin_normal.y() - normal.y()) > tol || 02973 fabs(lin_normal.z() - normal.z()) > tol) 02974 { 02975 int mydebug = 0; 02976 if (mydebug) 02977 { 02978 CubitVector pt; 02979 eval_bezier_patch(facet, areacoord, pt); 02980 dcolor(CUBIT_GREEN_INDEX); 02981 dray(pt,normal,1.0); 02982 dcolor(CUBIT_RED_INDEX); 02983 dray(pt,lin_normal,1.0); 02984 dview(); 02985 } 02986 02987 PRINT_INFO("^=============^==============^=============^=============^\n"); 02988 } 02989 } 02990 #endif 02991 } 02992 02993 break; 02994 } 02995 02996 return CUBIT_SUCCESS; 02997 } 02998 02999 03000 //=========================================================================== 03001 //Function Name: eval_quadratic 03002 // 03003 //Member Type: PRIVATE 03004 //Descriptoin: Evaluate the point based on a quadratic approximation 03005 //=========================================================================== 03006 CubitStatus FacetEvalTool::eval_quadratic( CubitFacet *facet, 03007 int pt_idx, 03008 CubitVector &eval_pt, 03009 CubitVector &qpoint, 03010 CubitVector &qnorm ) 03011 { 03012 // interpolate a point on a circle that is defined by two points and 03013 // two normals. The first pont is a vertex on the facet, the second 03014 // is a point on the opposite edge. The point to be interpolated lies 03015 // somewhere between the two 03016 03017 CubitVector normA = facet->point(pt_idx)->normal( facet ); 03018 CubitVector ptA = facet->point(pt_idx)->coordinates(); 03019 int idx0 = -1, idx1 = -1; 03020 switch(pt_idx) { 03021 case 0: 03022 idx0 = 1; 03023 idx1 = 2; 03024 break; 03025 case 1: 03026 idx0 = 2; 03027 idx1 = 0; 03028 break; 03029 case 2: 03030 idx0 = 0; 03031 idx1 = 1; 03032 break; 03033 } 03034 CubitVector ptB, normB, pt0, pt1, norm0, norm1; 03035 pt0 = facet->point(idx0)->coordinates(); 03036 pt1 = facet->point(idx1)->coordinates(); 03037 norm0 = facet->point(idx0)->normal( facet ); 03038 norm1 = facet->point(idx1)->normal( facet ); 03039 on_circle( pt0, norm0, pt1, norm1, 03040 eval_pt, ptB, normB ); 03041 on_circle( ptA, normA, ptB, normB, 03042 eval_pt, qpoint, qnorm ); 03043 03044 return CUBIT_SUCCESS; 03045 03046 } 03047 03048 //=========================================================================== 03049 //Function Name: on_circle 03050 // 03051 //Member Type: PRIVATE 03052 //Description: compute a projection of a point onto a circle. The circle 03053 // is defined by two points and two normals. Return the 03054 // projected point and its normal 03055 //=========================================================================== 03056 void FacetEvalTool::on_circle( CubitVector &ptA, 03057 CubitVector &normA, 03058 CubitVector &ptB, 03059 CubitVector &normB, 03060 CubitVector &eval_pt, 03061 CubitVector &pt_on_circle, 03062 CubitVector &normal ) 03063 { 03064 // angle between the normals 03065 03066 double cosang = normA%normB; 03067 03068 // check for flat surfaces - project to the segment 03069 03070 if (cosang >= 0.99999 || cosang <= -0.99999) { 03071 CubitVector vAB = ptB - ptA; 03072 vAB.normalize(); 03073 CubitVector vAeval_pt = eval_pt - ptA; 03074 double len = vAB%vAeval_pt; 03075 pt_on_circle = ptA + len * vAB; 03076 if (cosang <= -0.99999) { // this is bad! (facet spans 180 degrees) 03077 normal = normA; 03078 } 03079 else { 03080 normal = 0.5e0 * (normA + normB); 03081 } 03082 } 03083 else { 03084 03085 // curved surface 03086 // define a common plane at eval_pt 03087 03088 CubitVector pnorm = normA*normB; 03089 pnorm.normalize(); 03090 double pcoefd = -pnorm%eval_pt; 03091 03092 // project everything to common plane 03093 03094 double pdist = pnorm%ptA + pcoefd; 03095 CubitVector pptA = ptA - pnorm * pdist; 03096 pdist = pnorm%ptB + pcoefd; 03097 CubitVector pptB = ptB - pnorm * pdist; 03098 03099 double angle = acos(cosang); 03100 double dist = pptA.distance_between(pptB); 03101 03102 // kradius is the radius of curvature 03103 // center is the center of curvature 03104 // centerA and centerB should be the same within tol 03105 03106 double kradius = dist / (2.0e0 * sin( angle * 0.5e0 )); 03107 CubitVector centerA = pptA - kradius * normA; 03108 CubitVector centerB = pptB - kradius * normB; 03109 CubitVector center = (centerA + centerB) * 0.5e0; 03110 03111 normal = eval_pt - center; 03112 normal.normalize(); 03113 pt_on_circle = center + kradius * normal; 03114 } 03115 } 03116 03117 //=========================================================================== 03118 //Function Name: eval_quadric 03119 // 03120 //Member Type: PRIVATE 03121 //Description: evaluate a point on an interpolated quadric surface 03122 //=========================================================================== 03123 void FacetEvalTool::eval_quadric( CubitFacet *facet, 03124 int pt_index, 03125 CubitVector &eval_pt, 03126 CubitVector &qpt ) 03127 { 03128 // transform the point to the local system 03129 03130 CubitPoint *point = facet->point(pt_index); 03131 CubitVector loc_eval_pt; 03132 point->transform_to_local( eval_pt, loc_eval_pt ); 03133 // point->transform_to_local( point->coordinates(), loc_pt ); 03134 03135 // interpolate a "z" value in the local coordinate system 03136 03137 double *coef = point->coef_vector(); 03138 loc_eval_pt.z( coef[0] * loc_eval_pt.x() + 03139 coef[1] * loc_eval_pt.y() + 03140 coef[2] * FacetEvalToolUtils::sqr(loc_eval_pt.x()) + 03141 coef[3] * loc_eval_pt.x() * loc_eval_pt.y() + 03142 coef[4] * FacetEvalToolUtils::sqr(loc_eval_pt.y()) ); 03143 03144 03145 // loc_eval_pt.z( point->z() - 03146 // coef[0] * loc_eval_pt.x() - 03147 // coef[1] * loc_eval_pt.y() + 03148 // coef[2] * sqr(loc_eval_pt.x()) + 03149 // coef[3] * loc_eval_pt.x() * loc_eval_pt.y() + 03150 // coef[4] * sqr(loc_eval_pt.y()) ); 03151 03152 // transform back to global system 03153 03154 point->transform_to_global( loc_eval_pt, qpt ); 03155 03156 } 03157 03158 //=========================================================================== 03159 //Function Name: project_to_facet_plane 03160 // 03161 //Member Type: PUBLIC 03162 //Descriptoin: Project a point to the plane of a facet 03163 //=========================================================================== 03164 void FacetEvalTool::project_to_facet_plane( 03165 CubitFacet *facet, 03166 const CubitVector &pt, 03167 CubitVector &point_on_plane, 03168 double &dist_to_plane) 03169 { 03170 CubitVector normal = facet->normal(); 03171 normal.normalize(); 03172 CubitPoint *facPoint = facet->point(0); 03173 double coefd = -(normal.x() * facPoint->x() + 03174 normal.y() * facPoint->y() + 03175 normal.z() * facPoint->z()); 03176 double dist = normal.x() * pt.x() + 03177 normal.y() * pt.y() + 03178 normal.z() * pt.z() + coefd; 03179 dist_to_plane = fabs(dist); 03180 03181 point_on_plane.set( pt.x() - normal.x() * dist, 03182 pt.y() - normal.y() * dist, 03183 pt.z() - normal.z() * dist ); 03184 03185 } 03186 03187 //=========================================================================== 03188 //Function Name: facet_area_coordinate 03189 // 03190 //Member Type: PUBLIC 03191 //Descriptoin: Determine the area coordinates of a point on the plane 03192 // of a facet 03193 //=========================================================================== 03194 void FacetEvalTool::facet_area_coordinate( 03195 CubitFacet *facet, 03196 const CubitVector &pt_on_plane, 03197 CubitVector &areacoord ) 03198 { 03199 double area2; 03200 CubitVector normal = facet->normal(); 03201 CubitPoint *pt0 = facet->point(0); 03202 CubitPoint *pt1 = facet->point(1); 03203 CubitPoint *pt2 = facet->point(2); 03204 double tol = GEOMETRY_RESABS * 1.e-5; 03205 CubitVector v1( pt1->x() - pt0->x(), 03206 pt1->y() - pt0->y(), 03207 pt1->z() - pt0->z());//(*p1-*p0); 03208 CubitVector v2( pt2->x() - pt0->x(), 03209 pt2->y() - pt0->y(), 03210 pt2->z() - pt0->z());// = (*p2-*p0); 03211 area2 = (v1*v2).length_squared(); 03212 if(area2 < 100 * tol){ 03213 tol = .01 * area2; 03214 } 03215 CubitVector absnorm( fabs(normal.x()), fabs(normal.y()), fabs(normal.z()) ); 03216 03217 // project to the closest coordinate plane so we only have to do this in 2D 03218 03219 if (absnorm.x() >= absnorm.y() && absnorm.x() >= absnorm.z()) { 03220 area2 = FacetEvalToolUtils::determ3(pt0->y(), pt0->z(), 03221 pt1->y(), pt1->z(), 03222 pt2->y(), pt2->z()); 03223 if (fabs(area2) < tol) { 03224 areacoord.set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX ); 03225 } 03226 else if ( pt_on_plane.within_tolerance( pt0->coordinates(), GEOMETRY_RESABS ) ) 03227 { 03228 areacoord.set( 1.0, 0.0, 0.0 ); 03229 } 03230 else if ( pt_on_plane.within_tolerance( pt1->coordinates(), GEOMETRY_RESABS ) ) 03231 { 03232 areacoord.set( 0.0, 1.0, 0.0 ); 03233 } 03234 else if ( pt_on_plane.within_tolerance( pt2->coordinates(), GEOMETRY_RESABS ) ) 03235 { 03236 areacoord.set( 0.0, 0.0, 1.0 ); 03237 } 03238 else { 03239 areacoord.x( 03240 FacetEvalToolUtils::determ3( pt_on_plane.y(), pt_on_plane.z(), 03241 pt1->y(), pt1->z(), pt2->y(), pt2->z() ) / area2 ); 03242 areacoord.y( 03243 FacetEvalToolUtils::determ3( pt0->y(), pt0->z(), 03244 pt_on_plane.y(), pt_on_plane.z(), 03245 pt2->y(), pt2->z() ) / area2 ); 03246 areacoord.z( 03247 FacetEvalToolUtils::determ3( pt0->y(), pt0->z(), pt1->y(), pt1->z(), 03248 pt_on_plane.y(), pt_on_plane.z() ) / area2 ); 03249 } 03250 } 03251 else if(absnorm.y() >= absnorm.x() && absnorm.y() >= absnorm.z()) { 03252 area2 = FacetEvalToolUtils::determ3(pt0->x(), pt0->z(), 03253 pt1->x(), pt1->z(), 03254 pt2->x(), pt2->z()); 03255 if (fabs(area2) < tol) { 03256 areacoord.set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX ); 03257 } 03258 else if ( pt_on_plane.within_tolerance( pt0->coordinates(), GEOMETRY_RESABS ) ) 03259 { 03260 areacoord.set( 1.0, 0.0, 0.0 ); 03261 } 03262 else if ( pt_on_plane.within_tolerance( pt1->coordinates(), GEOMETRY_RESABS ) ) 03263 { 03264 areacoord.set( 0.0, 1.0, 0.0 ); 03265 } 03266 else if ( pt_on_plane.within_tolerance( pt2->coordinates(), GEOMETRY_RESABS ) ) 03267 { 03268 areacoord.set( 0.0, 0.0, 1.0 ); 03269 } 03270 else { 03271 areacoord.x( 03272 FacetEvalToolUtils::determ3( pt_on_plane.x(), pt_on_plane.z(), 03273 pt1->x(), pt1->z(), pt2->x(), pt2->z() ) / area2 ); 03274 areacoord.y( 03275 FacetEvalToolUtils::determ3( pt0->x(), pt0->z(), 03276 pt_on_plane.x(), pt_on_plane.z(), 03277 pt2->x(), pt2->z() ) / area2 ); 03278 areacoord.z( 03279 FacetEvalToolUtils::determ3( pt0->x(), pt0->z(), pt1->x(), pt1->z(), 03280 pt_on_plane.x(), pt_on_plane.z() ) / area2 ); 03281 } 03282 } 03283 else { 03284 area2 = FacetEvalToolUtils::determ3(pt0->x(), pt0->y(), 03285 pt1->x(), pt1->y(), 03286 pt2->x(), pt2->y()); 03287 if (fabs(area2) < tol) { 03288 areacoord.set( -CUBIT_DBL_MAX, -CUBIT_DBL_MAX, -CUBIT_DBL_MAX ); 03289 } 03290 else if ( pt_on_plane.within_tolerance( pt0->coordinates(), GEOMETRY_RESABS ) ) 03291 { 03292 areacoord.set( 1.0, 0.0, 0.0 ); 03293 } 03294 else if ( pt_on_plane.within_tolerance( pt1->coordinates(), GEOMETRY_RESABS ) ) 03295 { 03296 areacoord.set( 0.0, 1.0, 0.0 ); 03297 } 03298 else if ( pt_on_plane.within_tolerance( pt2->coordinates(), GEOMETRY_RESABS ) ) 03299 { 03300 areacoord.set( 0.0, 0.0, 1.0 ); 03301 } 03302 else { 03303 areacoord.x( 03304 FacetEvalToolUtils::determ3( pt_on_plane.x(), pt_on_plane.y(), 03305 pt1->x(), pt1->y(), pt2->x(), pt2->y() ) / area2 ); 03306 areacoord.y( 03307 FacetEvalToolUtils::determ3( pt0->x(), pt0->y(), 03308 pt_on_plane.x(), pt_on_plane.y(), 03309 pt2->x(), pt2->y() ) / area2 ); 03310 areacoord.z( 03311 FacetEvalToolUtils::determ3( pt0->x(), pt0->y(), pt1->x(), pt1->y(), 03312 pt_on_plane.x(), pt_on_plane.y() ) / area2 ); 03313 } 03314 } 03315 } 03316 03317 //=========================================================================== 03318 //Function Name: is_outside 03319 // 03320 //Member Type: PRIVATE 03321 //Descriptoin: Determines if the areacoord is actually outside the range 03322 // of the surface facets. 03323 //=========================================================================== 03324 CubitBoolean FacetEvalTool::is_outside( 03325 CubitFacet *facet, 03326 CubitVector &areacoord) 03327 { 03328 if (areacoord.x() < -GEOMETRY_RESABS) { 03329 if (NULL == facet->shared_facet_on_surf( facet->point(1), 03330 facet->point(2), 03331 facet->tool_id() )) { 03332 return CUBIT_TRUE; 03333 } 03334 } 03335 if (areacoord.y() < -GEOMETRY_RESABS) { 03336 if (NULL == facet->shared_facet_on_surf( facet->point(2), 03337 facet->point(0), 03338 facet->tool_id() )) { 03339 return CUBIT_TRUE; 03340 } 03341 } 03342 if (areacoord.z() < -GEOMETRY_RESABS) { 03343 if (NULL == facet->shared_facet_on_surf( facet->point(0), 03344 facet->point(1), 03345 facet->tool_id() )) { 03346 return CUBIT_TRUE; 03347 } 03348 } 03349 return CUBIT_FALSE; 03350 } 03351 03352 //=========================================================================== 03353 //Function Name: closest_point_trimmed 03354 // 03355 //Member Type: PUBLIC 03356 //Descriptoin: Finds the closest point from the vector (this_point) to the 03357 // set of facets that lies on the set of facets. If the point 03358 // lies outside this set, the closest point will be on the edge 03359 // of the closest facet. 03360 // This function also determines if the point is outside or 03361 // inside the current set of facets. You should call 03362 // a bounding box test first before this... 03363 //=========================================================================== 03364 CubitStatus FacetEvalTool::closest_point_trimmed( 03365 CubitVector &this_point, 03366 CubitVector *closest_point_ptr, 03367 CubitBoolean &lies_outside, 03368 CubitVector *normal_ptr) 03369 { 03370 03371 CubitBoolean trim = CUBIT_TRUE; 03372 return project_to_facets ( this_point, trim, &lies_outside, 03373 closest_point_ptr, normal_ptr ); 03374 } 03375 03376 //=========================================================================== 03377 //Function Name: destroy_facets 03378 // 03379 //Member Type: PRIVATE 03380 //Descriptoin: Deletes the points and facets. 03381 //=========================================================================== 03382 void FacetEvalTool::destroy_facets() 03383 { 03384 int i, j; 03385 CubitPoint *point; 03386 CubitFacet *facet; 03387 CubitFacetEdge *edge; 03388 myFacetList.last(); 03389 CubitFacetEdgeData *cfe_data = NULL; 03390 for( i = myFacetList.size(); i > 0; i-- ) 03391 { 03392 facet = myFacetList.pop(); 03393 for (j = 0; j<3; j++) 03394 { 03395 point = facet->point( j ); 03396 point->remove_facet( facet ); 03397 edge = facet->edge( j ); 03398 cfe_data = CAST_TO( edge, CubitFacetEdgeData ); 03399 if (cfe_data) 03400 cfe_data->remove_facet( facet ); 03401 } 03402 delete facet; 03403 } 03404 for( i = myEdgeList.size(); i > 0; i-- ) 03405 { 03406 edge = myEdgeList.pop(); 03407 if (edge && edge->num_adj_facets() == 0) 03408 { 03409 delete edge; 03410 } 03411 } 03412 for( i = myPointList.size(); i > 0; i-- ) 03413 { 03414 point = myPointList.pop(); 03415 if (point && point->num_adj_facets() == 0) 03416 { 03417 delete point; 03418 } 03419 } 03420 } 03421 03422 //=========================================================================== 03423 //Function Name: get_points_from_facets 03424 // 03425 //Member Type: PRIVATE 03426 //Descriptoin: Gets the set of points contained in the list of facets. 03427 // Populates the point_list with those points. 03428 //=========================================================================== 03429 CubitStatus FacetEvalTool::get_points_from_facets( 03430 DLIList<CubitFacet*> &facet_list, 03431 DLIList<CubitPoint*> &point_list ) 03432 { 03433 int i, j; 03434 03435 DLIList<CubitPoint*> all_points; 03436 03437 for ( i = 0; i < facet_list.size(); i++) 03438 { 03439 CubitFacet* facet = facet_list.get_and_step(); 03440 facet->points(all_points); 03441 } 03442 for ( i = 0; i < all_points.size(); i++) 03443 { 03444 all_points.get_and_step()->marked( CUBIT_FALSE ); 03445 } 03446 03447 for ( j = 0; j < all_points.size(); j++) 03448 { 03449 CubitPoint* point = all_points.get_and_step(); 03450 if (!point->marked()) 03451 { 03452 point->marked(CUBIT_TRUE); 03453 point_list.append(point); 03454 } 03455 } 03456 03457 // unmark the found points 03458 03459 for (i = 0; i < point_list.size(); i++) 03460 { 03461 point_list.get_and_step()->marked(CUBIT_FALSE); 03462 } 03463 return CUBIT_SUCCESS; 03464 } 03465 03466 //=========================================================================== 03467 //Function Name: get_loops_from_facets 03468 // 03469 //Member Type: PRIVATE 03470 //Descriptoin: generate an ordered list of facetedge lists representing the 03471 // boundary loops for this set of facets 03472 //=========================================================================== 03473 CubitStatus FacetEvalTool::get_loops_from_facets( 03474 DLIList<CubitFacetEdge*> &all_edge_list, // all the edges on the facets 03475 DLIList<DLIList<CubitFacetEdge*>*> &loop_list ) // return a list of edge lists 03476 { 03477 int i; 03478 int mydebug = 0; 03479 CubitFacetEdge* edge, *startedge; 03480 CubitFacet *facet, *nextfacet; 03481 CubitBoolean found; 03482 03483 if (mydebug) 03484 { 03485 GfxDebug::clear(); 03486 for (i = 0; i< myFacetList.size(); i++) 03487 myFacetList.get_and_step()->debug_draw( CUBIT_GREEN_INDEX, false); 03488 GfxDebug::flush(); 03489 GfxDebug::mouse_xforms(); 03490 } 03491 03492 for ( i = 0; i < all_edge_list.size(); i++) 03493 { 03494 startedge = all_edge_list.get_and_step(); 03495 if (startedge->get_flag() == 0) { 03496 startedge->set_flag( 1 ); 03497 03498 // Find an edge without a neighboring facet or a facet that 03499 // is not on the current surface to start a loop 03500 03501 if (startedge->num_adj_facets_on_surf(toolID) == 1) 03502 { 03503 03504 // Start a new loop 03505 03506 DLIList<CubitFacetEdge*> *edge_list = new DLIList<CubitFacetEdge*>; 03507 loop_list.append( edge_list ); 03508 edge_list->append( startedge ); 03509 if (mydebug) debug_draw_edge(startedge); 03510 03511 // find the next ccw edge on the loop. Edges are placed on the 03512 // list based on ccw order wrt the orientation of the facets 03513 // (ie. same orientation as facets) 03514 03515 edge = startedge; 03516 facet = edge->adj_facet_on_surf(toolID); 03517 int num_failures = 0; 03518 do { 03519 found = CUBIT_FALSE; 03520 do { 03521 edge = facet->next_edge( edge ); 03522 assert(edge != NULL); 03523 edge->set_flag( 1 ); 03524 03525 nextfacet = edge->other_facet_on_surf(facet); 03526 03527 if (nextfacet == NULL) { 03528 if (edge != startedge) { 03529 num_failures = 0; 03530 edge_list->append( edge ); 03531 } 03532 found = CUBIT_TRUE; 03533 } 03534 else { 03535 num_failures++; 03536 facet = nextfacet; 03537 } 03538 } while (!found && num_failures < myFacetList.size() ); 03539 } while (edge != startedge && num_failures < myFacetList.size() ); 03540 03541 if( edge != startedge ) 03542 return CUBIT_FAILURE; 03543 } 03544 } 03545 } 03546 03547 // reset the flags 03548 03549 for ( i = 0; i < all_edge_list.size(); i++) { 03550 all_edge_list.get_and_step()->set_flag( 0 ); 03551 } 03552 return CUBIT_SUCCESS; 03553 } 03554 03555 //=========================================================================== 03556 //Function Name: get_edges_from_facets 03557 // 03558 //Member Type: PRIVATE 03559 //Descriptoin: Populates the edge list from the list of facets 03560 //=========================================================================== 03561 CubitStatus FacetEvalTool::get_edges_from_facets( 03562 DLIList<CubitFacet*> &facet_list, 03563 DLIList<CubitFacetEdge*> &edge_list ) 03564 { 03565 int i, j, k; 03566 CubitPoint *p0, *p1; 03567 CubitFacet *facet, *adj_facet; 03568 CubitFacetEdge *edge; 03569 for ( i = 0; i < facet_list.size(); i++) { 03570 facet = facet_list.get_and_step(); 03571 for (j=0; j<3; j++) { 03572 if (!(edge = facet->edge(j))) 03573 { 03574 facet->get_edge_pts( j, p0, p1 ); 03575 edge = NULL; 03576 k = -1; 03577 //find another facet on this surface sharing these two points 03578 adj_facet = facet->shared_facet( p0, p1 ); 03579 03580 if (adj_facet) { 03581 edge = adj_facet->edge_from_pts(p0, p1, k); 03582 } 03583 03584 if (!edge) { 03585 edge = (CubitFacetEdge *) 03586 new CubitFacetEdgeData( p0, p1, facet, adj_facet, j, k ); 03587 } 03588 else{ 03589 facet->add_edge( edge ); 03590 } 03591 } 03592 edge->set_flag( 0 ); 03593 } 03594 } 03595 // create a unique list of edges 03596 03597 for ( i = 0; i < facet_list.size(); i++) 03598 { 03599 facet = facet_list.get_and_step(); 03600 for (j=0; j<3; j++) 03601 { 03602 edge = facet->edge(j); 03603 if ( !edge ) 03604 return CUBIT_FAILURE; 03605 if (0 == edge->get_flag()) 03606 { 03607 edge->set_flag( 1 ); 03608 edge_list.append( edge ); 03609 } 03610 } 03611 } 03612 03613 // reset the flags on the edges 03614 03615 for ( i = 0; i < edge_list.size(); i++) 03616 { 03617 edge = edge_list.get_and_step(); 03618 edge->set_flag( 0 ); 03619 } 03620 return CUBIT_SUCCESS; 03621 } 03622 03623 03624 //=========================================================================== 03625 //Function Name: check_faceting 03626 // 03627 //Member Type: PRIVATE 03628 //Descriptoin: check the edge/face orientations 03629 //=========================================================================== 03630 void FacetEvalTool::check_faceting() 03631 { 03632 int ii; 03633 for (ii = 0; ii< myFacetList.size(); ii++) 03634 myFacetList.get_and_step()->debug_draw( CUBIT_YELLOW_INDEX ); 03635 GfxDebug::flush(); 03636 GfxDebug::mouse_xforms(); 03637 03638 CubitFacet *facet = myFacetList.get_and_step(); 03639 CubitVector snorm = facet->normal(); 03640 snorm.normalize(); 03641 for (ii=1; ii<myFacetList.size(); ii++) 03642 { 03643 facet = myFacetList.get_and_step(); 03644 CubitVector norm = facet->normal(); 03645 norm.normalize(); 03646 if (norm % snorm < 0.8) 03647 { 03648 facet->debug_draw( CUBIT_RED_INDEX ); 03649 } 03650 else 03651 { 03652 facet->debug_draw( CUBIT_BLUE_INDEX ); 03653 } 03654 } 03655 } 03656 03657 03658 //=========================================================================== 03659 //Function Name: draw_facets 03660 // 03661 //Member Type: PRIVATE 03662 //Descriptoin: draw the facets for debug 03663 //=========================================================================== 03664 void FacetEvalTool::debug_draw_facets( int color ) 03665 { 03666 int ii; 03667 if ( color == -1 ) 03668 color = CUBIT_YELLOW_INDEX; 03669 CubitBoolean flush_it = CUBIT_FALSE; 03670 for ( ii = myFacetList.size(); ii > 0; ii-- ) 03671 { 03672 myFacetList.get_and_step()->debug_draw(color, flush_it); 03673 } 03674 GfxDebug::flush(); 03675 } 03676 03677 //=========================================================================== 03678 //Function Name: draw_vec 03679 // 03680 //Member Type: PRIVATE 03681 //Descriptoin: draw a single point 03682 //=========================================================================== 03683 void FacetEvalTool::debug_draw_vec( CubitVector &vec, int color ) 03684 { 03685 if ( color == -1 ) 03686 color = CUBIT_YELLOW_INDEX; 03687 GfxDebug::draw_point(vec, color); 03688 GfxDebug::flush(); 03689 } 03690 03691 //=========================================================================== 03692 //Function Name: draw_facet_normals 03693 // 03694 //Member Type: PRIVATE 03695 //Descriptoin: the the normal at the centroid of the facets 03696 //=========================================================================== 03697 void FacetEvalTool::debug_draw_facet_normals(int color) 03698 { 03699 int ii,jj; 03700 if ( color == -1 ) 03701 color = CUBIT_RED_INDEX; 03702 for ( ii = myFacetList.size(); ii > 0; ii-- ) 03703 { 03704 CubitFacet *facet = myFacetList.get_and_step(); 03705 CubitVector center(0.0e0, 0.0e0, 0.0e0); 03706 for (jj = 0; jj < 3; jj++) 03707 { 03708 center += facet->point(jj)->coordinates(); 03709 } 03710 center /= 3.0; 03711 CubitVector normal = facet->normal(); 03712 double mag = sqrt(FacetEvalToolUtils::sqr(normal.x()) + FacetEvalToolUtils::sqr(normal.y()) + FacetEvalToolUtils::sqr(normal.z())); 03713 mag = sqrt(mag); 03714 normal.normalize(); 03715 CubitVector end = center + normal*mag; 03716 GfxDebug::draw_line(center.x(), center.y(), center.z(), 03717 end.x(), end.y(), end.z(), color); 03718 } 03719 GfxDebug::flush(); 03720 } 03721 03722 //=========================================================================== 03723 //Function Name: draw_point_normals 03724 // 03725 //Member Type: PRIVATE 03726 //Descriptoin: the the normal at the points 03727 //=========================================================================== 03728 void FacetEvalTool::debug_draw_point_normals(int color) 03729 { 03730 int ii; 03731 if ( color == -1 ) 03732 color = CUBIT_RED_INDEX; 03733 double len = 0.1 * sqrt(FacetEvalToolUtils::sqr(myBBox->x_range()) + 03734 FacetEvalToolUtils::sqr(myBBox->y_range()) + 03735 FacetEvalToolUtils::sqr(myBBox->z_range())); 03736 for ( ii = myPointList.size(); ii > 0; ii-- ) 03737 { 03738 CubitPoint *point = myPointList.get_and_step(); 03739 CubitVector normal = point->normal(); 03740 CubitVector end = point->coordinates() + normal*len; 03741 GfxDebug::draw_line(point->x(), point->y(), point->z(), 03742 end.x(), end.y(), end.z(), color); 03743 } 03744 GfxDebug::flush(); 03745 } 03746 03747 //=========================================================================== 03748 //Function Name: draw_edges 03749 // 03750 //Member Type: PRIVATE 03751 //Descriptoin: draw the facet edges 03752 //=========================================================================== 03753 void FacetEvalTool::debug_draw_edges(int color) 03754 { 03755 int ii; 03756 if ( color == -1 ) 03757 color = CUBIT_BLUE_INDEX; 03758 for ( ii = myEdgeList.size(); ii > 0; ii-- ) 03759 { 03760 CubitFacetEdge *edge = myEdgeList.get_and_step(); 03761 CubitPoint *begin_point = edge->point(0); 03762 CubitPoint *end_point = edge->point(1); 03763 GfxDebug::draw_line(begin_point->x(), 03764 begin_point->y(), 03765 begin_point->z(), 03766 end_point->x(), 03767 end_point->y(), 03768 end_point->z(), 03769 color); 03770 } 03771 GfxDebug::flush(); 03772 } 03773 03774 //=========================================================================== 03775 //Function Name: draw_edge 03776 // 03777 //Member Type: PRIVATE 03778 //Descriptoin: draw the facet edge 03779 //=========================================================================== 03780 void FacetEvalTool::debug_draw_edge(CubitFacetEdge *edge, int color) 03781 { 03782 if ( color == -1 ) { 03783 color = CUBIT_YELLOW_INDEX; 03784 } 03785 CubitPoint *begin_point = edge->point(0); 03786 CubitPoint *end_point = edge->point(1); 03787 GfxDebug::draw_line(begin_point->x(), 03788 begin_point->y(), 03789 begin_point->z(), 03790 end_point->x(), 03791 end_point->y(), 03792 end_point->z(), 03793 color); 03794 GfxDebug::flush(); 03795 } 03796 03797 //=========================================================================== 03798 //Function Name: draw_bezier_edges 03799 // 03800 //Member Type: PRIVATE 03801 //Descriptoin: draw the control polygons from the bezier control points on 03802 // the edges 03803 //=========================================================================== 03804 void FacetEvalTool::debug_draw_bezier_edges(int color) 03805 { 03806 int ii, i; 03807 CubitVector ctrl_pts[5], begin, end; 03808 if ( color == -1 ) 03809 color = CUBIT_RED_INDEX; 03810 for ( ii = myEdgeList.size(); ii > 0; ii-- ) 03811 { 03812 CubitFacetEdge *edge = myEdgeList.get_and_step(); 03813 edge->control_points( ctrl_pts ); 03814 for (i=1; i<5; i++) { 03815 begin = ctrl_pts[i-1]; 03816 end = ctrl_pts[i]; 03817 GfxDebug::draw_line(begin.x(), begin.y(), begin.z(), 03818 end.x(), end.y(), end.z(), color); 03819 } 03820 } 03821 GfxDebug::flush(); 03822 } 03823 03824 //=========================================================================== 03825 //Function Name: draw_bezier_facets 03826 // 03827 //Member Type: PRIVATE 03828 //Descriptoin: draw the control polygons from the bezier control points on 03829 // the facets 03830 //=========================================================================== 03831 void FacetEvalTool::debug_draw_bezier_facets(int color) 03832 { 03833 int ii; 03834 if ( color == -1 ) 03835 color = CUBIT_WHITE_INDEX; 03836 for ( ii = myFacetList.size(); ii > 0; ii-- ) 03837 { 03838 debug_draw_bezier_facet( myFacetList.get_and_step(), color ); 03839 } 03840 03841 } 03842 03843 //=========================================================================== 03844 //Function Name: draw_bezier_facet 03845 // 03846 //Member Type: PRIVATE 03847 //Descriptoin: draw the control polygons from the bezier control points on 03848 // a facet 03849 //=========================================================================== 03850 void FacetEvalTool::debug_draw_bezier_facet(CubitFacet *facet, int color) 03851 { 03852 CubitVector areacoord( 0.3333333333333333333, 03853 0.3333333333333333333, 03854 0.3333333333333333333 ); 03855 03856 // interpolate internal control points 03857 03858 CubitVector gctrl_pts[6]; 03859 facet->get_control_points( gctrl_pts ); 03860 CubitVector P_facet[3]; 03861 03862 //2,1,1 03863 P_facet[0] = (1.0e0 / (areacoord.y() + areacoord.z())) * 03864 (areacoord.y() * gctrl_pts[3] + 03865 areacoord.z() * gctrl_pts[4]); 03866 //1,2,1 03867 P_facet[1] = (1.0e0 / (areacoord.x() + areacoord.z())) * 03868 (areacoord.x() * gctrl_pts[0] + 03869 areacoord.z() * gctrl_pts[5]); 03870 //1,1,2 03871 P_facet[2] = (1.0e0 / (areacoord.x() + areacoord.y())) * 03872 (areacoord.x() * gctrl_pts[1] + 03873 areacoord.y() * gctrl_pts[2]); 03874 03875 CubitVector cp0[5], cp1[5], cp2[5]; 03876 03877 facet->edge(0)->control_points(facet,cp0); 03878 facet->edge(1)->control_points(facet,cp1); 03879 facet->edge(2)->control_points(facet,cp2); 03880 03881 color = CUBIT_WHITE_INDEX; 03882 debug_draw_line(cp0[1], cp2[3], color); 03883 debug_draw_line(cp0[2], P_facet[1], color); 03884 debug_draw_line(P_facet[1], cp2[2], color); 03885 debug_draw_line(cp0[3], P_facet[2], color); 03886 debug_draw_line(P_facet[2], P_facet[0], color); 03887 debug_draw_line(P_facet[0], cp2[1], color); 03888 03889 color = CUBIT_GREEN_INDEX; 03890 debug_draw_line(cp1[1], P_facet[2], color); 03891 debug_draw_line(P_facet[2], P_facet[1], color); 03892 debug_draw_line(P_facet[1], cp2[3], color); 03893 debug_draw_line(cp1[2], P_facet[0], color); 03894 debug_draw_line(P_facet[0], cp2[2], color); 03895 debug_draw_line(cp1[3], cp2[1], color); 03896 03897 color = CUBIT_BLUE_INDEX; 03898 debug_draw_line(cp0[1], P_facet[1], color); 03899 debug_draw_line(P_facet[1], P_facet[0], color); 03900 debug_draw_line(P_facet[0], cp1[3], color); 03901 debug_draw_line(cp0[2], P_facet[2], color); 03902 debug_draw_line(P_facet[2], cp1[2], color); 03903 debug_draw_line(cp0[3], cp1[1], color); 03904 } 03905 03906 //=========================================================================== 03907 //Function Name: draw_eval_bezier_facet 03908 // 03909 //Member Type: PRIVATE 03910 //Descriptoin: draw points on the evaluated bezier patch 03911 //=========================================================================== 03912 void FacetEvalTool::debug_draw_eval_bezier_facet( CubitFacet *facet ) 03913 { 03914 CubitVector areacoord, pt, loc; 03915 double u, v, w; 03916 CubitBoolean outside; 03917 #if 0 03918 for (int i=0; i<=10; i++) { 03919 v = w = 0.5 * (double)i/10.0; 03920 u = 1.0 - v - w; 03921 areacoord.set(u, v, w); 03922 eval_facet(facet, pt, areacoord, loc, outside); 03923 draw_location(loc); 03924 v = 0.25 * (double)i/10.0; 03925 w = 0.75 * (double)i/10.0; 03926 u = 1.0 - v - w; 03927 areacoord.set(u, v, w); 03928 eval_facet(facet, pt, areacoord, loc, outside); 03929 draw_location(loc); 03930 w = 0.25 * (double)i/10.0; 03931 v = 0.75 * (double)i/10.0; 03932 u = 1.0 - v - w; 03933 areacoord.set(u, v, w); 03934 eval_facet(facet, pt, areacoord, loc, outside); 03935 debug_draw_location(loc); 03936 } 03937 #endif 03938 for (int j=0; j<=10; j++) { 03939 for (int i=0; i<=20; i++) { 03940 u = ((double)j/10.0) * (double)i/20.0; 03941 w = (1.0 - ((double)j/10.0)) * (double)i/20.0; 03942 v = 1.0 - u - w; 03943 areacoord.set(u, v, w); 03944 eval_facet(facet, pt, areacoord, loc, outside); 03945 debug_draw_location(loc); 03946 } 03947 } 03948 03949 #if 0 03950 for (i=0; i<=10; i++) { 03951 u = v = 0.5 * (double)i/10.0; 03952 w = 1.0 - u - v; 03953 areacoord.set(u, v, w); 03954 eval_facet(facet, pt, areacoord, loc, outside); 03955 draw_location(loc); 03956 u = 0.25 * (double)i/10.0; 03957 v = 0.75 * (double)i/10.0; 03958 w = 1.0 - u - v; 03959 areacoord.set(u, v, w); 03960 eval_facet(facet, pt, areacoord, loc, outside); 03961 draw_location(loc); 03962 v = 0.25 * (double)i/10.0; 03963 u = 0.75 * (double)i/10.0; 03964 w = 1.0 - u - v; 03965 areacoord.set(u, v, w); 03966 eval_facet(facet, pt, areacoord, loc, outside); 03967 draw_location(loc); 03968 } 03969 #endif 03970 03971 } 03972 03973 //=========================================================================== 03974 //Function Name: draw_line 03975 // 03976 //Member Type: PRIVATE 03977 //=========================================================================== 03978 void FacetEvalTool::debug_draw_line(CubitVector &begin, CubitVector &end, int color) 03979 { 03980 GfxDebug::draw_line(begin.x(), begin.y(), begin.z(), 03981 end.x(), end.y(), end.z(), color); 03982 GfxDebug::flush(); 03983 } 03984 03985 //=========================================================================== 03986 //Function Name: draw_location 03987 // 03988 //Member Type: PRIVATE 03989 //=========================================================================== 03990 void FacetEvalTool::debug_draw_location(CubitVector &loc, int color ) 03991 { 03992 if ( color == -1 ) 03993 color = CUBIT_YELLOW_INDEX; 03994 GfxDebug::draw_point(loc, color); 03995 GfxDebug::flush(); 03996 } 03997 03998 03999 //=========================================================================== 04000 //Function Name: write_loops 04001 // 04002 //Member Type: PRIVATE 04003 //=========================================================================== 04004 void FacetEvalTool::write_loops() 04005 { 04006 int ii, jj; 04007 for (ii=0; ii<myLoopList.size(); ii++) 04008 { 04009 DLIList<CubitFacetEdge*> *loop = myLoopList.get_and_step(); 04010 PRINT_INFO("======= Loop %d =========\n", ii); 04011 for (jj=0; jj<loop->size(); jj++) 04012 { 04013 CubitFacetEdge *edge = loop->get_and_step(); 04014 CubitPoint *point0 = edge->point( 0 ); 04015 CubitPoint *point1 = edge->point( 1 ); 04016 PRINT_INFO(" (%d) %f, %f, %f (%d) %f, %f, %f\n", 04017 point0->id(), point0->x(), point0->y(), point0->z(), 04018 point1->id(), point1->x(), point1->y(), point1->z()); 04019 } 04020 } 04021 } 04022 04023 //=========================================================================== 04024 //Function Name: transform_control_points 04025 // 04026 //Member Type: PUBLIC 04027 //=========================================================================== 04028 void FacetEvalTool::transform_control_points( CubitTransformMatrix &tfmat ) 04029 { 04030 if (interpOrder != 4) 04031 return; 04032 04033 CubitVector control_points[6]; 04034 CubitFacet *facet; 04035 int ii, jj; 04036 for (ii=0; ii<myFacetList.size(); ii++) 04037 { 04038 facet = myFacetList.get_and_step(); 04039 facet->get_control_points( control_points ); 04040 for (jj=0; jj<6; jj++) 04041 { 04042 control_points[jj] = tfmat * control_points[jj]; 04043 } 04044 facet->set_control_points( control_points ); 04045 } 04046 04047 CubitFacetEdge *edge; 04048 for (ii=0; ii<myEdgeList.size(); ii++) 04049 { 04050 edge = myEdgeList.get_and_step(); 04051 if (!edge->get_flag()) 04052 { 04053 edge->set_flag(1); 04054 edge->control_points( control_points ); 04055 04056 // assumes the end control points (the vertices) have already 04057 // been transformed 04058 04059 control_points[0] = tfmat * control_points[1]; 04060 control_points[1] = tfmat * control_points[2]; 04061 control_points[2] = tfmat * control_points[3]; 04062 edge->control_points( control_points, 4 ); 04063 } 04064 } 04065 } 04066 04067 //=========================================================================== 04068 //Function Name: area 04069 // 04070 //Member Type: PUBLIC 04071 //=========================================================================== 04072 double FacetEvalTool::area() 04073 { 04074 if (myArea < 0.0) 04075 calculate_area(); 04076 04077 return myArea; 04078 } 04079 //=========================================================================== 04080 //Function Name: calcualte_area 04081 // 04082 //Member Type: Public 04083 //=========================================================================== 04084 void FacetEvalTool::calculate_area() 04085 { 04086 myArea = 0.0; 04087 int ii; 04088 CubitFacet *facet; 04089 for (ii=0; ii<myFacetList.size(); ii++) 04090 { 04091 facet = myFacetList.get_and_step(); 04092 myArea += facet->area(); 04093 } 04094 } 04095 04096 //=========================================================================== 04097 //Function Name: parameterize 04098 //Description: compute the parameterization of the facetted representation 04099 //Member Type: PUBLIC 04100 //=========================================================================== 04101 CubitStatus FacetEvalTool::parameterize() 04102 { 04103 04104 if (myLoopList.size() != 1) 04105 { 04106 PRINT_WARNING("Cannot parameterize surface. Multiple loops detected\n"); 04107 isParameterized = CUBIT_FALSE; 04108 return CUBIT_FAILURE; 04109 } 04110 04111 // make arrays out of the points and facets 04112 04113 double *points = new double [3 * myPointList.size()]; 04114 int *facets = new int [3 * myFacetList.size()]; 04115 if (!points || !facets) 04116 { 04117 PRINT_ERROR("Could not define parameterization for surface (out of memory)\n"); 04118 return CUBIT_FAILURE; 04119 } 04120 int ii; 04121 CubitPoint *pt; 04122 myPointList.reset(); 04123 for (ii=0; ii<myPointList.size(); ii++) 04124 { 04125 pt = myPointList.get_and_step(); 04126 points[ii*3] = pt->x(); 04127 points[ii*3+1] = pt->y(); 04128 points[ii*3+2] = pt->z(); 04129 pt->marked(ii); 04130 } 04131 CubitFacet *facet; 04132 CubitPoint *pts[3]; 04133 for (ii=0; ii<myFacetList.size(); ii++) 04134 { 04135 facet = myFacetList.get_and_step(); 04136 facet->points( pts[0], pts[1], pts[2] ); 04137 facets[ii*3] = pts[0]->marked(); 04138 facets[ii*3+1] = pts[1]->marked(); 04139 facets[ii*3+2] = pts[2]->marked(); 04140 } 04141 04142 // do the parameterization 04143 04144 // comment out for now 04145 // Note to sjowen: this depends on FacetParamTool and facetParamTool is a ParamTool 04146 // (which is in geom directory). We ned a solution that breaks that dependency. 04147 // FacetParamTool facetparamtool( myPointList.size(), myFacetList.size(), 04148 // points, facets ); 04149 if(1) 04150 { 04151 PRINT_ERROR("Surface Parameterizer Failed\n"); 04152 isParameterized = CUBIT_FALSE; 04153 } 04154 else 04155 { 04156 double *sizes = NULL; 04157 double *uv = NULL;//facetparamtool.get_uvs_sizing( ratio, sizes ); 04158 04159 // update the points with uv values 04160 04161 TDFacetBoundaryPoint *td_fbp; 04162 CubitBoolean on_internal_boundary; 04163 myPointList.reset(); 04164 for (ii=0; ii<myPointList.size(); ii++) 04165 { 04166 pt = myPointList.get_and_step(); 04167 DLIList <CubitFacet *> facet_list; 04168 pt->facets_on_surf( toolID, facet_list, on_internal_boundary ); 04169 if (on_internal_boundary) 04170 { 04171 td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt ); 04172 if (!td_fbp) 04173 { 04174 TDFacetBoundaryPoint::add_facet_boundary_point( pt ); 04175 td_fbp = TDFacetBoundaryPoint::get_facet_boundary_point( pt ); 04176 td_fbp->add_surf_facets( facet_list ); 04177 td_fbp->set_uv( facet_list.get(), uv[ii*2], uv[ii*2+1] ); 04178 } 04179 else 04180 { 04181 if (td_fbp->set_uv( facet_list.get(), 04182 uv[ii*2], uv[ii*2+1] ) != CUBIT_SUCCESS) 04183 { 04184 td_fbp->add_surf_facets( facet_list ); 04185 td_fbp->set_uv( facet_list.get(), uv[ii*2], uv[ii*2+1] ); 04186 } 04187 } 04188 } 04189 else 04190 { 04191 pt->set_uv( uv[ii*2], uv[ii*2+1] ); 04192 } 04193 } 04194 isParameterized = CUBIT_TRUE; 04195 PRINT_INFO("Surface Parameterization succeeded\n"); 04196 delete [] sizes; 04197 delete [] uv; 04198 } 04199 04200 // clean up 04201 04202 delete [] points; 04203 delete [] facets; 04204 return CUBIT_SUCCESS; 04205 } 04206 04207 //=========================================================================== 04208 //Function Name: compute_curve_tangent 04209 // 04210 //Member Type: PRIVATE 04211 //Descriptoin: compute the tangents to the endpoints of a boundary edge. 04212 //=========================================================================== 04213 CubitStatus FacetEvalTool::compute_curve_tangent( 04214 CubitFacetEdge *edge, 04215 double min_dot, 04216 CubitVector &T0, 04217 CubitVector &T3 ) 04218 { 04219 04220 CubitPoint *p0 = edge->point( 0 ); 04221 CubitPoint *p1 = edge->point( 1 ); 04222 CubitFacetEdge *prev_edge = next_boundary_edge( edge, p0 ); 04223 if (prev_edge == NULL) // could be end of a hard line 04224 { 04225 T0 = p1->coordinates() - p0->coordinates(); 04226 T0.normalize(); 04227 } 04228 else 04229 { 04230 CubitPoint *p2 = prev_edge->other_point( p0 ); 04231 CubitVector e0 = p0->coordinates() - p2->coordinates(); 04232 CubitVector e1 = p1->coordinates() - p0->coordinates(); 04233 e0.normalize(); 04234 e1.normalize(); 04235 if (e0 % e1 >= min_dot) 04236 { 04237 T0 = (p0->coordinates() - p2->coordinates()) + 04238 (p1->coordinates() - p0->coordinates()); 04239 T0.normalize(); 04240 } 04241 else 04242 { 04243 T0 = e1; 04244 } 04245 } 04246 04247 04248 CubitFacetEdge *next_edge = next_boundary_edge( edge, p1 ); 04249 if (next_edge == NULL) // could be end of a hard line 04250 { 04251 T3 = p1->coordinates() - p0->coordinates(); 04252 T3.normalize(); 04253 } 04254 else 04255 { 04256 CubitPoint *p2 = next_edge->other_point( p1 ); 04257 CubitVector e0 = p2->coordinates() - p1->coordinates(); 04258 CubitVector e1 = p1->coordinates() - p0->coordinates(); 04259 e0.normalize(); 04260 e1.normalize(); 04261 if (e0 % e1 >= min_dot) 04262 { 04263 T3 = (p2->coordinates() - p1->coordinates()) + 04264 (p1->coordinates() - p0->coordinates()); 04265 T3.normalize(); 04266 } 04267 else 04268 { 04269 T3 = e1; 04270 } 04271 } 04272 04273 return CUBIT_SUCCESS; 04274 } 04275 04276 04277 //=========================================================================== 04278 //Function Name: next_boundary_edge 04279 // 04280 //Member Type: PRIVATE 04281 //Descriptoin: given a facet boundary edge and one of its nodes, find the 04282 // next edge on the same surface 04283 //=========================================================================== 04284 CubitFacetEdge *FacetEvalTool::next_boundary_edge( 04285 CubitFacetEdge *this_edge, 04286 CubitPoint *p0 ) 04287 { 04288 CubitFacetEdge *next_edge = NULL; 04289 04290 DLIList<CubitFacetEdge*> edge_list; 04291 p0->edges( edge_list ); 04292 int ii; 04293 04294 CubitFacetEdge *edge_ptr = NULL; 04295 for (ii=0; ii<edge_list.size() && next_edge == NULL; ii++) 04296 { 04297 edge_ptr = edge_list.get_and_step(); 04298 if (edge_ptr != this_edge) 04299 { 04300 if (edge_ptr->num_adj_facets() <= 1) 04301 { 04302 next_edge = edge_ptr; 04303 } 04304 } 04305 } 04306 04307 return next_edge; 04308 } 04309 04310 //=========================================================================== 04311 //Function Name: save 04312 // 04313 //Member Type: PRIVATE 04314 //Description: save the facet eval tool to a cubit file 04315 // Assumption: contained facets have been previuosly saved. This function 04316 // saves only the facet ids. 04317 //=========================================================================== 04318 CubitStatus FacetEvalTool::save( 04319 FILE *fp ) 04320 { 04321 NCubitFile::CIOWrapper cio(fp); 04322 typedef NCubitFile::UnsignedInt32 int32; 04323 04324 cio.Write(reinterpret_cast<int32*>(&interpOrder), 1); 04325 cio.Write(reinterpret_cast<int32*>(&isFlat), 1); 04326 int32 is_param = isParameterized ? 1 : 0; 04327 cio.Write(&is_param, 1); 04328 04329 cio.Write(&myArea, 1); 04330 cio.Write(&minDot, 1); 04331 04332 // write ids of facets that belong to this tool 04333 int32 ii; 04334 CubitFacet *facet_ptr; 04335 int32 nfacets = myFacetList.size(); 04336 int32* facet_id = new int32 [nfacets]; 04337 myFacetList.reset(); 04338 for (ii=0; ii<nfacets; ii++) 04339 { 04340 facet_ptr = myFacetList.get_and_step(); 04341 facet_id[ii] = facet_ptr->id(); 04342 } 04343 cio.Write(&nfacets, 1); 04344 if (nfacets > 0) 04345 { 04346 cio.Write(facet_id, nfacets); 04347 } 04348 delete [] facet_id; 04349 04350 // write ids of edges that belong to this tool 04351 CubitFacetEdge *edge_ptr; 04352 int32 nedges = myEdgeList.size(); 04353 int32* edge_id = new int32 [nedges]; 04354 myEdgeList.reset(); 04355 for (ii=0; ii<nedges; ii++) 04356 { 04357 edge_ptr = myEdgeList.get_and_step(); 04358 edge_id[ii] = edge_ptr->id(); 04359 //volatile int test_int = edge_id[ii] + 1; // this is a test line to look for uninitialized data rjm 04360 } 04361 cio.Write( &nedges, 1); 04362 if (nedges > 0) 04363 { 04364 cio.Write(edge_id, nedges); 04365 } 04366 delete [] edge_id; 04367 04368 // write ids of points that belong to this tool 04369 CubitPoint *point_ptr; 04370 int32 npoints = myPointList.size(); 04371 int32* point_id = new int32 [npoints]; 04372 myPointList.reset(); 04373 for (ii=0; ii<npoints; ii++) 04374 { 04375 point_ptr = myPointList.get_and_step(); 04376 point_id[ii] = point_ptr->id(); 04377 } 04378 cio.Write(&npoints, 1); 04379 if (npoints > 0) 04380 { 04381 cio.Write(point_id, npoints); 04382 } 04383 delete [] point_id; 04384 04385 return CUBIT_SUCCESS; 04386 } 04387 04388 //=========================================================================== 04389 //Function Name: restore 04390 // 04391 //Member Type: PRIVATE 04392 //Description: restore a facetevaltool from a CUB file 04393 //=========================================================================== 04394 CubitStatus FacetEvalTool::restore( 04395 FILE *fp, 04396 unsigned int endian, 04397 int num_facets, 04398 int num_edges, 04399 int num_points, 04400 CubitFacet **facets, 04401 CubitFacetEdge **edges, 04402 CubitPoint **points ) 04403 { 04404 NCubitFile::CIOWrapper cio(endian, fp); 04405 typedef NCubitFile::UnsignedInt32 int32; 04406 04407 // read interpOrder, isFlat, isParameterized 04408 int int_data[3]; 04409 cio.Read(reinterpret_cast<int32*>(int_data), 3); 04410 interpOrder = int_data[0]; 04411 isFlat = int_data[1]; 04412 isParameterized = (int_data[2] != 0); 04413 04414 // read myArea, minDot 04415 double double_data[2]; 04416 cio.Read( double_data, 2); 04417 myArea = double_data[0]; 04418 minDot = double_data[1]; 04419 04420 lastFacet = NULL; 04421 04422 // read the facet ids and assign facets to this eval tool 04423 int nfacets; 04424 cio.Read(reinterpret_cast<int32*>(&nfacets), 1); 04425 int32 *facet_id = NULL; 04426 if (nfacets > 0) 04427 { 04428 facet_id = new int32 [nfacets]; 04429 cio.Read(facet_id, nfacets); 04430 int ii, id; 04431 for(ii=0; ii<nfacets; ii++) 04432 { 04433 id = facet_id[ii]; 04434 if (ii < 0 || ii >= num_facets) 04435 { 04436 delete [] facet_id; 04437 return CUBIT_FAILURE; 04438 } 04439 myFacetList.append( facets[id] ); 04440 facets[id]->set_tool_id( toolID ); 04441 } 04442 delete [] facet_id; 04443 } 04444 04445 // read the edges 04446 int nedges; 04447 cio.Read(reinterpret_cast<int32*>(&nedges), 1); 04448 int32 *edge_id = NULL; 04449 if (nedges > 0) 04450 { 04451 edge_id = new int32 [nedges]; 04452 cio.Read(edge_id, nedges); 04453 int ii, id; 04454 for(ii=0; ii<nedges; ii++) 04455 { 04456 id = edge_id[ii]; 04457 if (ii < 0 || ii >= num_edges) 04458 { 04459 delete [] edge_id; 04460 return CUBIT_FAILURE; 04461 } 04462 myEdgeList.append( edges[id] ); 04463 } 04464 delete [] edge_id; 04465 } 04466 04467 // read the points 04468 int npoints; 04469 cio.Read(reinterpret_cast<int32*>(&npoints), 1); 04470 int32 *point_id = NULL; 04471 if (npoints > 0) 04472 { 04473 point_id = new int32 [npoints]; 04474 cio.Read(point_id, npoints); 04475 int ii, id; 04476 for(ii=0; ii<npoints; ii++) 04477 { 04478 id = point_id[ii]; 04479 if (ii < 0 || ii >= num_points) 04480 { 04481 delete [] point_id; 04482 return CUBIT_FAILURE; 04483 } 04484 myPointList.append( points[id] ); 04485 } 04486 delete [] point_id; 04487 } 04488 04489 bounding_box(); 04490 double diag = sqrt(FacetEvalToolUtils::sqr(myBBox->x_range()) + 04491 FacetEvalToolUtils::sqr(myBBox->y_range()) + 04492 FacetEvalToolUtils::sqr(myBBox->z_range())); 04493 compareTol = 1.0e-3 * diag; 04494 04495 return CUBIT_SUCCESS; 04496 } 04497 04498 CubitStatus FacetEvalTool::get_intersections(CubitVector point1, 04499 CubitVector point2, 04500 DLIList<CubitVector*>& intersection_list, 04501 bool bounded) 04502 { 04503 //Find the points were the line intersects the bounding box. 04504 CubitVector intersect_1; 04505 CubitVector intersect_2; 04506 CubitBox bbox = *myBBox; 04507 04508 //Increase the size of the box in each direction. 04509 //Don't use scale because the box may be too thin (planar surface). 04510 double offset = 2.0 * (point1 - point2).length(); 04511 04512 CubitVector min; 04513 min.x( bbox.min_x() - offset ); 04514 min.y( bbox.min_y() - offset ); 04515 min.z( bbox.min_z() - offset ); 04516 CubitVector max; 04517 max.x( bbox.max_x() + offset ); 04518 max.y( bbox.max_y() + offset ); 04519 max.z( bbox.max_z() + offset ); 04520 04521 bbox.reset( min, max ); 04522 int box_intersections = FacetDataUtil::get_bbox_intersections( point1, point2, bbox, 04523 intersect_1, intersect_2 ); 04524 04525 //The bounding box is larger than the surface we are checking. 04526 //This means that if there are less than two intersections 04527 //the line will not intersect the surface. 04528 if( 2 > box_intersections ) 04529 return CUBIT_SUCCESS; 04530 04531 bbox.reset( intersect_1 ); 04532 bbox |= intersect_2; 04533 04534 //Find the facets that are intersected by the bbox that was just created. 04535 DLIList<CubitFacet*> search_facets; 04536 if( aTree ) 04537 { 04538 //Get the facets from the tree. 04539 aTree->find( bbox, search_facets ); 04540 } 04541 else 04542 search_facets = myFacetList; 04543 04544 int ii; 04545 for( ii = search_facets.size(); ii > 0; ii-- ) 04546 { 04547 CubitFacet* test_facet = search_facets.get_and_step(); 04548 04549 CubitVector intersection; 04550 CubitVector area_coord; 04551 CubitPointContainment contain = FacetDataUtil::intersect_facet( intersect_1, intersect_2, test_facet, 04552 intersection, area_coord ); 04553 04554 if( bounded ) 04555 { 04556 CubitVector dir1 = point2 - point1; 04557 CubitVector dir2 = intersection - point1; 04558 04559 if( dir2.length_squared() > (GEOMETRY_RESABS * GEOMETRY_RESABS) ) 04560 { 04561 if( dir1 % dir2 < 0 || 04562 ( ( dir2.length_squared() - dir1.length_squared() ) > 04563 ( GEOMETRY_RESABS * GEOMETRY_RESABS ) ) ) 04564 { 04565 //The inserction point is not between the two end points. 04566 contain = CUBIT_PNT_OUTSIDE; 04567 } 04568 } 04569 } 04570 04571 if( CUBIT_PNT_BOUNDARY == contain || 04572 CUBIT_PNT_INSIDE == contain ) 04573 { 04574 //The point intersects the facets. 04575 CubitVector* new_intersection = new CubitVector; 04576 *new_intersection = intersection; 04577 intersection_list.append( new_intersection ); 04578 } 04579 } 04580 04581 //Remove duplicate intersections. 04582 intersection_list.reset(); 04583 for( ii = 0; ii < intersection_list.size(); ii++ ) 04584 { 04585 CubitVector* base_vec = intersection_list.next(ii); 04586 if( NULL == base_vec ) 04587 continue; 04588 04589 int jj; 04590 for( jj = ii+1; jj < intersection_list.size(); jj++ ) 04591 { 04592 CubitVector* compare_vec = intersection_list.next(jj); 04593 if( NULL != compare_vec ) 04594 { 04595 if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS ) 04596 { 04597 intersection_list.step(jj); 04598 delete intersection_list.get(); 04599 intersection_list.change_to( NULL ); 04600 intersection_list.reset(); 04601 } 04602 } 04603 } 04604 } 04605 intersection_list.remove_all_with_value( NULL ); 04606 04607 return CUBIT_SUCCESS; 04608 } 04609 04610 int FacetEvalTool::intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacet* facet, CubitVector* point, double &distance ) 04611 { 04612 // This algorithm can be found at http://geometryalgorithms.com/ 04613 04614 CubitVector n; // triangle vectors 04615 CubitVector w0, w; // ray vectors 04616 double a, b; // params to calc ray-plane intersect 04617 04618 // get triangle edge vectors and plane normal 04619 //CubitVector normal = facet->normal(); 04620 CubitPoint *pt0 = facet->point(0); 04621 CubitPoint *pt1 = facet->point(1); 04622 CubitPoint *pt2 = facet->point(2); 04623 double tol = GEOMETRY_RESABS; 04624 04625 CubitVector u( pt1->x() - pt0->x(), 04626 pt1->y() - pt0->y(), 04627 pt1->z() - pt0->z()); //(*p1-*p0); 04628 CubitVector v( pt2->x() - pt0->x(), 04629 pt2->y() - pt0->y(), 04630 pt2->z() - pt0->z()); // = (*p2-*p0); 04631 04632 //u = T.V1 - T.V0; 04633 //v = T.V2 - T.V0; 04634 n = u * v; // cross product 04635 if (n.length_squared() == 0) // triangle is degenerate 04636 return -1; // do not deal with this case 04637 04638 //dir = R.P1 - R.P0; // ray direction vector 04639 //w0 = R.P0 - T.V0; 04640 w0 = CubitVector(origin.x() - pt0->x(), 04641 origin.y() - pt0->y(), 04642 origin.z() - pt0->z()); 04643 04644 a = -(n%w0); 04645 b = (n%direction); 04646 if (fabs(b) < tol) { // ray is parallel to triangle plane 04647 if (a == 0) // ray lies in triangle plane 04648 return 2; 04649 else return 0; // ray disjoint from plane 04650 } 04651 04652 // get intersect point of ray with triangle plane 04653 distance = a / b; 04654 if (distance < 0.0) // ray goes away from triangle 04655 return 0; // => no intersect 04656 // for a segment, also test if (r > 1.0) => no intersect 04657 04658 point->set(origin + distance * direction); // intersect point of ray and plane 04659 04660 // the distance we want to return is real distance, not distance/magnitude 04661 distance *= direction.length(); 04662 04663 // is point inside facet? 04664 double uu, uv, vv, wu, wv, D; 04665 uu = u%u; 04666 uv = u%v; 04667 vv = v%v; 04668 //w = *I - T.V0; 04669 w = CubitVector(point->x() - pt0->x(), 04670 point->y() - pt0->y(), 04671 point->z() - pt0->z()); 04672 wu = w%u; 04673 wv = w%v; 04674 D = uv * uv - uu * vv; 04675 04676 // get and test parametric coords 04677 double s, t; 04678 s = (uv * wv - vv * wu) / D; 04679 if (s < 0.0 || s > 1.0) // point is outside facet 04680 return 0; 04681 t = (uv * wu - uu * wv) / D; 04682 if (t < 0.0 || (s + t) > 1.0) // point is outside facet 04683 return 0; 04684 04685 return 1; // point is in facet 04686 04687 } 04688 04689 int FacetEvalTool::intersect_ray( CubitVector &origin, CubitVector &direction, CubitFacetEdge* facet_edge, CubitVector* point, double &hit_distance ) 04690 { 04691 // This algorithm can be found at http://geometryalgorithms.com/ 04692 double tol = GEOMETRY_RESABS; 04693 04694 CubitPoint* p0 = facet_edge->point(0); 04695 CubitPoint* p1 = facet_edge->point(1); 04696 CubitVector u0 = CubitVector(p0->x(), p0->y(), p0->z()); 04697 CubitVector u1 = CubitVector(p1->x(), p1->y(), p1->z()); 04698 04699 CubitVector u = CubitVector(u0, u1); 04700 CubitVector v = direction; 04701 v.normalize(); 04702 04703 CubitVector w = CubitVector(origin, u0); 04704 04705 double sc, tc; // sc is fraction along facet edge, tc is distance along ray 04706 04707 double a = u%u; // always >= 0 04708 double b = u%v; 04709 double c = v%v; // always >= 0 04710 double d = u%w; 04711 double e = v%w; 04712 double D = a*c - b*b; // always >= 0 04713 04714 // compute the line parameters of the two closest points 04715 if (D < tol) 04716 { 04717 // the lines are almost parallel 04718 sc = 0.0; 04719 tc = (b>c ? d/b : e/c); // use the largest denominator 04720 } 04721 else 04722 { 04723 sc = (b*e - c*d) / D; 04724 tc = (a*e - b*d) / D; 04725 } 04726 04727 // get the difference of the two closest points 04728 CubitVector dP = CubitVector(w + (sc * u) - (tc * v)); // = <0 0 0> if intersection 04729 04730 double distance = sqrt(dP % dP); // return the closest distance (0 if intersection) 04731 04732 point->set(u0 + (sc * u)); 04733 hit_distance = tc; //distance from origin to intersection point 04734 04735 if (distance < tol) 04736 { 04737 //check if parallel (infinite intersection) 04738 if (D < tol) 04739 return 2; 04740 //check if on edge 04741 if (sc <= 1.0 && sc >= 0.0) 04742 return 1; 04743 else 04744 return 0; 04745 } 04746 04747 return 0; 04748 } 04749 04750 double FacetEvalTool::contained_volume( DLIList<CubitFacet *> &facets ) 04751 { 04752 CubitVector p0, p1, p2, p3, normal; 04753 double volume = 0.0; 04754 04755 facets.reset(); 04756 for (int i = facets.size(); i--; ) 04757 { 04758 CubitFacet* facet = facets.get_and_step(); 04759 p1 = facet->point(0)->coordinates(); 04760 p2 = facet->point(1)->coordinates(); 04761 p3 = facet->point(2)->coordinates(); 04762 normal = (p3 - p1) * (p2 - p1); 04763 04764 double two_area = normal.length(); 04765 if (two_area > CUBIT_RESABS ) 04766 { 04767 normal /= two_area; 04768 04769 double height = normal % (p0 - p1); 04770 double vol = two_area * height; 04771 volume += vol; 04772 } 04773 } 04774 04775 volume /= 6.0; 04776 return volume; 04777 } 04778