cgma
VGLoopTool.cpp
Go to the documentation of this file.
00001 
00002 #include "VGLoopTool.hpp"
00003 #include "GMem.hpp"
00004 #include "GeometryQueryEngine.hpp"
00005 #include "CubitVector.hpp"
00006 /*
00007 //-------------------------------------------------------------------------
00008 // Purpose       : Remove a curve from a loop
00009 //
00010 // Special Notes : 
00011 //
00012 // Creator       : Jason Kraftcheck
00013 //
00014 // Creation Date : 08/14/02
00015 //-------------------------------------------------------------------------
00016 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00017 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00018 remove_curve( COEDGE* coedge1, COEDGE* coedge2,
00019               DLIList<COEDGE*>& new_loop_coedges )
00020 {
00021   new_loop_coedges.clean_out();
00022   
00023   if( !coedge1->get_loop() || !coedge2->get_loop() )
00024     return CUBIT_FAILURE;
00025   
00026     // remove sipe or split loop?
00027   if( coedge1->get_loop() == coedge2->get_loop() )
00028   {
00029       // split loop?
00030     if( coedge1->next() != coedge2 && coedge1->prev() != coedge2 )
00031     {
00032       COEDGE* coedge = coedge1->next();
00033       while( coedge != coedge2 )
00034       {
00035         COEDGE* next = coedge;
00036         coedge->get_loop()->remove( coedge );
00037         new_loop_coedges.append( coedge );
00038         coedge = next;
00039       }
00040     }
00041     
00042     coedge1->get_loop()->remove( coedge1 );
00043     coedge2->get_loop()->remove( coedge2 );
00044   }
00045   
00046     // stitch/combine loops
00047   else
00048   {
00049     COEDGE* coedge;
00050     
00051       // insert coedges
00052     while( coedge2->next() != coedge2 )  // loop has more than 1 coedge
00053     {
00054       coedge = coedge2->next();
00055       coedge2->get_loop()->remove( coedge );
00056       coedge1->insert_before( coedge, coedge1 );
00057     }
00058     coedge1->get_loop()->remove( coedge1 );
00059     coedge2->get_loop()->remove( coedge2 );
00060   }
00061   
00062   return CUBIT_SUCCESS;
00063 }
00064 
00065 //-------------------------------------------------------------------------
00066 // Purpose       : Insert a curve in a loop
00067 //
00068 // Special Notes : 
00069 //
00070 // Creator       : Jason Kraftcheck
00071 //
00072 // Creation Date : 08/14/02
00073 //-------------------------------------------------------------------------
00074 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00075 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00076 insert_curve( COEDGE* coedge1, COEDGE* coedge2,
00077               SURFACE* surface, LOOP*& new_loop1, LOOP*& new_loop2 )
00078 {
00079   assert( coedge1 && coedge2 && 
00080           coedge1->get_curve() == coedge2->get_curve() &&
00081           coedge1->sense() != coedge2->sense() );
00082   new_loop1 = new_loop2 = 0;
00083   
00084   if( coedge1->sense() == CUBIT_REVERSED )
00085   {
00086     COEDGE* tmp = coedge1;
00087     coedge2 = coedge2;
00088     coedge2 = tmp;
00089   }
00090   
00091     // Find loop insertion locations.
00092   COEDGE *start_prev = 0, *end_prev = 0;
00093   if( ! previous_coedge( coedge2, surface, start_prev ) ||
00094       ! previous_coedge( coedge1, surface, end_prev ) )
00095     return CUBIT_FAILURE;
00096   
00097     // If no loop was passed, just pass back the coedges
00098     // so that the caller can create new loop(s)
00099   if( !(start_prev || end_prev) )
00100   {
00101     new_loop1 = new LOOP;
00102     new_loop1->insert_after( coedge1, 0 );
00103     if( coedge1->start_point() == coedge1->end_point() )
00104     {
00105       new_loop2 = new LOOP;
00106       new_loop2->insert_after( coedge2, 0 );
00107     }
00108     else
00109     {
00110       new_loop1->insert_after( coedge2, coedge1 );
00111     }
00112     
00113     return CUBIT_SUCCESS;
00114   }
00115   
00116   
00117     // sipe?
00118   if( !loop1_prev || !loop2_prev )
00119   {
00120     COEDGE *prev = loop1_prev ? loop1_prev : loop2_prev;
00121     if( coedge1->start_point() == prev->end_point() )
00122     {
00123       prev->get_loop()->insert_after( coedge1, prev );
00124       prev->get_loop()->insert_after( coedge2, coedge1 );
00125     }
00126     else if( coedge1->end_point() == prev->end_point() )
00127     {
00128       prev->get_loop()->insert_after( coedge2, prev );
00129       prev->get_loop()->insert_after( coedge1, coedge2 );
00130     }
00131     else
00132     {
00133       assert(0);
00134       return CUBIT_FAILURE;
00135     }
00136   }
00137   
00138     // combine loops?
00139   else if( loop1_prev->get_loop() != loop2_prev->get_loop() )
00140   {
00141     COEDGE* prev = 0;
00142 
00143       // Which of the two coedges for the curve are
00144       // inserting do we want to begin with?
00145     if( coedge1->start_point() == loop1_prev->end_point() )
00146     {
00147       loop1_prev->get_loop()->insert_after( coedge1, loop1_prev );
00148       loop1_prev->get_loop()->insert_after( coedge2, coedge1 );
00149       prev = coedge1;
00150     }
00151     else if( coedge2->start_point() == loop1_prev->end_point() )
00152     {
00153       loop1_prev->get_loop()->insert_after( coedge2, loop1_prev );
00154       loop1_prev->get_loop()->insert_after( coedge1, coedge2 );
00155       prev = coedge2;
00156     }
00157     else
00158     {
00159       assert(0);
00160       return CUBIT_FAILURE;
00161     }
00162     
00163     COEDGE* coedge = loop2_prev->next();
00164     COEDGE* next = 0;
00165     while( loop2_prev->get_loop() != loop1_prev->get_loop() )
00166     {
00167       next = coedge->next();
00168       coedge->get_loop()->remove( coedge );
00169       loop1_prev->get_loop()->insert_after( coedge, prev );
00170       prev = coedge;
00171       coedge = next;
00172     }
00173     
00174   }
00175   
00176     // split the loop
00177   else
00178   {
00179     assert( loop1_prev->get_loop() == loop2_prev->get_loop() );
00180     
00181       // check for and handle a hole insersecting the original
00182       // loop at just one vertex
00183     if( coedge1->start_point() == coedge1->end_point() )
00184     {
00185       assert( loop1_prev == loop2_prev );
00186       
00187       CubitVector prev_tan, coe1_tan, coe2_tan, norm, junk;
00188       CubitVector point = coedge1->start_point()->coordinates();
00189       loop1_prev->get_curve()->closest_point( point, junk, &prev_tan );
00190       if( loop1_prev->sense() == CUBIT_FORWARD ) // yes, I mean forward here!!
00191         prev_tan *= -1.0;
00192       coedge1->get_curve()->closest_point( point, junk, &coe1_tan );
00193       coe2_tan = coe1_tan;
00194       if( coedge1->sense() == CUBIT_REVERSED )
00195         coe1_tan *= -1.0;
00196       if( coedge2->sense() == CUBIT_REVERSED )
00197         coe2_tan *= -1.0;
00198       loop1_prev->get_loop()->get_surface()->closest_point( point, 0, &norm );
00199       
00200       double angle1 = norm.vector_angle( prev_tan, coe1_tan );
00201       double angle2 = norm.vector_angle( prev_tan, coe2_tan );
00202       
00203       if( angle2 < angle1 )
00204       {
00205         COEDGE* temp = coedge2;
00206         coedge2 = coedge1;
00207         coedge1 = temp;
00208       }
00209     }
00210     
00211     else if( coedge1->end_point() == loop2_prev->end_point() )
00212     {
00213       COEDGE* temp = coedge2;
00214       coedge2 = coedge1;
00215       coedge1 = temp;
00216     }
00217   
00218     
00219     new_loop1 = new LOOP;
00220     loop1_prev->insert_after( coedge1, loop2_prev );
00221     new_loop1->insert_after( coedge2, 0 );
00222     COEDGE* prev = coedge2;
00223     
00224     COEDGE* coedge = loop2_prev->next();
00225     COEDGE* stop = loop1_prev->next();
00226     while( coedge != stop )
00227     {
00228       COEDGE* next = coedge->next();
00229       coedge->get_loop()->remove( coedge );
00230       new_loop1->insert_after( coedge, prev );
00231       prev = coedge;
00232       coedge = next;
00233     }
00234     
00235   }
00236   
00237   return CUBIT_SUCCESS;
00238 }
00239 */
00240 /*
00241 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT>
00242 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00243 VGLoopTool::curves_in_loop( LOOP* loop, POINT* point, DLIList<CURVE*>& results )
00244 {
00245   CURVE* curve = 0;
00246   while ( (curve = point->next_curve(curve)) )
00247   {
00248     COEDGE* coedge = 0;
00249     while ( (coedge = curve->next_coedge(coedge)) )
00250     {
00251       if (coedge->get_loop() == loop)
00252       {
00253         results.append(curve);
00254         break;
00255       }
00256     }
00257   }
00258   return CUBIT_SUCCESS;
00259 }
00260 
00261 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT>
00262 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00263 VGLoopTool::traverse_coedges( LOOP* loop, COEDGE* coedge, DLIList<COEDGE*>& results )
00264 {  
00265     // Traverse coedges, appending them to the list until
00266     // the end point is reached.
00267   POINT* loop_point = coedge->start_point();
00268   results.append(coedge);
00269   DLIList<CURVE*> loop_curves;
00270   while ( coedge->end_point() != loop_point )
00271   {
00272     POINT* point = coedge->end_point();
00273     loop_curves.clean_out();
00274     curves_in_loop( loop, point, loop_curves );
00275     
00276     COEDGE *boundary_coedge = 0, *split_coedge = 0;
00277     while( loop_curves.size() )
00278     {
00279       CURVE* curve = loop_curves.pop();
00280       if ( curve == coedge->get_curve() )
00281         continue;
00282       
00283       COEDGE* curve_coedge = 0;
00284       while ( (curve_coedge = curve->next_coedge(curve_coedge)) )
00285       {
00286         if ((curve_coedge->get_loop() != loop_to_split()) ||
00287             (curve_coedge->start_point() != point))
00288           continue;
00289         
00290         if (curve_coedge->get_curve()->mark == 2)
00291         {
00292           if (split_coedge) 
00293             { assert(0); return CUBIT_FAILURE; }
00294           split_coedge = curve_coedge;
00295         }
00296         else if(curve_coedge->get_curve()->mark == 0)
00297         {
00298           if (boundary_coedge) 
00299             { assert(0); return CUBIT_FAILURE; }
00300           boundary_coedge = curve_coedge;
00301         }
00302       }
00303     }
00304     
00305     if (split_coedge)
00306       coedge = split_coedge;
00307     else if(boundary_coedge)
00308       coedge = boundary_coedge;
00309     else
00310       { assert(0); return CUBIT_FAILURE; }
00311 
00312     results.append(coedge);
00313   }
00314   
00315   return CUBIT_SUCCESS;
00316 }
00317 
00318 
00319 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT>
00320 LOOP* VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00321 VGLoopTool::split_loop( LOOP* loop_to_split )
00322 {
00323     // Make sure all coedge curve marks are cleared,
00324     // and count coedges (use the count to make sure
00325     // things are going okay later)
00326   int coedge_count = 0;
00327   COEDGE* coedge = loop_to_split->first_coedge();
00328   do {
00329     coedge->mark = 0;
00330     coedge->get_curve()->mark = 0;
00331     coedge_count++;
00332     coedge = loop_to_split->next_coedge(coedge);
00333   } while ( coedge != loop_to_split->first_coedge() );
00334   
00335     // Identify non-manifold curves, marking them either
00336     // with a 2 if they can be used to split the surface
00337     // (if they are part of a connected patch for which the
00338     // bounadary of that patch intersects the surface boundary
00339     // at all points) or a 3 if they are other non-manifold
00340     // curves.  This will get a bit tricky if there are
00341     // non-manifold curves hanging off of the patch of
00342     // split curves.
00343   
00344     // First for all non-manifold curves, if the curve has
00345     // a point that is not shared with any other curve, mark
00346     // it with a 3.  Otherwise mark it with a 2.
00347   DLIList<CURVE*> curve_stack, loop_curves, nonman_curves;
00348   coedge = loop_to_split->first_coedge();
00349   do {
00350     CURVE* curve = coedge->get_curve();
00351       // If we haven't done this curve yet and it is non-manifold
00352     if ( !curve->mark && curve->find_next(coedge) )
00353     {
00354       curve->mark = 2;
00355  
00356       for ( int i = 2; i--; )
00357       {
00358         POINT* point = i ? curve->start_point() : curve->end_point();
00359         loop_curves.clean_out();
00360         curves_in_loop( loop_to_split, curve->start_point(), loop_curves );
00361         if ( loop_curves.size() == 1 )
00362         {
00363           curve->mark = 3;
00364           curve_stack.append(curve);
00365           nonman_curves.append(curve);
00366           break;
00367         }
00368       }
00369     }
00370     
00371     coedge = loop_to_split->next_coedge(coedge);
00372   } while( coedge != loop_to_split->first_coedge() );
00373   
00374     // Now for each curve we marked with a three, traverse
00375     // and mark adjacent curve until we come to a point
00376     // connected to more that two curves.
00377   while( curve_stack.size() ) 
00378   {
00379     CURVE* curve = curve_stack.pop();
00380     
00381     for ( int i = 2; i--; )
00382     {
00383       POINT* point = i ? curve->start_point() : curve->end_point();
00384       loop_curves.clean_out();
00385       curves_in_loop( loop_to_split, curve->start_point(), loop_curves );
00386       if ( loop_curves.size() != 2 )
00387         continue;
00388       
00389       loop_curves.move_to(curve);
00390       CURVE* other = loop_curves.next();
00391       assert(other && other != curve );
00392       
00393       if ( other->mark != 3 )
00394       {
00395         other->mark = 3;
00396         curve_stack.append(other);
00397         nonman_curves.append(other);
00398       }
00399     }
00400   }
00401   
00402     // Find a split curve to begin at.
00403   coedge = loop_to_split->first_coedge();
00404   do
00405   {
00406     if ( coedge->get_curve()->mark == 2 )
00407       break;
00408     coedge = loop_to_split->next_coedge(coedge);
00409   } while( coedge != loop_to_split->first_coedge() );
00410   
00411   if ( coedge->get_curve()->mark != 2 )
00412     { assert(0); return 0; }
00413     
00414     // Get two coedges for split curve
00415   COEDGE *coedge1 = coedge, *coedge2 = 0;
00416   coedge = 0;
00417   while ( (coedge = coedge1->get_curve()->next_coedge(coedge)) )
00418     if (coedge != coedge1)
00419       { coedge2 = coedge; break; }
00420   assert( coedge2 && coedge2->sense() != coedge1->sense() );
00421   
00422     // Get coedges for each loop by traversing from 
00423     // split curve coedges
00424   DLIList<COEDGE*> old_loop_coedges, new_loop_coedges;
00425   if ( !traverse_loop(loop_to_split, coedge1, old_loop_coedges) )
00426     return 0;
00427   if ( !traverse_loop(loop_to_split, coedge2, new_loop_coedges) )
00428     return 0;
00429   
00430     // Make sure everything adds up
00431   if ( old_loop_coedges.size() + new_loop_coedges.size() 
00432        + 2*nonman_curves.size() != coedge_count)
00433     { assert(0); return 0; }
00434   
00435     // Leave the larger list on the existing loop, as this
00436     // is more likely to result in the expected behavior
00437   if (new_loop_coedges.size() > old_loop_coedges.size())
00438   {
00439     DLIList<COEDGE*> tmp_list(old_loop_coedges);
00440     old_loop_coedges = new_loop_coedges;
00441     new_loop_coedges = tmp_list;
00442   }
00443   
00444     // Remove all coedges from old loop (faster this way)
00445   while( loop_to_split->first_coedge() )
00446     loop_to_split->remove( loop_to_split->first_coedge() );
00447   
00448     // Put old_loop_coedges in loop_to_split
00449   COEDGE* next = 0;
00450   while ( old_loop_coedges.size() )
00451   {
00452     coedge = old_loop_coedges.pop();
00453     coedge->get_curve()->mark = 0;
00454     loop_to_split->insert_before( coedge, next );
00455     next = coedge;
00456   }
00457   
00458     // Put new_loop_coedges in new_loop
00459   LOOP* new_loop = new LOOP;
00460   next = 0;
00461   while ( new_loop_coedges.size() )
00462   {
00463     coedge = new_loop_coedges.pop();
00464     coedge->get_curve()->mark = 0;
00465     new_loop->insert_before( coedge, next );
00466     next = coedge;
00467   }
00468   
00469     // Now sort out other non-manifold curves
00470   
00471     // Clear marks
00472   for ( int j = nonman_curves.size(); j--; )
00473     nonman_curves->step_and_get()->mark = 0;
00474   
00475   if( nonman_curves.size() )
00476     insert_nonmanifold_curves( nonman_curves, loop_to_split, new_loop );
00477   return new_shell;
00478 }
00479   
00480 template <class SURFACE, class LOOP, class COEDGE, class CURVE, class POINT>
00481 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00482 VGLoopTool::insert_nonmanifold_curves( DLIList<CURVE*>& curve_stack,
00483                                        LOOP* loop1, LOOP* loop2 )
00484 {
00485   return CUBIT_FAILURE;
00486 }
00487 
00488 */
00489 
00490 /*  
00491 //-------------------------------------------------------------------------
00492 // Purpose       : Check if a curve occurs an odd number of times in a loop
00493 //
00494 // Special Notes : Input is the coedge connecting the relevent curve & loop
00495 //
00496 // Creator       : Jason Kraftcheck
00497 //
00498 // Creation Date : 08/14/02
00499 //-------------------------------------------------------------------------
00500 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00501 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00502 odd_coedge_count( COEDGE* coedge )
00503 {
00504   COEDGE* curve_coedge = 0;
00505   int count = 0;
00506   while( curve_coedge = coedge->get_curve()->next_coedge( curve_coedge ) )
00507     if( curve_coedge->get_loop() == coedge->get_loop() )
00508       count++;
00509     
00510   return (bool)(count % 2);
00511 }
00512 
00513 //-------------------------------------------------------------------------
00514 // Purpose       : Find the previous coedge in loop
00515 //
00516 // Special Notes : 
00517 //
00518 // Creator       : Jason Kraftcheck
00519 //
00520 // Creation Date : 10/28/02
00521 //-------------------------------------------------------------------------
00522 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00523 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00524 previous_coedge( COEDGE* coedge, SURFACE* surface, COEDGE*& result )
00525 {
00526   result = 0;
00527   
00528   POINT* point = coedge->end_point();
00529   CubitVector normal, tanget, closest;
00530   surface->closest_point( point->coordinates(), &closest, &normal );
00531   
00532   coedge->get_curve()->closest_point( point->coordinates(), closest, &tangent );
00533   if( coedge->sense() == CUBIT_REVERSED )
00534     tangent *= -1.0;
00535   
00536   CURVE* curve = 0;
00537   while( curve = point->next_curve( curve ) )
00538   {
00539     COEDGE* coedge = 0;
00540     while( coedge = curve->next_coedge( coedge ) )
00541     {
00542       if( coedge->end_point() != point )
00543         continue;
00544       
00545       if( !coedge->get_loop() || coedge->get_loop()->get_surface() != surface )
00546         continue;
00547       
00548       if( ! result )
00549       {
00550         result = coedge;
00551       }
00552       else if( result->get_loop() != coedge->get_loop() )
00553       {
00554         result = 0;
00555         return CUBIT_FAILURE;
00556       }
00557       else
00558       {
00559         CubitVector result_tan, coedge_tan, closest;
00560         result->get_curve()->closest_point( point->coordinates(), closest, &result_tan );
00561         coedge->get_curve()->closest_point( point->coordinates(), closest, &coedge_tan );
00562         if( result->sense() == CUBIT_FORWARD )
00563           result_tan *= -1.0;
00564         if( coedge->sense() == CUBIT_FORWARD )
00565           result_tan *= -1.0;
00566       
00567         double result_angle = normal.vector_angle( result_tan, tangent );
00568         double coedge_angle = normal.vector_angle( coedge_tan, tangent );
00569         if( result_angle < 0.0 ) result_angle += 2.0*CUBIT_PI;
00570         if( coedge_angle < 0.0 ) coedge_angle += 2.0*CUBIT_PI;
00571         if( coedge_angle < result_angle )
00572           result = coedge;
00573       }
00574     }
00575   }
00576   
00577   return CUBIT_SUCCESS;
00578 }
00579 
00580 */
00581 
00582 
00583 //-------------------------------------------------------------------------
00584 // Purpose       : Get a polygon representation of a loop as a point list
00585 //
00586 // Special Notes : 
00587 //
00588 // Creator       : Jason Kraftcheck
00589 //
00590 // Creation Date : 08/14/02
00591 //-------------------------------------------------------------------------
00592 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00593 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00594 get_loop_polygon( COEDGE* first_coedge, DLIList<CubitVector*>& polygon )
00595 {
00596   if( !first_coedge )
00597     return CUBIT_FAILURE;
00598   
00599   DLIList<CubitVector*> interior;
00600   CubitSense sense;
00601   polygon.clean_out();
00602 
00603   COEDGE* coedge = first_coedge;
00604   do
00605   {
00606       polygon.append( new CubitVector( coedge->start_point()->coordinates() ) );
00607 
00608       interior.clean_out();
00609       if( !coedge->get_curve()->get_interior_extrema( interior, sense ) )
00610       {
00611         while( polygon.size() ) delete polygon.pop();
00612         return CUBIT_FAILURE;
00613       }
00614 
00615       if( sense != coedge->sense() )
00616         interior.reverse();
00617       polygon += interior;
00618        
00619     coedge = coedge->next();
00620   } while( coedge != first_coedge );
00621   
00622   return CUBIT_SUCCESS;
00623 }
00624   
00625   
00626 //-------------------------------------------------------------------------
00627 // Purpose       : Calculate loop angle metric
00628 //
00629 // Special Notes : 
00630 //
00631 // Creator       : Jason Kraftcheck
00632 //
00633 // Creation Date : 08/14/02
00634 //-------------------------------------------------------------------------
00635 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00636 double VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00637 loop_angle_metric( COEDGE* first_coedge )
00638 {
00639   if( !first_coedge )
00640     return 0.0;
00641     
00642   assert( first_coedge 
00643        && first_coedge->get_loop()
00644        && first_coedge->get_loop()->get_surface() );
00645   
00646   DLIList<CubitVector*> polygon;
00647   get_loop_polygon( first_coedge, polygon );
00648   
00649   double result = 0.0;
00650   CubitVector *point[3], segment[2], normal;
00651   point[0] = polygon.step_and_get();
00652   point[1] = polygon.step_and_get();
00653   segment[0] = *point[1] - *point[0];
00654   for( int i = polygon.size(); i--; )
00655   {
00656     point[2] = polygon.step_and_get();
00657     segment[1] = *point[1] - *point[2];
00658     first_coedge->get_loop()->get_surface()->closest_point( *point[1], 0, &normal );
00659     result += normal.vector_angle( segment[1], segment[0] );
00660     
00661     point[1] = point[2];
00662     segment[0] = -segment[1];
00663   }
00664   
00665   result /= CUBIT_PI;
00666   result -= polygon.size();
00667   
00668   while( polygon.size() )
00669     delete polygon.pop();
00670   
00671   return result;
00672 }
00673 
00674 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00675 void VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00676 get_loop_polyline( COEDGE* first_coedge, std::vector<CubitVector>& list )
00677 {
00678   COEDGE* coedge = first_coedge;
00679   GMem gmem;
00680   list.resize(0);
00681   
00682   do {
00683     coedge->get_curve()->get_geometry_query_engine()->
00684       get_graphics( coedge->get_curve(), &gmem );
00685     int num_pts = gmem.pointListCount;
00686     if ( num_pts > 1 ) {
00687     
00688       int start = list.size();
00689       list.resize( start + num_pts - 1 );
00690       std::vector<CubitVector>::iterator itor = list.begin() + start;
00691       if ( coedge->sense() == CUBIT_FORWARD ) {
00692         GPoint* pitor = gmem.point_list();
00693         GPoint* pend = pitor + num_pts - 1;
00694         for ( ; pitor != pend; ++pitor ) {
00695           itor->set( pitor->x, pitor->y, pitor->z );
00696           ++itor;
00697         }
00698       } else {
00699         GPoint* pend = gmem.point_list();
00700         GPoint* pitor = pend + num_pts - 1;
00701         for ( ; pitor != pend; --pitor ) {
00702           itor->set( pitor->x, pitor->y, pitor->z );
00703           ++itor;
00704         }
00705       }
00706    }
00707     
00708     coedge = coedge->next();
00709   } while ( coedge != first_coedge );
00710 }
00711       
00712 
00713 /*
00714 //-------------------------------------------------------------------------
00715 // Purpose       : Check if a position is to the "left" of a coedge
00716 //
00717 // Special Notes : 
00718 //
00719 // Creator       : Jason Kraftcheck
00720 //
00721 // Creation Date : 08/14/02
00722 //-------------------------------------------------------------------------
00723 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00724 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00725 inside_of_curve( const CubitVector& tangent,
00726                  const CubitVector& curve_pos,
00727                  const CubitVector& surf_pos,
00728                  const CubitVector& normal )
00729 {
00730   CubitVector cross = tangent * ( surf_pos - curve_pos );
00731   return cross % normal > -CUBIT_RESABS;
00732 }
00733 
00734 //-------------------------------------------------------------------------
00735 // Purpose       : Find the coedge in a loop that is closest to the passed 
00736 //                 point
00737 //
00738 // Special Notes : 
00739 //
00740 // Creator       : Jason Kraftcheck
00741 //
00742 // Creation Date : 08/14/02
00743 //-------------------------------------------------------------------------
00744 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00745 COEDGE* VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00746 closest_loop_coedge( const CubitVector& from_pt,
00747                      COEDGE* first_coedge,
00748                      COEDGE*& other_coedge,
00749                      CubitVector* closest )
00750 {
00751   CubitVector closest_pt, current_pt;
00752   double current_dst, closest_dst;
00753   COEDGE* closest_coedge = 0;
00754   other_coedge = 0;
00755 
00756     // Skip coedges for curves that occur twice in the loop (sipes, etc)
00757   COEDGE* coedge = first_coedge;
00758   while( !odd_coedge_count(coedge) )
00759   {
00760     coedge = coedge->next();
00761     if( coedge == first_coedge )
00762       return false;
00763   }
00764 
00765     // Search for a) a curve who's bounding box contains the point
00766     // or b) the curve who's box is closest to the point
00767   closest_coedge = coedge;
00768   closest_dst = coedge->get_curve()->bounding_box().distance_squared(from_pt);
00769   coedge = coedge->next();
00770   while( (coedge != first_coedge) && (closest_dst > CUBIT_RESABS) )
00771   {
00772     if( odd_coedge_count(coedge) )
00773     {
00774       current_dst = coedge->get_curve()->bounding_box().distance_squared(from_pt);
00775       if( current_dst < closest_dst )
00776       {
00777         closest_coedge = coedge;
00778         closest_dst = current_dst;
00779       }
00780     }
00781     coedge = coedge->next();
00782   }
00783   
00784     // Now find actual distance from the curve 
00785   closest_coedge->get_curve()->closest_point_trimmed( from_pt, closest_pt );
00786   closest_dst = (from_pt - closest_pt).length_squared();
00787   
00788     // Look for any curves that are closer
00789   first_coedge = closest_coedge;
00790   coedge = first_coedge.next();
00791   while( coedge != first_coedge )
00792   {
00793     if( odd_coedge_count(coedge) )
00794     {
00795       if( coedge->get_curve()->bounding_box().distance_squared(from_pt) < closest_dst )
00796       {
00797         coedge->get_curve()->closest_point_trimmed( from_pt, current_pt );
00798         current_dst = (from_pt - current_pt).length_squared();
00799 
00800         if( (closest_pt - current_pt).length_squared() < RESSQR )
00801         {
00802           if( current_dst < closest_dst )
00803           {
00804             closest_dst = current_dst;
00805             closest_pt = current_pt;
00806           }
00807           other_coedge = coedge;
00808         }
00809         else if( current_dst < closest_dst )
00810         {
00811           closest_coedge = coedge;
00812           closest_dst = current_dst;
00813           closest_pt = current_pt;
00814           other_coedge = 0;
00815         }
00816       }
00817     }
00818     coedge = coedge->next();
00819   }
00820 
00821   //make sure we have things in the correct order
00822   if( other_coedge )
00823   {
00824     if( closest_coedge->start_point() == other_coedge->end_point() )
00825     {
00826       COEDGE* tmp = closest_coedge;
00827       closest_coedge = other_coedge;
00828       other_coedge = tmp;
00829     }
00830     else if( closest_coedge->end_point() != other_coedge->start_point() )
00831     {
00832       other_coedge = 0;
00833     }
00834   }    
00835 
00836   if( closest ) *closest = closest_pt;
00837   return closest_coedge;
00838 }
00839   
00840 
00841 //-------------------------------------------------------------------------
00842 // Purpose       : Test if a position is on the surface side of a loop.
00843 //
00844 // Special Notes : 
00845 //
00846 // Creator       : Jason Kraftcheck
00847 //
00848 // Creation Date : 08/14/02
00849 //-------------------------------------------------------------------------
00850 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00851 bool VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00852 is_position_within_loop( const CubitVector& position,
00853                          COEDGE* first_coedge,
00854                          CubitVector* closest_on_loop,
00855                          CubitVector* passed_normal )
00856 {
00857   CubitVector surf_point, normal, pt_on_curve;
00858   if( passed_normal )
00859   {
00860     surf_point = position;
00861     normal = *pased_normal;
00862   }
00863   else
00864   {
00865     first_coedge->get_loop()->get_surface()
00866       ->closest_point( position, &surf_point, &normal );
00867   }
00868   
00869   COEDGE* other_coedge = 0;
00870   COEDGE* closest_coedge = 
00871     closest_loop_coedge( first_coedge, position, other_coedge, &pt_on_curve );
00872   if( !closest_coedge ) 
00873     return true;
00874   
00875   if( closest_on_loop )
00876     *closest_on_loop = pt_on_curve;
00877   
00878   CubitVector coe_normal, coe_cross, tangent1, tangent2, junk;
00879   
00880   if( ! other_coedge )
00881   {
00882     double u = closest_coedge->get_curve()->u_from_position( pt_on_curve );
00883     
00884     // Special case: closest point on loop at G1 discontinuity 
00885     if( closest_coedge->get_curve()->G1_discontinuous( u, &tangent1, &tangent2 ) )
00886     {
00887       if( closest_coedge->sense() == CUBIT_REVERSED )
00888       {
00889         tangent1 *= -1.0;
00890         tangent2 *= -1.0;
00891       }
00892       
00893       closest_coedge->get_loop()->get_surface()->
00894         closest_point( pt_on_curve, 0, &coe_normal );
00895       coe_cross = tangent1 * tangent2;
00896       bool inside1 = inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00897       bool inside2 = inside_of_curve( tangent2, pt_on_curve, surf_point, normal );
00898       if( cross % coe_normal > -CUBIT_RESABS )
00899         return inside1 && inside2;
00900       else
00901         return inside1 || inside2;
00902     }
00903     
00904     else // **** This is the normal, non-special case part ****
00905     { 
00906       closest_coedge->closest_point( pt_on_curve, junk, &tangent1 );
00907       if( closest_coedge->sense() == CUBIT_REVERSED )
00908         tangent1 *= -1.0;
00909       
00910       return inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00911     }
00912   }
00913     // Special case: closest point on loop at vertex 
00914   else
00915   {
00916     closest_coedge->get_curve()->closest_point( pt_on_curve, junk, &tangent1 );
00917       other_coedge->get_curve()->closest_point( pt_on_curve, junk, &tangent2 );
00918     if( closest_coedge->sense() == CUBIT_REVERSED )
00919       tangent1 *= -1.0;
00920     if(   other_coedge->sense() == CUBIT_REVERSED )
00921       tangent2 *= -1.0;
00922     
00923     closest_coedge->get_loop()->get_surface()->
00924       closest_point( pt_on_curve, 0, &coe_normal );
00925     
00926     coe_cross = tangent1 * tangent2;
00927     bool inside1 = inside_of_curve( tangent1, pt_on_curve, surf_point, normal );
00928     bool inside2 = inside_of_curve( tangent2, pt_on_curve, surf_point, normal );
00929     
00930     if( coe_cross % coe_normal > -CUBIT_RESABS )
00931       return inside1 && inside2;
00932     else
00933       return inside1 || inside2;
00934   }
00935 }
00936 
00937 
00938 //-------------------------------------------------------------------------
00939 // Purpose       : Very rough approximation of the area bounded by a loop
00940 //
00941 // Special Notes : 
00942 //
00943 // Creator       : Jason Kraftcheck
00944 //
00945 // Creation Date : 08/14/02
00946 //-------------------------------------------------------------------------
00947 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
00948 double VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
00949 loop_area( COEDGE* first_coedge )
00950 {
00951   int i;
00952   
00953   DLIList<CubitVector*> polygon;
00954   get_loop_polygon( first_coedge );
00955 
00956     // Get surface normal at each polygon point
00957   DLIList<CubitVector*> normals;
00958   polygon.reset();
00959   for( i = polygon.size(); i--; )
00960   {
00961     CubitVector norm, *pt = polygon.get_and_step();
00962     first_coedge->get_loop()->get_surface()->closest_point(*pt,0,&norm);
00963     normals.append( new CubitVector(norm) );
00964   }
00965   
00966     // Average surface normals
00967   normal_list.reset();
00968   CubitVector mean_normal(0.,0.,0.);
00969   for( i = normals.size(); i--; )
00970     mean_normal += *normals.get_and_step();
00971   mean_normal /= normals.size();
00972   
00973     // Choose base point at which the surface normal
00974     // is closest to the mean normal from above
00975   point_list.reset();
00976   normal_list.reset();
00977   CubitVector* base_point = polygon.get_and_step();
00978   CubitVector* base_normal = normals.get_and_step();
00979   double largest_dot = mean_normal % *base_normal;
00980   
00981   for( i = polygon.size(); i > 1; i-- )
00982   {
00983     CubitVector* normal = normals.get_and_step();
00984     double dot = mean_normal % *normal;
00985     if( dot > largest_dot )
00986     {
00987       base_point = polygon.get();
00988       base_normal = normal;
00989     }
00990     polygon.step();
00991   }
00992   
00993   polygon.move_to( base_point );
00994   normals.move_to( base_normal );
00995   polygon.step();
00996   normals.step();
00997   
00998     // Do simple 2-D area calculation and hope it isn't too
00999     // inaccurate for the 3-D refface.
01000   double double_area = 0.0;
01001   CubitVector *prev_point = polygon.get_and_step(),
01002               *curr_point = polygon.get_and_step();
01003   CubitVector *prev_normal = normals.get_and_step(),
01004               *curr_normal = normals.get_and_step();
01005     
01006   while( curr_point != base_point )
01007   {
01008     CubitVector cross = (*prev_point - *base_point)*(*curr_point  - *base_point);
01009     CubitVector normal = *base_normal + *prev_normal + *curr_normal;
01010     double dot_product = cross % normal;
01011     double_area += dot_product >= 0.0 ? cross.length() : -(cross.length());
01012     
01013     prev_point = curr_point;
01014     prev_normal = curr_normal;
01015     curr_point = polygon.get_and_step();
01016     curr_normal = normals.get_and_step();
01017   }
01018 
01019   while( polygon.size() > 0 ) delete polygon.pop();
01020   while( normals.size() > 0 ) delete normals.pop();
01021   return double_area / 2.0;
01022 }
01023   
01024 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
01025 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
01026 closest_point_trimmed( DLIList<COEDGE*>& surface_coedges, const CubitVector& from_pt,
01027                        CubitVector& result_pt, CubitPointContainment* containment )
01028 {
01029   CubitVector pt_on_surf, normal;
01030   if( ! surface->closest_point( from_pt, &pt_on_surf, &normal ) )
01031     return CUBIT_FAILURE;
01032   
01033 
01034   CubitVector pt_on_curve;  
01035   COEDGE *closest_coedge = 0, *other_coedge = 0;
01036   if( ! closest_surface_coedge( surface, from_pt, closest_coedge,
01037             other_coedge, &pt_on_curve ) )
01038     return CUBIT_FAILURE;
01039   
01040   CubitVector coe_normal, coe_cross, tangent1, tangent2, junk;
01041   bool inside;
01042   if( ! other_coedge )
01043   {
01044     CURVE* curve_ptr = closest_coedge->get_curve();
01045     double u = curve_ptr->u_from_position( pt_on_curve );
01046     
01047     // **** Special case: closest point on loop at G1 discontinuity ****
01048     if( curve_ptr->G1_discontinuous( u, &tangent1, &tangent2 ) )
01049     {
01050       if( closest_coedge->sense() == CUBIT_REVERSED )
01051       {
01052         tangent1 *= -1.0;
01053         tangent2 *= -1.0;
01054       }
01055       surface->closest_point( pt_on_curve, NULL, &coe_normal );
01056       coe_cross = tangent1 * tangent2;
01057       double sum  = (coe_cross + coe_normal).length_squared();
01058       double diff = (coe_cross - coe_normal).length_squared();
01059     
01060       CubitBoolean inside1 = 
01061         inside_of_curve( tangent1, pt_on_curve, pt_on_surf, normal );
01062       CubitBoolean inside2 = 
01063         inside_of_curve( tangent2, pt_on_curve, pt_on_surf, normal );
01064         
01065       if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 
01066         //discontinuity is at a convexity
01067       {
01068         //the point must be inside of both sub-edges
01069         inside = inside1 && inside2;
01070       }
01071       else //discontinuity is at a concavity
01072       {
01073         //the point must be inside of one of the sub-edges
01074         inside = inside1 || inside2;
01075       }
01076     }
01077 
01078     else // **** This is the normal, non-special case part ****
01079     { 
01080       curve_ptr->closest_point( pt_on_curve, junk, &tangent1 );
01081       if( closest_coedge->sense() == CUBIT_REVERSED )
01082         tangent1 *= -1.0;
01083         
01084       inside = (inside_of_curve(tangent1, pt_on_curve, pt_on_surf, normal) == CUBIT_TRUE);
01085     }
01086   }
01087     // **** Special case: closest point on loop at vertex ****
01088   else
01089   {
01090     CURVE* curve1_ptr = closest_coedge->get_curve();
01091     CURVE* curve2_ptr =   other_coedge->get_curve();
01092     curve1_ptr->closest_point( pt_on_curve, junk, &tangent1 );
01093     curve2_ptr->closest_point( pt_on_curve, junk, &tangent2 );
01094 
01095     if( closest_coedge->sense() == CUBIT_REVERSED )
01096       tangent1 *= -1.0;
01097     if(   other_coedge->sense() == CUBIT_REVERSED )
01098       tangent2 *= -1.0;
01099 
01100     surface->closest_point( pt_on_curve, NULL, &coe_normal );
01101     
01102     coe_cross = tangent1 * tangent2;
01103     double sum  = (coe_cross + coe_normal).length_squared();
01104     double diff = (coe_cross - coe_normal).length_squared();
01105     
01106     CubitBoolean inside1 = 
01107       inside_of_curve( tangent1, pt_on_curve, pt_on_surf, normal );
01108     CubitBoolean inside2 = 
01109       inside_of_curve( tangent2, pt_on_curve, pt_on_surf, normal );
01110         
01111     if( (sum > diff) || (diff < CUBIT_DBL_MIN) ) 
01112       //the common vertex is at a convexity
01113     {
01114       //the point must be inside of both coedges
01115       inside = inside1 && inside2;
01116     }
01117     else //the common vertex is at a concavity
01118     {
01119       //the point must be inside of one of the coedges
01120       inside = inside1 || inside2;
01121     }
01122   }
01123         
01124   result_pt = inside ? pt_on_surf : pt_on_curve;
01125   if( containment )
01126   {
01127     if( (pt_on_surf-pt_on_curve).length_squared() < (GEOMETRY_RESABS*GEOMETRY_RESABS) )
01128       *containment = CUBIT_PNT_BOUNDARY;
01129     else 
01130       *containment = inside ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE;
01131   }
01132 
01133   return CUBIT_SUCCESS;
01134 }  
01135 
01136 template <class SURFACE, class LOOP, class COEDGE,class CURVE, class POINT>
01137 CubitStatus VGLoopTool<SURFACE,LOOP,COEDGE,CURVE,POINT>::
01138 closest_surface_coedge( SURFACE* surface, const CubitVector& from_pt,
01139                         COEDGE*& coedge1, COEDGE*& coedge2,
01140                         CubitVector* pt_on_curve )
01141 {
01142   coedge1 = coedge2 = 0;
01143   LOOP* loop = 0;
01144   COEDGE* coedge;
01145   const double ressqr = CUBIT_RESABS * CUBIT_RESABS;
01146 
01147 
01148   
01149   //Find the first bounding box that the point is within, or if the 
01150   // point isn't in any bounding box, the closest one
01151   closest_dst = CUBIT_DBL_MAX;
01152   while( loop = surface->next_loop( loop ) )
01153   {
01154     coedge = loop->first_coedge();
01155     do
01156     {
01157       if( odd_coedge_count( coedge ) )
01158       {
01159         double dist_sqr = 
01160           coedge->get_curve()->bounding_box().distance_squared(from_pt);
01161         if( dist_sqr < closest_dst )
01162         {
01163           coedge1 = coedge;
01164           closest_dst = dist_sqr;
01165           if( dist_sqr < ressqr )
01166             break;
01167         }
01168       }
01169       
01170       coedge = coedge->next();
01171     } while( coedge != loop->first_coedge() );
01172     
01173     if( closest_dst < ressqr )
01174       break;
01175   }
01176 
01177   if( !coedge1 )
01178     return CUBIT_FAILURE;
01179   
01180   //Start by assuming that the curve we found above is the closest
01181   CubitVector closest_pt;
01182   coedge1->get_curve()->closest_point_trimmed( from_pt, closest_pt );
01183   closest_dst = ( from_pt - closest_pt ).length_squared();
01184   
01185   //Now look for a closer curve
01186   while( loop = surface->next_loop( loop ) )
01187   {
01188     coedge = loop->first_coedge();
01189     do
01190     {
01191       if( odd_coedge_count( coedge ) )
01192       {
01193         if( coedge->get_curve()->bounding_box().distance_squared(from_pt) <=
01194           closest_dst+GEOMETRY_RESABS )
01195         {
01196           CubitVector current_pt;
01197           coedge->get_curve()->closest_point_trimmed( from_pt, current_pt );
01198           double current_dst = (from_pt - current_pt).length_squared();
01199 
01200           if( (closest_pt = current_pt).length_squared() < ressqr )
01201           {
01202             if( current_dst < closest_dst )
01203             {
01204               closest_dst = current_dst;
01205               closest_pt = current_pt;
01206               coedge2 = coedge;
01207             }
01208             else
01209             {
01210               coedge2 = coedge;
01211             }
01212           }
01213           else if( current_dst < closest_dst )
01214           {
01215             coedge1 = coedge;
01216             closest_dst = current_dst;
01217             closest_pt = current_pt;
01218             coedge2 = 0;
01219           }
01220         }
01221       }
01222       coedge = coedge->next();
01223     } while( coedge != loop->first_coedge() );
01224   }
01225   
01226   
01227   //make sure we have things in the correct order
01228   if( coedge2 )
01229   {
01230     POINT* common = coedge1->get_curve()->common( coedge2->get_curve() );
01231     if( ! common ) 
01232       coedge2 = 0;
01233     else if( coedge1->start_point() == coedge2->end_point() )
01234     {
01235       COEDGE* tmp = coedge1;
01236       coedge1 = coedge2;
01237       coedge2 = tmp;
01238     }
01239   }
01240 
01241   if( pt_on_curve ) *pt_on_curve = closest_pt;
01242   return CUBIT_SUCCESS;
01243 }  
01244 */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines