cgma
FacetEvalTool.cpp
Go to the documentation of this file.
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 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines