cgma
GeometryUtil.cpp
Go to the documentation of this file.
00001 //-------------------------------------------------------------------------
00002 // Filename      : GeometryUtil.cc
00003 //
00004 // Purpose       : 
00005 //
00006 // Special Notes : 
00007 //
00008 // Creator       : Jason Kraftcheck
00009 //
00010 // Creation Date : 08/03/98
00011 //-------------------------------------------------------------------------
00012 #define COMPSURF_KEEP_CPT_STATS
00013 
00014 #include "GeometryUtil.hpp"
00015 #include "GeometryQueryEngine.hpp"
00016 
00017 #include "CubitUtil.hpp"
00018 #include "CubitString.hpp"
00019 #include "CubitVector.hpp"
00020 
00021 #include "BodySM.hpp"
00022 #include "Lump.hpp"
00023 #include "ShellSM.hpp"
00024 #include "Surface.hpp"
00025 #include "LoopSM.hpp"
00026 #include "CoEdgeSM.hpp"
00027 #include "Curve.hpp"
00028 #include "Point.hpp"
00029 
00030 #include "RefVolume.hpp"
00031 #include "RefFace.hpp"
00032 #include "RefEdge.hpp"
00033 #include "RefVertex.hpp"
00034 
00035 #include "Body.hpp"
00036 #include "Shell.hpp"
00037 #include "Loop.hpp"
00038 #include "CoFace.hpp"
00039 #include "CoEdge.hpp"
00040 #include "Chain.hpp"
00041 #include "CoVertex.hpp"
00042 
00043 #include "DLIList.hpp"
00044 
00045 #include "CpuTimer.hpp"
00046 #include "GfxDebug.hpp"
00047 
00048 GeometryUtil* GeometryUtil::instance_ = NULL;
00049 
00050 
00051 
00052 //-------------------------------------------------------------------------
00053 // Purpose       : Test if a point lies within a loop.
00054 //
00055 // Special Notes : Uses loop angle metric.
00056 //
00057 // Creator       : Jason Kraftcheck 
00058 //
00059 // Creation Date : 08/04/98
00060 //-------------------------------------------------------------------------
00061 CubitBoolean GeometryUtil::is_position_within_loop( 
00062                                               const CubitVector& position,
00063                                               Loop* loop_ptr,
00064                                               CubitVector* closest_on_loop,
00065                                               CubitVector* passed_normal )
00066 {
00067   CubitVector surf_point, normal, pt_on_curve;
00068   if( passed_normal )
00069   {
00070     surf_point = position;
00071     normal = *passed_normal;
00072   }
00073   else
00074   {
00075     loop_ptr->get_ref_face_ptr()->get_surface_ptr()->
00076       closest_point( position, &surf_point, &normal );
00077   }
00078   
00079   CoEdge* other_coedge = 0;
00080   CoEdge* closest_coedge = 
00081     closest_loop_coedge( loop_ptr, position, other_coedge, &pt_on_curve );
00082   //If we got back NULL, either the loop has no CoEdges, or all Curves
00083   //occur multiple times.
00084   if( !closest_coedge ) return CUBIT_TRUE;
00085   
00086   if( closest_on_loop ) *closest_on_loop = pt_on_curve;
00087   
00088   CubitVector coe_normal, coe_cross, tangent1, tangent2, junk;
00089 
00090   if( ! other_coedge )
00091   {
00092     Curve* curve_ptr = closest_coedge->get_ref_edge_ptr()->get_curve_ptr();
00093     double u = curve_ptr->u_from_position( pt_on_curve );
00094     
00095     /**** Special case: closest point on loop at G1 discontinuity ****/
00096     if( curve_ptr->G1_discontinuous( u, &tangent1, &tangent2 ) )
00097     {
00098       if( closest_coedge->get_sense() == CUBIT_REVERSED )
00099       {
00100         tangent1 *= -1.0;
00101         tangent2 *= -1.0;
00102       }
00103       loop_ptr->get_ref_face_ptr()->get_surface_ptr()->
00104         closest_point( pt_on_curve, NULL, &coe_normal );
00105       coe_cross = tangent1 * tangent2;
00106       double sum  = (coe_cross + coe_normal).length_squared();
00107       double diff = (coe_cross - coe_normal).length_squared();
00108     
00109       CubitBoolean inside1 = 
00110         inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00111       CubitBoolean inside2 = 
00112         inside_of_curve( tangent2, pt_on_curve, surf_point, normal );
00113         
00114       if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 
00115         //discontinuity is at a convexity
00116       {
00117         //the point must be inside of both sub-edges
00118         return (inside1 && inside2) ? CUBIT_TRUE : CUBIT_FALSE;
00119       }
00120       else //discontinuity is at a concavity
00121       {
00122         //the point must be inside of one of the sub-edges
00123         return (inside1 || inside2) ? CUBIT_TRUE : CUBIT_FALSE;
00124       }
00125     }
00126 
00127     else /**** This is the normal, non-special case part ****/
00128     { 
00129       curve_ptr->closest_point( pt_on_curve, junk, &tangent1 );
00130       if( closest_coedge->get_sense() == CUBIT_REVERSED )
00131         tangent1 *= -1.0;
00132         
00133       return inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00134     }
00135   }
00136     /**** Special case: closest point on loop at vertex ****/
00137   else
00138   {
00139     Curve* curve1_ptr = closest_coedge->get_ref_edge_ptr()->get_curve_ptr();
00140     Curve* curve2_ptr =   other_coedge->get_ref_edge_ptr()->get_curve_ptr();
00141     curve1_ptr->closest_point( pt_on_curve, junk, &tangent1 );
00142     curve2_ptr->closest_point( pt_on_curve, junk, &tangent2 );
00143 
00144     if( closest_coedge->get_sense() == CUBIT_REVERSED )
00145       tangent1 *= -1.0;
00146     if(   other_coedge->get_sense() == CUBIT_REVERSED )
00147       tangent2 *= -1.0;
00148 
00149     loop_ptr->get_ref_face_ptr()->get_surface_ptr()->
00150       closest_point( pt_on_curve, NULL, &coe_normal );
00151     
00152     coe_cross = tangent1 * tangent2;
00153     double sum  = (coe_cross + coe_normal).length_squared();
00154     double diff = (coe_cross - coe_normal).length_squared();
00155     
00156     CubitBoolean inside1 = 
00157       inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00158     CubitBoolean inside2 = 
00159       inside_of_curve( tangent2, pt_on_curve, surf_point, normal );
00160         
00161     if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 
00162       //the common vertex is at a convexity
00163     {
00164       //the point must be inside of both coedges
00165       return (inside1 && inside2) ? CUBIT_TRUE : CUBIT_FALSE;
00166     }
00167     else //the common vertex is at a concavity
00168     {
00169       //the point must be inside of one of the coedges
00170       return (inside1 || inside2) ? CUBIT_TRUE : CUBIT_FALSE;
00171     }
00172   }
00173 }
00174 
00175 
00176 
00177                             
00178 //-------------------------------------------------------------------------
00179 // Purpose       : Attempt to calculate the area of a loop
00180 //
00181 // Special Notes : 
00182 //
00183 // Creator       : Jason Kraftcheck
00184 //
00185 // Creation Date : 11/19/99
00186 //-------------------------------------------------------------------------
00187 /*
00188 double GeometryUtil::loop_area( Loop* loop_ptr )
00189 {
00190   int i;
00191   
00192   DLIList<CoEdge*> coedges;
00193   loop_ptr->co_edges( coedges );
00194   
00195   RefFace* ref_face_ptr = loop_ptr->get_ref_face_ptr();
00196   
00197   
00198     // Get list of segment points around loop
00199   DLIList<CubitVector*> point_list, interior_edge_points;
00200   coedges.reset();
00201   for( i = coedges.size(); i > 0; i-- )
00202   {
00203     CoEdge* coedge_ptr = coedges.get_and_step();
00204     RefEdge* edge_ptr = coedge_ptr->get_ref_edge_ptr();
00205     CubitSense list_sense;
00206     interior_edge_points.clean_out();
00207     edge_ptr->get_interior_extrema( interior_edge_points, list_sense );
00208     if( coedge_ptr->get_sense() == CUBIT_REVERSED )
00209     {
00210       list_sense = CubitUtil::opposite_sense( list_sense );
00211       point_list.append( new CubitVector( 
00212         edge_ptr->end_vertex()->coordinates() ) );
00213     }
00214     else point_list.append( new CubitVector( 
00215       edge_ptr->start_vertex()->coordinates() ) );
00216       
00217     if( list_sense == CUBIT_REVERSED )
00218       interior_edge_points.reverse();
00219     
00220     point_list += interior_edge_points;
00221   }
00222   
00223     // Pick any point for which the refface has a valid normal
00224   const double STEP = 1e2 * GEOMETRY_RESABS;
00225   const double SMALL = CUBIT_RESABS * CUBIT_RESABS;
00226   CubitVector normal, *point, *prev, *current;
00227   for( i = point_list.size(); i--; )
00228   {
00229     point = point_list.get_and_step();
00230     normal = ref_face_ptr->normal_at( *point );
00231     if( normal.length_squared() > SMALL )
00232       break;
00233   }
00234   
00235     // If we did not find a valid normal at any point (this should
00236     // almost never happen), try stepping a small distance along 
00237     // each segment
00238   for( i = point_list.size(); (normal.length_squared() <= SMALL) && (i > 0); i-- )
00239   {
00240     prev = point;
00241     point = point_list.get_and_step();
00242     CubitVector direction = *prev - *point;
00243     double length = direction.length();
00244     if( length < CUBIT_RESABS )
00245       continue;
00246     double step_fraction = STEP / length;
00247     if( step_fraction >= 1.0 )
00248       continue;
00249     
00250     CubitVector position = *point + step_fraction * direction;
00251     normal = ref_face_ptr->normal_at( position );
00252     if( normal.length_squared() > SMALL )
00253     {
00254       point = new CubitVector( position );
00255       point_list.back();
00256       point_list.insert( point );
00257       break;
00258     }
00259   }
00260   
00261     // RefFace does not have a valid normal anywhere??
00262   if( normal.length_squared() <= SMALL )
00263     return 0.0;
00264     
00265     // Do simple 2-D area calculation and hope it isn't too
00266     // inaccurate for the 3-D refface.
00267   double double_area = 0.0;
00268   assert( point_list.prev() == point );
00269   prev = point_list.get_and_step();
00270   current = point_list.get_and_step();
00271     
00272   while( current != point )
00273   {
00274     CubitVector cross = (*prev - *point) * (*current  - *point);
00275     double dot_product = cross % normal;
00276     double_area += dot_product >= 0.0 ? cross.length() : -(cross.length());
00277     prev = current;
00278     current = point_list.get_and_step();
00279   }
00280 
00281   while( point_list.size() > 0 ) delete point_list.pop();
00282   return double_area / 2.0;
00283 }
00284 */
00285 
00286 struct CoEdgeDataList {
00287   CoEdge* coe_ptr;
00288   Curve* curve_ptr;
00289   double box_dist_sqr;
00290   int mark;
00291 };
00292 
00293 
00294 //-------------------------------------------------------------------------
00295 // Purpose       : Find the closest point on a loop.
00296 //
00297 // Special Notes : 
00298 //
00299 // Creator       : Jason Kraftcheck 
00300 //
00301 // Creation Date : 08/04/98
00302 //-------------------------------------------------------------------------
00303 CoEdge* GeometryUtil::closest_loop_coedge( Loop* loop_ptr,
00304                                            const CubitVector& from_pt,
00305                                            CoEdge*& other_coedge,
00306                                            CubitVector* closest )
00307 {
00308   static CoEdgeDataList* coe_array = NULL;
00309   static int coe_array_size = 0;
00310   const double ressqr = CUBIT_RESABS * CUBIT_RESABS;
00311   
00312   DLIList<CoEdge*> coedge_list;
00313   coedge_list.clean_out();
00314     
00315   int i;
00316   CubitVector closest_pt, current_pt;
00317   double current_dst, closest_dst;
00318   CoEdge* closest_coedge = 0;
00319 
00320   //We need the ordered coedges so that we can make sure that, when
00321   //we pass back other_coedge, it is the coedge following the returned
00322   //coedge in the loop, and not the other way around.
00323   loop_ptr->ordered_co_edges( coedge_list );
00324   
00325   //Make sure we have enough space in the array
00326   int count = coedge_list.size();
00327   if( coe_array_size < count )
00328   {
00329     if( coe_array ) delete [] coe_array;
00330     coe_array = new CoEdgeDataList[count];
00331     coe_array_size = count;
00332   }
00333   
00334   //remove from consideration any coedges for which the RefEdge occurs
00335   //more than once on the face.
00336   for( i = coedge_list.size(); i > 0; i-- )
00337     coedge_list.get_and_step()->get_ref_edge_ptr()->marked( 0 );
00338   for( i = coedge_list.size(); i > 0; i-- )
00339   {
00340     RefEdge* edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr();
00341     edge_ptr->marked( edge_ptr->marked() + 1 );
00342   }
00343 
00344   //Start at one of the coedges we want to remove.
00345   coedge_list.reset();
00346   for( i = coedge_list.size(); i > 0; i-- )
00347     if( coedge_list.get()->get_ref_edge_ptr()->marked() > 1 )
00348       break;
00349     else 
00350       coedge_list.step();
00351   
00352   //Populate the array with the coedges we want to keep.
00353   count = 0;
00354   int last_mark = 0;
00355   for( i = coedge_list.size(); i > 0; i-- )
00356   {
00357     RefEdge* edge_ptr = coedge_list.get()->get_ref_edge_ptr();
00358     if( edge_ptr->marked() == 1 )
00359     {
00360       coe_array[count].coe_ptr = coedge_list.get();
00361       coe_array[count].curve_ptr = edge_ptr->get_curve_ptr();
00362       coe_array[count].box_dist_sqr = 
00363         coe_array[count].curve_ptr->bounding_box().distance_squared(from_pt);
00364       coe_array[count].mark = 0;
00365       count++;
00366     }
00367     else if( count == 0 )
00368       last_mark = 1;
00369     else 
00370       coe_array[count-1].mark = 1;
00371     
00372     edge_ptr->marked(0);
00373     coedge_list.step();
00374   }
00375   if( last_mark == 0 )
00376     coe_array[count-1].mark = 1;
00377   
00378   //Do we have any coedges left?
00379   if( count == 0 )
00380     return 0;
00381   
00382   //Find the first bounding box that the point is within
00383   int current_coe = -1;
00384   for( i = 0; (i < count) && (current_coe < 0); i++ )
00385     if( coe_array[i].box_dist_sqr < CUBIT_RESABS )
00386       current_coe = i;
00387   
00388   //If the point wasn't in any bounding box, choose the closest one
00389   closest_dst = CUBIT_DBL_MAX;
00390   if( current_coe < 0 )
00391     for( i = 0; i < count; i++ )
00392       if( coe_array[i].box_dist_sqr < closest_dst ) 
00393       {
00394         closest_dst = coe_array[i].box_dist_sqr;
00395         current_coe = i;
00396       }
00397   
00398   //Start by assuming that the curve we found above is the closest
00399   closest_coedge = coe_array[current_coe].coe_ptr;
00400   coe_array[current_coe].curve_ptr->closest_point_trimmed( from_pt, closest_pt );
00401   closest_dst = ( from_pt - closest_pt ).length_squared();
00402   other_coedge = 0;
00403   
00404   int start = current_coe;
00405   int closest_index = start;
00406   int other_index = -1;
00407   current_coe = ( current_coe + 1 ) % count;
00408   
00409   //Now look for a closer curve
00410   while( start != current_coe )
00411   {
00412     if( coe_array[current_coe].box_dist_sqr <= (closest_dst+GEOMETRY_RESABS) )
00413     {
00414       coe_array[current_coe].curve_ptr
00415         ->closest_point_trimmed( from_pt, current_pt );
00416       current_dst = ( from_pt - current_pt ).length_squared();
00417     
00418       if( (closest_pt - current_pt).length_squared() < ressqr )
00419       {
00420         if( current_dst < closest_dst ) 
00421         {
00422           closest_dst = current_dst;
00423           closest_pt = current_pt;
00424           other_coedge = coe_array[current_coe].coe_ptr;
00425         }
00426         else
00427         {
00428           other_coedge = coe_array[current_coe].coe_ptr;
00429         }
00430         other_index = current_coe;
00431       } 
00432       else if( current_dst < closest_dst )
00433       {
00434         closest_coedge = coe_array[current_coe].coe_ptr;
00435         closest_dst = current_dst;
00436         closest_pt = current_pt;
00437         other_coedge = 0;
00438         closest_index = current_coe;
00439         other_index = -1;
00440       }
00441     }
00442     current_coe = ( current_coe + 1 ) % count;
00443   }
00444   
00445   //make sure we have things in the correct order
00446   if( other_coedge )
00447   {
00448     RefVertex* common = closest_coedge->get_ref_edge_ptr()->
00449       common_ref_vertex( other_coedge->get_ref_edge_ptr() );
00450     if( ! common ) 
00451       other_coedge = 0;
00452   }
00453   
00454   CubitBoolean swap = CUBIT_FALSE;
00455   if( other_coedge )
00456   {
00457     if( ((closest_index + 1)%count) == other_index )
00458       swap = CUBIT_FALSE;
00459     else if( ((other_index+1)%count) == closest_index )
00460       swap = CUBIT_TRUE;
00461     else
00462     {
00463       //locate the start and end of the subsection of the loop
00464       int begin, end;
00465       if( closest_index < other_index )
00466       { 
00467         begin = closest_index;
00468         end = other_index;
00469       }
00470       else
00471       {
00472         begin = other_index;
00473         end = closest_index;
00474       }
00475       
00476       while( (begin > 0) && (coe_array[begin-1].mark != 1) )
00477         begin--;
00478       
00479       while( (end < count) && (coe_array[end].mark != 1) )
00480         end++;
00481         
00482       if( (closest_index == begin) && (other_index == end) )
00483         swap = CUBIT_TRUE;
00484       else
00485         swap = CUBIT_FALSE;
00486     }
00487   }
00488    
00489   if( swap )
00490   {
00491     CoEdge* tmp = other_coedge;
00492     other_coedge = closest_coedge;
00493     closest_coedge = tmp;
00494   }
00495 
00496   if( closest ) *closest = closest_pt;
00497   return closest_coedge;
00498 }
00499 CoEdge* GeometryUtil::closest_face_coedge( RefFace* face_ptr,
00500                                            const CubitVector& from_pt,
00501                                            CoEdge*& other_coedge,
00502                                            CubitVector* closest )
00503 {
00504   static CoEdgeDataList* coe_array = NULL;
00505   static int coe_array_size = 0;
00506   const double ressqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
00507   
00508   DLIList<CoEdge*> coedge_list;
00509   coedge_list.clean_out();
00510     
00511   int i;
00512   CubitVector closest_pt, current_pt;
00513   double current_dst, closest_dst;
00514   CoEdge* closest_coedge = 0;
00515 
00516   face_ptr->co_edges( coedge_list );
00517   
00518   //Make sure we have enough space in the array
00519   int count = coedge_list.size();
00520   if( coe_array_size < count )
00521   {
00522     if( coe_array ) delete [] coe_array;
00523     coe_array = new CoEdgeDataList[count];
00524     coe_array_size = count;
00525   }
00526   
00527   //remove from consideration any coedges for which the RefEdge occurs
00528   //more than once on the face.
00529   for( i = coedge_list.size(); i > 0; i-- )
00530     coedge_list.get_and_step()->get_ref_edge_ptr()->marked( 0 );
00531   for( i = coedge_list.size(); i > 0; i-- )
00532   {
00533     RefEdge* edge_ptr = coedge_list.get_and_step()->get_ref_edge_ptr();
00534     edge_ptr->marked( edge_ptr->marked() + 1 );
00535   }
00536 
00537   //Start at one of the coedges we want to remove.
00538   coedge_list.reset();
00539   for( i = coedge_list.size(); i > 0; i-- )
00540     if( coedge_list.get()->get_ref_edge_ptr()->marked() > 1 )
00541       break;
00542     else 
00543       coedge_list.step();
00544   
00545   //Populate the array with the coedges we want to keep.
00546   count = 0;
00547   int last_mark = 0;
00548   for( i = coedge_list.size(); i > 0; i-- )
00549   {
00550     RefEdge* edge_ptr = coedge_list.get()->get_ref_edge_ptr();
00551     if( edge_ptr->marked() == 1 )
00552     {
00553       coe_array[count].coe_ptr = coedge_list.get();
00554       coe_array[count].curve_ptr = edge_ptr->get_curve_ptr();
00555       coe_array[count].box_dist_sqr = 
00556         coe_array[count].curve_ptr->bounding_box().distance_squared(from_pt);
00557       coe_array[count].mark = 0;
00558       count++;
00559     }
00560     else if( count == 0 )
00561       last_mark = 1;
00562     else 
00563       coe_array[count-1].mark = 1;
00564     
00565     edge_ptr->marked(0);
00566     coedge_list.step();
00567   }
00568   if( last_mark == 0 )
00569     coe_array[count-1].mark = 1;
00570   
00571   
00572   //Find the first bounding box that the point is within
00573   int current_coe = -1;
00574   for( i = 0; (i < count) && (current_coe < 0); i++ )
00575     if( coe_array[i].box_dist_sqr < ressqr )
00576       current_coe = i;
00577   
00578   //If the point wasn't in any bounding box, choose the closest one
00579   closest_dst = CUBIT_DBL_MAX;
00580   if( current_coe < 0 )
00581     for( i = 0; i < count; i++ )
00582       if( coe_array[i].box_dist_sqr < closest_dst ) 
00583       {
00584         closest_dst = coe_array[i].box_dist_sqr;
00585         current_coe = i;
00586       }
00587   
00588   //Start by assuming that the curve we found above is the closest
00589   closest_coedge = coe_array[current_coe].coe_ptr;
00590   coe_array[current_coe].curve_ptr->closest_point_trimmed( from_pt, closest_pt );
00591   closest_dst = ( from_pt - closest_pt ).length_squared();
00592   other_coedge = 0;
00593   
00594   int start = current_coe;
00595   current_coe = ( current_coe + 1 ) % count;
00596   
00597   //Now look for a closer curve
00598   while( start != current_coe )
00599   {
00600     if( coe_array[current_coe].box_dist_sqr <= (closest_dst+GEOMETRY_RESABS) )
00601     {
00602       coe_array[current_coe].curve_ptr
00603         ->closest_point_trimmed( from_pt, current_pt );
00604       current_dst = ( from_pt - current_pt ).length_squared();
00605     
00606       if( (closest_pt - current_pt).length_squared() < ressqr )
00607       {
00608         if( current_dst < closest_dst ) 
00609         {
00610           closest_dst = current_dst;
00611           closest_pt = current_pt;
00612           other_coedge = coe_array[current_coe].coe_ptr;
00613         }
00614         else
00615         {
00616           other_coedge = coe_array[current_coe].coe_ptr;
00617         }
00618 //        other_index = current_coe;
00619       } 
00620       else if( current_dst < closest_dst )
00621       {
00622         closest_coedge = coe_array[current_coe].coe_ptr;
00623         closest_dst = current_dst;
00624         closest_pt = current_pt;
00625         other_coedge = 0;
00626 //        closest_index = current_coe;
00627 //        other_index = -1;
00628       }
00629     }
00630     current_coe = ( current_coe + 1 ) % count;
00631   }
00632   
00633   //make sure we have things in the correct order
00634   if( other_coedge )
00635   {
00636     RefEdge* closest_edge = closest_coedge->get_ref_edge_ptr();
00637     RefEdge* other_edge = other_coedge->get_ref_edge_ptr();
00638     RefVertex* common = closest_edge->common_ref_vertex( other_edge );
00639     if( ! common ) 
00640       other_coedge = 0;
00641     else if( closest_coedge->get_sense() == CUBIT_FORWARD )
00642     {
00643       if( closest_edge->start_vertex() == common )
00644       {
00645         CoEdge* tmp = closest_coedge;
00646         closest_coedge = other_coedge;
00647         other_coedge = tmp;
00648       }
00649     }
00650     else if( closest_coedge->get_sense() == CUBIT_REVERSED )
00651     {
00652       if( closest_edge->end_vertex() == common )
00653       {
00654         CoEdge* tmp = closest_coedge;
00655         closest_coedge = other_coedge;
00656         other_coedge = tmp;
00657       }
00658     }
00659   }
00660 
00661   if( closest ) *closest = closest_pt;
00662   return closest_coedge;
00663 }
00664 
00665 //-------------------------------------------------------------------------
00666 // Purpose       : recursive method to make a segmented curve on a surface.
00667 //
00668 // Special Notes : This method is was written for use by VirtualCurve,
00669 //                 which is why virtual curve debug flags (86) appear
00670 //                 here.
00671 //
00672 // Creator       : Jason Kraftcheck 
00673 //
00674 // Creation Date : 08/07/98
00675 //-------------------------------------------------------------------------
00676 CubitStatus GeometryUtil::recursive_make_curve( Surface* surface_ptr,
00677                                          const CubitVector& start_pt,
00678                                          const CubitVector& end_pt,
00679                                          DLIList<CubitVector*>& segment_points,
00680                                          double arc_angle_tol,
00681                                          double midpoint_dist_tol )
00682 {
00683   if( midpoint_dist_tol < GEOMETRY_RESABS )
00684     midpoint_dist_tol = GEOMETRY_RESABS;
00685   
00686   CubitVector seg_mid_point, mid_point, mid_pt_norm;
00687   CubitVector start_pt_norm, end_pt_norm, tangent;
00688   double angle = arc_angle_tol;
00689   double midpt_dist = midpoint_dist_tol;
00690   
00691   seg_mid_point = (start_pt + end_pt) / 2;
00692   surface_ptr->closest_point_trimmed( seg_mid_point, mid_point );
00693   surface_ptr->closest_point( mid_point, NULL, &mid_pt_norm   );
00694   surface_ptr->closest_point( start_pt,  NULL, &start_pt_norm );
00695   surface_ptr->closest_point( end_pt,    NULL, &end_pt_norm   );
00696   tangent = start_pt - end_pt;
00697   
00698   if( tangent.length() < GEOMETRY_RESABS )
00699   {
00700     PRINT_DEBUG_86( "Solution for polyline on surface not converging.\n"
00701                     "GeometryUtil::recursive_make_curve(..) returning "
00702                     "FAILURE.\n");
00703     return CUBIT_FAILURE;
00704   }
00705   
00706   CubitBoolean split = CUBIT_FALSE;
00707   
00708   if( !split && ( midpoint_dist_tol < CUBIT_DBL_MAX ) )
00709   {
00710     midpt_dist = (seg_mid_point - mid_point).length();
00711     if( midpt_dist > midpoint_dist_tol )
00712     {
00713       split = CUBIT_TRUE;
00714     }
00715   }
00716 
00717   if( !split && (arc_angle_tol < (CUBIT_PI / 2)) )
00718   {
00719     double seg_angle, half1_angle, half2_angle, sum;
00720     seg_angle = fabs( tangent.vector_angle( start_pt_norm, end_pt_norm ) );
00721     half1_angle = fabs((start_pt-mid_point).
00722                         vector_angle( start_pt_norm, mid_pt_norm ));
00723     half2_angle = fabs((end_pt-mid_point).
00724                         vector_angle( end_pt_norm, mid_pt_norm ));
00725     sum = half1_angle + half2_angle;
00726     angle = seg_angle > sum ? seg_angle : sum;
00727     
00728     if( angle > arc_angle_tol ) 
00729     {
00730       split = CUBIT_TRUE;
00731     }
00732   }
00733   
00734   if( split )
00735   {
00736     if( DEBUG_FLAG(86) )
00737     {
00738       GfxDebug::draw_label( ++linearized_curve_debug_count_,
00739         float(mid_point.x()), float(mid_point.y()), float(mid_point.z()),
00740         CUBIT_WHITE_INDEX );
00741       GfxDebug::flush();
00742     }
00743 
00744     double start_len = (start_pt - mid_point).length();
00745     double end_len = (end_pt - mid_point).length();
00746     double half_tol = 0.5 * midpoint_dist_tol;
00747     if( ((start_len < half_tol) && (end_len < half_tol)) ||
00748         (start_len < GEOMETRY_RESABS) || (end_len < GEOMETRY_RESABS) )
00749         return CUBIT_SUCCESS;
00750     
00751     CubitStatus status;
00752     status = recursive_make_curve( surface_ptr, start_pt, mid_point, 
00753              segment_points, arc_angle_tol, midpoint_dist_tol );
00754     segment_points.append( new CubitVector( mid_point ) );
00755     
00756     if( status != CUBIT_SUCCESS ) return status;
00757     
00758     status = recursive_make_curve( surface_ptr, mid_point, end_pt,
00759              segment_points, arc_angle_tol, midpoint_dist_tol );
00760 
00761     return status;
00762   }
00763 
00764   return CUBIT_SUCCESS;
00765 }
00766 
00767 
00768 
00769 //-------------------------------------------------------------------------
00770 // Purpose       : constructor
00771 //
00772 // Special Notes : 
00773 //
00774 // Creator       : Jason Kraftcheck 
00775 //
00776 // Creation Date : 08/03/98
00777 //-------------------------------------------------------------------------
00778 GeometryUtil::GeometryUtil()
00779 {
00780   default_angle_tol = CUBIT_PI / 20;
00781   default_midpoint_tol = CUBIT_DBL_MAX;
00782   surface_cpu_time = 0.0;
00783   other_cpu_time = 0.0;
00784 }
00785 
00786 
00787 
00788 //-------------------------------------------------------------------------
00789 // Purpose       : Find the closest coface in a Shell to the passed point
00790 //
00791 // Special Notes : 
00792 //
00793 // Creator       : Jason Kraftcheck
00794 //
00795 // Creation Date : 11/24/99
00796 //-------------------------------------------------------------------------
00797 CubitStatus GeometryUtil::closest_shell_coface( Shell* shell_ptr,
00798                                             const CubitVector& from_pt,
00799                                             DLIList<CoFace*>& result_set,
00800                                             CubitVector* closest )
00801 {
00802   static DLIList<CoFace*> coface_list, shell_cofaces;
00803   coface_list.clean_out();
00804   shell_cofaces.clean_out();
00805   result_set.clean_out();
00806   
00807   int i;
00808   CubitVector closest_pt, current_pt;
00809   CoFace *current_cof;
00810   double current_dst, closest_dst;
00811 
00812   shell_ptr->co_faces( shell_cofaces );
00813   
00814   //remove from consideration any cofaces for which the RefFace occurs
00815   //more than once on the Shell.
00816   for( i = shell_cofaces.size(); i > 0; i-- )
00817     shell_cofaces.get_and_step()->get_ref_face_ptr()->marked( 0 );
00818   for( i = shell_cofaces.size(); i > 0; i-- )
00819   {
00820     RefFace* face_ptr = shell_cofaces.get_and_step()->get_ref_face_ptr();
00821     face_ptr->marked( face_ptr->marked() + 1 );
00822   }
00823   for( i = shell_cofaces.size(); i > 0; i-- )
00824   {
00825     CoFace* cof_ptr = shell_cofaces.get_and_step();
00826     if( cof_ptr->get_ref_face_ptr()->marked() == 1 )
00827       coface_list.append( cof_ptr );
00828   }
00829   for( i = shell_cofaces.size(); i > 0; i-- )
00830     shell_cofaces.get_and_step()->get_ref_face_ptr()->marked( 0 );
00831   
00832   if( !coface_list.size() )
00833     return CUBIT_FAILURE;
00834   
00835   current_cof = coface_list.get_and_step();
00836   current_cof->get_ref_face_ptr()->
00837     find_closest_point_trimmed( from_pt, closest_pt );
00838   closest_dst = ( from_pt - closest_pt ).length_squared();
00839   result_set.append( current_cof );
00840 
00841   for( i = coface_list.size(); i > 1; i-- )
00842   {
00843     current_cof = coface_list.get_and_step();
00844     current_cof->get_ref_face_ptr()->
00845       find_closest_point_trimmed( from_pt, current_pt );
00846     current_dst = ( from_pt - current_pt ).length_squared();
00847     
00848     if( fabs( current_dst - closest_dst ) < CUBIT_RESABS )
00849     {
00850       result_set.append( current_cof );
00851     } 
00852     else if( current_dst < closest_dst )
00853     {
00854       result_set.clean_out();
00855       result_set.append( current_cof );
00856       closest_dst = current_dst;
00857       closest_pt = current_pt;
00858     }
00859   }
00860   if( closest != NULL ) *closest = closest_pt;
00861   
00862   return CUBIT_SUCCESS;
00863 }
00864 
00865 
00866 //-------------------------------------------------------------------------
00867 // Purpose       : Test if a position is within a Shell
00868 //
00869 // Special Notes : 
00870 //
00871 // Creator       : Jason Kraftcheck
00872 //
00873 // Creation Date : 11/24/99
00874 //-------------------------------------------------------------------------
00875 CubitBoolean GeometryUtil::is_position_within_shell( 
00876                                             const CubitVector& position,
00877                                             Shell* shell_ptr,
00878                                             CubitVector* closest_on_shell )
00879 {
00880   DLIList<CoFace*> result_cofaces;
00881   CubitVector closest_pt;
00882   closest_shell_coface( shell_ptr, position, result_cofaces, &closest_pt );
00883   if( closest_on_shell ) *closest_on_shell = closest_pt;
00884   
00885   //test each resulting coface
00886   CubitVector vector_to_surf = closest_pt - position;
00887   for( int i = result_cofaces.size(); i > 0; i-- )
00888   {
00889     CoFace* coface_ptr = result_cofaces.get_and_step();
00890     RefFace* ref_face_ptr = coface_ptr->get_ref_face_ptr();
00891     CubitVector normal = ref_face_ptr->normal_at( closest_pt );
00892     if( coface_ptr->get_sense() == CUBIT_REVERSED )
00893       normal *= -1.0;
00894     
00895     double sum  = (normal + vector_to_surf).length_squared();
00896     double diff = (normal - vector_to_surf).length_squared();
00897     if( diff > sum ) return CUBIT_FALSE;
00898   }
00899   return CUBIT_TRUE;
00900 }
00901 
00902 
00903 //-------------------------------------------------------------------------
00904 // Purpose       : Test if a shell is a void
00905 //
00906 // Special Notes : 
00907 //
00908 // Creator       : Jason Kraftcheck
00909 //
00910 // Creation Date : 11/27/99
00911 //-------------------------------------------------------------------------
00912 CubitBoolean GeometryUtil::is_shell_a_void( Shell* shell_ptr )
00913 {
00914   assert( shell_ptr != 0 );
00915   DLIList<CoFace*> shell_cofaces;
00916   
00917   CubitBox box = shell_ptr->bounding_box();
00918   double box_diag = box.diagonal().length();
00919   double epsilon = box_diag / 1000;
00920   
00921   CubitVector base_point( box.minimum() );
00922   CubitVector opposite_point;
00923   CubitVector point, normal;
00924   
00925   closest_shell_coface( shell_ptr, base_point, shell_cofaces, &point );
00926   base_point = point;
00927   
00928   if( !shell_cofaces.size() )
00929     return CUBIT_TRUE;
00930     
00931   CoFace* coface_ptr = shell_cofaces.get();
00932   normal = coface_ptr->get_ref_face_ptr()->normal_at( base_point );
00933   if( coface_ptr->get_sense() == CUBIT_REVERSED ) normal *= -1.0;
00934   normal.length( box_diag );
00935   
00936   opposite_point = base_point + normal;
00937   closest_shell_coface( shell_ptr, opposite_point, shell_cofaces, &point );
00938   
00939   return (base_point - point).length() < epsilon ? CUBIT_FALSE : CUBIT_TRUE;
00940 }
00941   
00942 
00943 //-------------------------------------------------------------------------
00944 // Purpose       : Check if a point is on the inside or outside of a curve,
00945 //                 given the surface normal, and the sense of the curve on
00946 //                 the surface.
00947 //
00948 // Special Notes : The passed position is assumed to be on the surface.
00949 //
00950 // Creator       : Jason Kraftcheck
00951 //
00952 // Creation Date : 05/02/00
00953 //-------------------------------------------------------------------------
00954 CubitBoolean GeometryUtil::inside_of_curve( const CubitVector& tangent,
00955                                             const CubitVector& curve_pos,
00956                                             const CubitVector& surf_pos,
00957                                             const CubitVector& normal )
00958 {
00959   CubitVector cross = tangent * ( surf_pos - curve_pos );
00960   double sum  = (cross + normal).length_squared();
00961   double diff = (cross - normal).length_squared();
00962   return (sum < diff) ? CUBIT_FALSE : CUBIT_TRUE;
00963 }
00964 
00965 //-------------------------------------------------------------------------
00966 // Purpose       : Given a coordinate and a list of curves, determine if
00967 //                 any of the curves has that coordinate as an end point
00968 //                 and return that curve and whether it is start or end. 
00969 //
00970 // Special Notes : The passed position is assumed to be on the surface.
00971 //
00972 // Creator       : Steve Storm
00973 //
00974 // Creation Date : 05/30/00
00975 //-------------------------------------------------------------------------
00976 RefEdge* GeometryUtil::
00977 find_connected_ref_edge_by_coord( CubitVector& coords, 
00978                                   DLIList<RefEdge*>& ref_edge_list,
00979                                   int& start_flg )
00980 {
00981    RefEdge* ref_edge;
00982    DLIList<RefEdge*> tmp_list = ref_edge_list;
00983 
00984    ref_edge = ref_edge_list.get();
00985    GeometryQueryEngine* gqe_ptr = ref_edge->get_geometry_query_engine();
00986    double tol = gqe_ptr->get_sme_resabs_tolerance();
00987 
00988    tmp_list.reset();
00989    for( int i=0; i<tmp_list.size(); i++ )
00990    {
00991       ref_edge = tmp_list.get_and_step();
00992 
00993       if( ref_edge->start_coordinates().within_tolerance( coords, tol ) )
00994       {
00995          start_flg = 1;
00996          return ref_edge;
00997       }
00998 
00999       if( ref_edge->end_coordinates().within_tolerance( coords, tol ) )
01000       {
01001          start_flg = 0;
01002          return ref_edge;
01003       }
01004    }
01005    return NULL;
01006 }
01007 
01008 void 
01009 GeometryUtil::find_connected_ref_edges_by_coord( CubitVector& coords, 
01010                                                  DLIList<RefEdge*>& ref_edge_list,
01011                                                  DLIList<RefEdge*>& connected_edges_list )
01012 {
01013    RefEdge* ref_edge;
01014    DLIList<RefEdge*> tmp_list = ref_edge_list;
01015 
01016    ref_edge = ref_edge_list.get();
01017    GeometryQueryEngine* gqe_ptr = ref_edge->get_geometry_query_engine();
01018    double tol = gqe_ptr->get_sme_resabs_tolerance();
01019 
01020    tmp_list.reset();
01021    for( int i=0; i<tmp_list.size(); i++ )
01022    {
01023       ref_edge = tmp_list.get_and_step();
01024 
01025       if( ref_edge->start_coordinates().within_tolerance( coords, tol ) )
01026          connected_edges_list.append_unique( ref_edge );
01027 
01028       if( ref_edge->end_coordinates().within_tolerance( coords, tol ) )
01029          connected_edges_list.append_unique( ref_edge );
01030    }
01031 }
01032 
01033 CubitStatus 
01034 GeometryUtil::form_ref_edge_loop_by_coord( DLIList<RefEdge*>& ref_edge_list )
01035 {
01036    int i;
01037 
01038    if( ref_edge_list.size() == 0 )
01039       return CUBIT_FAILURE;
01040 
01041    if( ref_edge_list.size() == 1 )
01042    {
01043       double period;
01044       if( ref_edge_list.get()->is_periodic( period ) )
01045          return CUBIT_SUCCESS;
01046       else
01047       {
01048          // Could be a spline
01049          RefEdge *ref_edge_ptr = ref_edge_list.get();
01050          GeometryQueryEngine* gqe_ptr = ref_edge_ptr->get_geometry_query_engine();
01051          double tol = gqe_ptr->get_sme_resabs_tolerance();
01052          if( ref_edge_ptr->start_coordinates().within_tolerance( 
01053             ref_edge_ptr->end_coordinates(), tol ) )
01054             return CUBIT_SUCCESS;
01055       }
01056       return CUBIT_FAILURE;
01057    }
01058 
01059    // First form a chain (which can be a loop)
01060    if( form_ref_edge_chain_by_coord( ref_edge_list ) == CUBIT_FAILURE )
01061       return CUBIT_FAILURE;
01062 
01063    // Now check to make sure a valid loop was formed.  For a valid loop 
01064    // every vertex must have exactly 2 edges connected to it.  The only
01065    // exception is a periodic curve where there is only one vertex, which
01066    // was checked for before.
01067    DLIList<RefEdge*> connected_edges;
01068    RefEdge* ref_edge_ptr;
01069    CubitVector vector;
01070    for( i=0; i<ref_edge_list.size(); i++ )
01071    {
01072       ref_edge_ptr = ref_edge_list.get_and_step();
01073    
01074       connected_edges.clean_out();
01075       vector = ref_edge_ptr->start_coordinates();
01076       find_connected_ref_edges_by_coord( vector ,
01077                                          ref_edge_list, connected_edges );
01078       if( connected_edges.size() != 2 )
01079          return CUBIT_FAILURE;
01080 
01081       connected_edges.clean_out();
01082       vector =  ref_edge_ptr->end_coordinates();
01083       find_connected_ref_edges_by_coord( vector ,
01084                                          ref_edge_list, connected_edges );
01085       if( connected_edges.size() != 2 )
01086          return CUBIT_FAILURE;
01087    }
01088  
01089    return CUBIT_SUCCESS;
01090 }
01091 
01092 CubitStatus 
01093 GeometryUtil::form_ref_edge_chain_by_coord( DLIList<RefEdge*>& ref_edge_list )
01094 {
01095    if( ref_edge_list.size() == 1 )
01096       return CUBIT_SUCCESS;
01097 
01098    int i;
01099    int start_flg = 0;
01100    
01101    CubitVector vector_start, vector_end;
01102    RefEdge* curr_edge;
01103    RefEdge* next_edge;
01104 
01105    DLIList<RefEdge*> temp_list = ref_edge_list;
01106    DLIList<RefEdge*> ordered_list;
01107    
01108    // Start vertex must be attached to only one ref_edge in our list. 
01109    // Otherwise this is really a loop, which is still okay
01110 
01111    // Search to find the starting edge
01112    RefEdge* start_edge = NULL;
01113    for( i=0; i<temp_list.size(); i++ )
01114    {
01115       curr_edge = temp_list.get();
01116 
01117       // Since DLList doesn't allow a NULL item
01118       DLIList<RefEdge*> temp_list2;
01119       temp_list2 = temp_list;
01120       temp_list2.remove( curr_edge ); // Next item becomes current item
01121    
01122       // get the vectors to start and end
01123       vector_start = curr_edge->start_coordinates();
01124       vector_end   = curr_edge->end_coordinates();
01125       
01126       if( !find_connected_ref_edge_by_coord( vector_start ,
01127          temp_list2, start_flg ) ||
01128          !find_connected_ref_edge_by_coord( vector_end,
01129          temp_list2, start_flg ) )
01130 
01131       {
01132          start_edge = curr_edge;
01133          //temp_list.change_to( curr_edge );
01134          break;
01135       }
01136    }
01137 
01138    temp_list.reset();
01139 
01140    if( start_edge == NULL )
01141       start_edge = ref_edge_list.get();
01142    
01143    curr_edge = start_edge;
01144    ordered_list.append( curr_edge );
01145    temp_list.move_to( start_edge );
01146    temp_list.remove();
01147 
01148    next_edge = temp_list.get();
01149 
01150    // Attempt to use second edge in list as second edge in chain to 
01151    // preserve original chain direction.
01152    RefEdge* next_edge_tmp = NULL;
01153    RefEdge* next_edge_tmp2 = NULL;
01154    // Check start first - if this fails check end next so chain order
01155    // will be established properly.
01156    vector_start =  curr_edge->start_coordinates();
01157    next_edge_tmp = find_connected_ref_edge_by_coord( vector_start,
01158                                                      temp_list, start_flg );
01159    if( next_edge_tmp != next_edge )
01160    {
01161       vector_end    = curr_edge->end_coordinates();
01162       next_edge_tmp2 = find_connected_ref_edge_by_coord( vector_end,
01163                                                          temp_list, start_flg );
01164    }
01165 
01166    if( next_edge_tmp2 )
01167      next_edge_tmp = next_edge_tmp2;
01168 
01169    if( next_edge_tmp  )
01170    {
01171       curr_edge = next_edge_tmp;
01172       ordered_list.append( next_edge_tmp );
01173       temp_list.remove( next_edge_tmp );
01174    }
01175    else
01176    {
01177       return CUBIT_FAILURE;
01178    }
01179 
01180    while( temp_list.size() )
01181    {
01182       if( start_flg ) // Curr edge was found on prev start, so use end 1st
01183       {
01184      vector_end = curr_edge->end_coordinates();
01185          next_edge = find_connected_ref_edge_by_coord( vector_end ,
01186                                                        temp_list, start_flg );
01187       }  
01188       else
01189       {
01190      vector_start = curr_edge->start_coordinates();
01191          next_edge = find_connected_ref_edge_by_coord( vector_start ,
01192                                                        temp_list, start_flg );
01193       }  
01194 
01195       if( next_edge )
01196       {
01197          curr_edge = next_edge;
01198          ordered_list.append( next_edge );
01199          temp_list.remove( next_edge );
01200       }
01201       else
01202       {
01203          return CUBIT_FAILURE;
01204       }
01205    }
01206 
01207    ref_edge_list.clean_out();
01208    ref_edge_list = ordered_list;
01209 
01210    // Validate the chain
01211    DLIList<RefVertex*> problem_vertices;
01212    return check_valid_chain_by_coord( ref_edge_list, problem_vertices );
01213 }
01214 
01215 CubitStatus 
01216 GeometryUtil::check_valid_chain_by_coord( DLIList<RefEdge*>& ref_edge_list, 
01217                                           DLIList<RefVertex*>& problem_vertices )
01218 {
01219    CubitStatus status = CUBIT_SUCCESS;
01220 
01221    DLIList<RefEdge*> connected_edges;
01222    RefEdge* ref_edge_ptr;
01223    CubitVector vector_start, vector_end;
01224    
01225    for( int i=0; i<ref_edge_list.size(); i++ )
01226    {
01227       ref_edge_ptr = ref_edge_list.get_and_step();
01228    
01229       connected_edges.clean_out();
01230       vector_start = ref_edge_ptr->start_coordinates();
01231       find_connected_ref_edges_by_coord( vector_start ,
01232                                          ref_edge_list, connected_edges );
01233       if( connected_edges.size() != 1 && connected_edges.size() != 2 )
01234       {
01235          status = CUBIT_FAILURE;
01236          problem_vertices.append_unique( ref_edge_ptr->start_vertex() );
01237       }
01238       
01239       connected_edges.clean_out();
01240       vector_end = ref_edge_ptr->end_coordinates();
01241       find_connected_ref_edges_by_coord( vector_end ,
01242                                          ref_edge_list, connected_edges );
01243       if( connected_edges.size() != 1 && connected_edges.size() != 2 )
01244       {
01245          status = CUBIT_FAILURE;
01246          problem_vertices.append_unique( ref_edge_ptr->end_vertex() );
01247       }
01248    }
01249    return status;
01250 }
01251 
01252 CubitStatus 
01253 GeometryUtil::check_valid_loop_by_coord( DLIList<RefEdge*>& ref_edge_list,
01254                                          DLIList<RefVertex*>& problem_vertices )
01255 {
01256    CubitStatus status = CUBIT_SUCCESS;
01257 
01258    DLIList<RefEdge*> connected_edges;
01259    RefEdge* ref_edge_ptr;
01260    CubitVector vector_start, vector_end;
01261    
01262    for( int i=0; i<ref_edge_list.size(); i++ )
01263    {
01264       ref_edge_ptr = ref_edge_list.get_and_step();
01265    
01266       connected_edges.clean_out();
01267       vector_start = ref_edge_ptr->start_coordinates();
01268       find_connected_ref_edges_by_coord( vector_start ,
01269                                          ref_edge_list, connected_edges );
01270       if( connected_edges.size() != 2 )
01271       {
01272          status = CUBIT_FAILURE;
01273          problem_vertices.append_unique( ref_edge_ptr->start_vertex() );
01274       }
01275       
01276       connected_edges.clean_out();
01277       vector_end = ref_edge_ptr->end_coordinates();
01278       find_connected_ref_edges_by_coord( vector_end ,
01279                                          ref_edge_list, connected_edges );
01280       if( connected_edges.size() != 2 )
01281       {
01282          status = CUBIT_FAILURE;
01283          problem_vertices.append_unique( ref_edge_ptr->end_vertex() );
01284       }
01285    }
01286    return status;
01287 }
01288 
01289 // Added by CAT (SRS)
01290 RefEdge* 
01291 GeometryUtil::find_connected_ref_edge( RefVertex* ref_vertex_ptr, 
01292                                        DLIList<RefEdge*>& ref_edge_list,
01293                                        int& start_flg )
01294 {
01295    RefEdge* ref_edge;
01296    DLIList<RefEdge*> tmp_list = ref_edge_list;
01297 
01298    tmp_list.reset();
01299    for( int i=0; i<tmp_list.size(); i++ )
01300    {
01301       ref_edge = tmp_list.get_and_step();
01302 
01303       if( ref_edge->start_vertex() == ref_vertex_ptr )
01304       {
01305          start_flg = 1;
01306          return ref_edge;
01307       }
01308 
01309       if( ref_edge->end_vertex() == ref_vertex_ptr )
01310       {
01311          start_flg = 0;
01312          return ref_edge;
01313       }
01314    }
01315    return NULL;
01316 }
01317 
01318 void
01319 GeometryUtil::find_connected_ref_edges( RefVertex* ref_vertex_ptr, 
01320                                         DLIList<RefEdge*>& ref_edge_list,
01321                                         DLIList<RefEdge*>& connected_edges_list )
01322 {
01323   RefEdge* ref_edge;
01324   DLIList<RefEdge*> tmp_list = ref_edge_list;
01325   
01326   tmp_list.reset();
01327   for( int i=0; i<tmp_list.size(); i++ )
01328   {
01329     ref_edge = tmp_list.get_and_step();
01330     
01331     if( ref_edge->start_vertex() == ref_vertex_ptr )
01332       connected_edges_list.append_unique( ref_edge );
01333     
01334     if( ref_edge->end_vertex() == ref_vertex_ptr )
01335       connected_edges_list.append_unique( ref_edge );
01336   }
01337 }
01338 
01339 CubitStatus 
01340 GeometryUtil::form_ref_edge_loop( DLIList<RefEdge*>& ref_edge_list )
01341 {
01342    int i;
01343 
01344    if( ref_edge_list.size() == 0 )
01345       return CUBIT_FAILURE;
01346 
01347    if( ref_edge_list.size() == 1 )
01348    {
01349       double period;
01350       if( ref_edge_list.get()->is_periodic( period ) )
01351          return CUBIT_SUCCESS;
01352    }
01353 
01354    // First form a chain (which can be a loop)
01355    if( form_ref_edge_chain( ref_edge_list ) == CUBIT_FAILURE )
01356       return CUBIT_FAILURE;
01357 
01358    // Now check to make sure a valid loop was formed.  For a valid loop 
01359    // every vertex must have exactly 2 edges connected to it.  The only
01360    // exception is a periodic curve where there is only one vertex, which
01361    // was checked for before.
01362    DLIList<RefEdge*> connected_edges;
01363    RefEdge* ref_edge_ptr;
01364    for( i=0; i<ref_edge_list.size(); i++ )
01365    {
01366       ref_edge_ptr = ref_edge_list.get_and_step();
01367    
01368       connected_edges.clean_out();
01369       find_connected_ref_edges( ref_edge_ptr->start_vertex(), ref_edge_list, connected_edges );
01370       if( connected_edges.size() != 2 )
01371          return CUBIT_FAILURE;
01372 
01373       connected_edges.clean_out();
01374       find_connected_ref_edges( ref_edge_ptr->end_vertex(), ref_edge_list, connected_edges );
01375       if( connected_edges.size() != 2 )
01376          return CUBIT_FAILURE;
01377    }
01378  
01379    return CUBIT_SUCCESS;
01380 }
01381 
01382 CubitStatus 
01383 GeometryUtil::form_ref_edge_chain( DLIList<RefEdge*>& ref_edge_list )
01384 {
01385    if( ref_edge_list.size() == 1 )
01386       return CUBIT_SUCCESS;
01387 
01388    int i;
01389    int start_flg = 0;
01390    
01391    RefVertex* ref_vertex_start, *ref_vertex_end;
01392    RefEdge* curr_edge;
01393    RefEdge* next_edge;
01394 
01395    DLIList<RefEdge*> temp_list = ref_edge_list;
01396    DLIList<RefEdge*> ordered_list;
01397    
01398    // Start vertex must be attached to only one ref_edge in our list. 
01399    // Otherwise this is really a loop, which is still okay
01400 
01401    // Search to find the starting edge
01402    RefEdge* start_edge = NULL;
01403    for( i=0; i<temp_list.size(); i++ )
01404    {
01405       curr_edge = temp_list.get();
01406 
01407       // Since DLList doesn't allow a NULL item
01408       DLIList<RefEdge*> temp_list2;
01409       temp_list2 = temp_list;
01410       temp_list2.remove( curr_edge ); // Next item becomes current item
01411    
01412       // get the vectors to start and end
01413       ref_vertex_start = curr_edge->start_vertex();
01414       ref_vertex_end   = curr_edge->end_vertex();
01415       
01416       if( !find_connected_ref_edge( ref_vertex_start,
01417          temp_list2, start_flg ) ||
01418          !find_connected_ref_edge( ref_vertex_end,
01419          temp_list2, start_flg ) )
01420 
01421       {
01422          start_edge = curr_edge;
01423          //temp_list.change_to( curr_edge );
01424          break;
01425       }
01426    }
01427 
01428    temp_list.reset();
01429 
01430    if( start_edge == NULL )
01431       start_edge = ref_edge_list.get();
01432    
01433    curr_edge = start_edge;
01434    ordered_list.append( curr_edge );
01435    temp_list.move_to( start_edge );
01436    temp_list.remove();
01437 
01438    next_edge = temp_list.get();
01439 
01440    // Attempt to use second edge in list as second edge in chain to 
01441    // preserve original chain direction.
01442    RefEdge* next_edge_tmp = NULL;
01443    RefEdge* next_edge_tmp2 = NULL;
01444    // Check start first - if this fails check end next so chain order
01445    // will be established properly.
01446    ref_vertex_start =  curr_edge->start_vertex();
01447    next_edge_tmp = find_connected_ref_edge( ref_vertex_start,
01448                                             temp_list, start_flg );
01449    if( next_edge_tmp != next_edge )
01450    {
01451       ref_vertex_end    = curr_edge->end_vertex();
01452       next_edge_tmp2 = find_connected_ref_edge( ref_vertex_end,
01453                                                 temp_list, start_flg );
01454    }
01455 
01456    if( next_edge_tmp2 )
01457      next_edge_tmp = next_edge_tmp2;
01458 
01459    if( next_edge_tmp  )
01460    {
01461       curr_edge = next_edge_tmp;
01462       ordered_list.append( next_edge_tmp );
01463       temp_list.remove( next_edge_tmp );
01464    }
01465    else
01466    {
01467       return CUBIT_FAILURE;
01468    }
01469 
01470    while( temp_list.size() )
01471    {
01472       if( start_flg ) // Curr edge was found on prev start, so use end 1st
01473       {
01474            ref_vertex_end = curr_edge->end_vertex();
01475          next_edge = find_connected_ref_edge( ref_vertex_end, temp_list, start_flg );
01476       }  
01477       else
01478       {
01479            ref_vertex_start = curr_edge->start_vertex();
01480          next_edge = find_connected_ref_edge( ref_vertex_start, temp_list, start_flg );
01481       }  
01482 
01483       if( next_edge )
01484       {
01485          curr_edge = next_edge;
01486          ordered_list.append( next_edge );
01487          temp_list.remove( next_edge );
01488       }
01489       else
01490       {
01491          return CUBIT_FAILURE;
01492       }
01493    }
01494 
01495    ref_edge_list.clean_out();
01496    ref_edge_list = ordered_list;
01497 
01498    // Validate the chain
01499    DLIList<RefVertex*> problem_vertices;
01500    return check_valid_chain( ref_edge_list, problem_vertices );
01501 }
01502 
01503 CubitStatus 
01504 GeometryUtil::check_valid_chain( DLIList<RefEdge*>& ref_edge_list, 
01505                                  DLIList<RefVertex*>& problem_vertices )
01506 {
01507   CubitStatus status = CUBIT_SUCCESS;
01508   
01509   DLIList<RefEdge*> connected_edges;
01510   RefEdge* ref_edge_ptr;
01511   RefVertex* vertex_start, *vertex_end;
01512   
01513   for( int i=0; i<ref_edge_list.size(); i++ )
01514   {
01515     ref_edge_ptr = ref_edge_list.get_and_step();
01516     
01517     connected_edges.clean_out();
01518     vertex_start = ref_edge_ptr->start_vertex();
01519     find_connected_ref_edges( vertex_start ,
01520       ref_edge_list, connected_edges );
01521     if( connected_edges.size() != 1 && connected_edges.size() != 2 )
01522     {
01523       status = CUBIT_FAILURE;
01524       problem_vertices.append_unique( ref_edge_ptr->start_vertex() );
01525     }
01526     
01527     connected_edges.clean_out();
01528     vertex_end = ref_edge_ptr->end_vertex();
01529     find_connected_ref_edges( vertex_end ,
01530       ref_edge_list, connected_edges );
01531     if( connected_edges.size() != 1 && connected_edges.size() != 2 )
01532     {
01533       status = CUBIT_FAILURE;
01534       problem_vertices.append_unique( ref_edge_ptr->end_vertex() );
01535     }
01536   }
01537   return status;
01538 }
01539 
01540 CubitStatus 
01541 GeometryUtil::check_valid_loop( DLIList<RefEdge*>& ref_edge_list,
01542                                 DLIList<RefVertex*>& problem_vertices )
01543 {
01544   CubitStatus status = CUBIT_SUCCESS;
01545   
01546   DLIList<RefEdge*> connected_edges;
01547   RefEdge* ref_edge_ptr;
01548   RefVertex* vertex_start;
01549   RefVertex* vertex_end;
01550   
01551   for( int i=0; i<ref_edge_list.size(); i++ )
01552   {
01553     ref_edge_ptr = ref_edge_list.get_and_step();
01554     
01555     connected_edges.clean_out();
01556     vertex_start = ref_edge_ptr->start_vertex();
01557     find_connected_ref_edges( vertex_start ,
01558       ref_edge_list, connected_edges );
01559     if( connected_edges.size() != 2 )
01560     {
01561       status = CUBIT_FAILURE;
01562       problem_vertices.append_unique( ref_edge_ptr->start_vertex() );
01563     }
01564     
01565     connected_edges.clean_out();
01566     vertex_end = ref_edge_ptr->end_vertex();
01567     find_connected_ref_edges( vertex_end ,
01568       ref_edge_list, connected_edges );
01569     if( connected_edges.size() != 2 )
01570     {
01571       status = CUBIT_FAILURE;
01572       problem_vertices.append_unique( ref_edge_ptr->end_vertex() );
01573     }
01574   }
01575   return status;
01576 }
01577   
01578 //-------------------------------------------------------------------------
01579 // Purpose       : check vertex order and tangent direction for RefEdge
01580 //
01581 // Special Notes : 
01582 //
01583 // Creator       : Jason Kraftcheck
01584 //
01585 // Creation Date : 09/07/00
01586 //-------------------------------------------------------------------------
01587 CubitBoolean GeometryUtil::valid_edge( RefEdge* edge_ptr,
01588                                        CubitBoolean print_error )
01589 {
01590   RefVertex* start_vertex = edge_ptr->start_vertex();
01591   RefVertex* end_vertex = edge_ptr->end_vertex();
01592   CubitBoolean result = CUBIT_TRUE;
01593   
01594   if (!edge_ptr->get_curve_ptr())
01595   {
01596     if (print_error)
01597       PRINT_ERROR("Curve %d does not have a TopologyBridge.\n", edge_ptr->id());
01598     return CUBIT_FALSE;
01599   }
01600   else if(!start_vertex)
01601   {
01602     if (print_error)
01603       PRINT_ERROR("Curve %d has no start vertex.\n", edge_ptr->id());
01604     return CUBIT_FALSE;
01605   }
01606   else if(!end_vertex)
01607   {
01608     if (print_error)
01609       PRINT_ERROR("Curve %d has no end vertex.\n", edge_ptr->id());
01610     return CUBIT_FALSE;
01611   }
01612   else if (!start_vertex->get_point_ptr())
01613   {
01614     if (print_error)
01615       PRINT_ERROR("Vertex %d has no Point.\n", start_vertex->id());
01616     return CUBIT_FALSE;
01617   }
01618   else if (!end_vertex->get_point_ptr())
01619   {
01620     if (print_error)
01621       PRINT_ERROR("Vertex %d has no Point.\n", end_vertex->id());
01622     return CUBIT_FALSE;
01623   }
01624   else if (edge_ptr->get_curve_ptr()->geometry_type() == POINT_CURVE_TYPE)
01625   {
01626     if (start_vertex != end_vertex)
01627     {
01628       if (print_error) 
01629         PRINT_ERROR("Curve %d is a point-curve but has different "
01630                      "vertices (%d and %d).\n", edge_ptr->id(),
01631                      start_vertex->id(), end_vertex->id());
01632       result = CUBIT_FALSE;
01633     }
01634   }
01635   else
01636   {
01637     double u_start = edge_ptr->start_param();
01638     double u_end = edge_ptr->end_param();
01639     double period;
01640     CubitBoolean periodic = edge_ptr->is_periodic( period );
01641     if( start_vertex == end_vertex )
01642     {
01643       if( !periodic && print_error )
01644         PRINT_WARNING("Curve %d is closed but not periodic.\n",edge_ptr->id());
01645     }
01646 
01647     double u_start_vtx = edge_ptr->u_from_position( start_vertex->coordinates() );
01648     double u_end_vtx = edge_ptr->u_from_position( end_vertex->coordinates() );
01649 
01650     if (periodic)
01651     {
01652       // For a periodic curve the point perp operation could return u_start or
01653       // u_end for both start_vertex and end_vertex so try to put everything
01654       // in the range from u_start to u_end and recognize cases where u_start_vtx
01655       // equals u_end by accident (and vice versa).
01656       if (period > 0.0)
01657       {
01658         // Logically, if u_start_vtx >= u_end...
01659         while (u_start_vtx > u_end - CUBIT_RESABS)
01660           u_start_vtx -= period;
01661         // Logically, if u_start_vtx < u_start...
01662         while (u_start_vtx < u_start - CUBIT_RESABS)
01663           u_start_vtx += period;
01664         // Logically, if u_end_vtx > u_end...
01665         while (u_end_vtx > u_end + CUBIT_RESABS)
01666           u_end_vtx -= period;
01667         // Logically, if u_end_vtx <= u_start...
01668         while (u_end_vtx < u_start + CUBIT_RESABS)
01669           u_end_vtx += period;
01670       }
01671       else if (period < 0.0)
01672       {
01673         // Logically, if u_start_vtx <= u_end ...
01674         while (u_start_vtx < u_end + CUBIT_RESABS)
01675           u_start_vtx += period;
01676         // Logically, if u_start_vtx > u_start...
01677         while (u_start_vtx > u_start + CUBIT_RESABS)
01678           u_start_vtx -= period;
01679         // Logically, if u_end_vtx < u_end...
01680         while (u_end_vtx < u_end - CUBIT_RESABS)
01681           u_end_vtx += period;
01682         // Logically, if u_end_vtx >= u_start...
01683         while (u_end_vtx > u_start - CUBIT_RESABS)
01684           u_end_vtx -= period;
01685       }
01686     }
01687       
01688 
01689 
01690     if( (fabs( u_start_vtx - u_start ) > CUBIT_RESABS) && print_error )
01691       PRINT_WARNING("Vertex %d does not appear to be at the start of curve %d.\n",
01692           start_vertex->id(), edge_ptr->id() );
01693     if( (fabs( u_end_vtx - u_end ) > CUBIT_RESABS) && print_error )
01694       PRINT_WARNING("Vertex %d does not appear to be at the end of curve %d.\n",
01695           end_vertex->id(), edge_ptr->id() );
01696 
01697     double u_diff = u_start - u_end;
01698     double u_diff_vtx = u_start_vtx - u_end_vtx;
01699     if( (u_diff * u_diff_vtx) < 0 )
01700     {
01701       if( print_error )
01702       {
01703         PRINT_ERROR("Vertices on curve %d appear to be in the wrong order.\n",
01704           edge_ptr->id());
01705         PRINT_INFO("\tstart_param = %f, end_param = %f, u(start_vtx) = %f, "
01706                    "u(end_vtx) = %f\n",u_start,u_end,u_start_vtx,u_end_vtx);
01707       }
01708       result = CUBIT_FALSE;
01709     }
01710 
01711     double step = (u_end - u_start) / 100.;
01712     if( step > 0.0 )
01713     {
01714       if( step < CUBIT_RESABS ) step = CUBIT_RESABS;
01715       if( (u_start + step) > u_end ) step = u_end - u_start;
01716     }
01717     else
01718     {
01719       if( step > -CUBIT_RESABS ) step = -CUBIT_RESABS;
01720       if( (u_start + step) < u_end ) step = u_end - u_start;
01721     }
01722 
01723     CubitVector closest, tangent, next_pos;
01724     edge_ptr->closest_point( start_vertex->coordinates(), closest, &tangent );
01725     /* This fails a lot with spline curves, so skip it.
01726     double distance = (start_vertex->coordinates() - closest).length();
01727     if( (distance > GEOMETRY_RESABS) && print_error )
01728     {
01729       PRINT_WARNING("Vertex %d of curve %d does not appear to lie on the curve.\n",
01730         start_vertex->id(), edge_ptr->id() );
01731     }
01732     */
01733     edge_ptr->position_from_u( u_start + step, next_pos );
01734     next_pos -= closest;
01735     if( tangent.length_squared() < CUBIT_RESABS )
01736     {
01737       if( print_error )
01738         PRINT_ERROR("Zero-length tangent vector returned at start of curve %d\n", edge_ptr->id());
01739       result = CUBIT_FALSE;
01740     }
01741     else if( next_pos.length_squared() < CUBIT_RESABS )
01742     {
01743       if( print_error )
01744         PRINT_WARNING("Distance for delta-u of %f in [%f,%f] near start"
01745                       " of curve %d appears to be zero.\n",
01746                       step, u_start, u_end, edge_ptr->id());
01747     }
01748     else if( tangent.interior_angle( next_pos ) > (90. - CUBIT_RESABS) )
01749     {
01750       if( print_error )
01751         PRINT_ERROR("The tangent at the start of curve %d appears "
01752                     "to be in the wrong direction.\n",edge_ptr->id());
01753       result = CUBIT_FALSE;
01754     }
01755 
01756     edge_ptr->closest_point( end_vertex->coordinates(), closest, &tangent );
01757     /* This fails a lot with spline curves, so skip it.
01758     distance = (end_vertex->coordinates() - closest).length();
01759     if( (distance > GEOMETRY_RESABS) && print_error )
01760     {
01761       PRINT_WARNING("Vertex %d of curve %d does not appear to lie on the curve.\n",
01762         end_vertex->id(), edge_ptr->id() );
01763     }
01764     */
01765     edge_ptr->position_from_u( u_end - step, next_pos );
01766     next_pos = closest - next_pos;
01767     if( tangent.length_squared() < CUBIT_RESABS )
01768     {
01769       if( print_error )
01770         PRINT_ERROR("Zero-length tangent vector returned at end of %d\n", edge_ptr->id());
01771       result = CUBIT_FALSE;
01772     }
01773     else if( next_pos.length_squared() < CUBIT_RESABS )
01774     {
01775       if( print_error )
01776         PRINT_WARNING("Distance for delta-u of %f in [%f,%f] near end"
01777                       " of curve %d appears to be zero.\n",
01778                       step, u_start, u_end, edge_ptr->id());
01779     }
01780     else if( tangent.interior_angle( next_pos ) > (90. - CUBIT_RESABS) )
01781     {
01782       if( print_error )
01783         PRINT_ERROR("The tangent at the end of curve %d appears "
01784                     "to be in the wrong direction.\n",edge_ptr->id());
01785       result = CUBIT_FALSE;
01786     }
01787   }
01788   
01789   return result;
01790 }
01791 
01792 CubitBoolean GeometryUtil::valid_loop_coedges( Loop* loop_ptr,
01793                                                CubitBoolean print_error )
01794 {
01795   CubitBoolean result = CUBIT_TRUE;
01796   RefFace* loop_owner = loop_ptr->get_ref_face_ptr();
01797   int surf_id = loop_owner ? loop_owner->id() : 0;
01798 
01799   if( !loop_ptr->get_loop_sm_ptr() && print_error )
01800   {
01801     PRINT_WARNING("Loop in Surface %d has no OSME pointer.\n",surf_id);
01802   }
01803   
01804   DLIList<CoEdge*> coedge_list;
01805   CubitStatus status = loop_ptr->ordered_co_edges( coedge_list );
01806   if( ! status )
01807   {
01808     if( print_error ) 
01809       PRINT_ERROR("Query for loop coedges failed!\n");
01810     return CUBIT_FALSE;
01811   }
01812   
01813   if( coedge_list.size() < 2 ) return CUBIT_TRUE;
01814   
01815   CoEdge* prev_coedge = coedge_list.get_and_step();
01816   RefEdge* prev_edge = prev_coedge->get_ref_edge_ptr();
01817   for( int i = coedge_list.size(); i > 0; i-- )
01818   {
01819     CoEdge* curr_coedge = coedge_list.get_and_step();
01820     RefEdge* curr_edge = curr_coedge->get_ref_edge_ptr();
01821     
01822     if (!curr_edge)
01823     {
01824       if (print_error)
01825         PRINT_ERROR("CoEdge in surface %d has no Curve.\n", surf_id);
01826       result = CUBIT_FAILURE;
01827       continue;
01828     }
01829     
01830     if( !curr_coedge->get_co_edge_sm_ptr() && print_error )
01831     {
01832       PRINT_WARNING("CoEdge between surface %d and curve %d has "
01833                     "no OSME pointer.\n", surf_id, curr_edge->id() );
01834     }
01835     
01836     RefVertex* common = curr_edge->common_ref_vertex( prev_edge );
01837     if( !common )
01838     {
01839       if( print_error )
01840         PRINT_ERROR("Curves %d and %d are ajacent in a Loop on surface %d, "
01841                     "but do not have a common vertex.\n",
01842           prev_edge->id(), curr_edge->id(), surf_id );
01843       result = CUBIT_FALSE;
01844     }
01845     
01846     RefVertex* start_vtx = 0;
01847     CubitSense sense = curr_coedge->get_sense();
01848     switch( sense )
01849     {
01850       case CUBIT_FORWARD:
01851         start_vtx = curr_edge->start_vertex();
01852         break;
01853       case CUBIT_REVERSED:
01854         start_vtx = curr_edge->end_vertex();
01855         break;
01856       case CUBIT_UNKNOWN:
01857       default:
01858         start_vtx = 0;
01859         break;
01860     }
01861     
01862     RefVertex* end_vtx = 0;
01863     switch( prev_coedge->get_sense() )
01864     {
01865       case CUBIT_FORWARD:
01866         end_vtx = prev_edge->end_vertex();
01867         break;
01868       case CUBIT_REVERSED:
01869         end_vtx = prev_edge->start_vertex();
01870         break;
01871       default:
01872         break;
01873     }
01874     
01875     if( start_vtx == NULL )
01876     {
01877       if( print_error )
01878         PRINT_ERROR("Curve %d has an unknown sense on surface %d.\n",
01879           curr_edge->id(), surf_id );
01880       result = CUBIT_FALSE;
01881     }
01882     else if( start_vtx != end_vtx )
01883     {
01884       if( print_error )
01885         PRINT_ERROR("The sense of curve %d (%s) on surface %d appears "
01886                     "to be incorrect with respect to the previous curve "
01887                     "in the loop (curve %d).\n", curr_edge->id(),
01888                     sense == CUBIT_FORWARD ? "forward" : "reverse",
01889                     surf_id, prev_edge->id() );
01890       result = CUBIT_FALSE;
01891     }
01892   
01893     prev_edge = curr_edge;
01894     prev_coedge = curr_coedge;
01895   }  
01896   
01897   return result;
01898 }
01899 
01900 CubitBoolean GeometryUtil::valid_shell_cofaces( Shell* shell_ptr,
01901                                                 CubitBoolean print_error )
01902 {
01903   DLIList<CoFace*> coface_list, ajacent_cofaces;
01904   DLIList<CoEdge*> coedge_list;
01905   shell_ptr->co_faces( coface_list );
01906   CubitBoolean result = CUBIT_TRUE;
01907   RefVolume* vol_ptr = shell_ptr->get_ref_volume_ptr();
01908   int vol_id = vol_ptr ? vol_ptr->id() : 0;
01909   
01910   if( ! shell_ptr->get_shell_sm_ptr() && print_error)
01911   {
01912     PRINT_WARNING("Shell in volume %d has no OSME pointer.\n",vol_id);
01913   }
01914       
01915   
01916   while( coface_list.size() > 0 )
01917   {
01918     CoFace* coface_ptr = coface_list.pop();
01919     RefFace* face_ptr = coface_ptr->get_ref_face_ptr();
01920     if( !face_ptr )
01921     {
01922       if( print_error )
01923         PRINT_ERROR("Encountered a CoFace without a RefFace in volume %d.\n",vol_id);
01924       result = CUBIT_FALSE;
01925       continue;
01926     }
01927     if (face_ptr->is_nonmanifold(shell_ptr))
01928     {
01929       continue;
01930     }
01931     CubitSense sense = coface_ptr->get_sense();
01932     if( sense == CUBIT_UNKNOWN )
01933     {
01934       if( print_error )
01935         PRINT_ERROR("Surface %d has an unknown sense with respect to volume %d.\n",
01936           face_ptr->id(), vol_id );
01937       result = CUBIT_FALSE;
01938       continue;
01939     }
01940  
01941     
01942     coedge_list.clean_out();
01943     face_ptr->co_edges( coedge_list );
01944     
01945     for( int i = coedge_list.size(); i > 0; i-- )
01946     {
01947       CoEdge* coedge_ptr = coedge_list.get_and_step();
01948       RefEdge* edge_ptr = coedge_ptr->get_ref_edge_ptr();
01949       if( !edge_ptr )
01950       {
01951         result = CUBIT_FALSE;
01952         if( print_error )
01953           PRINT_ERROR("CoEdge @ %p in Surface %d has no Curve!\n",
01954             (void*)coedge_ptr, face_ptr->id() );
01955         continue;
01956       }
01957       
01958       ajacent_cofaces.clean_out();
01959       edge_ptr->co_faces( ajacent_cofaces );
01960       ajacent_cofaces.intersect( coface_list );
01961       
01962       CubitSense coedge_sense = coedge_ptr->get_sense();
01963       if( coedge_sense == CUBIT_UNKNOWN )
01964       {
01965         if( print_error )
01966           PRINT_ERROR("CoEdge connecting Curve %d to surface %d "
01967                       "has UNKNOWN sense.\n",edge_ptr->id(), face_ptr->id() );
01968         result = CUBIT_FALSE;
01969         continue;
01970       }
01971       
01972       if( (ajacent_cofaces.size() > 1) && print_error )
01973       {
01974         PRINT_WARNING("Non-manifold topology at curve %d on volume %d "
01975                       "may result in false errors being reported.\n",
01976                       edge_ptr->id(), vol_id );
01977       }
01978       
01979       for( int j = ajacent_cofaces.size(); j > 0; j-- )
01980       {
01981         CoFace* other_coface = ajacent_cofaces.get_and_step();
01982         RefFace* other_face = other_coface->get_ref_face_ptr();
01983         if( ! other_face )
01984         {
01985           if( print_error )
01986             PRINT_ERROR("Encountered a CoFace on volume %d that does not "
01987                         "have a RefFace!\n",vol_id);
01988           result = CUBIT_FALSE;
01989           continue;
01990         }
01991         CubitSense other_coedge_sense = edge_ptr->sense( other_face );
01992         if( other_coedge_sense == CUBIT_UNKNOWN )
01993         {
01994           if( print_error )
01995             PRINT_ERROR("Curve %d has unknown sense with respect to "
01996                         "surface %d.\n",edge_ptr->id(), other_face->id() );
01997           result = CUBIT_FALSE;
01998           continue;
01999         }
02000         CubitSense other_sense = other_coface->get_sense();
02001         if( other_sense == CUBIT_UNKNOWN )
02002         {
02003           if( print_error )
02004             PRINT_ERROR("Surface %d has an unknown sense with respect "
02005                         "to volume %d.\n", other_face->id(), vol_id );
02006           result = CUBIT_FALSE;
02007           continue;
02008         }
02009         
02010         if( ((sense == other_sense) && (coedge_sense == other_coedge_sense))
02011           ||((sense != other_sense) && (coedge_sense != other_coedge_sense)) )
02012         {
02013           if( print_error )
02014             PRINT_ERROR("Incompatible CoFace senses found at curve %d in "
02015                         "volume %d.\n"
02016                         "  Surface  CoFace Sense  CoEdge Sense\n"
02017                         "  -------  ------------  ------------\n"
02018                         "  %7d  %12s  %12s\n  %7d  %12s  %12s\n",
02019                         edge_ptr->id(), vol_id,
02020                         face_ptr->id(), 
02021                         sense == CUBIT_FORWARD ? "forward" : "reverse",
02022                         coedge_sense == CUBIT_FORWARD ? "forward" : "reverse",
02023                         other_face->id(),
02024                         other_sense == CUBIT_FORWARD ? "forward" : "reverse",
02025                         other_coedge_sense == CUBIT_FORWARD ? 
02026                                        "forward" : "reverse");
02027           result = CUBIT_FALSE;
02028         }
02029       } // end for( j )
02030     
02031     } // end for( i )
02032   
02033   } // end while( coface_list.size() )
02034   
02035   return result;
02036 }
02037 
02038 CubitBoolean GeometryUtil::valid_topology(  TopologyEntity* topo_ptr,
02039                                CubitBoolean print_error,
02040                                DLIList<TopologyEntity*>* invalid_list )
02041 {
02042   CubitBoolean result = CUBIT_TRUE;
02043   DLIList<Shell*> shell_list;
02044   DLIList<Loop*> loop_list;
02045   DLIList<RefEdge*> edge_list;
02046   Shell* shell_ptr;
02047   Loop* loop_ptr;
02048   RefEdge* edge_ptr;
02049   int i;  
02050 
02051   if( CAST_TO( topo_ptr, Body ) ||
02052       CAST_TO( topo_ptr, CoVolume ) ||
02053       CAST_TO( topo_ptr, RefVolume ) )
02054   {
02055     shell_list.clean_out();
02056     topo_ptr->shells( shell_list );
02057     for( i = shell_list.size(); i > 0; i-- )
02058     {
02059       shell_ptr = shell_list.get_and_step();
02060       if( ! valid_shell_cofaces( shell_ptr, print_error ) )
02061       {
02062         if( invalid_list ) invalid_list->append( shell_ptr );
02063         result = CUBIT_FALSE;
02064       }
02065     }
02066   }
02067   if(CAST_TO( topo_ptr, Body ) ||
02068      CAST_TO( topo_ptr, CoVolume ) ||
02069      CAST_TO( topo_ptr, RefVolume ) ||
02070      CAST_TO( topo_ptr, Shell ) ) 
02071   {
02072     shell_ptr = CAST_TO( topo_ptr, Shell );
02073     if( shell_ptr && !valid_shell_cofaces( shell_ptr, print_error ) )
02074     {
02075       if( invalid_list ) invalid_list->append( shell_ptr );
02076       result = CUBIT_FALSE;
02077     }
02078   }
02079   if(CAST_TO( topo_ptr, Body ) ||
02080      CAST_TO( topo_ptr, CoVolume ) ||
02081      CAST_TO( topo_ptr, RefVolume ) ||
02082      CAST_TO( topo_ptr, Shell ) ||
02083      CAST_TO( topo_ptr, CoFace ) ||
02084      CAST_TO( topo_ptr, RefFace ) )
02085   {
02086     loop_list.clean_out();
02087     topo_ptr->loops( loop_list );
02088     for( i = loop_list.size(); i > 0; i-- )
02089     {
02090       loop_ptr = loop_list.get_and_step();
02091       if( ! valid_loop_coedges( loop_ptr, print_error ) )
02092       {
02093         if( invalid_list ) invalid_list->append( loop_ptr );
02094         result = CUBIT_FALSE;
02095       }
02096     }
02097   }
02098   if(CAST_TO( topo_ptr, Body ) ||
02099      CAST_TO( topo_ptr, CoVolume ) ||
02100      CAST_TO( topo_ptr, RefVolume ) ||
02101      CAST_TO( topo_ptr, Shell ) ||
02102      CAST_TO( topo_ptr, CoFace ) ||
02103      CAST_TO( topo_ptr, RefFace ) ||
02104      CAST_TO( topo_ptr, Loop ) )
02105   {
02106     loop_ptr = CAST_TO( topo_ptr, Loop );
02107     if( loop_ptr && !valid_loop_coedges( loop_ptr, print_error ) )
02108     {
02109       if( invalid_list ) invalid_list->append( loop_ptr );
02110       result = CUBIT_FALSE;
02111     }
02112   }
02113   if(CAST_TO( topo_ptr, Body ) ||
02114      CAST_TO( topo_ptr, CoVolume ) ||
02115      CAST_TO( topo_ptr, RefVolume ) ||
02116      CAST_TO( topo_ptr, Shell ) ||
02117      CAST_TO( topo_ptr, CoFace ) ||
02118      CAST_TO( topo_ptr, RefFace ) ||
02119      CAST_TO( topo_ptr, Loop ) ||
02120      CAST_TO( topo_ptr, CoEdge ) )
02121   {
02122     edge_list.clean_out();
02123     topo_ptr->ref_edges( edge_list );
02124     for( i = edge_list.size(); i > 0; i-- )
02125     {
02126       edge_ptr = edge_list.get_and_step();
02127       if( !valid_edge( edge_ptr, print_error ) )
02128       {
02129         if( invalid_list ) invalid_list->append( edge_ptr );
02130         result = CUBIT_FALSE;
02131       }
02132     }
02133   }
02134   if(CAST_TO( topo_ptr, Body ) ||
02135      CAST_TO( topo_ptr, CoVolume ) ||
02136      CAST_TO( topo_ptr, RefVolume ) ||
02137      CAST_TO( topo_ptr, Shell ) ||
02138      CAST_TO( topo_ptr, CoFace ) ||
02139      CAST_TO( topo_ptr, RefFace ) ||
02140      CAST_TO( topo_ptr, Loop ) ||
02141      CAST_TO( topo_ptr, CoEdge ) ||
02142      CAST_TO( topo_ptr, RefEdge ) )
02143   {
02144     edge_ptr = CAST_TO( topo_ptr, RefEdge );
02145     if( edge_ptr && !valid_edge( edge_ptr, print_error ) )
02146     {
02147       if( invalid_list ) invalid_list->append( edge_ptr );
02148       result = CUBIT_FALSE;
02149     }
02150   }
02151   else if( CAST_TO( topo_ptr, Chain ) ||
02152            CAST_TO( topo_ptr, CoVertex ) ||
02153            CAST_TO( topo_ptr, RefVertex ) )
02154      ;//Do nothing
02155   else
02156   {
02157     if( print_error )
02158        PRINT_WARNING("Unknown entity type '%s' passed to GeometryUtil::"
02159                      "valid_topology(..).\n",topo_ptr->class_name() );
02160   }
02161   
02162   return result;
02163 }
02164 
02165 //-------------------------------------------------------------------------
02166 // Purpose       : Compare VGI topology to SM topology
02167 //
02168 // Special Notes : 
02169 //
02170 // Creator       : Jason Kraftcheck
02171 //
02172 // Creation Date : 01/19/01
02173 //-------------------------------------------------------------------------
02174 CubitBoolean GeometryUtil::valid_sm_topology( DLIList<RefEntity*>& entity_list,
02175                                               CubitBoolean print_error )
02176 {
02177   CubitBoolean result = CUBIT_TRUE;
02178   
02179   DLIList<Body*>     body_list;
02180   DLIList<RefVolume*> vol_list, child_vols ;
02181   DLIList<RefFace*>  face_list, child_faces;
02182   DLIList<RefEdge*>  edge_list, child_edges;
02183   DLIList<RefVertex*> vtx_list, child_vtx;
02184   CAST_LIST( entity_list, body_list, Body     );
02185   CAST_LIST( entity_list, vol_list , RefVolume);
02186   CAST_LIST( entity_list, face_list, RefFace  );
02187   CAST_LIST( entity_list, edge_list, RefEdge  );
02188   CAST_LIST( entity_list, vtx_list , RefVertex);
02189   
02190   int i;
02191   for( i = body_list.size(); i--; )
02192   {
02193     Body* body_ptr = body_list.get_and_step();
02194     if( !valid_sm_topology( body_ptr, print_error ) )
02195       result = CUBIT_FALSE;
02196     child_vols.clean_out();
02197     body_ptr->ref_volumes( child_vols );
02198     vol_list.merge_unique( child_vols );
02199   }
02200   for( i = vol_list.size(); i--; )
02201   {
02202     RefVolume* vol_ptr = vol_list.get_and_step();
02203     if( !valid_sm_topology( vol_ptr, print_error ) )
02204       result = CUBIT_FALSE;
02205     child_faces.clean_out();
02206     vol_ptr->ref_faces( child_faces );
02207     face_list.merge_unique( child_faces );
02208   }
02209   for( i = face_list.size(); i--; )
02210   {
02211     RefFace* face_ptr = face_list.get_and_step();
02212     if( !valid_sm_topology( face_ptr, print_error ) )
02213       result = CUBIT_FALSE;
02214     child_edges.clean_out();
02215     face_ptr->ref_edges( child_edges );
02216     edge_list.merge_unique( child_edges );
02217   }
02218   for( i = edge_list.size(); i--; )
02219   {
02220     RefEdge* edge_ptr = edge_list.get_and_step();
02221     if( !valid_sm_topology( edge_ptr, print_error ) )
02222       result = CUBIT_FALSE;
02223     child_vtx.clean_out();
02224     edge_ptr->ref_vertices( child_vtx );
02225     vtx_list.merge_unique( child_vtx );
02226   }
02227   for( i = vtx_list.size(); i--; )
02228     if( !valid_sm_topology(vtx_list.get_and_step(), print_error ) )
02229       result = CUBIT_FALSE;
02230   
02231   return result;
02232 }
02233 CubitBoolean GeometryUtil::valid_sm_topology( Body* body_ptr, CubitBoolean print )
02234 {
02235   CubitBoolean result = CUBIT_TRUE;
02236   int i;
02237   
02238     // This function checks for extraneous links in the VGI between
02239     // the passed body and its child volumes.  To check for missing
02240     // links, use valid_sm_topology(RefVolume*).
02241   
02242   DLIList<RefVolume*> vol_list;
02243   body_ptr->ref_volumes( vol_list );
02244   
02245     // Get all child TopologyBridges
02246   DLIList<TopologyBridge*> body_bridges, lump_bridges, temp_list;
02247   body_ptr->bridge_manager()->get_bridge_list( body_bridges );
02248   
02249   if ( body_bridges.size() != 1 )
02250   {
02251     PRINT_ERROR("%s (Body %d) has %d attached BodySM(s).\n", 
02252       body_ptr->entity_name().c_str(), body_ptr->id(), body_bridges.size() ); 
02253     result = CUBIT_FALSE;
02254   }
02255 
02256   for( i = body_bridges.size(); i > 0; i-- )
02257   {
02258     TopologyBridge* bodysm = body_bridges.get_and_step();
02259     temp_list.clean_out();
02260     bodysm->get_children( temp_list );
02261     lump_bridges.merge_unique( temp_list );
02262   }
02263   
02264     // Check that each child VGI RefVolume has atleast one
02265     // TopologyBridge in the list we got from the solid modeler.
02266   for( i = vol_list.size(); i > 0; i-- )
02267   {
02268     RefVolume* vol_ptr = vol_list.get_and_step();
02269     temp_list.clean_out();
02270     vol_ptr->bridge_manager()->get_bridge_list( temp_list );
02271     temp_list.intersect( lump_bridges );
02272     if( temp_list.size() == 0 )
02273     {
02274       if( print ) PRINT_ERROR(
02275         "Extraneous VGI link between %s and %s.\n",
02276         body_ptr->entity_name().c_str(),
02277         vol_ptr->entity_name().c_str() );
02278       result = CUBIT_FALSE;
02279     }
02280   }
02281   
02282   for( i = lump_bridges.size(); i--; )
02283   {
02284     TopologyBridge* lump = lump_bridges.get_and_step();
02285     TopologyEntity* owner = lump->topology_entity();
02286     RefVolume* vol_ptr = dynamic_cast<RefVolume*>(owner);
02287     if( ! vol_ptr )
02288     {
02289       if( print ) PRINT_ERROR(
02290         "No RefVolume for Lump %p in %s\n",
02291         (void*)lump, body_ptr->entity_name().c_str() );
02292       result = CUBIT_FALSE;
02293     }
02294   } 
02295 
02296   return result;
02297 }
02298 
02299 CubitBoolean GeometryUtil::valid_sm_topology( RefVolume* vol_ptr, CubitBoolean print )
02300 {
02301   CubitBoolean result = CUBIT_TRUE;
02302   int i;
02303   
02304     // This method checks for 
02305     //  a.) Missing links between the passed RefVolume and its parent Body(s)
02306     //  b.) Extraneous links between the RefVolume and its child shell(s)
02307     //  c.) Invalid Shells by calling valid_sm_topology(Shell*)
02308   
02309   DLIList<Body*> body_list;
02310   vol_ptr->bodies( body_list );
02311   DLIList<Shell*> shell_list;
02312   vol_ptr->shells( shell_list );
02313   DLIList<TopologyBridge*> vol_bridges, shell_bridges, temp_list;
02314   vol_ptr->bridge_manager()->get_bridge_list( vol_bridges );
02315   
02316   if ( vol_bridges.size() != 1 )
02317   {
02318     PRINT_ERROR("%s (RefVolume %d) has %d attached Lump(s).\n", 
02319       vol_ptr->entity_name().c_str(), vol_ptr->id(), vol_bridges.size() ); 
02320     result = CUBIT_FALSE;
02321   }
02322   
02323   for( i = vol_bridges.size(); i > 0; i-- )
02324   {
02325     TopologyBridge* lump = vol_bridges.get_and_step();
02326     
02327     // Check for missing links between this RefVolume and parent Body(s)
02328     temp_list.clean_out();
02329     lump->get_parents( temp_list );
02330     for( int j = temp_list.size(); j > 0; j-- )
02331     {
02332       TopologyBridge* bodysm = temp_list.get_and_step();
02333       TopologyEntity* te_ptr = bodysm->topology_entity();
02334       Body* body_ptr = CAST_TO( te_ptr, Body );
02335       CubitString body_name;
02336       const char* body_str = "PARENT BODY";
02337       if( body_ptr )
02338       {
02339         body_name = body_ptr->entity_name();
02340         body_str = body_name.c_str();
02341       }
02342       if( (body_ptr == NULL) || !body_list.is_in_list(body_ptr) )
02343       {
02344         if( print ) PRINT_ERROR(
02345           "Missing VGI link between %s and %s\n",
02346           body_str,
02347           vol_ptr->entity_name().c_str() );
02348         result = CUBIT_FALSE;
02349       }
02350     }
02351     
02352     // Build ShellSM list for next part
02353     temp_list.clean_out();
02354     lump->get_children( temp_list );
02355     shell_bridges.merge_unique( temp_list );
02356   }
02357   
02358   // Check for extraneous VGI links between this RefVolume and child Shell(s)
02359   for( i = shell_list.size(); i > 0; i-- )
02360   {
02361     Shell* shell_ptr = shell_list.get_and_step();
02362     temp_list.clean_out();
02363     shell_ptr->bridge_manager()->get_bridge_list( temp_list );
02364     temp_list.intersect( shell_bridges );
02365     if( temp_list.size() == 0 )
02366     {
02367       DLIList<RefFace*> shell_faces;
02368       shell_ptr->ref_faces( shell_faces );
02369       CubitString face_name;
02370       const char* face_str = "NO REFFACE";
02371       if( shell_faces.size() )
02372       {
02373         face_name = shell_faces.get()->entity_name();
02374         face_str = face_name.c_str();
02375       }
02376       if( print ) PRINT_ERROR(
02377         "Extraneous VGI link between %s and Shell with %s.\n",
02378         vol_ptr->entity_name().c_str(),
02379         face_str );
02380       result = CUBIT_FALSE;
02381     }
02382   }
02383   
02384   for( i = shell_bridges.size(); i--; )
02385   {
02386     TopologyBridge* shell = shell_bridges.get_and_step();
02387     TopologyEntity* owner = shell->topology_entity();
02388     Shell* shell_ptr = dynamic_cast<Shell*>(owner);
02389     if( ! shell_ptr )
02390     {
02391       if( print ) PRINT_ERROR(
02392         "No Shell for ShellSM %p in %s\n",
02393         (void*)shell, vol_ptr->entity_name().c_str() );
02394       result = CUBIT_FALSE;
02395     }
02396   } 
02397   
02398   for( i = shell_list.size(); i > 0; i-- )
02399     if( !valid_sm_topology( shell_list.get_and_step(), print ) )
02400       result = CUBIT_FALSE;
02401   
02402   return result;
02403 }
02404 
02405 
02406 CubitBoolean GeometryUtil::valid_sm_topology(Shell* shell_ptr, CubitBoolean print )
02407 {
02408   CubitBoolean result = CUBIT_TRUE;
02409   int i;
02410   
02411     // This method checks for 
02412     //  a.) Missing links between the passed Shell and its parent RefVolume(s)
02413     //  b.) Extraneous links between the Shell and its child RefFace(s)
02414   
02415   DLIList<RefVolume*> vol_list;
02416   shell_ptr->ref_volumes( vol_list );
02417   DLIList<RefFace*> face_list;
02418   shell_ptr->ref_faces( face_list );
02419   DLIList<TopologyBridge*> shell_bridges, face_bridges, temp_list;
02420   shell_ptr->bridge_manager()->get_bridge_list( shell_bridges );
02421   
02422   if ( shell_bridges.size() != 1 )
02423   {
02424     PRINT_ERROR("Shell %p (in Volume %d) has %d attached ShellSM(s).\n", 
02425       (void*)shell_ptr,  shell_ptr->get_ref_volume_ptr() ?
02426       shell_ptr->get_ref_volume_ptr()->id() : 0,
02427       shell_bridges.size() );
02428     result = CUBIT_FALSE;
02429   }
02430   
02431   for( i = shell_bridges.size(); i > 0; i-- )
02432   {
02433     TopologyBridge* shellsm = shell_bridges.get_and_step();
02434     
02435     // Check for missing links between this Shell and parent RefVolume(s)
02436     temp_list.clean_out();
02437     shellsm->get_parents( temp_list );
02438     if (temp_list.size() != 1)
02439     {
02440       PRINT_ERROR("Bad SolidModel Topology!\n");
02441       PRINT_ERROR("ShellSM %p in Shell %p (in Volume %d) has %d parent Lumps.\n",
02442        (void*)shellsm, (void*)shell_ptr,
02443        shell_ptr->get_ref_volume_ptr() ? shell_ptr->get_ref_volume_ptr()->id() : 0,
02444        temp_list.size() );
02445     }
02446     else
02447     {
02448       TopologyBridge* lump = temp_list.get_and_step();
02449       TopologyEntity* te_ptr = lump->topology_entity();
02450       RefVolume* vol_ptr = CAST_TO( te_ptr, RefVolume );
02451       if( (vol_ptr == NULL) || !vol_list.is_in_list(vol_ptr) )
02452       {
02453         DLIList<RefFace*> faces;
02454         shell_ptr->ref_faces( faces );
02455         CubitString vol_name, face_name;
02456         const char* vol_str = "PARENT VOLUME";
02457         const char* face_str = "NO REFFACES";
02458         if( vol_ptr )
02459         {
02460           vol_name = vol_ptr->entity_name();
02461           vol_str = vol_name.c_str();
02462         }
02463         if( faces.size() )
02464         {
02465           face_name = faces.get()->entity_name();
02466           face_str = face_name.c_str();
02467         }
02468         if( print ) PRINT_ERROR(
02469           "Missing VGI link between %s and Shell with %s\n",
02470           vol_str, face_str );
02471         result = CUBIT_FALSE;
02472       }
02473     }
02474     // Build Surface list for next part
02475     temp_list.clean_out();
02476     shellsm->get_children( temp_list );
02477     face_bridges.merge_unique( temp_list );
02478   }
02479   
02480   // Check for extraneous VGI links between this Shell and child RefFaces(s)
02481   for( i = face_list.size(); i > 0; i-- )
02482   {
02483     RefFace* face_ptr = face_list.get_and_step();
02484     temp_list.clean_out();
02485     face_ptr->bridge_manager()->get_bridge_list( temp_list );
02486     temp_list.intersect( face_bridges );
02487     if( temp_list.size() == 0 )
02488     {
02489       DLIList<RefFace*> faces;
02490       shell_ptr->ref_faces( faces );
02491       CubitString face_name;
02492       const char* face_str = "NO REFFACES";
02493       if( faces.size() )
02494       {
02495         face_name = faces.get()->entity_name();
02496         face_str = face_name.c_str();
02497       }
02498       if( print ) PRINT_ERROR(
02499         "Extraneous VGI link between Shell with %s and %s.\n",
02500         face_str,
02501         face_ptr->entity_name().c_str() );
02502       result = CUBIT_FALSE;
02503     }
02504   }
02505   
02506   for( i = face_bridges.size(); i--; )
02507   {
02508     TopologyBridge* surface = face_bridges.get_and_step();
02509     TopologyEntity* owner = surface->topology_entity();
02510     RefFace* face_ptr = dynamic_cast<RefFace*>(owner);
02511     if( ! face_ptr )
02512     {
02513       if( print ) PRINT_ERROR(
02514         "No RefFace for Surface %p in Shell %p in %s\n",
02515         (void*)surface, (void*)shell_ptr,
02516         vol_list.size() ?
02517           vol_list.get()->entity_name().c_str() :
02518           "NO REFVOLUME" );
02519       result = CUBIT_FALSE;
02520     }
02521   } 
02522   
02523   return result;
02524 }
02525 
02526 
02527 CubitBoolean GeometryUtil::valid_sm_topology( RefFace* face_ptr, CubitBoolean print )
02528 {
02529   CubitBoolean result = CUBIT_TRUE;
02530   int i;
02531   
02532     // This method checks for 
02533     //  a.) Missing links between the passed RefFace and its parent Shell(s)
02534     //  b.) Extraneous links between the RefFace and its child Loop(s)
02535     //  c.) Invalid Loops by calling valid_sm_topology(Loop*)
02536   
02537   DLIList<Shell*> shell_list;
02538   face_ptr->shells( shell_list );
02539   DLIList<Loop*> loop_list;
02540   face_ptr->loops( loop_list );
02541   DLIList<TopologyBridge*> face_bridges, loop_bridges, temp_list;
02542   face_ptr->bridge_manager()->get_bridge_list( face_bridges );
02543   
02544   if ( face_bridges.size() == 0 )
02545   {
02546     PRINT_ERROR("%s (RefFace %d) has no attached Surface(s).\n", 
02547       face_ptr->entity_name().c_str(), face_ptr->id() ); 
02548     result = CUBIT_FALSE;
02549   }
02550   
02551   for( i = face_bridges.size(); i > 0; i-- )
02552   {
02553     TopologyBridge* surf = face_bridges.get_and_step();
02554     
02555     // Check for missing links between this RefFace and parent Shell(s)
02556     temp_list.clean_out();
02557     surf->get_parents( temp_list );
02558     for( int j = temp_list.size(); j > 0; j-- )
02559     {
02560       TopologyBridge* shellsm = temp_list.get_and_step();
02561       TopologyEntity* te_ptr = shellsm->topology_entity();
02562       Shell* shell_ptr = CAST_TO( te_ptr, Shell );
02563       if( (shell_ptr == NULL) || !shell_list.is_in_list(shell_ptr) )
02564       {
02565         DLIList<RefVolume*> vols;
02566         if( shell_ptr != NULL ) 
02567           shell_ptr->ref_volumes( vols );
02568         CubitString vol_name;
02569         const char* vol_str = "PARENT REFVOLUME";
02570         if( vols.size() )
02571         {
02572           vol_name = vols.get()->entity_name();
02573           vol_str = vol_name.c_str();
02574         }
02575         if( print ) PRINT_ERROR(
02576           "Missing VGI link between Shell with %s and %s\n",
02577           vol_str,
02578           face_ptr->entity_name().c_str() );
02579         result = CUBIT_FALSE;
02580       }
02581     }
02582     
02583     // Build LoopSM list for next part
02584     temp_list.clean_out();
02585     surf->get_children( temp_list );
02586     loop_bridges.merge_unique( temp_list );
02587   }
02588   
02589   // Check for extraneous VGI links between this RefFace and child Loop(s)
02590   for( i = loop_list.size(); i > 0; i-- )
02591   {
02592     Loop* loop_ptr = loop_list.get_and_step();
02593     temp_list.clean_out();
02594     loop_ptr->bridge_manager()->get_bridge_list( temp_list );
02595     temp_list.intersect( loop_bridges );
02596     if( temp_list.size() == 0 )
02597     {
02598       DLIList<RefEdge*> edges;
02599       loop_ptr->ref_edges( edges );
02600       CubitString edge_name;
02601       const char* edge_str = "NO REFEDGE";
02602       if( edges.size() )
02603       {
02604         edge_name = edges.get()->entity_name();
02605         edge_str = edge_name.c_str();
02606       }
02607       if( print ) PRINT_ERROR(
02608         "Extraneous VGI link between %s and Loop with %s.\n",
02609         face_ptr->entity_name().c_str(),
02610         edge_str );
02611       result = CUBIT_FALSE;
02612     }
02613   }
02614   
02615   for( i = loop_bridges.size(); i--; )
02616   {
02617     TopologyBridge* loop = loop_bridges.get_and_step();
02618     TopologyEntity* owner = loop->topology_entity();
02619     Loop* loop_ptr = dynamic_cast<Loop*>(owner);
02620     if( ! loop_ptr )
02621     {
02622       if( print ) PRINT_ERROR(
02623         "No Loop for LoopSM %p in %s\n",
02624         (void*)loop, face_ptr->entity_name().c_str() );
02625       result = CUBIT_FALSE;
02626     }
02627   } 
02628   
02629   for( i = loop_list.size(); i > 0; i-- )
02630     if( !valid_sm_topology( loop_list.get_and_step(), print ) )
02631       result = CUBIT_FALSE;
02632   
02633   return result;
02634 }
02635 
02636 
02637 CubitBoolean GeometryUtil::valid_sm_topology( Loop* loop_ptr, CubitBoolean print )
02638 {
02639   CubitBoolean result = CUBIT_TRUE;
02640   CoEdge* coedge_ptr;
02641   int i;
02642 
02643     // This method checks for 
02644     //  a.) Missing links between the passed Loop and its parent RefFace(s)
02645     //  b.) Extraneous links between the Loop and its child CoEdge(s)
02646     //  c.) Invalid CoEdges by calling valid_sm_topology(CoEdge*)
02647     //  d.) CoEdgeSMs w/out CoEdges
02648     //  e.) Correct CoEdge order given CoEdgeSM order.
02649   
02650   DLIList<RefFace*> face_list;
02651   loop_ptr->ref_faces( face_list );
02652   DLIList<CoEdge*> coedge_list;
02653   loop_ptr->co_edges( coedge_list );
02654   DLIList<TopologyBridge*> loop_bridges, coedge_bridges, temp_list;
02655   loop_ptr->bridge_manager()->get_bridge_list( loop_bridges );
02656   
02657   if ( loop_bridges.size() == 0 )
02658   {
02659     PRINT_ERROR("Loop %p (in surface %d) has no attached LoopSM(s).\n", 
02660       (void*)loop_ptr,
02661       loop_ptr->get_ref_face_ptr() ? loop_ptr->get_ref_face_ptr()->id() : 0 );
02662     result = CUBIT_FALSE;
02663   }
02664   
02665   for( i = loop_bridges.size(); i > 0; i-- )
02666   {
02667     TopologyBridge* loopsm = loop_bridges.get_and_step();
02668     
02669     // Check for missing links between this Loop and parent RefFace(s)
02670     temp_list.clean_out();
02671     loopsm->get_parents( temp_list );
02672     for( int j = temp_list.size(); j > 0; j-- )
02673     {
02674       TopologyBridge* surf = temp_list.get_and_step();
02675       TopologyEntity* te_ptr = surf->topology_entity();
02676       RefFace* face_ptr = CAST_TO( te_ptr, RefFace );
02677       if( (face_ptr == NULL) || !face_list.is_in_list(face_ptr) )
02678       {
02679         DLIList<RefEdge*> edges;
02680         loop_ptr->ref_edges( edges );
02681         CubitString face_name;
02682         CubitString edge_name;
02683         const char* face_str = "PARENT REFFACE";
02684         const char* edge_str = "NO REFEDGES";
02685         if( face_ptr )
02686         {
02687           face_name = face_ptr->entity_name();
02688           face_str = face_name.c_str();
02689         }
02690         if( edges.size() )
02691         {
02692           edge_name = edges.get()->entity_name();
02693           edge_str = edge_name.c_str();
02694         }
02695         if( print ) PRINT_ERROR(
02696           "Missing VGI link between %s and Loop with %s\n", face_str, edge_str);
02697         result = CUBIT_FALSE;
02698       }
02699     }
02700     
02701     // Build CoEdgeSM list for next part
02702     temp_list.clean_out();
02703     loopsm->get_children( temp_list );
02704     coedge_bridges.merge_unique( temp_list );
02705   }
02706   
02707   // Check for extraneous VGI links between this Loop and child CoEdge(s)
02708   for( i = coedge_list.size(); i > 0; i-- )
02709   {
02710     coedge_ptr = coedge_list.get_and_step();
02711     temp_list.clean_out();
02712     coedge_ptr->bridge_manager()->get_bridge_list( temp_list );
02713     temp_list.intersect( coedge_bridges );
02714     if( temp_list.size() == 0 )
02715     {
02716       DLIList<RefEdge*> edges;
02717       DLIList<RefFace*> faces;
02718       loop_ptr->ref_faces( faces );
02719       coedge_ptr->ref_edges( edges );
02720       CubitString face_name;
02721       CubitString edge_name;
02722       const char* face_str = "NO REFFACE";
02723       const char* edge_str = "NO REFEDGE";
02724       if( faces.size() )
02725       {
02726         face_name = faces.get()->entity_name();
02727         face_str = face_name.c_str();
02728       }
02729       if( edges.size() )
02730       {
02731         edge_name = edges.get()->entity_name();
02732         edge_str = edge_name.c_str();
02733       }
02734       if( print ) PRINT_ERROR(
02735         "Extraneous VGI link between Loop in %s and CoEdge with %s.\n",
02736         face_str, edge_str );
02737       result = CUBIT_FALSE;
02738     }
02739   }
02740   
02741     // Check for missing CoedgeSMs
02742   for( i = coedge_bridges.size(); i--; )
02743   {
02744     TopologyBridge* coedge = coedge_bridges.get_and_step();
02745     TopologyEntity* owner = coedge->topology_entity();
02746     coedge_ptr = dynamic_cast<CoEdge*>(owner);
02747     if( ! coedge_ptr )
02748     {
02749       CubitString face_name = "NO REFFACE";
02750       if( face_list.size() )
02751         face_name = face_list.get()->entity_name();
02752       if( print ) PRINT_ERROR(
02753         "No CoEdge for CoEdgeSM %p in Loop %p in %s\n",
02754         (void*)coedge, (void*)loop_ptr, face_name.c_str() );
02755       result = CUBIT_FALSE;
02756     }
02757   } 
02758   
02759   
02760   for( i = coedge_list.size(); i > 0; i-- )
02761     if( !valid_sm_topology( coedge_list.get_and_step(), print ) )
02762       result = CUBIT_FALSE;
02763 
02764   if( !result )
02765     return result;
02766 
02767   
02768   RefFace* face_ptr = loop_ptr->get_ref_face_ptr();
02769   CubitString face_name_str;
02770   const char* face_str_ptr = "NO PARENT REFFACE";
02771   if( face_ptr )
02772   {
02773     face_name_str = face_ptr->entity_name();
02774     face_str_ptr = face_name_str.c_str();
02775   }
02776   
02777   
02778     // Check correct order of CoEdges
02779   for( i = loop_bridges.size(); i--; )
02780   {
02781     TopologyBridge* loopsm_ptr = loop_bridges.get_and_step();
02782     coedge_bridges.clean_out();
02783     loopsm_ptr->get_children( coedge_bridges );
02784   
02785     if( coedge_bridges.size() != coedge_list.size() )
02786     {
02787       if( print ) PRINT_ERROR(
02788         "Loop %p in %s has %d coedges, while LoopSM %p has %d coedgesms.\n",
02789           (void*)loop_ptr, face_str_ptr, coedge_list.size(),
02790           (void*)loopsm_ptr, coedge_bridges.size() );
02791       result = CUBIT_FAILURE;
02792       continue;
02793     }
02794 
02795       // Remaining code checks the order of coedges in the loop.
02796       // There is no wrong order if only one or two coedges.
02797     if( coedge_bridges.size() <= 2 )
02798       continue;
02799   
02800     coedge_bridges.reset();
02801     coedge_ptr = dynamic_cast<CoEdge*>(coedge_bridges.get()->topology_entity());
02802     if( !coedge_list.move_to( coedge_ptr ) )
02803       continue;
02804 
02805     coedge_ptr = dynamic_cast<CoEdge*>(coedge_bridges.next()->topology_entity());
02806     if( coedge_list.next() != coedge_ptr &&
02807         coedge_list.prev() != coedge_ptr )
02808     {
02809       if( print ) PRINT_ERROR(
02810         "Order of CoEdges in Loop %p in %s is incorrect w.r.t. LoopSM %p.\n",
02811         (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr);
02812       result = CUBIT_FAILURE;
02813       continue;
02814     }
02815 
02816     bool loop_reversed = false;
02817     TopologyBridge* coedge_bridge;
02818     if( coedge_list.prev() == coedge_ptr )
02819     {
02820       coedge_bridge = coedge_bridges.get();
02821       coedge_bridges.reverse();
02822       coedge_bridges.move_to(coedge_bridge);
02823       loop_reversed = true;
02824     }
02825 
02826     for( int j = coedge_bridges.size(); j--; )
02827     {
02828       coedge_bridge = coedge_bridges.get_and_step();
02829       coedge_ptr = coedge_list.get_and_step();
02830       if( coedge_bridge->topology_entity() != coedge_ptr )
02831       {
02832         if( print ) PRINT_ERROR(
02833           "Order of CoEdges in Loop %p in %s is incorrect w.r.t. loopsm %p.\n",
02834           (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr);
02835         result = CUBIT_FAILURE;
02836         break;
02837       }
02838     }
02839     
02840     temp_list.clean_out();
02841     loopsm_ptr->get_parents(temp_list);
02842     if (temp_list.size() != 1)
02843       continue;
02844     
02845     bool surf_reversed = (temp_list.get()->bridge_sense() == CUBIT_REVERSED);
02846     if (surf_reversed != loop_reversed)
02847     {
02848       result = CUBIT_FAILURE;
02849       if (print) PRINT_ERROR(
02850         "Loop %p in %s is reversed w.r.t. loopsm %p.\n",
02851         (void*)loop_ptr, face_str_ptr, (void*)loopsm_ptr);
02852     }
02853     
02854   }       
02855   
02856   return result;
02857 }
02858 
02859 
02860 CubitBoolean GeometryUtil::valid_sm_topology(CoEdge* coedge_ptr, CubitBoolean print )
02861 {
02862   CubitBoolean result = CUBIT_TRUE;
02863   int i;
02864   
02865     // This method checks for 
02866     //  a.) Missing links between the passed CoEdge and its parent Loop(s)
02867     //  b.) Extraneous links between the Loop and its child RefEdge(s)
02868   
02869   DLIList<Loop*> loop_list;
02870   coedge_ptr->loops( loop_list );
02871   DLIList<RefEdge*> edge_list;
02872   coedge_ptr->ref_edges( edge_list );
02873   DLIList<TopologyBridge*> coedge_bridges, edge_bridges, temp_list;
02874   coedge_ptr->bridge_manager()->get_bridge_list( coedge_bridges );
02875   
02876   if ( coedge_bridges.size() == 0 )
02877   {
02878     if (print) PRINT_ERROR(
02879       "CoEdge %p (curve %d %s in surface %d) has no attached CoEdgeSM(s).\n", 
02880       (void*)coedge_ptr,
02881       coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0,
02882       coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" :
02883       coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN",
02884       coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0 );
02885     result = CUBIT_FALSE;
02886   }
02887   
02888   for( i = coedge_bridges.size(); i > 0; i-- )
02889   {
02890     CoEdgeSM* coedgesm = dynamic_cast<CoEdgeSM*>(coedge_bridges.get_and_step());
02891     
02892     // Check for missing links between this CoEdge and parent Loop(s)
02893     temp_list.clean_out();
02894     coedgesm->get_parents( temp_list );
02895     if (temp_list.size() != 1)
02896     {
02897       PRINT_ERROR(
02898         "Bad SolidModel topology.  CoEdgeSM %p in CoEdge %p "
02899         "(curve %d %s in surface %d) has %d parent LoopSMs.\n", 
02900         (void*)coedgesm, (void*)coedge_ptr,
02901         coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0,
02902         coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" :
02903         coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN",
02904         coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0,
02905         temp_list.size() );
02906       continue;
02907     }
02908                  
02909     TopologyBridge* loopsm = temp_list.get_and_step();
02910     TopologyEntity* te_ptr = loopsm->topology_entity();
02911     Loop* loop_ptr = CAST_TO( te_ptr, Loop );
02912     if( !loop_ptr )
02913     {
02914       const char* edge_str = "NO REFEDGE";
02915       CubitString edge_name;
02916       DLIList<RefEdge*> edges;
02917       coedge_ptr->ref_edges( edges );
02918       if( edges.size() )
02919       {
02920         edge_name = edges.get()->entity_name();
02921         edge_str = edge_name.c_str();
02922       }
02923       if( print ) PRINT_ERROR(
02924         "Missing VGI Entity for LoopSM %p. Discovered on CoEdge with %s\n",
02925         (void*)loopsm, edge_str );
02926       result = CUBIT_FALSE;
02927     }
02928     else if( !loop_list.is_in_list(loop_ptr) )
02929     {
02930       DLIList<RefFace*> faces;
02931       DLIList<RefEdge*> edges;
02932       loop_ptr->ref_faces( faces );
02933       coedge_ptr->ref_edges( edges );
02934       CubitString face_name, edge_name;
02935       const char* face_str = "NO REFFACE";
02936       const char* edge_str = "NO REFEDGE";
02937       if( faces.size() )
02938       {
02939         face_name = faces.get()->entity_name();
02940         face_str = face_name.c_str();
02941       }
02942       if( edges.size() )
02943       {
02944         edge_name = edges.get()->entity_name();
02945         edge_str = edge_name.c_str();
02946       }
02947       if( print ) PRINT_ERROR(
02948         "Missing VGI link between Loop in %s and CoEdge with %s\n",
02949         face_str, edge_str );
02950       result = CUBIT_FALSE;
02951     }
02952     
02953     
02954     // Build curve list for next part
02955     temp_list.clean_out();
02956     coedgesm->get_children( temp_list );
02957     edge_bridges.merge_unique( temp_list );
02958     
02959     // Get curve and surface connected by this CoEdgeSM
02960     if (temp_list.size() != 1) // should never happen!
02961       continue;
02962     TopologyBridge* curv_bridge = temp_list.get();
02963     temp_list.clean_out();
02964     loopsm->get_parents(temp_list);
02965     if (temp_list.size() != 1) // should never happen!
02966       continue;
02967     TopologyBridge* surf_bridge = temp_list.get();
02968     
02969     bool curv_reversed = curv_bridge->bridge_sense() == CUBIT_REVERSED;
02970     bool surf_reversed = surf_bridge->bridge_sense() == CUBIT_REVERSED;
02971     bool want_reversed = curv_reversed != surf_reversed;
02972     bool  are_reversed = coedgesm->sense() != coedge_ptr->get_sense();
02973     if (want_reversed != are_reversed)
02974     {
02975       result = CUBIT_FAILURE;
02976       if (print) PRINT_ERROR(
02977         "CoEdge %p (curve %d %s in surface %d) has wrong sense w.r.t CoEdgeSM.\n", 
02978         (void*)coedge_ptr,
02979         coedge_ptr->get_ref_edge_ptr() ? coedge_ptr->get_ref_edge_ptr()->id() : 0,
02980         coedge_ptr->get_sense() == CUBIT_FORWARD ? "FORWARD" :
02981         coedge_ptr->get_sense() == CUBIT_REVERSED ? "REVERSED" : "UNKNOWN",
02982         coedge_ptr->get_ref_face() ? coedge_ptr->get_ref_face()->id() : 0 );
02983     }    
02984   }
02985   
02986   // Check for extraneous VGI links between this CoEdge and child RefEdge(s)
02987   for( i = edge_list.size(); i > 0; i-- )
02988   {
02989     RefEdge* edge_ptr = edge_list.get_and_step();
02990     temp_list.clean_out();
02991     edge_ptr->bridge_manager()->get_bridge_list( temp_list );
02992     temp_list.intersect( edge_bridges );
02993     if( temp_list.size() == 0 )
02994     {
02995       DLIList<RefEdge*> edges;
02996       coedge_ptr->ref_edges( edges );
02997       CubitString edge_name;
02998       const char* edge_str = "NO REFEDGE";
02999       if( edges.size() )
03000       {
03001         edge_name = edges.get()->entity_name();
03002         edge_str = edge_name.c_str();
03003       }
03004       if( print ) PRINT_ERROR(
03005         "Extraneous VGI link between CoEdge with %s and %s.\n",
03006         edge_str,
03007         edge_ptr->entity_name().c_str() );
03008       result = CUBIT_FALSE;
03009     }
03010   }
03011   
03012   for( i = edge_bridges.size(); i--; )
03013   {
03014     TopologyBridge* curve = edge_bridges.get_and_step();
03015     TopologyEntity* owner = curve->topology_entity();
03016     RefEdge* edge_ptr = dynamic_cast<RefEdge*>(owner);
03017     if( ! edge_ptr )
03018     {
03019       DLIList<RefFace*> faces;
03020       coedge_ptr->ref_faces( faces );
03021       CubitString face_name = "NO REFFACE";
03022       if( faces.size() )
03023         face_name = faces.get()->entity_name();
03024       if( print ) PRINT_ERROR(
03025         "No RefEdge for Curve %p in CoEdge %p in %s\n",
03026         (void*)curve, (void*)coedge_ptr, face_name.c_str() );
03027       result = CUBIT_FALSE;
03028     }
03029   } 
03030   
03031   return result;
03032 }
03033 
03034 
03035 CubitBoolean GeometryUtil::valid_sm_topology( RefEdge* edge_ptr, CubitBoolean print )
03036 {
03037   CubitBoolean result = CUBIT_TRUE;
03038   int i;
03039   
03040     // This method checks for 
03041     //  a.) Missing links between the passed RefEdge and its parent CoEdge(s)
03042     //  b.) Extraneous links between the RefEdge and its child vert(ex/ices)
03043   
03044   DLIList<CoEdge*> coedge_list;
03045   edge_ptr->co_edges( coedge_list );
03046   DLIList<RefVertex*> vtx_list;
03047   edge_ptr->ref_vertices( vtx_list );
03048   DLIList<TopologyBridge*> edge_bridges, vtx_bridges, temp_list;
03049   edge_ptr->bridge_manager()->get_bridge_list( edge_bridges );
03050   
03051   if ( edge_bridges.size() == 0 )
03052   {
03053     PRINT_ERROR("%s (RefEdge %d) has no attached Curve(s).\n", 
03054       edge_ptr->entity_name().c_str(), edge_ptr->id());
03055     result = CUBIT_FALSE;
03056   }
03057   
03058   for( i = edge_bridges.size(); i > 0; i-- )
03059   {
03060     TopologyBridge* curve = edge_bridges.get_and_step();
03061     
03062     // Check for missing links between this RefEdge and parent CoEdge(s)
03063     temp_list.clean_out();
03064     curve->get_parents( temp_list );
03065     for( int j = temp_list.size(); j > 0; j-- )
03066     {
03067       TopologyBridge* coedgesm = temp_list.get_and_step();
03068       TopologyEntity* te_ptr = coedgesm->topology_entity();
03069       CoEdge* coedge_ptr = CAST_TO( te_ptr, CoEdge );
03070       if( (coedge_ptr == NULL) || !coedge_list.is_in_list(coedge_ptr) )
03071       {
03072         DLIList<RefFace*> faces;
03073         if( coedge_ptr ) 
03074           coedge_ptr->ref_faces( faces );
03075         CubitString face_name;
03076         const char* face_str = "NO REFFACE";
03077         if( faces.size() )
03078         {
03079           face_name = faces.get()->entity_name();
03080           face_str = face_name.c_str();
03081         }
03082         
03083         if( print ) PRINT_ERROR(
03084           "Missing VGI link between CoEdge with %s and %s\n",
03085           face_str,
03086           edge_ptr->entity_name().c_str() );
03087         result = CUBIT_FALSE;
03088       }
03089     }
03090     
03091     // Build Point list for next part
03092     temp_list.clean_out();
03093     curve->get_children( temp_list );
03094     vtx_bridges.merge_unique( temp_list );
03095   }
03096   
03097   // Check for extraneous VGI links between this RefEdge and child RefVert(s)
03098   for( i = vtx_list.size(); i > 0; i-- )
03099   {
03100     RefVertex* vtx_ptr = vtx_list.get_and_step();
03101     temp_list.clean_out();
03102     vtx_ptr->bridge_manager()->get_bridge_list( temp_list );
03103     temp_list.intersect( vtx_bridges );
03104     if( temp_list.size() == 0 )
03105     {
03106       if( print ) PRINT_ERROR(
03107         "Extraneous VGI link between %s and %s.\n",
03108         edge_ptr->entity_name().c_str(),
03109         vtx_ptr->entity_name().c_str() );
03110       result = CUBIT_FALSE;
03111     }
03112   }
03113   
03114   for( i = vtx_bridges.size(); i--; )
03115   {
03116     TopologyBridge* point = vtx_bridges.get_and_step();
03117     TopologyEntity* owner = point->topology_entity();
03118     RefVertex* vtx_ptr = dynamic_cast<RefVertex*>(owner);
03119     if( ! vtx_ptr )
03120     {
03121       if( print ) PRINT_ERROR(
03122         "No RefVertex for Point %p in %s\n",
03123         (void*)point, edge_ptr->entity_name().c_str() );
03124       result = CUBIT_FALSE;
03125     }
03126   } 
03127   
03128   return result;
03129 }
03130 
03131 
03132 CubitBoolean GeometryUtil::valid_sm_topology( RefVertex* vtx_ptr, CubitBoolean print )
03133 {
03134   CubitBoolean result = CUBIT_TRUE;
03135   int i;
03136   
03137     // This method checks for 
03138     //  a.) Missing links between the RefVertex and its parent RefEdge(s)
03139   
03140   DLIList<RefEdge*> edge_list;
03141   vtx_ptr->ref_edges( edge_list );
03142   DLIList<TopologyBridge*> vtx_bridges, temp_list;
03143   vtx_ptr->bridge_manager()->get_bridge_list( vtx_bridges );
03144   
03145   if ( vtx_bridges.size() == 0 )
03146   {
03147     PRINT_ERROR("%s (RefVertex %d) has no attached Point(s).\n", 
03148       vtx_ptr->entity_name().c_str(), vtx_ptr->id());
03149     result = CUBIT_FALSE;
03150   }
03151   
03152   for( i = vtx_bridges.size(); i > 0; i-- )
03153   {
03154     TopologyBridge* point = vtx_bridges.get_and_step();
03155     
03156     // Check for missing links between this RefVertex and parent RefEdge(s)
03157     temp_list.clean_out();
03158     point->get_parents( temp_list );
03159     for( int j = temp_list.size(); j > 0; j-- )
03160     {
03161       TopologyBridge* curve = temp_list.get_and_step();
03162       TopologyEntity* te_ptr = curve->topology_entity();
03163       RefEdge* edge_ptr = CAST_TO( te_ptr, RefEdge );
03164       if( !edge_ptr )
03165       {
03166         if( print ) PRINT_ERROR(
03167           "Missing VGI Entity for Curve %p.  Discovered as parent of %s\n",
03168             (void*)curve, vtx_ptr->entity_name().c_str() );
03169         result = CUBIT_FAILURE;
03170       }
03171       else if( !edge_list.is_in_list(edge_ptr) )
03172       {
03173         if( print ) PRINT_ERROR(
03174           "Missing VGI link between %s and %s\n",
03175           edge_ptr->entity_name().c_str(),
03176           vtx_ptr->entity_name().c_str() );
03177         result = CUBIT_FALSE;
03178       }
03179     }
03180   }
03181   
03182   return result;
03183 }
03184 
03185 void GeometryUtil::list_SM_topology( TopologyBridge* bridge, int depth )
03186 {
03187   int counts[8] = {0,0,0,0,0,0,0,0};
03188   const char* names[8] = {"BodySM","Lump","ShellSM", "Surface", "LoopSM",
03189                           "CoEdgeSM", "Curve", "Point"};
03190   list_SM_topology( bridge, depth, 0, counts );
03191   
03192   for( int i = 0; i < 8; i++ )
03193     if( counts[i] == 1 )
03194       PRINT_INFO("%d %s, ", counts[i], names[i] );
03195     else if( counts[i] > 1 )
03196       PRINT_INFO("%d %ss, ", counts[i], names[i] );
03197   PRINT_INFO("\n");
03198 }
03199 
03200 void GeometryUtil::list_SM_topology( TopologyBridge* bridge, int depth,
03201                                      int indent, int counts[8] )
03202 {
03203   DLIList<TopologyBridge*> relatives;
03204 
03205   if( depth < 0 )
03206   {
03207     bridge->get_parents( relatives );
03208     relatives.reset();
03209     for( int i = relatives.size(); i--; )
03210       list_SM_topology( relatives.get_and_step(), depth+1, indent+1, counts );
03211   }
03212 
03213   int index = print_topo_bridge( bridge, indent );
03214   if( index >= 0 && index <= 8 )
03215     counts[index]++;
03216   
03217   if( depth > 0 )
03218   {
03219     bridge->get_children( relatives );
03220     relatives.reset();
03221     for( int i = relatives.size(); i--; )
03222       list_SM_topology( relatives.get_and_step(), depth-1, indent+1, counts );
03223   }
03224 }
03225 
03226 int GeometryUtil::print_topo_bridge( TopologyBridge* bridge, int indent )
03227 {
03228   const char* label = bridge ? typeid(*bridge).name() : "(null)";
03229 #ifdef __GNUC__
03230   while( isdigit(*label) ) label++;
03231 #endif
03232 
03233   int index = -1;
03234   if( dynamic_cast<BodySM*>(bridge) )
03235     index = 0;
03236   else if( dynamic_cast<Lump*>(bridge) )
03237     index = 1;
03238   else if( dynamic_cast<ShellSM*>(bridge) )
03239     index = 2;
03240   else if( dynamic_cast<Surface*>(bridge) )
03241     index = 3;
03242   else if( dynamic_cast<LoopSM*>(bridge) )
03243     index = 4;
03244   else if( dynamic_cast<CoEdgeSM*>(bridge) )
03245     index = 5;
03246   else if( dynamic_cast<Curve*>(bridge) )
03247     index = 6;
03248   else if( dynamic_cast<TBPoint*>(bridge) )
03249     index = 7;
03250   
03251   CubitString name("");
03252   RefEntity* re = 0;
03253   if( bridge && (re = dynamic_cast<RefEntity*>(bridge->topology_entity())) )
03254     name = re->entity_name();
03255   PRINT_INFO("%*s%s 0x%lx (%s)\n", indent*3, "", label, (long)bridge, name.c_str());
03256   
03257   return index;
03258 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines