cgma
CubitFacetEdge.cpp
Go to the documentation of this file.
00001 //======================================================================= 
00002 // 
00003 //  File: CubitFacetEdge 
00004 //  Description: used for edges of CubitFacets.  These are optional 
00005 //               and used only if specific information must be stored at  
00006 //               the edge common to two facets. 
00007 //  Notes: See notes in CubitFacetEdge.hpp 
00008 //  Owner: sjowen 
00009 // 
00010 //======================================================================= 
00011  
00012 #include "CubitFacetEdge.hpp" 
00013 #include "CubitFacet.hpp" 
00014 #include "CubitPoint.hpp" 
00015 #include "CubitVector.hpp" 
00016 #include "GeometryDefines.h" 
00017 #include "FacetEvalTool.hpp" 
00018 #include "GfxDebug.hpp"
00019 #include "IntersectionTool.hpp"
00020 #include "CubitMessage.hpp"
00021 
00022  
00023 //====================================================================== 
00024 // Function: CubitFacetEdge (PUBLIC) 
00025 // Description: constructor 
00026 // Author: sjowen 
00027 // Date: 8/00 
00028 //====================================================================== 
00029 CubitFacetEdge::CubitFacetEdge( )  
00030     : bezierOrder(0), markedFlag(0), isFeature(0), isFlipped(CUBIT_FALSE) 
00031 {  
00032 } 
00033  
00034  
00035 //====================================================================== 
00036 // Function: ~CubitFacetEdge (PUBLIC) 
00037 // Description: destructor 
00038 // Author: sjowen 
00039 // Date: 8/00 
00040 //====================================================================== 
00041 CubitFacetEdge::~CubitFacetEdge() 
00042 { 
00043 } 
00044  
00045 //====================================================================== 
00046 // Function: set_control_points (PUBLIC) 
00047 // Description: set the control points from an array of doubles 
00048 // Author: sjowen 
00049 // Date: 8/00 
00050 //====================================================================== 
00051 void CubitFacetEdge::set_control_points( const double *ctrl_pt_array )  
00052 { 
00053   int ii;
00054   for (ii=0; ii<3; ii++)
00055   {
00056     controlPoints[ii].x( ctrl_pt_array[ii*3] );
00057     controlPoints[ii].y( ctrl_pt_array[ii*3+1] );
00058     controlPoints[ii].z( ctrl_pt_array[ii*3+2] );
00059   }
00060 }
00061 
00062 //====================================================================== 
00063 // Function: control_points (PUBLIC) 
00064 // Description: return the Bezier control points (including the end points) 
00065 //        The order of the bezier is returned. 
00066 // Author: sjowen 
00067 // Date: 8/00 
00068 //====================================================================== 
00069 int CubitFacetEdge::control_points( CubitVector *ctrl_pts )  
00070 { 
00071   DLIList<CubitPoint*> my_points; 
00072   points(my_points); 
00073    
00074   ctrl_pts[0] = my_points.get()->coordinates(); 
00075   for(int i=0; i<bezierOrder-1; i++) { 
00076     ctrl_pts[i+1] = controlPoints[i]; 
00077   } 
00078   ctrl_pts[bezierOrder] = my_points.next()->coordinates(); 
00079   return bezierOrder; 
00080 }
00081  
00082 //====================================================================== 
00083 // Function: control_points (PUBLIC) 
00084 // Description: return the control points on the edge of a facet based 
00085 //        on its edge use direction 
00086 // Author: sjowen 
00087 // Date: 8/00 
00088 //====================================================================== 
00089 CubitStatus CubitFacetEdge::control_points(  
00090   CubitFacet *facet, CubitVector *ctrl_pts ) 
00091 { 
00092   int index = -1; 
00093   CubitBoolean found = CUBIT_FALSE; 
00094   for (int i=0; i<3 && !found; i++) { 
00095     if (this == facet->edge(i)) { 
00096       index = i; 
00097       found = CUBIT_TRUE; 
00098     } 
00099   } 
00100   if (!found) { 
00101     return CUBIT_FAILURE; 
00102   } 
00103  
00104   DLIList<CubitPoint*> my_points; 
00105   points(my_points); 
00106    
00107   switch (facet->edge_use(index)) { 
00108   case 1: 
00109     ctrl_pts[0] = my_points.get()->coordinates(); 
00110     ctrl_pts[1] = controlPoints[0]; 
00111     ctrl_pts[2] = controlPoints[1]; 
00112     ctrl_pts[3] = controlPoints[2]; 
00113     ctrl_pts[4] = my_points.next()->coordinates(); 
00114     break; 
00115   case -1: 
00116     ctrl_pts[0] = my_points.next()->coordinates(); 
00117     ctrl_pts[1] = controlPoints[2]; 
00118     ctrl_pts[2] = controlPoints[1]; 
00119     ctrl_pts[3] = controlPoints[0]; 
00120     ctrl_pts[4] = my_points.get()->coordinates(); 
00121     break; 
00122   default: 
00123     return CUBIT_FAILURE; 
00124   } 
00125   return CUBIT_SUCCESS; 
00126 } 
00127  
00128 //=========================================================================== 
00129 //Function Name: evaluate_position 
00130 // 
00131 //Member Type:  PUBLIC 
00132 //Description:  evaluate the facet edge at a position 
00133 //              eval_tangent is NULL if tangent not needed 
00134 //=========================================================================== 
00135 CubitStatus CubitFacetEdge::evaluate_position( const CubitVector &start_position, 
00136                                                CubitVector *eval_point, 
00137                                                CubitVector *eval_tangent)  
00138 { 
00139   CubitStatus stat = CUBIT_SUCCESS; 
00140  
00141   // find the adjacent facet 
00142  
00143   CubitFacet *facet_ptr = this->adj_facet( 0 ); 
00144  
00145   // If there is none or this is a linear representation -  
00146   // then project to the linear edge  
00147  
00148   if (!facet_ptr || facet_ptr->eval_order() == 0 || facet_ptr->is_flat()) 
00149   { 
00150     if (eval_point) 
00151     { 
00152       closest_point(start_position, *eval_point); 
00153     } 
00154     if (eval_tangent) 
00155     { 
00156       *eval_tangent = point(1)->coordinates() - point(0)->coordinates(); 
00157       (*eval_tangent).normalize(); 
00158     } 
00159   } 
00160   else 
00161   { 
00162     int vert0 = facet_ptr->point_index( point(0) ); 
00163     int vert1 = facet_ptr->point_index( point(1) ); 
00164     CubitVector pt_on_plane, close_point; 
00165     CubitVector start = start_position; 
00166     double dist_to_plane; 
00167     CubitBoolean outside_facet; 
00168     FacetEvalTool::project_to_facet_plane( facet_ptr, start,  
00169                                            pt_on_plane, dist_to_plane ); 
00170     stat = FacetEvalTool::project_to_facetedge( facet_ptr,  
00171                                                 vert0, vert1, 
00172                                                 start, 
00173                                                 pt_on_plane,  
00174                                                 close_point, 
00175                                                 outside_facet ); 
00176     if (eval_point) 
00177     { 
00178       *eval_point = close_point; 
00179     } 
00180     if (eval_tangent) 
00181     { 
00182       CubitVector edvec = point(1)->coordinates() - point(0)->coordinates(); 
00183       edvec.normalize(); 
00184       CubitVector areacoord; 
00185       FacetEvalTool::facet_area_coordinate( facet_ptr, close_point, areacoord );  
00186       FacetEvalTool::eval_facet_normal(facet_ptr, areacoord, *eval_tangent); 
00187       CubitVector cross = edvec * *eval_tangent; 
00188       *eval_tangent = *eval_tangent * cross; 
00189       (*eval_tangent).normalize(); 
00190     } 
00191   }
00192 
00193   return stat;
00194 } 
00195  
00196 //=========================================================================== 
00197 //Function Name: evaluate 
00198 // 
00199 //Member Type:  PUBLIC 
00200 //Description:  evaluate the facet at area coordinates 
00201 //              eval_normal is NULL if normal not needed 
00202 //Note:         t is a value from -1 to 1.  t=0 is the midpoint 
00203 //=========================================================================== 
00204 CubitStatus CubitFacetEdge::evaluate( double &t,  
00205                                       CubitVector *eval_point, 
00206                                       CubitVector *eval_tangent )      
00207 { 
00208   CubitStatus stat = CUBIT_SUCCESS; 
00209  
00210   // project the position to the linear edge 
00211    
00212   double tt = (t + 1) * 0.5; 
00213   if (tt <= 0.0) tt = 0.0; 
00214   if (tt >= 1.0) tt = 1.0; 
00215   *eval_point = point(0)->coordinates() +  
00216     tt * (point(1)->coordinates() - point(0)->coordinates()); 
00217  
00218   // evaluate the point on the facet (if the order is higher than 0) 
00219  
00220   CubitFacet *facet_ptr = this->adj_facet( 0 ); 
00221   if (!facet_ptr || facet_ptr->is_flat()) 
00222   { 
00223     if (eval_tangent) 
00224     { 
00225       *eval_tangent = point(1)->coordinates() - point(0)->coordinates(); 
00226       (*eval_tangent).normalize(); 
00227     } 
00228   } 
00229   else 
00230   { 
00231     CubitVector areacoord; 
00232     FacetEvalTool::facet_area_coordinate( facet_ptr, *eval_point, areacoord ); 
00233     stat = facet_ptr->evaluate( areacoord, eval_point, eval_tangent ); 
00234     if (stat != CUBIT_SUCCESS) 
00235       return stat; 
00236     if (eval_tangent) 
00237     { 
00238       CubitVector edvec = point(1)->coordinates() - point(0)->coordinates(); 
00239       edvec.normalize(); 
00240       CubitVector cross = edvec * *eval_tangent; 
00241       *eval_tangent = *eval_tangent * cross; 
00242       (*eval_tangent).normalize(); 
00243     } 
00244   } 
00245   return stat; 
00246 } 
00247  
00248 //=========================================================================== 
00249 //Function Name: evaluate_single 
00250 // 
00251 //Member Type:  PUBLIC 
00252 //Description:  evaluate edge not associated with a facet. 
00253 //Note:         t is a value from -1 to 1.
00254 //=========================================================================== 
00255 CubitStatus CubitFacetEdge::evaluate_single(double &t,
00256                             CubitVector *outv)
00257 {
00258 CubitVector P0, P1;
00259 double t4, t3, t2, one_minus_t, one_minus_t2, one_minus_t3, one_minus_t4;
00260 DLIList<CubitPoint*> my_points; 
00261   // project the position to the linear edge 
00262    
00263   double tt = (t + 1) * 0.5; 
00264   if (tt <= 0.0) tt = 0.0; 
00265   if (tt >= 1.0) tt = 1.0; 
00266 
00267   points(my_points);
00268  
00269   P0 = my_points.get()->coordinates();
00270   P1 = my_points.next()->coordinates();
00271 
00272   t2 = tt*tt;
00273   t3 = t2*tt;
00274   t4 = t3*tt;  
00275   one_minus_t = 1.-tt;
00276   one_minus_t2 = one_minus_t*one_minus_t;
00277   one_minus_t3 = one_minus_t2*one_minus_t;
00278   one_minus_t4 = one_minus_t3*one_minus_t;
00279   
00280   *outv = one_minus_t4*P0 + 
00281        4.*one_minus_t3*tt* controlPoints[0] + 
00282        6.*one_minus_t2*t2*controlPoints[1] + 
00283        4.*one_minus_t* t3*controlPoints[2] + 
00284                     t4*P1;
00285 
00286   return CUBIT_SUCCESS;
00287 }
00288  
00289 //=========================================================================== 
00290 //Function Name: evaluate_single_tangent 
00291 // 
00292 //Member Type:  PUBLIC 
00293 //Description:  evaluate tangent to edge not associated with a facet. 
00294 //Note:         t is a value from -1 to 1.
00295 //=========================================================================== 
00296 CubitStatus CubitFacetEdge::evaluate_single_tangent(double &t,
00297                                                     CubitVector *outv)
00298 {
00299 CubitVector P0, P1;
00300 double t3, t2, one_minus_t, one_minus_t2, one_minus_t3;
00301 DLIList<CubitPoint*> my_points; 
00302   // project the position to the linear edge 
00303    
00304   double tt = (t + 1) * 0.5; 
00305   if (tt <= 0.0) tt = 0.0; 
00306   if (tt >= 1.0) tt = 1.0; 
00307 
00308   points(my_points);
00309  
00310   P0 = my_points.get()->coordinates();
00311   P1 = my_points.next()->coordinates();
00312 
00313   t2 = tt*tt;
00314   t3 = t2*tt;
00315   one_minus_t = 1.-tt;
00316   one_minus_t2 = one_minus_t*one_minus_t;
00317   one_minus_t3 = one_minus_t2*one_minus_t;
00318   
00319   *outv = -4.*one_minus_t3*P0 +
00320           4.*(one_minus_t3 -3.*tt*one_minus_t2)*controlPoints[0] +
00321           12.*(tt*one_minus_t2 - t2*one_minus_t)*controlPoints[1] +
00322           4.*(3.*t2*one_minus_t - t3)*controlPoints[2] +
00323           4.*t3*P1;
00324 
00325   return CUBIT_SUCCESS;
00326 }
00327   
00328 //=========================================================================== 
00329 //Function Name: evaluate_2nd_derivative 
00330 // 
00331 //Member Type:  PUBLIC 
00332 //Description:  evaluate tangent to edge not associated with a facet. 
00333 //Note:         t is a value from -1 to 1.
00334 //=========================================================================== 
00335 CubitStatus CubitFacetEdge::evaluate_2nd_derivative(double &t,
00336                                                     CubitVector *outv)
00337 {
00338 CubitVector P0, P1, second_d;
00339 DLIList<CubitPoint*> my_points; 
00340 double val;
00341   // project the position to the linear edge 
00342    
00343   double tt = (t + 1) * 0.5; 
00344   if (tt <= 0.0) tt = 0.0; 
00345   if (tt >= 1.0) tt = 1.0; 
00346 
00347   points(my_points);
00348  
00349   P0 = my_points.get()->coordinates();
00350   P1 = my_points.next()->coordinates();
00351 
00352   val = 12.*(1.-tt)*(1.-tt)*P0.x() -
00353         24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].x() +
00354         12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].x() +
00355         24.*(tt - 2.*tt*tt)*controlPoints[2].x() +
00356         12.*tt*tt*P1.x();
00357   second_d.x(val);
00358   val = 12.*(1.-tt)*(1.-tt)*P0.y() -
00359         24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].y() +
00360         12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].y() +
00361         24.*(tt - 2.*tt*tt)*controlPoints[2].y() +
00362         12.*tt*tt*P1.y();
00363   second_d.y(val);
00364   val = 12.*(1.-tt)*(1.-tt)*P0.z() -
00365         24.*(2.*tt*tt - 3.*tt + 1.)*controlPoints[0].z() +
00366         12.*(6.*tt*tt - 6.*tt + 1.)*controlPoints[1].z() +
00367         24.*(tt - 2.*tt*tt)*controlPoints[2].z() +
00368         12.*tt*tt*P1.z();
00369   second_d.z(val);
00370   *outv = second_d;
00371   
00372   return CUBIT_SUCCESS;
00373 }
00374 
00375 //=========================================================================== 
00376 //Function Name: closest_point 
00377 // 
00378 //Member Type:  PUBLIC 
00379 //Description:  return the closest point on segment defined by the edge 
00380 //=========================================================================== 
00381 CubitStatus CubitFacetEdge::closest_point(const CubitVector &point,  
00382                                           CubitVector &closest_point ) 
00383 {  
00384   //CubitStatus rv = CUBIT_SUCCESS; 
00385   CubitPoint *pt0 = this->point(0); 
00386   CubitPoint *pt1 = this->point(1); 
00387  
00388   // the edge vector 
00389  
00390   CubitVector e0 ( pt1->x() - pt0->x(), 
00391                    pt1->y() - pt0->y(), 
00392                    pt1->z() - pt0->z() ); 
00393   double elen = e0.normalize(); 
00394    
00395   // vector from vert0 to point 
00396  
00397   CubitVector v0 ( point.x() - pt0->x(), 
00398                    point.y() - pt0->y(), 
00399                    point.z() - pt0->z() ); 
00400    
00401   // project to edge 
00402  
00403   double len = v0%e0; 
00404   if (len <= 0.0) 
00405   { 
00406     closest_point = pt0->coordinates(); 
00407   } 
00408   else if( len >= elen ) 
00409   { 
00410     closest_point = pt1->coordinates(); 
00411   } 
00412   else 
00413   { 
00414     closest_point.x ( pt0->x() + e0.x() * len ); 
00415     closest_point.y ( pt0->y() + e0.y() * len ); 
00416     closest_point.z ( pt0->z() + e0.z() * len ); 
00417   } 
00418  
00419   return CUBIT_SUCCESS; 
00420 }
00421 
00422  //=========================================================================== 
00423 //Function Name: intersect 
00424 // 
00425 //Member Type:  PUBLIC 
00426 //Description:  intersect the edge with a segment.  Assumes segment and edge
00427 //              are on the same plane (project to facet plane first) 
00428 //=========================================================================== 
00429 CubitStatus CubitFacetEdge::intersect(
00430   CubitVector &aa, CubitVector &bb, // end point of segment
00431   CubitVector &norm,  // normal of the common plane
00432   CubitVector &qq,  // return the intersection point 
00433   CubitBoolean &does_intersect ) // return status of intersection
00434 {  
00435  
00436   CubitPoint *pt0 = this->point(0); 
00437   CubitPoint *pt1 = this->point(1); 
00438 
00439   double P0[2], P1[2], AA[2], BB[2];
00440   CubitVector absnorm(fabs(norm.x()), fabs(norm.y()), fabs(norm.z()));
00441   if (absnorm.x() >= absnorm.y() && absnorm.x() >= absnorm.z())
00442   {
00443     P0[0] = pt0->coordinates().y();  P0[1] = pt0->coordinates().z();
00444     P1[0] = pt1->coordinates().y();  P1[1] = pt1->coordinates().z();
00445     AA[0] = aa.y();                  AA[1] = aa.z();
00446     BB[0] = bb.y();                  BB[1] = bb.z();
00447   }
00448   else if (absnorm.y() >= absnorm.x() && absnorm.y() >= absnorm.z())
00449   {
00450     P0[0] = pt0->coordinates().z();  P0[1] = pt0->coordinates().x();
00451     P1[0] = pt1->coordinates().z();  P1[1] = pt1->coordinates().x();
00452     AA[0] = aa.z();                  AA[1] = aa.x();
00453     BB[0] = bb.z();                  BB[1] = bb.x();
00454   }
00455   else
00456   {
00457     P0[0] = pt0->coordinates().x();  P0[1] = pt0->coordinates().y();
00458     P1[0] = pt1->coordinates().x();  P1[1] = pt1->coordinates().y();
00459     AA[0] = aa.x();                  AA[1] = aa.y();
00460     BB[0] = bb.x();                  BB[1] = bb.y();
00461   }
00462 
00463   double QQ[4], s;
00464   int ninter = intersect_2D_segments(P0, P1, AA, BB, QQ);
00465 
00466   if (ninter != 1)
00467   {
00468     does_intersect = CUBIT_FALSE;
00469     return CUBIT_SUCCESS;
00470   }
00471   does_intersect = CUBIT_TRUE;
00472  
00473   double dx = P1[0] - P0[0];
00474   double dy = P1[1] - P0[1];
00475   if (fabs(dx) > fabs(dy))
00476     s = (QQ[0] - P0[0]) / dx;
00477   else
00478     s = (QQ[1] - P0[1]) / dy;
00479   
00480   qq = pt0->coordinates() + s * (pt1->coordinates() - pt0->coordinates());
00481  
00482   return CUBIT_SUCCESS; 
00483 }  
00484  
00485 //====================================================================== 
00486 // Function: boundary_edge_points (PUBLIC) 
00487 // Description: return the oriented endpoints of a facet edge assuming 
00488 //        the edge is at the frontier of the facets (only one adjacency) 
00489 // Author: sjowen 
00490 // Date: 8/00 
00491 //====================================================================== 
00492 void CubitFacetEdge::boundary_edge_points( CubitPoint * &pt0,  
00493                                            CubitPoint * &pt1, 
00494                                            int tool_id ) 
00495 { 
00496   if(num_adj_facets() == 0) 
00497   { 
00498     pt0 = point(0); 
00499     pt1 = point(1); 
00500     return; 
00501   } 
00502   CubitFacet *facet = NULL; 
00503   if (tool_id != 0) 
00504   { 
00505     int ii; 
00506     int found = 0; 
00507     DLIList <CubitFacet *> adj_facets; 
00508     facets(adj_facets); 
00509     for (ii=0; ii<adj_facets.size() && !found; ii++) 
00510     { 
00511       facet = adj_facets.get_and_step(); 
00512       if (facet->tool_id() == tool_id) 
00513         found = 1; 
00514     } 
00515     assert(found); 
00516   } 
00517   else 
00518   { 
00519     facet = adj_facet(0); 
00520     if (!facet) facet = adj_facet(1); 
00521     assert(facet != 0); 
00522   } 
00523    
00524   int index = facet->edge_index( this ); 
00525   int use = facet->edge_use( index ); 
00526   if (use == 1) { 
00527     pt0 = point(0); 
00528     pt1 = point(1); 
00529   } 
00530   else { 
00531     pt0 = point(1); 
00532     pt1 = point(0); 
00533   } 
00534 } 
00535  
00536 //====================================================================== 
00537 // Function: dist_to_edge 
00538 // Description: return the distance from the point to this edge 
00539 // Author: sjowen 
00540 // Date: 2/01 
00541 // Corrected by JFowler 5/03
00542 //====================================================================== 
00543 double CubitFacetEdge::dist_to_edge( 
00544   const CubitVector &this_point,  
00545   CubitVector &close_point,  
00546   CubitBoolean &outside_edge ) 
00547 { 
00548   double dist = 0.0; 
00549   CubitVector p0 = point(0)->coordinates(); 
00550   CubitVector p1 = point(1)->coordinates(); 
00551   CubitVector edge_vec( p1, p0 ); 
00552   CubitVector point_vec( this_point, p0 ); 
00553   double edge_length;  
00554   edge_length = edge_vec.normalize(); 
00555   double dist_on_edge = edge_vec % point_vec; 
00556   if (dist_on_edge < 0.0e0) 
00557   { 
00558     close_point = p0; 
00559     outside_edge = CUBIT_TRUE; 
00560   } 
00561   else if (dist_on_edge > edge_length) 
00562   { 
00563     close_point = p1; 
00564     outside_edge = CUBIT_TRUE; 
00565   } 
00566   else 
00567   { 
00568     close_point = p0 - edge_vec * dist_on_edge; 
00569     outside_edge = CUBIT_FALSE; 
00570   } 
00571   dist = close_point.distance_between( this_point );  
00572   return dist; 
00573 }
00574  
00575 /*//====================================================================== 
00576 // Function: dist_to_edge 
00577 // Description: return the distance from the point to this edge 
00578 // Author: sjowen 
00579 // Date: 2/01 
00580 //====================================================================== 
00581 double CubitFacetEdge::dist_to_edge( 
00582   CubitVector &this_point,  
00583   CubitVector &close_point,  
00584   CubitBoolean &outside_edge ) 
00585 { 
00586   double dist = 0.0; 
00587   CubitVector p0 = point(0)->coordinates(); 
00588   CubitVector p1 = point(1)->coordinates(); 
00589   CubitVector edge_vec( p1, p0 ); 
00590   CubitVector point_vec( this_point, p0 ); 
00591   point_vec.normalize(); 
00592   double dist_on_edge = edge_vec % point_vec; 
00593   double edge_length; 
00594   edge_length = edge_vec.normalize(); 
00595   if (dist_on_edge < 0.0e0) 
00596   { 
00597     close_point = p0; 
00598     outside_edge = CUBIT_TRUE; 
00599   } 
00600   else if (dist_on_edge > edge_length) 
00601   { 
00602     close_point = p1; 
00603     outside_edge = CUBIT_TRUE; 
00604   } 
00605   else 
00606   { 
00607     close_point = p0 + edge_vec * dist_on_edge; 
00608     outside_edge = CUBIT_FALSE; 
00609   } 
00610   dist = close_point.distance_between( this_point );  
00611   return dist; 
00612 } 
00613 */ 
00614 //====================================================================== 
00615 // Function: proj_to_line 
00616 // Description: project the point to a line defined by the edge 
00617 // Author: sjowen 
00618 // Date: 2/01 
00619 //====================================================================== 
00620 CubitStatus  CubitFacetEdge::proj_to_line(  
00621   const CubitVector &this_point,  
00622   CubitVector &proj_point ) 
00623 { 
00624   CubitStatus stat = CUBIT_SUCCESS; 
00625   CubitVector p0 = point(0)->coordinates(); 
00626   CubitVector p1 = point(1)->coordinates(); 
00627   CubitVector edge_vec( p0,p1 ); 
00628   CubitVector point_vec( p0, this_point ); 
00629   edge_vec.normalize(); 
00630   double dist_on_edge = edge_vec % point_vec;   
00631   proj_point = p0 + (edge_vec * dist_on_edge); 
00632  
00633   return stat; 
00634 } 
00635  
00636 //====================================================================== 
00637 // Function: edge_tangent 
00638 // Description: return tangent at a point on the edge 
00639 // Author: sjowen 
00640 // Date: 2/01 
00641 //====================================================================== 
00642 CubitStatus  CubitFacetEdge::edge_tangent(  
00643   const CubitVector &/*point_on_edge*/,  
00644   CubitVector &tangent ) 
00645 { 
00646   CubitStatus stat = CUBIT_SUCCESS; 
00647   tangent = point(1)->coordinates() - 
00648             point(0)->coordinates(); 
00649   tangent.normalize(); 
00650   return stat; 
00651 }
00652 
00653 //====================================================================== 
00654 // Function: edge_tangent 
00655 // Description: return curvature at a point on the edge 
00656 // Author: sjowen 
00657 // Date: 2/01 
00658 //====================================================================== 
00659 CubitStatus  CubitFacetEdge::edge_curvature(  
00660   const CubitVector &/*point_on_edge*/,  
00661   CubitVector &curvature,
00662   CubitFacetEdge *closest_edge ) 
00663 { 
00664   CubitVector vec_ba, vec_ca, center_point;
00665 
00666   //if point(0) is middle point
00667   if( closest_edge->other_point( point(0) ) )  
00668   {
00669     center_point = point(0)->coordinates();
00670     vec_ba = closest_edge->point(0)->coordinates() - center_point; 
00671     vec_ca = point(1)->coordinates() - center_point; 
00672   }
00673   //if point(1) is middle point
00674   else if( closest_edge->other_point( point(1) ) )  
00675   {
00676     center_point = point(1)->coordinates();
00677     vec_ba = point(0)->coordinates() - center_point; 
00678     vec_ca = closest_edge->point(1)->coordinates() - center_point; 
00679   }
00680   else
00681     assert(0);
00682   
00683   // Squares of lengths of the edges incident to `a'.
00684   double ba_length = vec_ba.length_squared();
00685   double ca_length = vec_ca.length_squared();
00686   
00687   // Cross product of these edges.
00688   // (Take your chances with floating-point roundoff.)
00689   CubitVector cross_bc = vec_ba * vec_ca;
00690   
00691   // Calculate the denominator of the formulae.
00692   double temp_dbl = cross_bc % cross_bc;
00693   CubitVector circle_center(0.0,0.0,0.0);
00694   if(fabs(temp_dbl) > CUBIT_DBL_MIN){
00695     double denominator = 0.5 / (temp_dbl);
00696     assert(denominator != 0.0);
00697   
00698     // Calculate offset (from `a') of circumcenter.
00699     circle_center  = (ba_length * vec_ca - ca_length * vec_ba) * cross_bc;
00700     circle_center *= denominator;
00701 
00702     //store radius
00703     double radius = circle_center.length();
00704     circle_center.normalize();
00705     circle_center /= radius;
00706   } 
00707   curvature = circle_center; 
00708 
00709   return CUBIT_SUCCESS; 
00710 } 
00711  
00712 //====================================================================== 
00713 // Function: length 
00714 // Description: return length of an edge 
00715 // Author: sjowen 
00716 // Date: 2/01 
00717 //====================================================================== 
00718 double CubitFacetEdge::length() 
00719 { 
00720   CubitVector start = point(0)->coordinates(); 
00721   CubitVector end = point(1)->coordinates(); 
00722   return start.distance_between( end ); 
00723 } 
00724 
00725 //====================================================================== 
00726 // Function: length 
00727 // Description: return length of an edge 
00728 // Author: jakraft 
00729 // Date: 3/04
00730 //====================================================================== 
00731 CubitVector CubitFacetEdge::position_from_fraction( double f )
00732 {
00733   return (1.0 - f) * point(0)->coordinates() +
00734                 f  * point(1)->coordinates();
00735 }
00736 
00737 //====================================================================== 
00738 // Function: other_point 
00739 // Description: return the other point on the edge 
00740 // Author: sjowen 
00741 // Date: 4/01 
00742 //====================================================================== 
00743 CubitPoint* CubitFacetEdge::other_point( CubitPoint *point_ptr ) 
00744 { 
00745   if (point(0) == point_ptr) 
00746     return point(1); 
00747   if(point(1) == point_ptr) 
00748     return point(0); 
00749   return NULL; 
00750 } 
00751  
00752 //====================================================================== 
00753 // Function: get_parents 
00754 // Description: return entities attached to this edge 
00755 // Author: sjowen 
00756 // Date: 4/01 
00757 //====================================================================== 
00758 void CubitFacetEdge::get_parents(DLIList<FacetEntity *> &facet_list) 
00759 { 
00760   DLIList<CubitFacet *> cf_list; 
00761   facets( cf_list ); 
00762   for (int ii=0; ii<cf_list.size(); ii++) 
00763     facet_list.append(cf_list.get_and_step()); 
00764 } 
00765  
00766 //====================================================================== 
00767 // Function: other_facet 
00768 // Description: return the other facet on the edge (assumes 
00769 //              max two facets per edge) 
00770 // Author: sjowen 
00771 // Date: 5/01 
00772 //====================================================================== 
00773 CubitFacet *CubitFacetEdge::other_facet( CubitFacet *facet_ptr ) 
00774 { 
00775   DLIList<CubitFacet *> cf_list; 
00776   facets( cf_list ); 
00777   assert(cf_list.size() < 3); 
00778   CubitFacet *adj_facet = NULL; 
00779   if (cf_list.size() > 0) 
00780   { 
00781     adj_facet = cf_list.get_and_step(); 
00782     if (adj_facet == facet_ptr) 
00783     { 
00784       if (cf_list.size() == 2) 
00785       { 
00786         adj_facet = cf_list.get(); 
00787       } 
00788     } 
00789   } 
00790   return adj_facet; 
00791 } 
00792  
00793 //====================================================================== 
00794 // Function: other_facet_on_surf 
00795 // Description: return the other facet on the edge that has the 
00796 //              same tool id. (finds the first occurrence 
00797 //              of the same tool id of the adjacent facets 
00798 //              to this edge that is not facet_ptr) 
00799 // Author: sjowen 
00800 // Date: 5/01 
00801 //====================================================================== 
00802 CubitFacet *CubitFacetEdge::other_facet_on_surf( CubitFacet *facet_ptr ) 
00803 { 
00804   assert(facet_ptr != 0); 
00805   int tool_id = facet_ptr->tool_id(); 
00806   DLIList<CubitFacet *> cf_list; 
00807   facets( cf_list ); 
00808   CubitFacet *adj_facet = NULL; 
00809   int found = 0; 
00810   for (int ii=0; ii<cf_list.size() && !found; ii++) 
00811   { 
00812     adj_facet = cf_list.get_and_step(); 
00813     if (adj_facet != facet_ptr) 
00814     { 
00815       if (adj_facet->tool_id() == tool_id) 
00816         found = 1; 
00817     } 
00818   } 
00819   if (!found) 
00820     adj_facet = NULL; 
00821   return adj_facet; 
00822 } 
00823  
00824 //====================================================================== 
00825 // Function: num_adj_facets_on_surf 
00826 // Description: count the number of adjacent facets to this edge that 
00827 //              have the specified tool id 
00828 // Author: sjowen 
00829 // Date: 5/01 
00830 //====================================================================== 
00831 int CubitFacetEdge::num_adj_facets_on_surf( int tool_id ) 
00832 { 
00833  
00834   DLIList<CubitFacet *> cf_list; 
00835   facets( cf_list ); 
00836   CubitFacet *adj_facet = NULL; 
00837   int nfacets = 0; 
00838   for (int ii=0; ii<cf_list.size(); ii++) 
00839   { 
00840     adj_facet = cf_list.get_and_step(); 
00841     if (adj_facet->tool_id() == tool_id) 
00842       nfacets++; 
00843   } 
00844   return nfacets; 
00845 } 
00846  
00847 //====================================================================== 
00848 // Function: adj_facet_on_surf 
00849 // Description: return the first facet on the adjacent facet list with  
00850 //              the indicated tool id 
00851 // Author: sjowen 
00852 // Date: 5/01 
00853 //====================================================================== 
00854 CubitFacet *CubitFacetEdge::adj_facet_on_surf( int tool_id ) 
00855 { 
00856   DLIList<CubitFacet *> cf_list; 
00857   facets( cf_list ); 
00858   CubitFacet *adj_facet = NULL; 
00859   int found = 0; 
00860   for (int ii=0; ii<cf_list.size() && !found; ii++) 
00861   { 
00862     adj_facet = cf_list.get_and_step(); 
00863     if (adj_facet->tool_id() == tool_id) 
00864     { 
00865       found = 1; 
00866     } 
00867   } 
00868   if (!found) 
00869     adj_facet = NULL; 
00870   return adj_facet; 
00871 } 
00872  
00873 //====================================================================== 
00874 // Function: contains 
00875 // Description: determines if point is contained in edge 
00876 // Author: sjowen 
00877 // Date: 5/01 
00878 //====================================================================== 
00879 CubitBoolean CubitFacetEdge::contains( CubitPoint *point_ptr ) 
00880 { 
00881   if (point(0) == point_ptr || point(1) == point_ptr) 
00882     return CUBIT_TRUE; 
00883   return CUBIT_FALSE; 
00884 } 
00885  
00886 //====================================================================== 
00887 // Function: draw 
00888 // Description: draw the edge 
00889 // Author: sjowen 
00890 // Date: 5/01 
00891 //====================================================================== 
00892 void CubitFacetEdge::debug_draw(int color, int flush, int /*draw_uv*/) 
00893 { 
00894   if ( color == -1 ) 
00895     color = CUBIT_RED_INDEX;
00896   GfxDebug::draw_facet_edge(this, color);
00897   GfxDebug::draw_point( point(0)->coordinates(), color );
00898   GfxDebug::draw_point( point(1)->coordinates(), color );
00899   if ( flush ) 
00900     GfxDebug::flush(); 
00901 } 
00902 
00903 //======================================================================
00904 // Function: shared_point (PUBLIC)
00905 // Description: find the common point
00906 // Author: sjowen
00907 // Date: 10/02
00908 //======================================================================
00909 CubitPoint *CubitFacetEdge::shared_point( CubitFacetEdge *edge_ptr )
00910 {
00911   CubitPoint *pA = this->point(0);
00912   CubitPoint *pB = this->point(1);
00913   CubitPoint *pC = edge_ptr->point(0);
00914   CubitPoint *pD = edge_ptr->point(1);
00915   CubitPoint *pShared = NULL;
00916   if (pA == pC || pA == pD)
00917   {
00918     pShared = pA;
00919   }
00920   else if (pB == pC || pB == pD)
00921   {
00922     pShared = pB;
00923   }
00924   return pShared;
00925 }
00926 
00927 
00928 //======================================================================
00929 // Function: bounding_box (PUBLIC)
00930 // Description: return the bounding box of the edge
00931 // Author: sjowen
00932 // Date: 10/02
00933 //======================================================================
00934 CubitBox CubitFacetEdge::bounding_box( )
00935 {
00936   CubitPoint *p1 = point (0);
00937   CubitPoint *p2 = point (1);
00938 
00939   CubitVector bbox_min, bbox_max;
00940   bbox_min.x(CUBIT_MIN(p1->x(),p2->x()));
00941   bbox_min.y(CUBIT_MIN(p1->y(),p2->y()));
00942   bbox_min.z(CUBIT_MIN(p1->z(),p2->z()));
00943   bbox_max.x(CUBIT_MAX(p1->x(),p2->x()));
00944   bbox_max.y(CUBIT_MAX(p1->y(),p2->y()));
00945   bbox_max.z(CUBIT_MAX(p1->z(),p2->z()));
00946   CubitBox edge_box(bbox_min,bbox_max);
00947   return edge_box;
00948 }
00949 
00950 //======================================================================
00951 //
00952 // The following 2 function really belong in IntersectionTool in the util
00953 // directory.  Because of the current distribution policy it was not easy
00954 // to get it into there without breaking the build.  These should be
00955 // removed at a later time and integrated with the IntersectionTool
00956 //
00957 //=======================================================================
00958 // Intersection of two line segments in 2D. Intersect [P0,P1] with [P2,P3]  
00959 // Return value is zero if there is no intersection, 1 if there is a unique 
00960 // intersection, and 2 if the 2 segments overlap and the intersection set is 
00961 // a segment itself.  The return value is the number of valid entries*2 in 
00962 // the array qq. 
00963 int CubitFacetEdge::intersect_2D_segments( double P0[2], double P1[2],
00964                                              double P2[2], double P3[2],
00965                                              double qq[4] )
00966 {
00967 
00968   double D0[2], D1[2];
00969   D0[0] = P1[0] - P0[0];  D0[1] = P1[1] - P0[1];
00970   D1[0] = P3[0] - P2[0];  D1[1] = P3[1] - P2[1];
00971 
00972   // segments P0 + s * D0 for s in [0,1],
00973   //          P2 + t * D1 for t in [0,1]
00974 
00975   double sqr_epsilon = DBL_EPSILON * DBL_EPSILON;
00976   double E[2];
00977   E[0] = P2[0] - P0[0];
00978   E[1] = P2[1] - P0[1];
00979 
00980   double kross = D0[0] * D1[1] - D0[1] * D1[0];
00981   double sqr_kross = kross * kross;
00982   double sqr_len0 = D0[0] * D0[0] + D0[1] * D0[1];
00983   double sqr_len1 = D1[0] * D1[0] + D1[1] * D1[1];
00984   if (sqr_kross > sqr_epsilon  * sqr_len0 * sqr_len1)
00985   {
00986     // lines of the segment are not parallel
00987 
00988     double s = (E[0] * D1[1] - E[1] * D1[0]) / kross;
00989     if (s < 0.0 || s > 1.0)
00990     {
00991        // intersection of lines is not a point on segment P0 + s * D0
00992       return 0;
00993     }
00994 
00995     double t = (E[0] * D0[1] - E[1] * D0[0]) / kross;
00996     if (t < 0.0 || t > 1.0)
00997     {
00998       // intersection of lines is not a point on segment P1 + t * D1
00999       return 0;
01000     }
01001 
01002     // intersection of lines is a point on each segment
01003 
01004     qq[0] = P0[0] + s * D0[0];
01005     qq[1] = P0[1] + s * D0[1];
01006     return 1;
01007   }
01008 
01009   // lines of the segments are parallel
01010 
01011   double sqr_lenE = E[0] * E[0] + E[1] * E[1];
01012   kross = E[0] * D0[1] - E[1] * D0[1];
01013   sqr_kross = kross * kross;
01014   if (sqr_kross > sqr_epsilon  * sqr_len0 * sqr_lenE)
01015   {
01016     // lines of the segments are different
01017     return 0;
01018   }
01019 
01020   // lines of the segment are the same.  Need to test for overlap of segments
01021 
01022   double s0 = (D0[0] * E[0] + D0[1] * E[1]) / sqr_len0;
01023   double s1 = s0 + (D0[0] * D1[0] + D0[1] * D1[1]) / sqr_len0;
01024   double smin = CUBIT_MIN(s0, s1);
01025   double smax = CUBIT_MAX(s0, s1);
01026 
01027   double w[2];
01028   int imax = intersect_intervals(0.0, 1.0, smin, smax, w);
01029   for (int i=0; i<imax; i++)
01030   {
01031     qq[i*2]   = P0[0] + w[i] * D0[0];
01032     qq[i*2+1] = P0[1] + w[i] * D0[1];
01033   }
01034   return imax;
01035 }
01036 
01037 // The intersection of two intervals [u0,u1] and [v0,v1], where u0<u1 and v0<v1.
01038 // Return value is zero if intervals do not intersect; 1 if they intersect at
01039 // a single point, in which case w[0] contains that point; or 2 if they intersect 
01040 // in an interval whose endpoints are stored in w[0] and w[1]
01041 int CubitFacetEdge::intersect_intervals( double u0, double u1,
01042                                            double v0, double v1,
01043                                            double w[2] )
01044 {
01045   if (u1 < v0 || u0 > v1)
01046     return 0;
01047 
01048   if (u1 > v0)
01049   {
01050     if (u0 < v1)
01051     {
01052       if (u0 < v0) 
01053         w[0] = v0;
01054       else 
01055         w[0] = u0;
01056       if (u1 > v1) 
01057         w[1] = v1;
01058       else 
01059         w[1] = u1;
01060       return 2;
01061     }
01062     else
01063     {
01064       w[0] = u0;
01065       return 1;
01066     }
01067   }
01068   else
01069   {
01070     w[0] = u1;
01071     return 1;
01072   }
01073   return 0;
01074 }
01075 
01076 //======================================================================
01077 // Function: add_facets (PUBLIC)
01078 // Description: add this edge to its adjacent facets
01079 // Author: sjowen
01080 // Date: 04/04
01081 //======================================================================
01082 void CubitFacetEdge::add_facets( )
01083 {
01084   CubitPoint *p0 = point (0);
01085   CubitPoint *p1 = point (1);
01086 
01087   DLIList<CubitFacet *> adj_facets;
01088   p0->shared_facets(p1, adj_facets );
01089 
01090   CubitFacet *facet;
01091   int ii;
01092   for(ii=0; ii<adj_facets.size(); ii++)
01093   {
01094     facet = adj_facets.get_and_step();
01095     facet->add_edge( this );
01096   }
01097 }
01098 
01099 double CubitFacetEdge::angle_between_facets()
01100 {
01101   CubitFacet *facet0 = adj_facet(0);
01102   CubitFacet *facet1 = adj_facet(1);
01103 
01104   // assumes facets are always oriented with outwards pointing normal
01105 
01106   CubitVector n0 = facet0->normal();
01107   CubitVector n1 = facet1->normal();
01108 
01109   // get orientation of edge with respect to facet0
01110 
01111   CubitPoint *p0 = point(0);
01112   CubitPoint *p1 = point(1);
01113   CubitPoint *pnext = facet0->next_node(p0);
01114   if (pnext != p1)
01115   {
01116     pnext = p0;
01117     p0 = p1;
01118     p1 = pnext;
01119   }
01120   CubitVector evec = p1->coordinates() - p0->coordinates();
01121   evec.normalize();
01122   CubitVector cross = n0 * n1;  cross.normalize();
01123   double angle;
01124   double edot = evec % cross;
01125   double ndot = n0 % n1;
01126   if (ndot >= 1.0)
01127     angle = 0.0;
01128   else if (ndot <= -1.0)
01129     angle = CUBIT_PI;
01130   else 
01131     angle = acos(ndot);
01132   if (edot <= 0.0)
01133   {
01134     angle = 2.0 * CUBIT_PI - angle;
01135   }
01136   return angle;
01137 }
01138 
01139 // order edges in list beginning at start_point
01140 // report the endpoint
01141 // return CUBIT_SUCCESS if all edges are connected and ordered successfully
01142 // otherwise return CUBIT_FAILURE, in which case no changes are made
01143 CubitStatus CubitFacetEdge::order_edge_list(DLIList<CubitFacetEdge*> &edge_list,
01144                                             CubitPoint *start_point,
01145                                             CubitPoint *&end_point)
01146 {
01147   int i;
01148   assert(start_point);
01149 
01150   end_point = NULL;
01151 
01152   // invalid input
01153   if (0 == edge_list.size())
01154     return CUBIT_FAILURE;
01155 
01156   // simple case of a single edge - endpoitn
01157   if (1 == edge_list.size())
01158   {
01159     end_point = edge_list.get()->other_point(start_point);
01160     return end_point ? CUBIT_SUCCESS : CUBIT_FAILURE;
01161   }
01162 
01163   edge_list.reset();
01164 
01165   // note that a periodic/closed curve will fail
01166   // we could handle that case here if needed, but we may need more information
01167   // to know where to start and end the curve
01168   if (NULL == start_point)
01169     return CUBIT_FAILURE;
01170 
01171   // put edges in a set for faster searching
01172   std::set<CubitFacetEdge *> edge_set;
01173   for (i=0; i<edge_list.size(); i++)
01174     edge_set.insert(dynamic_cast<CubitFacetEdge*> (edge_list.step_and_get()));
01175 
01176   // a vector for the ordered list
01177   std::vector<CubitFacetEdge*> ordered_edges;
01178 
01179   // find connected edges from the start point
01180   CubitPoint *cur_pt = start_point;
01181   do
01182   {
01183     // get edges connected to the current point and find the next edge
01184     DLIList<CubitFacetEdge *> pt_edges;
01185     cur_pt->edges(pt_edges);
01186 
01187     std::set<CubitFacetEdge *>::iterator iter_found;
01188     CubitFacetEdge *cur_edge = NULL;
01189     for (i=0; i<pt_edges.size() && !cur_edge; i++)
01190     {
01191       CubitFacetEdge *tmp_edge = pt_edges.get_and_step();
01192       iter_found = edge_set.find(tmp_edge);
01193       if ( iter_found != edge_set.end() )
01194         cur_edge = tmp_edge;
01195     }
01196 
01197     // if we don't find a connection before we empty the set
01198     // then not all the edges are connected  -- return failure
01199     if (NULL == cur_edge)
01200       return CUBIT_FAILURE;
01201 
01202     // add the edge to the ordered list
01203     ordered_edges.push_back( cur_edge );
01204     edge_set.erase(iter_found);
01205 
01206     cur_pt = cur_edge->other_point(cur_pt);
01207   }
01208   while ( edge_set.size());
01209 
01210   if (ordered_edges.size() != (size_t)edge_list.size())
01211     return CUBIT_FAILURE;
01212 
01213   // store the edges in the correct order
01214   edge_list.clean_out();
01215 
01216   std::vector<CubitFacetEdge*>::iterator iter;
01217   for (iter=ordered_edges.begin(); iter!=ordered_edges.end(); iter++)
01218     edge_list.append(*iter);
01219 
01220   // get the end point
01221   CubitFacetEdge *edge1 = edge_list[edge_list.size() - 1];
01222   CubitFacetEdge *edge2 = edge_list[edge_list.size() - 2];
01223 
01224   end_point = edge1->other_point( edge1->shared_point(edge2) );
01225 
01226   return CUBIT_SUCCESS;
01227 }
01228 
01229 CubitPoint *CubitFacetEdge::find_start_point_for_edge_list(DLIList<CubitFacetEdge*> edge_list)
01230 {
01231   // look for an edge with a point only connected to the one edge in the set
01232   //
01233   // TODO - this algorithm could be made more efficient by only checking one endpoint
01234   //        per edge.  The current implementation should match the order points were
01235   //        checked in previous functionality.
01236   //        If speed becomes an issue it could be reimplemented
01237   //
01238 
01239   if (1 == edge_list.size())
01240   {
01241     return edge_list[0]->point(0);
01242   }
01243 
01244   int i;
01245   CubitPoint *start_point = NULL;
01246   for (i=0; i<edge_list.size() && (start_point == NULL); i++)
01247   {
01248     CubitFacetEdge *tmp_edge = edge_list.get_and_step();
01249     DLIList<CubitFacetEdge*> pt_edges;
01250     tmp_edge->point(0)->edges(pt_edges);
01251 
01252     pt_edges.intersect_unordered(edge_list);
01253     if (pt_edges.size() == 1)
01254     {
01255       start_point = tmp_edge->point(0);
01256     }
01257     else
01258     {
01259       pt_edges.clean_out();
01260       tmp_edge->point(1)->edges(pt_edges);
01261       pt_edges.intersect_unordered(edge_list);
01262       if (pt_edges.size() == 1)
01263       {
01264         start_point = tmp_edge->point(1);
01265       }
01266     }
01267   }
01268   return start_point;
01269 }
01270 
01271 //EOF
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines