cgma
PartSurfFacetTool.cpp
Go to the documentation of this file.
00001 #include "PartSurfFacetTool.hpp"
00002 #include "CubitMessage.hpp"
00003 #include "DLIList.hpp"
00004 #include "GeometryQueryEngine.hpp"
00005 
00006 #include "PartitionSurface.hpp"
00007 #include "PartitionCurve.hpp"
00008 #include "PartitionPoint.hpp"
00009 #include "TDVGFacetOwner.hpp"
00010 
00011 #include "CubitFacetData.hpp"
00012 #include "CubitFacetEdgeData.hpp"
00013 #include "CubitPointData.hpp"
00014 
00015 #include "RefVertex.hpp"
00016 #include "RefEdge.hpp"
00017 #include "GfxDebug.hpp"
00018 #include "GMem.hpp"
00019 
00020 #undef PART_SURF_REFACET
00021 
00022 void PartSurfFacetTool::validate_facets( PartitionSurface* mySurface )
00023 {
00024   int i, j, k;
00025   DLIList<CubitFacetData*> facets;
00026   DLIList<CubitFacet*> pt_facets, edge_facets;
00027   DLIList<CubitFacetEdge*> pt_edges;
00028   mySurface->get_facet_data(facets);
00029   for( i = facets.size(); i--; )
00030   {
00031     CubitFacetData* facet = facets.get_and_step();
00032     for ( j = 0; j < 3; j++ )
00033     {
00034       CubitFacetEdge* edge = facet->edge(j);
00035       if ( !edge )
00036       {
00037         PRINT_ERROR("Facet with NULL edge.\n");
00038         continue;
00039       }
00040       
00041       if ( PartitionEntity* ent = TDVGFacetOwner::get(edge) )
00042       {
00043         PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
00044         if (!curve)
00045         {
00046           PRINT_ERROR("Facet edge owned by non-curve %s %p\n",
00047             typeid(*ent).name(), (void*)ent);
00048           GfxDebug::draw_line( edge->point(0)->coordinates(),
00049                                edge->point(1)->coordinates(),
00050                                CUBIT_RED_INDEX );
00051           continue;
00052         }
00053         
00054         int edge_use_count = 0;
00055         for ( k = 0; k < edge->num_adj_facets(); k++ )
00056           if ( (const PartitionEntity*)TDVGFacetOwner::get(edge->adj_facet(k)) == mySurface )
00057             edge_use_count++;
00058         assert(edge_use_count);
00059         
00060         int curve_use_count = 0;
00061         int coedge_count = 0;
00062         PartitionCoEdge* coedge = 0;
00063         while (( coedge = curve->next_coedge(coedge) ))
00064         {
00065           if (coedge->get_loop())
00066           {
00067             coedge_count++;
00068             if (coedge->get_loop()->get_surface() == mySurface)
00069               curve_use_count++;
00070           }
00071         }
00072           
00073         RefEdge* curve_owner = dynamic_cast<RefEdge*>(curve->topology_entity());
00074         if ( coedge_count != edge->num_adj_facets() )
00075         {
00076           PRINT_ERROR("Curve %p (RefEdge %d): Curve in %d partition surfaces "
00077                       "has facet edge in %d facets.\n", (void*)curve,
00078                       curve_owner ? curve_owner->id() : 0,
00079                       coedge_count, edge->num_adj_facets() );
00080           GfxDebug::draw_line( edge->point(0)->coordinates(),
00081                                edge->point(1)->coordinates(),
00082                                CUBIT_RED_INDEX );
00083         }
00084         
00085         if ( curve_use_count != edge_use_count )
00086         {
00087           PRINT_ERROR("Curve %p (RefEdge %d): Curve used in %d coedges of "
00088                       "this surface exists in %d facets of this surface.\n", 
00089                       (void*)curve,
00090                       curve_owner ? curve_owner->id() : 0,
00091                       curve_use_count, edge_use_count );
00092            GfxDebug::draw_line( edge->point(0)->coordinates(),
00093                                 edge->point(1)->coordinates(),
00094                                 CUBIT_RED_INDEX );
00095         }
00096       }
00097       else  // FacetEdge has no owner
00098       {
00099         if (edge->num_adj_facets() != 2)
00100         {
00101           PRINT_ERROR("Interior facet edge is %d-valent.\n", edge->num_adj_facets());
00102           GfxDebug::draw_line( edge->point(0)->coordinates(),
00103                                edge->point(1)->coordinates(),
00104                                CUBIT_RED_INDEX );
00105         }
00106       }
00107       
00108       bool found = false;
00109       for ( k = 0; k < edge->num_adj_facets(); k++ )
00110       {
00111         CubitFacet* edge_facet = edge->adj_facet(k);
00112         if( edge_facet == facet )
00113           found = true;
00114         
00115         int index = edge_facet->edge_index(edge);
00116         if( index < 0 )
00117         {
00118           PRINT_ERROR("edge->facet link missing facet->edge link.\n");
00119           continue;
00120         }
00121         CubitPoint* fp1 = edge_facet->point((index+1)%3);
00122         CubitPoint* fp2 = edge_facet->point((index+2)%3);
00123         int sense = 1;
00124         if( fp1 == edge->point(1) && fp2 == edge->point(0) )
00125           sense = -1;
00126         else if( fp1 != edge->point(0) || fp2 != edge->point(1) )
00127         {
00128           PRINT_ERROR("Facet adjacent to edge does not contain edge end points.\n");
00129           GfxDebug::draw_line( edge->point(0)->coordinates(),
00130                                edge->point(1)->coordinates(),
00131                                CUBIT_RED_INDEX );
00132           continue;
00133         }
00134         if ( sense != edge_facet->edge_use(index) )
00135         {
00136           //PRINT_ERROR("Facet has incorrect edge use\n");
00137         }
00138       }
00139       
00140       if( !found )
00141         PRINT_ERROR("facet->edge link missing edge->facet link.\n");
00142     }
00143     
00144     for ( j = 0; j < 3; j++ )
00145     {
00146       CubitPoint* point = facet->point(j);
00147       pt_facets.clean_out();
00148       point->facets(pt_facets);
00149       bool found = false;
00150       for ( k = pt_facets.size(); k--; )
00151       {
00152         CubitFacet* pt_facet = pt_facets.get_and_step();
00153         if ( pt_facet == facet )
00154           found = true;
00155         else if( pt_facet->point_index(point) < 0 )
00156           PRINT_ERROR("point->facet link missing facet->point link.\n");
00157       }
00158       if( ! found )
00159         PRINT_ERROR("facet->point link missing point->facet link.\n");
00160         
00161       point->edges(pt_edges);
00162       while (pt_edges.size())
00163       {
00164         CubitFacetEdge* edge = pt_edges.pop();
00165         edge_facets.clean_out();
00166         edge->facets(edge_facets);
00167         int count = 0;
00168         while (edge_facets.size())
00169           if (TDVGFacetOwner::get(edge_facets.pop()) == mySurface)
00170             count++;
00171         
00172         bool draw = false;
00173         if (count == 0) // not in this face
00174          ;
00175         else if (PartitionEntity* ent = TDVGFacetOwner::get(edge))
00176         {
00177           PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
00178           if (curve->is_nonmanifold(mySurface))
00179           {
00180             if (count != 2)
00181             {
00182               draw = true;
00183               PRINT_ERROR("Edge on non-manifold curve contained in %d facets.\n", count);
00184             }
00185           } 
00186           else if (count != 1)
00187           {
00188             draw = true; 
00189             PRINT_ERROR("Boundary edge contained in %d facets.\n", count); 
00190           }
00191         }
00192         else if (count != 2)
00193         { 
00194           draw = true; 
00195           PRINT_ERROR("Interior edge contained in %d facets.\n", count); 
00196         }
00197       
00198         if (draw) {
00199           CubitVector start = edge->point(0)->coordinates();
00200           CubitVector step = 0.05 * (edge->point(1)->coordinates() - start);
00201           for (int k = 0; k < 20; k++)
00202             GfxDebug::draw_point( start + k * step, CUBIT_RED_INDEX );
00203           GfxDebug::flush();
00204         }
00205       }
00206     }
00207   }
00208   
00209   
00210     // Check loops for contiguous chains of facet edges.
00211   DLIList<CubitFacetEdgeData*> curve_edges, loop_edges;
00212   PartitionLoop* loop = 0;
00213   while ((loop = mySurface->next_loop(loop)))
00214   {
00215     loop_edges.clean_out();
00216     PartitionCoEdge* coedge = loop->first_coedge();
00217     do {
00218       PartitionCurve* curve = coedge->get_curve();
00219       if (!curve->is_nonmanifold(mySurface))
00220       {
00221         curve_edges.clean_out();
00222         curve->get_facet_data(curve_edges);
00223         if (coedge->sense() == CUBIT_REVERSED)
00224           curve_edges.reverse();
00225         loop_edges += curve_edges;
00226       }
00227       coedge = loop->next_coedge(coedge);
00228     } while (coedge != loop->first_coedge());
00229   
00230     loop_edges.last();
00231     CubitFacetEdgeData* prev = loop_edges.get_and_step();
00232     PartitionCurve* prev_curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(prev));
00233     for (int i = 0; i < loop_edges.size(); i++)
00234     {
00235       CubitFacetEdgeData* edge = loop_edges.get_and_step();
00236       CubitPoint* shared = edge->shared_point(prev);
00237       PartitionCurve* curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
00238       
00239       if (!prev_curve || !curve)
00240       {
00241         PRINT_ERROR("Missing facet owner on boundary curve.\n");
00242         prev_curve = curve;
00243         prev = edge;
00244         continue;
00245       }
00246       
00247       if (!shared)
00248       {
00249         PRINT_ERROR("Broken facet-edge chain at curve %p (RefEdge %d):\n"
00250                     "      start of segment (%f,%f,%f)->(%f,%f,%f)\n",
00251                     (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
00252                     dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
00253                     edge->point(0)->coordinates().x(), 
00254                     edge->point(0)->coordinates().y(),
00255                     edge->point(0)->coordinates().z(),
00256                     edge->point(1)->coordinates().x(), 
00257                     edge->point(1)->coordinates().y(),
00258                     edge->point(1)->coordinates().z());
00259       }
00260       else if(PartitionPoint *pt = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(shared)))
00261       {
00262         if( (prev_curve == curve) &&
00263              !(pt == curve->start_point() && pt == curve->end_point()) )
00264         {
00265           PRINT_ERROR("Edges at point %p (vertex %d) (%f,%f,%f) owned\n"
00266                       "      by the same curve: %p (RefEdge %d)\n",
00267             (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
00268             dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
00269             pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z(),
00270             (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
00271             dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0);
00272         } 
00273         else if (!curve->other_point(pt))
00274         {
00275           PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n"
00276                       "      (vertex %d) (%f,%f,%f) doesn't match topology\n",
00277             (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
00278             dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
00279             (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
00280             dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
00281             pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z());
00282         }
00283         else if(!prev_curve->other_point(pt))
00284         {
00285           PRINT_ERROR("Edge owner curve %p (RefEdge %d) at point %p \n"
00286                       "      (vertex %d) (%f,%f,%f) doesn't match topology\n",
00287             (void*)prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())?
00288             dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0,
00289             (void*)pt, dynamic_cast<RefVertex*>(pt->topology_entity()) ?
00290             dynamic_cast<RefVertex*>(pt->topology_entity())->id() : 0,
00291             pt->coordinates().x(), pt->coordinates().y(), pt->coordinates().z());
00292         }
00293       }
00294       else if (prev_curve != curve)
00295       {
00296         PRINT_ERROR("Missing point-owner at  transition between\n"
00297                   "      curve %p (RefEdge %d) and curve %p (RefEdge %d):\n"
00298                   "      at location (%f,%f,%f)\n",
00299                   (void*)curve, curve && dynamic_cast<RefEdge*>(curve->topology_entity())?
00300                   dynamic_cast<RefEdge*>(curve->topology_entity())->id() : 0,
00301                   (void*)prev_curve, prev_curve && dynamic_cast<RefEdge*>(prev_curve->topology_entity())?
00302                   dynamic_cast<RefEdge*>(prev_curve->topology_entity())->id() : 0,
00303                   shared->coordinates().x(), 
00304                   shared->coordinates().y(),
00305                   shared->coordinates().z() );
00306       } 
00307       
00308       prev = edge;
00309       prev_curve = curve;
00310     }
00311   }
00312 }
00313    
00314 
00315 //-------------------------------------------------------------------------
00316 // Purpose       : Find closest point on passed facet
00317 //
00318 // Special Notes : static
00319 //
00320 // Creator       : Jason Kraftcheck
00321 //
00322 // Creation Date : 03/28/03
00323 //-------------------------------------------------------------------------
00324 void PartSurfFacetTool::closest_pt_on_facet( CubitFacet* facet,
00325                                              const CubitVector& p,
00326                                              CubitVector& result )
00327 {
00328     // Get triangle vertices
00329   CubitVector p0(facet->point(0)->coordinates());
00330   CubitVector p1(facet->point(1)->coordinates());
00331   CubitVector p2(facet->point(2)->coordinates());
00332 
00333 /*
00334   Algorithm from:
00335     "Distance Between Point and Triangle in 3D"
00336     David Eberly
00337     Magic Software, Inc.
00338     Sept. 28, 1999
00339 
00340   Use barycentric coordinates.  Coordinates are
00341   calculated in the range [0,det] rather than [0,1]
00342   to avoid the fp division entirely where it can
00343   be avoided.
00344 
00345     ^v*t                                 
00346  \R2|                 
00347   \ |                 
00348    \|                 
00349     *p2               
00350     |\                
00351     | \     R1        
00352  R3 |  \              
00353     |   \             
00354     | R0 \            
00355     |     \p1         
00356  ---*------*--->u*s   
00357     |p0     \  R6     
00358  R4 |   R5   \        
00359     |         \u+v=det  
00360 */
00361 
00362 
00363   CubitVector s(p1 - p0);  // the u (or s) axis in parameterized space
00364   CubitVector t(p2 - p0);  // the v (or t) axis in parameterized space
00365   CubitVector d(p0 - p);   // vector from input position to corner at (u,v) = (0,0)
00366     // Pre-calculate all the dot products we need
00367     // Name the dot product of vectors 'a' and 'b' as 'ab'
00368   double ss = s.length_squared();
00369   double st = s % t;
00370   double tt = t.length_squared();
00371   double sd = s % d;
00372   double td = t % d;
00373     // Calculate barycentric coordinates in the range [0,det]
00374   double det = ss*tt - st*st;
00375   double u = st*td - tt*sd;
00376   double v = st*sd - ss*td;
00377   
00378     // Big tree of conditionals to determine which of the 
00379     // regions in the above diagram the projection of
00380     // the point into the plane lies in.
00381   if ( u+v < det )
00382   {
00383     if ( u < 0 )
00384     {
00385       if( v < 0 )    // Region 4 
00386       {
00387         if ( sd < 0 )
00388         {
00389           if ( -sd > ss )
00390             result = p1;
00391           else
00392             result = p0 + (-sd/ss) * s;
00393         }
00394         else if ( td < 0 )
00395         {
00396           if ( -td > tt )
00397             result = p2;
00398           else
00399             result = p0 + (-td/tt) * t;
00400         }
00401         else
00402         {
00403           result = p0;
00404         }
00405       }
00406       else           // Region 3 (Edge p2-p0, u->0)
00407       {
00408         if ( td > 0 )
00409           result = p0;
00410         else if ( -td > tt )
00411           result = p2;
00412         else
00413           result = p0 + (-td/tt) * t;
00414       }
00415     }
00416     else if ( v < 0) // Region 5 (Edge p0-p1, v->0)
00417     {
00418       if ( sd > 0 )
00419         result = p0;
00420       else if ( -sd > ss )
00421         result = p1;
00422       else 
00423         result = p0 + (-sd/ss) * s;
00424     }
00425     else             // Region 0 (Interior)
00426     {
00427       result = p0 + (1.0/det) * (u*s + v*t);
00428     }
00429   }
00430   else if ( u < 0 )  // Region 2 
00431   {
00432     double num = tt + td - st - sd;
00433     if ( num > 0.0 )       
00434     {
00435       double den = ss - 2*st + tt;
00436       if ( num >= den )    // (Point p1)
00437         result = p1;
00438       else                 // (Edge p1-p2)
00439       {
00440         u = num / den;
00441         result = p0 + u*s + (1-u)*t;
00442       }
00443     } 
00444     else if ( td >= 0 )    // (Point p0)
00445       result = p0;
00446     else if ( tt+td <= 0 ) // (Point p2)
00447       result = p2;
00448     else                   // (Edge p2-p0)
00449       result = p0 + (-td/tt)*t;
00450   }
00451   else if ( v < 0 )  // Region 6 
00452   {
00453     double num = tt + td - st - sd;
00454     double den = ss - 2*st + tt;
00455     if (num < den)       
00456     {
00457       if ( num < 0 )    // (Point p1)
00458         result = p2;
00459       else                 // (Edge p1-p2)
00460       {
00461         u = num / den;
00462         result = p0 + u*s + (1-u)*t;
00463       }
00464     } 
00465     else if ( sd >= 0 )    // (Point p0)
00466       result = p0;
00467     else if ( ss+sd <= 0 ) // (Point p1)
00468       result = p1;
00469     else                   // (Edge p0-p1)
00470       result = p0 + (-sd/ss)*s;
00471   }
00472   else               // Region 1 (Edge p1-p2, u+v->1)
00473   {
00474     double num = tt + td - st - sd;
00475     if ( num <= 0 )
00476       result = p2;
00477     else
00478     {
00479       double den = ss - 2*st + tt;
00480       if ( num >= den )
00481         result = p1;
00482       else
00483       {
00484         u = num/den;
00485         result = p0 + u*s + (1-u)*t;
00486       }
00487     }
00488   }
00489 }
00490 
00491 //-------------------------------------------------------------------------
00492 // Purpose       : Local method for debug output
00493 //
00494 // Special Notes : 
00495 //
00496 // Creator       : Jason Kraftcheck
00497 //
00498 // Creation Date : 12/02/03
00499 //-------------------------------------------------------------------------
00500 static void draw_edges( DLIList<CubitFacetEdge*>& edges, int edge_color = 0, 
00501                  bool label_edges = false, bool draw_points = false,
00502                  int point_color = 0, bool label_points = false )
00503 {
00504   char buffer[2*sizeof(void*)+3];
00505 
00506   if (edge_color == 0)
00507     edge_color = CUBIT_WHITE_INDEX;
00508   if (point_color == 0)
00509     point_color = CUBIT_WHITE_INDEX;
00510   
00511   for (int i = edges.size(); i--; )
00512   {
00513     CubitFacetEdge* edge = edges.get_and_step();
00514     CubitVector start = edge->point(0)->coordinates();
00515     CubitVector end = edge->point(1)->coordinates();
00516     GfxDebug::draw_line(start, end, edge_color );
00517     
00518     if (label_edges)
00519     {
00520       CubitVector mid = 0.5 * (start + end);
00521       sprintf(buffer, "%p", (void*)edge);
00522       float x = (float)mid.x();
00523       float y = (float)mid.y();
00524       float z = (float)mid.z();
00525       GfxDebug::draw_label( buffer, x, y, z, edge_color );
00526     }
00527       
00528     for ( int j = 0; j < 2; j++ )
00529     {
00530       CubitPoint* point = edge->point(j);
00531       float x = (float)point->coordinates().x();
00532       float y = (float)point->coordinates().y();
00533       float z = (float)point->coordinates().z();
00534       
00535       if (draw_points)
00536       {
00537         GfxDebug::draw_point( x, y, z, point_color );
00538       }
00539       if (label_points)
00540       {
00541         sprintf(buffer, "%p", (void*)point);
00542         GfxDebug::draw_label( buffer, x, y, z, point_color );
00543       }
00544     }
00545   }
00546   GfxDebug::flush();
00547 }
00548 
00549     
00550 CubitStatus PartSurfFacetTool::init_facet_data( 
00551                                  DLIList<CubitFacetData*>& facets )
00552 {
00553   assert(!mySurface->has_facets());
00554   
00555   int i;
00556   CubitStatus rval;
00557   DLIList<CubitPoint*> boundary_points, interior_points;
00558   DLIList<CubitFacetEdge*> boundary_edges, interior_edges;
00559   DLIList<PartitionPoint*> geom_points, interior_geom_points;
00560   
00561     // Get facet data
00562   rval = get_facet_points_and_edges( facets, boundary_points, 
00563     interior_points, boundary_edges, interior_edges );
00564   if (!rval)
00565   {
00566     PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
00567     return CUBIT_FAILURE;
00568   }
00569 
00570     // Get real points on surface boundary
00571   mySurface->get_points(geom_points);
00572   for (i = 0; i < geom_points.size(); i++ )
00573   {
00574     if (!geom_points[i]->real_point())
00575       geom_points[i] = 0;
00576     // also process for hardpoints
00577     if (geom_points[i]) 
00578     {
00579       PartitionCurve* curve = geom_points[i]->next_curve();
00580       if ( curve->measure() < GEOMETRY_RESABS &&
00581            curve->start_point() == curve->end_point() )
00582       {
00583         geom_points[i] = 0;
00584       }
00585     }
00586   }
00587   geom_points.remove_all_with_value(0);
00588   
00589     // Group geometric points into boundary and interior sets
00590   for (i = geom_points.size(); i--; )
00591   {
00592     PartitionPoint* point = geom_points.step_and_get();
00593     bool boundary = false;
00594     PartitionCurve* curve = 0;
00595     while ( (curve = point->next_curve(curve)) )
00596       if (curve->is_in_surface(mySurface,true))
00597         boundary = true;
00598     if (!boundary)
00599     {
00600       geom_points.change_to(0);
00601       interior_geom_points.append(point);
00602     }
00603   }
00604   geom_points.remove_all_with_value(0);
00605   
00606     // Associate each boundary geometry point with the closest
00607     // boundary facet point.
00608   if(boundary_points.size() == 0 && geom_points.size() != 0)
00609     rval = CUBIT_FAILURE;
00610   else
00611     rval = associate_points( boundary_points, geom_points );
00612 
00613   if (!rval)
00614     return CUBIT_FAILURE;
00615  
00616     // Associate each interior geometry point with the closest 
00617     // interior facet point.
00618   rval = associate_points( interior_points, interior_geom_points );
00619   if (!rval)
00620     return CUBIT_FAILURE;
00621 
00622   if (DEBUG_FLAG(145))
00623   {
00624     draw_edges( boundary_edges, CUBIT_ORANGE_INDEX, true, false, CUBIT_WHITE_INDEX, true );
00625     draw_edges( interior_edges, CUBIT_WHITE_INDEX );
00626   }
00627   
00628   
00629     // Populate sets
00630   boundary_set.clear();
00631   interior_set.clear();
00632   for (i = boundary_edges.size(); i--; )
00633     boundary_set.insert(boundary_edges.step_and_get());
00634   for (i = interior_edges.size(); i--; )
00635     interior_set.insert(interior_edges.step_and_get());
00636  
00637     // For each loop on the surface...
00638   PartitionLoop* loop = 0;
00639   DLIList<PartitionCurve*> curve_set;
00640   DLIList<CubitFacetEdge*> point_edges, edge_set_1, edge_set_2;
00641   DLIList<PartitionCurve*> nonmanifold_stack;
00642   while ( (loop = mySurface->next_loop(loop)) )
00643   {
00644       // Find coedge beginning at real vertex (must be at least one)
00645     PartitionCoEdge* coedge = loop->first_coedge();
00646     while (!coedge->start_point()->real_point())
00647     { 
00648       coedge = coedge->next();
00649       assert(coedge != loop->first_coedge());
00650     }
00651     
00652     PartitionCoEdge* first_coedge = coedge; // so we know when to stop
00653     
00654      
00655     do // Loop until all curves in loop have been handled (back to first_coedge)
00656     {
00657         // Keep track of start and end
00658       PartitionCurve* first_curve = coedge->get_curve();
00659       PartitionPoint* start_point = coedge->start_point();
00660       PartitionPoint* end_point = coedge->end_point();
00661 
00662       // Hardpoints (meeting all cases below) are a special
00663       // case loop that should not be handled in the partitioning.
00664       if (loop->num_coedges() == 1 && 
00665           first_curve->measure() < GEOMETRY_RESABS &&
00666           start_point == end_point)
00667         break;
00668 
00669         // Get list of curves until next real vertex
00670       curve_set.clean_out();
00671       curve_set.append(first_curve);
00672       while (!coedge->end_point()->real_point())
00673       {
00674         coedge = coedge->next();
00675         curve_set.append(coedge->get_curve());
00676         end_point = coedge->end_point();
00677         assert(&first_curve->sub_entity_set() == &coedge->get_curve()->sub_entity_set());
00678       }
00679       
00680       if (DEBUG_FLAG(145))
00681       {
00682         curve_set.reset();
00683         for (i = curve_set.size(); i--; )
00684         {
00685           GMem gmem;
00686           PartitionCurve* c = curve_set.get_and_step();
00687           c->get_geometry_query_engine()->get_graphics( c, &gmem );
00688           GfxDebug::draw_polyline(gmem.point_list(), gmem.pointListCount, CUBIT_RED_INDEX );
00689         }
00690         GfxDebug::flush();
00691       }
00692 
00693         // Special case for non-manifold curves
00694       if (first_curve->is_nonmanifold(mySurface))
00695       {
00696           // Don't do the same non-manifold curve twice
00697         curve_set.reset();
00698         nonmanifold_stack.last();
00699         if (nonmanifold_stack.size() &&
00700             curve_set.get() == nonmanifold_stack.get())
00701         {
00702           for (i = curve_set.size(); i--; )
00703           {
00704             PartitionCurve* curv1 = curve_set.get_and_step();
00705             PartitionCurve* curv2 = nonmanifold_stack.pop();
00706             assert(curv1 == curv2);
00707             if (curv1 != curv2) {
00708               PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
00709               return CUBIT_FAILURE;
00710             }
00711           }
00712         }
00713         else
00714         {
00715           for (i = curve_set.size(); i--; )
00716             nonmanifold_stack.append(curve_set.get_and_step());
00717         
00718           if (!seam_nonmanifold_curves(curve_set, facets))
00719           {
00720             return CUBIT_FAILURE;
00721           }
00722         }
00723         coedge = coedge->next();
00724         if (coedge != first_coedge)
00725           continue;
00726         else
00727           break;
00728       }
00729 
00730         // Get facet edges adjacent to first point
00731       point_edges.clean_out();
00732       start_point->facet_point()->edges(point_edges);
00733 
00734         // For each boundary edge on the point, look for a chain
00735         // of connected boundary edges.
00736       edge_set_1.clean_out();
00737       edge_set_2.clean_out();
00738       while(point_edges.size())
00739       {
00740         CubitFacetEdge* edge = point_edges.pop();
00741         if (boundary_set.count(edge) == 0)  // skip non-boundary edges
00742           continue;
00743 
00744         edge_set_2.clean_out();
00745         if (!get_boundary_chain(start_point->facet_point(), edge, 
00746                                   end_point->facet_point(), edge_set_2))
00747           continue; // skip edges that don't begin a chain that reaches the end vertex
00748 
00749           // If only one chain found so far, store the chain and 
00750           // continue to the next edge around the point
00751         if (!edge_set_1.size())
00752         {
00753           edge_set_1 = edge_set_2;
00754           edge_set_2.clean_out();
00755           continue;
00756         }
00757 
00758           // If we reached this point, handle special case where
00759           // loop is composed of two real curves and we need a 
00760           // geometric check to determine which half of the facet edge
00761           // loop goes with which curve.
00762         edge_set_1.reset();
00763         edge_set_2.reset();
00764         CubitVector set_1_mid = edge_set_1.get()->center();
00765         CubitVector set_2_mid = edge_set_2.get()->center();
00766         CubitVector set_1_closest, set_2_closest;
00767         first_curve->closest_point_trimmed(set_1_mid, set_1_closest);
00768         first_curve->closest_point_trimmed(set_2_mid, set_2_closest);
00769 
00770         set_1_closest -= set_1_mid;
00771         set_2_closest -= set_2_mid;
00772         if (set_2_closest.length_squared() < set_1_closest.length_squared())
00773           edge_set_1 = edge_set_2;
00774       } // while(point_edges.size())
00775 
00776         // We have the chain of edges to associate with the curve
00777         // set.  Seam with adjacent surface facettings (if any)
00778       if (DEBUG_FLAG(145))
00779         draw_edges( edge_set_1, CUBIT_RED_INDEX, true );
00780       
00781       if (!seam_curves( curve_set, edge_set_1, facets ))
00782         return CUBIT_FAILURE;
00783       
00784       coedge = coedge->next();
00785     } while (coedge != first_coedge);
00786     
00787   } // while (loop)
00788   
00789     // attach facets to surface
00790   mySurface->set_facet_data(facets);
00791   
00792   return CUBIT_SUCCESS;
00793 }
00794 
00795 //-------------------------------------------------------------------------
00796 // Purpose       : Helper function for curve seaming functions.
00797 //                 Check that input curve list are partitions of the
00798 //                 same real curve and are all the partitions of that curve.
00799 //                 Returns the real curve and the PartitionPoints that
00800 //                 are the start and end of the real curve.
00801 //
00802 // Special Notes : Assumes the passed curves are either in order or in
00803 //                 the reverse order.  If the reverse order, the passed
00804 //                 list will be reversed.
00805 //
00806 // Creator       : Jason Kraftcheck
00807 //
00808 // Creation Date : 09/08/03
00809 //-------------------------------------------------------------------------
00810 Curve* PartSurfFacetTool::get_real_curve( DLIList<PartitionCurve*>& curve_list,
00811                                           PartitionPoint*& start_point,
00812                                           PartitionPoint*& end_point )
00813 {
00814   SubEntitySet* set = &(curve_list.get()->sub_entity_set());
00815   DLIList<PartitionEntity*> tmp_set(curve_list.size());
00816   set->get_sub_entities(tmp_set);
00817   if (tmp_set.size() != curve_list.size())
00818     return 0;
00819   
00820   tmp_set.reset();
00821   curve_list.reset();
00822   if (tmp_set.get() != curve_list.get())
00823   {
00824     curve_list.reverse();
00825     curve_list.reset();
00826   }
00827   
00828   for (int i = curve_list.size(); i--; )
00829     if (curve_list.get_and_step() != tmp_set.get_and_step())
00830       return 0;
00831    
00832     // Get real curve
00833   Curve* real_curve = dynamic_cast<Curve*>(set->get_entity());
00834   assert(!!real_curve);
00835   
00836   DLIList<TopologyBridge*> point_bridges(2);
00837   real_curve->get_children(point_bridges, false, set->get_owner_layer());
00838   point_bridges.reset();
00839   start_point = dynamic_cast<PartitionPoint*>(point_bridges.get());
00840   end_point = dynamic_cast<PartitionPoint*>(point_bridges.next());
00841   assert(start_point && end_point);
00842   
00843   return real_curve;
00844 }
00845 
00846 CubitStatus PartSurfFacetTool::get_boundary_chain( 
00847                                       CubitPoint* start_point,
00848                                       CubitFacetEdge* start_edge,
00849                                       CubitPoint* end_point,
00850                                       DLIList<CubitFacetEdge*>& result_list )
00851 {
00852   DLIList<CubitFacetEdge*> point_edges;
00853   
00854   //assert(start_edge->marked());
00855   assert(result_list.size() == 0);
00856   CubitPoint* point = start_point;
00857   CubitFacetEdge* edge = start_edge;
00858   while (true)
00859   {
00860     result_list.append(edge);
00861     point = edge->other_point(point);
00862     if (TDVGFacetOwner::get(point))
00863       return point == end_point ? CUBIT_SUCCESS : CUBIT_FAILURE;
00864     
00865     point->edges(point_edges);
00866     for (int i = point_edges.size(); i--; )
00867     {
00868       CubitFacetEdge* point_edge = point_edges.step_and_get();
00869       //if (point_edge->marked() != 1 || point_edge == edge)
00870       if (boundary_set.count(point_edge) == 0 || point_edge == edge)
00871         point_edges.change_to(0);
00872     }
00873     point_edges.remove_all_with_value(0);
00874     
00875     if (point_edges.size() != 1)
00876       return CUBIT_FAILURE;
00877     
00878     edge = point_edges.remove();
00879   }
00880   
00881     // unreachable
00882   return CUBIT_SUCCESS;
00883 }
00884       
00885 //-------------------------------------------------------------------------
00886 // Purpose       : Associate facet edges in the interior of a surface
00887 //                 facetting with the set of curve partitions of some
00888 //                 real, non-manifold curve in the surface.
00889 //
00890 // Special Notes : Assumes edges internal to the surface facetting
00891 //                 have been marked with a '2' by the caller.  Clears
00892 //                 marks on consumed edges.
00893 //
00894 // Creator       : Jason Kraftcheck
00895 //
00896 // Creation Date : 09/08/03
00897 //-------------------------------------------------------------------------
00898 CubitStatus PartSurfFacetTool::seam_nonmanifold_curves(
00899                                         DLIList<PartitionCurve*>& curve_list,
00900                                         DLIList<CubitFacetData*>& facet_list )
00901 {
00902     // All the curves in the attached coedge_list should belong
00903     // to the same real curve and thus have a single continuous 
00904     // parameterization over the entire set of curves.  Verify
00905     // this now.
00906   PartitionPoint *start_point, *end_point;
00907   Curve* real_curve = get_real_curve(curve_list, start_point, end_point);
00908   if (!real_curve)
00909   {
00910     PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
00911     assert(false);
00912     return CUBIT_FAILURE;
00913   }
00914   
00915     // Assume caller has marked all interior edges with a '2'.
00916     // Clear marks as we go to ensure we don't loop forever.
00917     // Find chain of curves closest to real curve and ending
00918     // at the end facet point.
00919   CubitPoint* const start_vtx = start_point->facet_point();
00920   CubitPoint* const   end_vtx =   end_point->facet_point();
00921   assert(start_vtx&&end_vtx);
00922   DLIList<CubitFacetEdge*> vtx_edges, seam_list;
00923   CubitPoint* vtx = start_vtx;
00924   do
00925   {
00926     vtx->edges(vtx_edges);
00927     CubitFacetEdge* edge = 0;
00928     double shortest_dist_sqr = CUBIT_DBL_MAX;
00929     while( vtx_edges.size() )
00930     {
00931       CubitFacetEdge* curr = vtx_edges.pop();
00932       //if (curr->marked() != 2 )
00933       if (interior_set.count(curr) == 0)
00934         continue;
00935       
00936       if (curr->other_point(vtx) == end_vtx)
00937       { 
00938         edge = curr;
00939         break;
00940       }
00941       
00942       CubitVector closest, tangent;
00943       CubitVector start(vtx->coordinates());
00944       CubitVector end(curr->other_point(vtx)->coordinates());
00945       real_curve->closest_point(0.5*(start+end), closest, &tangent);
00946       if (tangent % (end-start) < 0.0)
00947         continue;
00948       
00949       real_curve->closest_point(end, closest);
00950       closest -= end;
00951       double dist_sqr = closest.length_squared();
00952       if (dist_sqr < shortest_dist_sqr)
00953       {
00954         edge = curr;
00955         shortest_dist_sqr = dist_sqr;
00956       }
00957     }
00958     
00959     if (!edge)
00960     {
00961       PRINT_ERROR("Internal error at %s:%d:\n"
00962                   "Failed to associate facet edges with non-manofold curves.\n",
00963                   __FILE__, __LINE__ );
00964       return CUBIT_FAILURE;
00965     }
00966     if (DEBUG_FLAG(145))
00967     {
00968       GfxDebug::draw_facet_edge( edge, CUBIT_MAGENTA_INDEX );
00969       GfxDebug::flush();
00970     }
00971     
00972     seam_list.append(edge);
00973     //edge->marked(0);
00974     vtx = edge->other_point(vtx);
00975   } while (vtx != end_vtx);
00976   
00977   return seam_curves( curve_list, seam_list, facet_list );
00978 }
00979 
00980 
00981 CubitStatus PartSurfFacetTool::split_edge( CubitFacetEdge* old_edge,
00982                                           const CubitVector& position,
00983                                           CubitFacet* edge_facet,
00984                                           CubitPoint*& new_point,
00985                                           CubitFacetEdge*& new_edge,
00986                                           CubitFacet*& new_facet )
00987 {
00988   CubitVector v1, v2;
00989   int i = 0, junk;
00990   new_point = 0;
00991   new_edge = 0;
00992   new_facet = 0;
00993 
00994   CubitFacet* split_facet = edge_facet;
00995   if( !split_facet )
00996     split_facet = old_edge->adj_facet(0);
00997   else if( edge_facet->edge_index(old_edge) < 0 )
00998     { assert(0); return CUBIT_FAILURE; }
00999 
01000   CubitPoint* pt1 = old_edge->point(0);
01001   CubitPoint* pt2 = old_edge->point(1);
01002 
01003   v1 = position - pt1->coordinates();
01004   v2 = pt2->coordinates() - position;
01005   assert( v1.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS );
01006   assert( v2.length_squared() > GEOMETRY_RESABS*GEOMETRY_RESABS );
01007 #ifndef NDEBUG
01008   double dot = v1 % v2;
01009   assert( dot > 0 ); // projection of new point onto line lies outside edge.
01010 //  double cos_sqr = (dot * dot) / (v1.length_squared() * v2.length_squared());
01011 //  assert( cos_sqr > 0.99240387650610407 ); // angle less than 5 degrees
01012 #endif
01013 
01014 
01015   CubitPoint* new_pt = split_facet->split_edge( pt1, pt2, position );
01016   new_edge = new_pt->shared_edge(pt2);
01017   if( !new_edge ) { assert(0); return CUBIT_FAILURE; }
01018 
01019     // find new facet and update for other split facets
01020   CubitFacet *facet, *other_facet;
01021   PartitionEntity* facet_owner;
01022   while ( (facet = old_edge->adj_facet(i++)) ) {
01023     CubitPoint* pt3 = facet->point( facet->edge_index(pt1,new_pt,junk) );
01024     if( !pt3->shared_edge( new_pt ) )
01025       new CubitFacetEdgeData( pt3, new_pt );
01026       
01027     other_facet = facet->shared_facet( new_pt, pt3 );
01028     if( !other_facet ) { assert(0); continue; }
01029     if ( facet == edge_facet )
01030       new_facet = other_facet;
01031     else if( (facet_owner = TDVGFacetOwner::get(facet)) )
01032       facet_owner->notify_split( facet, other_facet );
01033   }
01034   if( (facet_owner = TDVGFacetOwner::get( old_edge )) )
01035       facet_owner->notify_split( old_edge, new_edge );
01036 
01037   if( edge_facet )
01038     assert(!!new_facet);
01039   else 
01040     new_facet = 0;
01041     
01042   new_point = new_pt;
01043   return CUBIT_SUCCESS;
01044 }
01045 
01046 CubitStatus PartSurfFacetTool::collapse_edge( CubitPoint* keep,
01047                                              CubitPoint* dead,
01048                                              DLIList<CubitFacetData*>* unowned )
01049 {
01050   int i;
01051   
01052   CubitPointData* keep_pt = dynamic_cast<CubitPointData*>(keep);
01053   CubitPointData* dead_pt = dynamic_cast<CubitPointData*>(dead);
01054   CubitFacetEdge* dead_edge;
01055   assert(keep_pt&&dead_pt);
01056   
01057     // Cannot proceed if dead_pt is owned by a PartitionPoint.
01058   if ( TDVGFacetOwner::get(dead_pt) )
01059     return CUBIT_FAILURE;
01060   
01061     // Get list of facets to be destroyed when edge is collapsed
01062   DLIList<CubitFacet*> dead_facets;
01063   keep->shared_facets(dead_pt,dead_facets);
01064   DLIList<PartitionSurface*> dead_facet_owners(dead_facets.size());
01065   DLIList<CubitFacetData*> dead_facet_ds(dead_facets.size());
01066   CAST_LIST(dead_facets, dead_facet_ds, CubitFacetData);
01067   
01068     // Find other edges to be destroyed when edge is collapsed.
01069     // cannot proceed if any of them belong to a PartitionCurve.
01070     // Also, find owners of each facet to be destroyed.
01071   dead_facets.reset();
01072   for ( i = dead_facets.size(); i--; )
01073   {
01074     CubitFacet* facet = dead_facets.get_and_step();
01075     int keep_index = facet->point_index(keep);
01076     int dead_index = facet->point_index(dead);
01077     int othr_index = (keep_index + 1) % 3;
01078     if ( othr_index == dead_index )
01079       othr_index = (keep_index + 2) % 3;
01080     assert( keep_index >= 0 && dead_index >= 0 );
01081     dead_edge = dead_pt->shared_edge(facet->point(othr_index));
01082     if ( TDVGFacetOwner::get(dead_edge) )
01083       return CUBIT_FAILURE;
01084       
01085     PartitionSurface* surf = dynamic_cast<PartitionSurface*>(TDVGFacetOwner::get(facet));
01086     dead_facet_owners.append( surf );
01087   }
01088 
01089 PRINT_INFO("Collapsing edge (%f,%f,%f)->(%f,%f,%f) (%f)\n",
01090   keep_pt->coordinates().x(), keep_pt->coordinates().y(), keep_pt->coordinates().z(),
01091   dead_pt->coordinates().x(), dead_pt->coordinates().y(), dead_pt->coordinates().z(),
01092   (keep_pt->coordinates()-dead_pt->coordinates()).length());
01093   
01094     // Get PartitionCurve to update for collapsed edge.
01095   PartitionCurve* dead_edge_owner = 0;
01096   dead_edge = dead_pt->shared_edge(keep_pt);
01097   if (dead_edge)
01098     dead_edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(dead_edge));
01099   
01100     // Collapse the edge
01101   if ( !keep_pt->collapse_edge(dead_pt) )
01102     return CUBIT_FAILURE;
01103   
01104     // Update owning curve
01105   if (dead_edge_owner)
01106     dead_edge_owner->remove_dead_facet( (CubitFacetEdgeData*)dead_edge );
01107   
01108     // Update facet owners for dead facets.
01109   dead_facet_ds.reset();
01110   dead_facet_owners.reset();
01111   for ( i = dead_facet_ds.size(); i--; )
01112   {
01113     CubitFacetData* facet = dead_facet_ds.get_and_step();
01114     PartitionSurface* facet_owner = dead_facet_owners.get_and_step();
01115     if (!facet_owner)
01116       unowned->append(facet);
01117     else 
01118       facet_owner->notify_destroyed(facet);
01119  }
01120   
01121   return CUBIT_SUCCESS;
01122 }
01123 
01124 
01125 
01126 
01127 //-------------------------------------------------------------------------
01128 // Purpose       : Seam a list of facet edges from the boundary of a
01129 //                 surface facetting with all the curves that are 
01130 //                 partitions of the same real curve on the boundary of
01131 //                 that surface.
01132 //
01133 // Special Notes : 
01134 //
01135 // Creator       : Jason Kraftcheck
01136 //
01137 // Creation Date : 09/08/03
01138 //-------------------------------------------------------------------------
01139 CubitStatus PartSurfFacetTool::seam_curves( DLIList<PartitionCurve*>& curve_list,
01140                                             DLIList<CubitFacetEdge*>& edge_list,
01141                                             DLIList<CubitFacetData*>& facets )
01142 {
01143   int i;
01144   if (!curve_list.size() || !edge_list.size())
01145     return CUBIT_FAILURE;
01146   
01147   if (DEBUG_FLAG(145))
01148     draw_edges( edge_list, CUBIT_WHITE_INDEX, true, true, CUBIT_WHITE_INDEX, false );
01149   
01150   DLIList<CubitFacetData*> old_facets, new_facets;
01151   DLIList<CubitFacetEdgeData*> dead_edge_ptrs;
01152   PartitionCurve* curve = 0;
01153   
01154     // All the curves in the attached coedge_list should belong
01155     // to the same real curve and thus have a single continuous 
01156     // parameterization over the entire set of curves.  Verify
01157     // this now.
01158   PartitionPoint *start_point, *end_point;
01159   Curve* real_curve = get_real_curve(curve_list, start_point, end_point);
01160   if (!real_curve)
01161   {
01162     PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
01163     assert(false);
01164     return CUBIT_FAILURE;
01165   }
01166   
01167   double period;
01168   const bool periodic = real_curve->is_periodic(period);
01169   const bool fwdparam = (periodic ?  period > 0.0 : real_curve->start_param() < real_curve->end_param());
01170   
01171   edge_list.reset();
01172   CubitPoint *next_vtx, *curr_vtx;
01173   if (edge_list.size() == 1)
01174   {
01175     next_vtx = edge_list.get()->point(1);
01176     curr_vtx = edge_list.get()->point(0);
01177   }
01178   else
01179   {
01180     next_vtx = edge_list.get()->shared_point(edge_list.next());
01181     curr_vtx = edge_list.get()->other_point(next_vtx);
01182   }
01183   assert(curr_vtx&&next_vtx);
01184     // Special case:  If curve_list is a closed loop of curves,
01185     // a geometric check is required to determine if the passed
01186     // list of facet edges is reversed wrt the curve list.
01187   if (start_point == end_point)
01188   {
01189     CubitVector tangent, closest, start(curr_vtx->coordinates()), end(next_vtx->coordinates());
01190     real_curve->closest_point( 0.5*(start+end), closest, &tangent );
01191     if ((end - start) % tangent < 0.0)
01192       edge_list.reverse();    
01193   }
01194     // Otherwise just compare end coordinates
01195   else
01196   {
01197     if ((start_point->coordinates() - curr_vtx->coordinates()).length_squared() >
01198         (end_point->coordinates() - curr_vtx->coordinates()).length_squared())
01199     {
01200       if (edge_list.size() == 1)
01201       {
01202         next_vtx = curr_vtx;
01203         curr_vtx = edge_list.get()->other_point(next_vtx);
01204       }
01205       else
01206       {
01207         edge_list.reverse();
01208         edge_list.reset();
01209         next_vtx = edge_list.get()->shared_point(edge_list.next());
01210         curr_vtx = edge_list.get()->other_point(next_vtx);
01211       }
01212       assert(next_vtx&&curr_vtx);
01213     }
01214   }
01215 
01216   DLIList<CubitFacetEdgeData*> edge_data_list;
01217   CAST_LIST(edge_list, edge_data_list, CubitFacetEdgeData);
01218   assert(edge_list.size() == edge_data_list.size());
01219   
01220     // Find the subset of edges which belong on each curve.
01221     // Begin with the first edge in the list, and the point
01222     // at the end (opposite the curve start point) of the edge.
01223   DLIList<CubitFacetEdgeData*> curve_edge_list;  // edges for current curve
01224   PartitionPoint* vertex = start_point;      // end point of current curve
01225   curve_list.reset(); 
01226   edge_data_list.reset();
01227   edge_data_list.reverse();
01228   CubitFacetEdgeData* edge = edge_data_list.pop();
01229   CubitPoint* point = start_point->facet_point(); // edge end point
01230   point = edge->other_point(point);
01231   if (!point)
01232   {
01233     PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
01234     assert(0);
01235     return CUBIT_FAILURE;
01236   }
01237   
01238     // Iterate over all but the last curve
01239   double prev_vtx_param = real_curve->start_param();
01240   double prev_pt_param = real_curve->start_param();
01241   for (i = curve_list.size() - 1; i--; )
01242   {
01243     curve_edge_list.clean_out();
01244     
01245     curve = curve_list.get_and_step();
01246     vertex = curve->other_point(vertex);
01247     const CubitVector vtx_pos(vertex->coordinates());
01248     double vtx_param = real_curve->u_from_position(vtx_pos);
01249     double point_param = real_curve->u_from_position(point->coordinates());
01250     if (periodic)
01251     {
01252       if ((vtx_param < prev_vtx_param) == fwdparam)
01253         vtx_param += period;
01254       if ((point_param < prev_pt_param) == fwdparam)
01255         point_param += period;
01256       prev_vtx_param = vtx_param;
01257       prev_pt_param = point_param;
01258     }
01259     
01260       // Iterate until the edge "containing" the vertex
01261     while ((vtx_param > point_param) == fwdparam)
01262     {
01263         // decrement edge count each time we add one of the
01264         // original, input edges to the cuve edge list.
01265       curve_edge_list.append(edge);
01266       
01267       if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; }
01268 
01269         // Get the next edge and facet point
01270       edge = edge_data_list.pop();
01271       point = edge->other_point(point);
01272       point_param = real_curve->u_from_position(point->coordinates());
01273       if (periodic)
01274       {
01275         if ((point_param < prev_pt_param) == fwdparam)
01276           point_param += period;
01277         prev_pt_param = point_param;
01278       }
01279     }
01280   
01281     CubitVector edge_pos;
01282     edge->closest_point(vtx_pos, edge_pos);
01283   
01284     CubitFacetEdgeData* new_edge;
01285     CubitPoint* new_point = split_edge_closest( edge, edge_pos, 0.1*edge->length(), new_edge, facets );
01286     if (!new_point)
01287       return CUBIT_FAILURE;
01288     
01289       // If the edge was split...
01290     if (new_edge)
01291     {
01292         // If new_edge ends at the "end" point
01293         // swap the edges.
01294       if (new_edge->other_point(point))
01295         std::swap(edge, new_edge);
01296         // Put the earlier peice of the edge in the curve
01297         // list.  Keep the latter peice for the next curve
01298         // iteration.
01299       curve_edge_list.append(new_edge);
01300     }
01301       // If the input position was the same as the edge end point...
01302     else if (new_point == point)
01303     {
01304         // Add edge to list for current curve and decrement count.
01305       curve_edge_list.append(edge);
01306       if (!edge_data_list.size()) { assert(0); return CUBIT_FAILURE; }
01307       
01308         // Get the next edge and facet point for the next iteration.
01309       edge = edge_data_list.pop();
01310       point = edge->other_point(point);
01311     }
01312     
01313       // Move edge split point to location of vertex
01314 #ifdef PART_SURF_REFACET
01315     double d_sqr = (vtx_pos - edge_pos).length_squared();
01316     bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
01317     old_facets.clean_out();
01318     new_facets.clean_out();
01319     if (close)
01320       dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos);
01321     else if (!fix_move_point( new_point, vtx_pos, facets, old_facets, new_facets ))
01322       return CUBIT_FAILURE;
01323     assert(!old_facets.size() == !new_facets.size());
01324     facets -= old_facets;
01325     facets += new_facets;
01326 #else
01327     dynamic_cast<CubitPointData*>(new_point)->set(vtx_pos); 
01328 #endif
01329       // Merge the points
01330     CubitPointData* vtx_pointd = vertex->facet_point();
01331     CubitPointData* new_pointd = dynamic_cast<CubitPointData*>(new_point);
01332     if (vtx_pointd)
01333       vtx_pointd->merge_points(new_pointd);
01334     else
01335       vertex->facet_point(new_pointd);
01336     
01337     if (!curve->has_facet_data())
01338       curve->set_facet_data(curve_edge_list);
01339     else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs ))
01340       return CUBIT_FAILURE;
01341       
01342     while (dead_edge_ptrs.size())
01343     {
01344       CubitFacetEdgeData* edge = dead_edge_ptrs.pop();
01345       boundary_set.erase(edge);
01346       interior_set.erase(edge);
01347     }
01348 
01349   } // for(curve_list)
01350   
01351     // Do last curve
01352 
01353   curve = curve_list.get();
01354   curve_edge_list.clean_out();
01355   if (edge)
01356     curve_edge_list.append(edge);
01357   while (edge_data_list.size())
01358     curve_edge_list.append(edge_data_list.pop());
01359   
01360   if(!curve_edge_list.size()) { assert(0); return CUBIT_FAILURE; }
01361   
01362   if (!curve->has_facet_data())
01363     curve->set_facet_data(curve_edge_list);
01364   else if(!seam_curve( curve_edge_list, curve, facets, &dead_edge_ptrs ))
01365     return CUBIT_FAILURE;
01366       
01367   while (dead_edge_ptrs.size())
01368   {
01369     CubitFacetEdgeData* edge = dead_edge_ptrs.pop();
01370     boundary_set.erase(edge);
01371     interior_set.erase(edge);
01372   }
01373     
01374   return CUBIT_SUCCESS;
01375 }
01376 
01377 //-------------------------------------------------------------------------
01378 // Purpose       : Seam a new list of facet edges with the list of facet
01379 //                 edges on a curve.
01380 //
01381 // Special Notes : 
01382 //
01383 // Creator       : Jason Kraftcheck
01384 //
01385 // Creation Date : 12/02/03
01386 //-------------------------------------------------------------------------
01387 CubitStatus PartSurfFacetTool::seam_curve( DLIList<CubitFacetEdgeData*>& edge_list,
01388                                            PartitionCurve* curve,
01389                                            DLIList<CubitFacetData*>& facets,
01390                                            DLIList<CubitFacetEdgeData*>* dead_ptrs )
01391 {
01392   DLIList<CubitFacetData*> old_facets, new_facets;
01393   const double FRACT_TOL = 0.1;
01394 
01395   int curve_color = CUBIT_GREEN_INDEX;
01396   if (DEBUG_FLAG(145))
01397   {
01398     RefEntity* ent = dynamic_cast<RefEntity*>(curve->topology_entity());
01399     while (ent && ent->color() < 0)
01400     {
01401       DLIList<RefEntity*> list;
01402       ent->get_parent_ref_entities(list);
01403       list.reset();
01404       if (!list.size()) break;
01405       ent = list.get();
01406     }
01407     if (ent)
01408       curve_color = ent->color();
01409   }
01410   
01411     // Vertices should already be "seamed".  Verify...
01412     
01413   PartitionPoint* start_vtx = curve->start_point();
01414   PartitionPoint* end_vtx = curve->end_point();
01415   CubitPointData* start_point = start_vtx->facet_point();
01416   CubitPointData* end_point = end_vtx->facet_point();
01417   
01418   edge_list.last();
01419   CubitFacetEdgeData* last_edge = edge_list.get();
01420   edge_list.reset();
01421   CubitFacetEdgeData* first_edge = edge_list.get();
01422   if (!first_edge->other_point(start_point) || 
01423       !last_edge->other_point(end_point))
01424   {
01425     PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
01426     assert(0);
01427     return CUBIT_FAILURE;
01428   }
01429   
01430     // Get direction of parameter (probably always increasing...)
01431   double period;
01432   const bool fwdparam = curve->is_periodic(period) ? period > 0.0 :
01433                         curve->start_param() < curve->end_param();
01434   
01435     // Get list of facet edges on curve.
01436   DLIList<CubitFacetEdgeData*> curve_edges;
01437   curve->get_facet_data(curve_edges);
01438   if (!curve_edges.size())
01439   {
01440     curve->set_facet_data( edge_list );
01441     return CUBIT_SUCCESS;
01442   }
01443   
01444     // Seam edge lists
01445   double curve_param = curve->start_param();
01446   double new_param = curve->start_param();
01447   curve_edges.reset();
01448   edge_list.reset();
01449   CubitFacetEdgeData* curve_edge = curve_edges.get_and_step();
01450   CubitFacetEdgeData* new_edge = edge_list.get_and_step();
01451   CubitPoint* prev_point = start_point;
01452   double orig_crv_len = curve_edge->length();
01453   double orig_new_len = new_edge->length();
01454   double split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01455   while (curve_edge || new_edge)
01456   {
01457     if (!curve_edge || !new_edge)
01458     {
01459       PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__ );
01460       assert(0);
01461       return CUBIT_FAILURE;
01462     }
01463   
01464     CubitPoint* curve_point = curve_edge->other_point(prev_point);
01465     CubitPoint* new_point = new_edge->other_point(prev_point);
01466     if (DEBUG_FLAG(145)) {
01467       GfxDebug::draw_point(curve_point->coordinates(), curve_color);
01468       GfxDebug::draw_facet_edge(curve_edge, curve_color);
01469       GfxDebug::draw_point(new_point->coordinates(), curve_color + 1);
01470       GfxDebug::draw_facet_edge(new_edge, curve_color + 1);
01471       GfxDebug::flush();
01472     }
01473     
01474     double prev_curve_param = curve_param;
01475     double prev_new_param = new_param;
01476     curve_param = curve->u_from_position(curve_point->coordinates());
01477     new_param = curve->u_from_position(new_point->coordinates());
01478     if (curve->is_periodic(period))
01479     {
01480       if ((prev_curve_param > curve_param) == fwdparam)
01481         curve_param += period;
01482       if ((prev_new_param > new_param) == fwdparam)
01483         new_param += period;
01484     }
01485     
01486     if ((curve_param > new_param) == fwdparam)
01487     {
01488       CubitFacetEdgeData* split_edge = 0;
01489       CubitVector edge_pos;
01490       curve_edge->closest_point( new_point->coordinates(), edge_pos );
01491       CubitPoint* split = split_edge_closest( curve_edge, 
01492                                               edge_pos, 
01493                                               split_tol,
01494                                               split_edge, 
01495                                               facets );
01496       if(!split)
01497         return CUBIT_FAILURE;
01498       
01499       if (split == prev_point)
01500       {
01501           // new_edge is very small compared to split_edge
01502         assert(!split_edge);
01503         old_facets.clean_out();
01504         if (!collapse_edge(prev_point, new_point, &old_facets))
01505         {
01506           if (!collapse_edge(new_point, prev_point, &old_facets))
01507           {
01508             return CUBIT_FAILURE;
01509           }
01510           std::swap(prev_point, new_point);
01511         }
01512         if (dead_ptrs)
01513           dead_ptrs->append( new_edge );
01514         facets -= old_facets;
01515       
01516         if (edge_list.is_at_beginning())
01517           new_edge = 0;
01518         else
01519         {
01520           new_edge = edge_list.get_and_step();
01521           orig_new_len = new_edge->length();
01522           split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01523         }
01524          
01525         continue;
01526       }
01527       
01528       if (split_edge)
01529       {
01530         if (curve_edge->other_point(prev_point))
01531           std::swap(split_edge, curve_edge);
01532       }
01533       else
01534       {
01535         assert(split == curve_point);
01536         split_edge = curve_edge;
01537         if (curve_edges.is_at_beginning())
01538           curve_edge = 0;
01539         else
01540         {
01541           curve_edge = curve_edges.get_and_step();
01542           orig_crv_len = curve_edge->length();
01543           split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01544         }
01545       }
01546       
01547         // Move split point to position of other point (safely)
01548 #ifdef PART_SURF_REFACET
01549       double d_sqr = (edge_pos - new_point->coordinates()).length_squared();
01550       bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
01551       old_facets.clean_out();
01552       new_facets.clean_out();
01553       if (close)
01554         dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates());
01555       else if (!fix_move_point( split, new_point->coordinates(), facets, old_facets, new_facets ))
01556         return CUBIT_FAILURE;
01557       facets -= old_facets;
01558       facets += new_facets;
01559 #else
01560       dynamic_cast<CubitPointData*>(split)->set(new_point->coordinates());
01561 #endif
01562       
01563       CubitStatus s1 = split->merge_points(new_point);
01564       CubitStatus s2 = split_edge->merge_edges(new_edge);
01565       if (dead_ptrs)
01566         dead_ptrs->append(new_edge);
01567       assert(s1 && s2);
01568       prev_point = split;
01569       
01570       if (edge_list.is_at_beginning())
01571         new_edge = 0;
01572       else
01573       {
01574         new_edge = edge_list.get_and_step();
01575         orig_new_len = new_edge->length();
01576         split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01577       }  
01578     }
01579     else
01580     {
01581       CubitFacetEdgeData* split_edge = 0;
01582       CubitVector edge_pos;
01583       new_edge->closest_point( curve_point->coordinates(), edge_pos );
01584       CubitPoint* split = split_edge_closest( new_edge, 
01585                                               edge_pos, 
01586                                               split_tol,
01587                                               split_edge,
01588                                               facets );
01589       if(!split)
01590         return CUBIT_FAILURE;
01591       
01592       if (split == prev_point)
01593       {
01594           // curve_edge is very small compared to split_edge
01595         assert(!split_edge);
01596         old_facets.clean_out();
01597         if (!collapse_edge(prev_point,curve_point,&old_facets))
01598         {
01599           if (!collapse_edge(curve_point, prev_point, &old_facets))
01600           {
01601             return CUBIT_FAILURE;
01602           }
01603           std::swap(curve_point, prev_point);
01604         }
01605         facets -= old_facets;
01606         if (dead_ptrs)
01607           dead_ptrs->append(curve_edge);
01608       
01609         if (curve_edges.is_at_beginning())
01610           curve_edge = 0;
01611         else
01612         {
01613           curve_edge = curve_edges.get_and_step();
01614           orig_crv_len = curve_edge->length();
01615           split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01616         }  
01617         continue;
01618       }
01619         
01620       if (split_edge)
01621       {
01622         if (new_edge->other_point(prev_point))
01623           std::swap(split_edge, new_edge);
01624       }
01625       else
01626       {
01627         assert(split == new_point);
01628         split_edge = new_edge;
01629         if (edge_list.is_at_beginning())
01630           new_edge = 0;
01631         else
01632         {
01633           new_edge = edge_list.get_and_step();
01634           orig_new_len = new_edge->length();
01635           split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01636         }  
01637       }    
01638       
01639         // Move split point to position of other point (safely)
01640 #ifdef PART_SURF_REFACET
01641       double d_sqr = (edge_pos - curve_point->coordinates()).length_squared();
01642       bool close = d_sqr < (GEOMETRY_RESABS*GEOMETRY_RESABS);
01643       old_facets.clean_out();
01644       new_facets.clean_out();
01645       if (close)
01646         dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates());
01647       else if (!fix_move_point( split, curve_point->coordinates(), facets, old_facets, new_facets ))
01648         return CUBIT_FAILURE;
01649       facets -= old_facets;
01650       facets += new_facets;
01651 #else
01652       dynamic_cast<CubitPointData*>(split)->set(curve_point->coordinates());
01653 #endif
01654       
01655       CubitStatus s2, s1 = CUBIT_SUCCESS;
01656       if (curve_point != split)
01657         s1 = curve_point->merge_points(split);
01658       s2 = curve_edge->merge_edges(split_edge);
01659       assert(s1 && s2);
01660       if (CUBIT_SUCCESS != s1 || CUBIT_SUCCESS != s2) {
01661         PRINT_ERROR("Internal error at %s:%d\n", __FILE__, __LINE__);
01662         return CUBIT_FAILURE;
01663       }
01664       if (dead_ptrs)
01665         dead_ptrs->append(split_edge);
01666       prev_point = curve_point;
01667       
01668       if (curve_edges.is_at_beginning())
01669         curve_edge = 0;
01670       else
01671       {
01672         curve_edge = curve_edges.get_and_step();
01673         orig_crv_len = curve_edge->length();
01674         split_tol = FRACT_TOL * CUBIT_MIN(orig_crv_len, orig_new_len);
01675       }  
01676     }
01677   }
01678   
01679   return CUBIT_SUCCESS;
01680 }
01681 
01682 
01683 //-------------------------------------------------------------------------
01684 // Purpose       : Retriangulate if necessary for moving a boundary point
01685 //                 into the interior of a facet patch.
01686 //
01687 // Special Notes : 
01688 //
01689 // Creator       : Jason Kraftcheck
01690 //
01691 // Creation Date : 12/07/03
01692 //-------------------------------------------------------------------------
01693 CubitStatus PartSurfFacetTool::fix_move_point( 
01694                                       CubitPoint* point,
01695                                       const CubitVector& new_pos,
01696                                       const DLIList<CubitFacetData*>& facetds,
01697                                       DLIList<CubitFacetData*>& old_facets,
01698                                       DLIList<CubitFacetData*>& new_facets,
01699                                       PartitionSurface* surface )
01700 {
01701   int i;
01702   DLIList<CubitFacet*> facets(facetds.size());
01703   for (i = 0; i < facetds.size(); i++)
01704     facets.append(facetds.next(i));
01705   
01706     // Look for a triangle containing the passed point.
01707   CubitVector closest_pos, vect;
01708   CubitFacet* facet = closest_facet(new_pos, facetds, closest_pos );
01709   if ( facet == NULL)
01710     return CUBIT_FAILURE;
01711 
01712   if (facet->point_index(point) >= 0)
01713   {
01714     dynamic_cast<CubitPointData*>(point)->set(new_pos);
01715     return CUBIT_SUCCESS;
01716   }
01717 
01718   PRINT_WARNING("Refacetting surface near (%f,%f,%f)\n",
01719     new_pos.x(), new_pos.y(), new_pos.z());
01720 
01721     // Line direction
01722   const CubitVector dir(point->coordinates() - new_pos);
01723 
01724   if (DEBUG_FLAG(145)) 
01725   { 
01726     GfxDebug::draw_facet(facet, CUBIT_BLUE_INDEX); 
01727     GfxDebug::draw_point(point->coordinates(), CUBIT_BLUE_INDEX);
01728     GfxDebug::draw_point(new_pos, CUBIT_CYAN_INDEX);
01729     GfxDebug::draw_line(point->coordinates(), new_pos, CUBIT_BLUE_INDEX);
01730     GfxDebug::flush(); 
01731   }
01732   
01733     // Find where line exits first triangle
01734   CubitFacetEdge* edge = 0;
01735   bool leftofpoint[3];
01736   for ( i = 0; i < 3; i++)
01737   {
01738     CubitVector vect = facet->point(i)->coordinates() - new_pos;
01739     vect *= dir;
01740     leftofpoint[i] = (vect % facet->normal()) >= 0.0;
01741   }
01742   
01743   for ( i = 0; i < 3; ++i)
01744     if (leftofpoint[i] && !leftofpoint[(i+1)%3])
01745     {
01746       edge = facet->edge((i+2)%3);
01747       break;
01748     }
01749   
01750   if (!edge)
01751     return CUBIT_FAILURE;
01752   
01753     // Find the set of triangles the line from the old 
01754     // position to the new position crosses.
01755   DLIList<CubitFacet*> intersect_list, edge_facets;
01756   while (facet->point_index(point) < 0)
01757   {
01758     intersect_list.append(facet);
01759 
01760     if (DEBUG_FLAG(145)) 
01761     { 
01762       GfxDebug::draw_facet_edge(edge, CUBIT_WHITE_INDEX); 
01763       GfxDebug::draw_facet(facet, CUBIT_BLUE_INDEX); 
01764       GfxDebug::flush(); 
01765     }
01766       
01767       // Find the facet on the other side of the edge
01768     edge_facets.clean_out();
01769     if (surface)
01770       PartSurfFacetTool::edge_facets(surface, edge, edge_facets);
01771     else
01772       PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
01773     edge_facets.move_to(facet);
01774     assert(edge_facets.get() == facet);
01775 
01776     if(edge_facets.size() != 2)
01777       break;
01778     
01779     facet = edge_facets.step_and_get();
01780     
01781       // Find the edge that the line intersects exiting the facet
01782     i = facet->edge_index(edge);
01783     vect = facet->point(i)->coordinates() - new_pos;
01784     vect *= dir;
01785     if (vect % facet->normal() >= 0.0)
01786       edge = facet->edge((i+1)%3);
01787     else
01788       edge = facet->edge((i+2)%3);
01789   }
01790   
01791   if (facet)
01792   {
01793     if (DEBUG_FLAG(145)) 
01794     { 
01795       GfxDebug::draw_facet_edge(edge, CUBIT_WHITE_INDEX); 
01796       GfxDebug::flush(); 
01797     }
01798     intersect_list.append_unique(facet);
01799   }
01800   
01801     // Get ordered boundary
01802   DLIList<CubitPoint*> boundary_list;
01803   DLIList<CubitFacetEdge*> point_edges;
01804   CubitFacetEdge* prev_edge = 0;
01805   CubitFacet* prev_facet = 0;
01806     // Find one boundary edge to start with
01807   for (i = intersect_list.size(); !prev_edge && i--; )
01808   {
01809     CubitFacet* facet = intersect_list.get_and_step();
01810     for (int j = 0; j < 3; j++)
01811     {
01812       CubitFacetEdge* edge = facet->edge(j);
01813       edge_facets.clean_out();
01814      if (surface)
01815        PartSurfFacetTool::edge_facets( surface, edge, edge_facets);
01816      else
01817        PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
01818       edge_facets.intersect(intersect_list);
01819       if (edge_facets.size() == 1)
01820       {
01821         prev_edge = edge;
01822         prev_facet = facet;
01823         break;
01824       }
01825     }
01826   }
01827   CubitFacetEdge* first_edge = prev_edge;
01828     // Traverse boundary edges in order
01829   do 
01830   {
01831     int direction = prev_facet->edge_use( prev_facet->edge_index(prev_edge) );
01832     CubitPoint* pt = prev_edge->point( direction == -1 ? 0 : 1 );
01833     point_edges.clean_out();
01834     pt->edges( point_edges );
01835     
01836     if (DEBUG_FLAG(145))
01837     {
01838       GfxDebug::draw_facet_edge( prev_edge, CUBIT_LIGHTBLUE_INDEX );
01839       GfxDebug::flush();
01840     }
01841     boundary_list.append(pt);
01842     
01843     point_edges.move_to(prev_edge);
01844     assert(point_edges.get() == prev_edge);
01845     point_edges.extract();
01846     prev_edge = 0;
01847 
01848     while (point_edges.size())
01849     {
01850       CubitFacetEdge* edge = point_edges.pop();
01851       edge_facets.clean_out();
01852       if (surface)
01853         PartSurfFacetTool::edge_facets( surface, edge, edge_facets);
01854       else
01855         PartSurfFacetTool::edge_facets( edge, facets, edge_facets );
01856       edge_facets.intersect(intersect_list);
01857       if (edge_facets.size() == 1)
01858       {
01859         if (prev_edge) {
01860           prev_edge = 0;
01861           break;
01862         }
01863         prev_edge = edge;
01864         prev_facet = edge_facets.get();
01865       }
01866     }
01867   
01868     if (!prev_edge)
01869     {
01870       PRINT_ERROR("Problems finding boundary to re-facet around split point.\n");
01871       return CUBIT_FAILURE;
01872     }
01873   } while (prev_edge != first_edge);
01874 
01875  
01876     // Construct new facets in affected region by connecting 
01877     // the split point to each boundary point
01878   int junk = 0;
01879   //DLIList<CubitFacetData*> new_facets, old_facets(intersect_list.size());
01880   if (!boundary_list.move_to(point))
01881   {
01882     PRINT_ERROR("Problems finding region around split point for re-facetting.\n");
01883     return CUBIT_FAILURE;
01884   }
01885   boundary_list.step();
01886   CubitPoint* prev_pt = boundary_list.get_and_step();
01887   for (i = boundary_list.size(); i > 2; i--)
01888   {
01889     CubitPoint* next_pt = boundary_list.get_and_step();
01890     CubitFacetData* new_facet = new CubitFacetData( point, prev_pt, next_pt, &junk);
01891     new_facets.append(new_facet);
01892     prev_pt = next_pt;
01893     
01894     if (DEBUG_FLAG(145))
01895     {
01896       GfxDebug::draw_facet( new_facet, CUBIT_YELLOW_INDEX );
01897       GfxDebug::flush();
01898     }
01899   }
01900   
01901   CAST_LIST( intersect_list, old_facets, CubitFacetData );
01902   assert(intersect_list.size() == old_facets.size());
01903   dynamic_cast<CubitPointData*>(point)->set(new_pos);
01904   //replace_facets( old_facets, new_facets );
01905   return CUBIT_SUCCESS;
01906 }
01907 
01908 //-------------------------------------------------------------------------
01909 // Purpose       : Find closest facet and point on facet
01910 //
01911 // Special Notes : 
01912 //
01913 // Creator       : Jason Kraftcheck
01914 //
01915 // Creation Date : 03/28/03
01916 //-------------------------------------------------------------------------
01917 CubitFacet* PartSurfFacetTool::closest_facet(
01918                                    const CubitVector& input_position,
01919                                    const DLIList<CubitFacetData*>& facet_list,
01920                                    CubitVector& result_position )
01921 {
01922   CubitFacet* return_val = 0;
01923   double closest_dist_sqr = CUBIT_DBL_MAX;
01924   CubitVector facet_position;
01925   
01926   const int size = facet_list.size();
01927   for ( int i = 0; i < size; i++ ) {
01928     CubitFacet* facet = facet_list.next(i);
01929     closest_pt_on_facet( facet, input_position, facet_position );
01930     double dist_sqr = (input_position - facet_position).length_squared();
01931     if ( dist_sqr < closest_dist_sqr ) {
01932       closest_dist_sqr = dist_sqr;
01933       result_position = facet_position;
01934       return_val = facet;
01935     }
01936   }
01937   
01938   return return_val;
01939 }
01940 
01941 //-------------------------------------------------------------------------
01942 // Purpose       : Return edge start/end if input position is sufficiently
01943 //                 close.  Otherwise split the edge and return the new
01944 //                 point.
01945 //
01946 // Special Notes : For all facets modified by this operation, owning surfaces
01947 //                 will be notified of the change.  For any un-owned facets,
01948 //                 new facets will be appended to the passed list.
01949 //
01950 // Creator       : Jason Kraftcheck
01951 //
01952 // Creation Date : 12/01/03
01953 //-------------------------------------------------------------------------
01954 CubitPoint* PartSurfFacetTool::split_edge_closest( 
01955                                      CubitFacetEdgeData* old_edge,
01956                                      const CubitVector& pos,
01957                                      double tolerance,
01958                                      CubitFacetEdgeData*& new_edge,
01959                                      DLIList<CubitFacetData*>& new_facets )
01960 {
01961     // square of absolute tolerance
01962   const double GEOM_TOL_SQR = GEOMETRY_RESABS*GEOMETRY_RESABS; 
01963     // tolerance as fraction of edge length.
01964   const double TOL_SQR = tolerance < GEOM_TOL_SQR ? GEOM_TOL_SQR : tolerance * tolerance;
01965   
01966   new_edge = 0;
01967 
01968   const CubitVector start(old_edge->point(0)->coordinates());
01969   const CubitVector end(old_edge->point(1)->coordinates());
01970 //   const CubitVector dir(end - start);
01971   //const double fract = (dir % (pos - start)) / dir.length_squared();
01972 
01973     // If near the start/end of the edge and start/end point is
01974     // not already owned by some other vertex
01975   const double start_sqr = (start - pos).length_squared();
01976   const double end_sqr   = (end   - pos).length_squared();
01977   if (start_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(0)))
01978     return old_edge->point(0);
01979   else if (end_sqr < TOL_SQR && !TDVGFacetOwner::get(old_edge->point(1)))
01980     return old_edge->point(1);
01981 
01982     // Else if start/end of edge are same position as vertex
01983   else if(start_sqr < GEOM_TOL_SQR)
01984     return old_edge->point(0);
01985   else if(end_sqr < GEOM_TOL_SQR)
01986     return old_edge->point(1);
01987 
01988     // Otherwise split the edge
01989   CubitFacet* a_face = old_edge->adj_facet(0);
01990   CubitFacetData* facet = dynamic_cast<CubitFacetData*>(a_face);
01991   if (!facet)
01992     return 0;
01993 
01994   //CubitVector edge_pos((1.0-edge_param)*edge_start + edge_param*edge_end);
01995   CubitPoint* start_pt = old_edge->point(0);
01996   CubitPoint*   end_pt = old_edge->point(1);
01997   CubitPoint*   new_pt = facet->split_edge( start_pt, end_pt, pos );
01998   CubitFacetEdge* temp_edge = new_pt->shared_edge(end_pt);
01999   new_edge = dynamic_cast<CubitFacetEdgeData*>(temp_edge);
02000   if (!new_edge)
02001     return 0;
02002   
02003     // Update partition curve facetting
02004   PartitionCurve* edge_owner = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(old_edge));
02005   if (edge_owner)
02006     edge_owner->notify_split(old_edge, new_edge);
02007 
02008     // Update partition surfaces for split of adjacent facets
02009   int i, junk = -1;
02010   DLIList<CubitFacet*> facets(old_edge->num_adj_facets());
02011   old_edge->facets(facets);
02012   
02013   for ( i = facets.size(); i--;  )
02014   {
02015     a_face = facets.get_and_step();
02016     facet = dynamic_cast<CubitFacetData*>(a_face);
02017     assert(!!facet);
02018     int edge_index = facet->edge_index( start_pt, new_pt, junk );
02019     CubitPoint* other_pt = facet->point( edge_index );
02020     if (!other_pt->shared_edge( new_pt ))
02021       new CubitFacetEdgeData( other_pt, new_pt );
02022 
02023     CubitFacet* a_face = facet->shared_facet( new_pt, other_pt );
02024     CubitFacetData* other_facet = dynamic_cast<CubitFacetData*>(a_face);
02025     if (!other_facet) { assert(0); continue; }
02026 
02027     PartitionEntity* owner = TDVGFacetOwner::get(facet);
02028 #ifndef NDEBUG
02029     PartitionSurface* surf = dynamic_cast<PartitionSurface*>(owner);
02030     assert(!owner || surf);
02031 #endif
02032     
02033     if (owner)
02034       owner->notify_split( facet, other_facet );
02035     else
02036       new_facets.append(other_facet);
02037   }
02038   
02039   return new_pt;
02040 }
02041 
02042 //-------------------------------------------------------------------------
02043 // Purpose       : Spatially match a set of geometric points one-to-one
02044 //                 with a subset of a set of facet vertices.
02045 //
02046 // Special Notes : If the geometric point already has an attached facet
02047 //                 point, the points will be merged such that the facet
02048 //                 point originally on the geometric point survives the
02049 //                 merge.  If the geometric point does not already have
02050 //                 a facet point, the input facet point will be attached
02051 //                 to the geometric point.
02052 //
02053 // Creator       : Jason Kraftcheck
02054 //
02055 // Creation Date : 09/08/03
02056 //-------------------------------------------------------------------------
02057 CubitStatus PartSurfFacetTool::associate_points( 
02058                                      DLIList<CubitPoint*>& facet_points,
02059                                      DLIList<PartitionPoint*>& geom_points )
02060 {
02061   int i;
02062   DLIList<int> geom_indices(geom_points.size());
02063   
02064   for (i = 0; i < geom_points.size(); i++ )
02065     geom_indices.append(i);
02066 
02067   for (i = facet_points.size(); i--; )
02068     facet_points.step_and_get()->marked(-1);
02069 
02070   geom_points.reset();
02071   facet_points.reset();
02072   while (geom_indices.size())
02073   {
02074     int index = geom_indices.pop();
02075     PartitionPoint* geom_pt = geom_points.next(index);
02076     const CubitVector pos(geom_pt->coordinates());
02077     double shortest_dist_sqr = CUBIT_DBL_MAX;
02078     int closest_index = -1;
02079     for (i = 0; i < facet_points.size(); i++ )
02080     {
02081       CubitPoint* facet_pt = facet_points.next(i);
02082       double dist_sqr = (pos - facet_pt->coordinates()).length_squared();
02083       if (dist_sqr < shortest_dist_sqr)
02084       {
02085         if (facet_pt->marked() == -1)
02086         {
02087           shortest_dist_sqr = dist_sqr;
02088           closest_index = i;
02089         }
02090         else 
02091         {
02092           int j = facet_pt->marked();
02093           CubitPoint* other_point = facet_points.next(j);
02094           double other_dist_sqr = (pos - other_point->coordinates()).length_squared();
02095           if (other_dist_sqr > dist_sqr)
02096           {
02097             shortest_dist_sqr = dist_sqr;
02098             closest_index = i;
02099             facet_pt->marked(-1);
02100             geom_indices.append(j);
02101           }
02102         }
02103       }
02104     }
02105     
02106     if (closest_index < 0)
02107     {
02108       assert(false);
02109       for (i = facet_points.size(); i--; )
02110         facet_points.step_and_get()->marked(0);
02111       for (i = geom_points.size(); i--; )
02112         geom_points.step_and_get()->mark = 0;
02113       return CUBIT_FAILURE;
02114     }
02115     geom_pt->mark = closest_index;
02116     facet_points.next(closest_index)->marked(index);
02117   }
02118   
02119   for (i = facet_points.size(); i--; )
02120     facet_points.step_and_get()->marked(0);
02121   
02122   facet_points.reset();
02123   for (i = geom_points.size(); i--; )
02124   {
02125     PartitionPoint* geom_pt = geom_points.step_and_get();
02126     CubitPoint* facet_pt = facet_points.next(geom_pt->mark);
02127     geom_pt->mark = 0;
02128     
02129     assert(!TDVGFacetOwner::get(facet_pt));
02130     facet_pt->set(geom_pt->coordinates());
02131     
02132     CubitPointData* point_data = dynamic_cast<CubitPointData*>(facet_pt);
02133     assert(!!point_data);
02134     
02135     if (geom_pt->facet_point())
02136       geom_pt->facet_point()->merge_points( point_data );
02137     else
02138       geom_pt->facet_point(point_data);
02139   }
02140   
02141   return CUBIT_SUCCESS;
02142 }
02143 
02144 //-------------------------------------------------------------------------
02145 // Purpose       : Get points and edges in facet patch, separated into
02146 //                 boundary and internal sets where a boundary point is
02147 //                 a point for which one or more adjacent edges is on the
02148 //                 boundary of the patch.
02149 //
02150 // Special Notes : Aborts and returns failure if the input facets are not
02151 //                 a manifold patch.
02152 //
02153 // Creator       : Jason Kraftcheck
02154 //
02155 // Creation Date : 09/08/03
02156 //-------------------------------------------------------------------------
02157 CubitStatus PartSurfFacetTool::get_facet_points_and_edges(
02158                                    const DLIList<CubitFacetData*>& facets,
02159                                    DLIList<CubitPoint*>& boundary_points,
02160                                    DLIList<CubitPoint*>& interior_points,
02161                                    DLIList<CubitFacetEdge*>& boundary_edges,
02162                                    DLIList<CubitFacetEdge*>& interior_edges )
02163 {
02164   int i, j;
02165   CubitStatus result = CUBIT_SUCCESS;
02166   CubitFacetData* facet;
02167   DLIList<CubitFacetEdge*> edge_list;
02168   const int count = facets.size();
02169   
02170     // Initialize marks
02171   for (i = 0; i < count; i++ )
02172   {
02173     facet = facets.next(i);
02174     for (j = 0; j < 3; j++)
02175     {
02176       facet->edge(j)->marked(0);
02177       facet->point(j)->marked(1);
02178     }
02179   }
02180   
02181     // Mark each edge with a count of the number of
02182     // adjcent facets.
02183   for (i = 0; i < count; i++ )
02184   {
02185     facet = facets.next(i);
02186     for (j = 0; j < 3; j++)
02187       facet->edge(j)->marked(facet->edge(j)->marked() + 1);
02188   }
02189   
02190     // Collect points and clear point marks
02191   for (i = 0; i < count; i++ )
02192   {
02193     facet = facets.next(i);
02194     for (j = 0; j < 3; j++)
02195     {
02196       CubitPoint* point = facet->point(j);
02197       if (!point->marked())
02198         continue;
02199       point->marked(0);
02200       
02201       point->edges(edge_list);
02202       bool boundary = false;
02203       while (edge_list.size())
02204         if (edge_list.pop()->marked() == 1)
02205           boundary = true;
02206       if (boundary)
02207         boundary_points.append(point);
02208       else 
02209         interior_points.append(point);
02210     }
02211   }
02212   
02213     // Collect edges and clear edge marks   
02214   for (i = 0; i < count; i++ )
02215   {
02216     facet = facets.next(i);
02217     for (j = 0; j < 3; j++)
02218     {
02219       CubitFacetEdge* edge = facet->edge(j);
02220       switch (edge->marked())
02221       {
02222         case 0:
02223           continue;
02224         case 1:
02225           boundary_edges.append(edge);
02226           break;
02227         case 2:
02228           interior_edges.append(edge);
02229           break;
02230         default:
02231           result = CUBIT_FAILURE;
02232           assert(false);
02233       }
02234       edge->marked(0);
02235     }
02236   }
02237   
02238   return result;
02239 }
02240 
02241 
02242 //-------------------------------------------------------------------------
02243 // Purpose       : Get facets adjacent to edge and owned by this surface.
02244 //
02245 // Special Notes : 
02246 //
02247 // Creator       : Jason Kraftcheck
02248 //
02249 // Creation Date : 12/07/03
02250 //-------------------------------------------------------------------------
02251 void PartSurfFacetTool::edge_facets( PartitionSurface* surf,
02252                                      CubitFacetEdge* edge,
02253                                      DLIList<CubitFacet*>& facets )
02254 {
02255   edge->facets(facets);
02256 
02257   for (int i = facets.size(); i--; )
02258     if (TDVGFacetOwner::get(facets.step_and_get()) != surf)
02259       facets.change_to(0);
02260   
02261   facets.remove_all_with_value(0);
02262 }
02263 
02264 
02265 
02266 //-------------------------------------------------------------------------
02267 // Purpose       : Get facets in passed list adjacent to passed edge
02268 //
02269 // Special Notes : 
02270 //
02271 // Creator       : Jason Kraftcheck
02272 //
02273 // Creation Date : 12/07/03
02274 //-------------------------------------------------------------------------
02275 void PartSurfFacetTool::edge_facets( CubitFacetEdge* edge,
02276                                     const DLIList<CubitFacet*>& input_facets,
02277                                     DLIList<CubitFacet*>& output_facets )
02278 {
02279   edge->facets(output_facets);
02280   output_facets.intersect( input_facets );
02281 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines