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