cgma
FacetDataUtil.cpp
Go to the documentation of this file.
00001 //- Class:       FacetDataUtil
00002 //- Description: static library of general functions for querying and/or
00003 //-              modifying facet entities
00004 //- Owner:       Steve Owen
00005 //- Checked by:
00006 //- Version:
00007 
00008 #include "FacetDataUtil.hpp"
00009 #include "FacetEvalTool.hpp"
00010 #include "CubitFacet.hpp"
00011 #include "CubitFacetEdge.hpp"
00012 #include "CubitPoint.hpp"
00013 #include "CubitPointData.hpp"
00014 #include "CubitFacetData.hpp"
00015 #include "CubitFacetEdgeData.hpp"
00016 #include "CubitQuadFacet.hpp"
00017 #include "GeometryDefines.h"
00018 #include "ChollaDebug.hpp"
00019 #include "GfxDebug.hpp"
00020 #include "KDDTree.hpp"
00021 
00022 //===========================================================================
00023 //Function Name: edges_by_count
00024 //Description:   find edges that are shared by "count" number of facets
00025 //Author: bwhanks
00026 //Date: 2003
00027 //===========================================================================
00028 void FacetDataUtil::edges_by_count(DLIList<CubitFacet*> &facets,
00029                                    unsigned int count,
00030                                    DLIList<CubitFacetEdge*> &edges)
00031 {
00032   int i;
00033   int j;
00034 
00035   // get a list of all edges from the facets
00036   DLIList<CubitFacetEdge*> edge_list;
00037   facets.reset();
00038   for (i=facets.size(); i>0; i--)
00039   {
00040     CubitFacet* p_facet = facets.get_and_step();
00041     for (j=0; j<3; j++)
00042     {
00043       edge_list.append(p_facet->edge(j));
00044     }
00045   }
00046 
00047   // reset edge marks
00048   edge_list.reset();
00049   for (i=edge_list.size(); i>0; i--)
00050     edge_list.get_and_step()->marked(0);
00051 
00052   // mark with the hit count
00053   edge_list.reset();
00054   for (i=edge_list.size(); i>0; i--)
00055   {
00056     CubitFacetEdge* p_edge = edge_list.get_and_step();
00057     p_edge->marked(p_edge->marked() + 1);
00058   }
00059 
00060   // create the output list of edges hit the number of times passed in
00061   edge_list.reset();
00062   for (i=edge_list.size(); i>0; i--)
00063   {
00064     CubitFacetEdge* p_edge = edge_list.get_and_step();
00065     if (static_cast<unsigned>(p_edge->marked()) == count)
00066       edges.append(p_edge);
00067   }
00068 
00069   // reset edge marks
00070   edge_list.reset();
00071   for (i=edge_list.size(); i>0; i--)
00072     edge_list.get_and_step()->marked(0);
00073 }
00074 
00075 //===========================================================================
00076 //Function Name: ordered_point_edge_bdry
00077 //Description:   get an ordered list of points and edges around the boundary
00078 //               of a set of facets. The output "chain" consists of point -
00079 //               edge - point - edge - ... around the boundary of the input
00080 //               facets.  Having the ordered points as well as the edges
00081 //               helps provides sense information for the bounding edges.
00082 //Author: bwhanks
00083 //Date: 2003
00084 //===========================================================================
00085 void FacetDataUtil::ordered_point_edge_bdry(DLIList<CubitFacet*> &facets,
00086                                             DLIList<FacetEntity*> &point_edge_chain)
00087 {
00088   assert(point_edge_chain.size() == 0);
00089   DLIList<CubitFacetEdge*> unordered_edges;
00090 
00091   int use_count = 1; // get boundary edges (used only once by facets in the facet list)
00092   FacetDataUtil::edges_by_count(facets, use_count, unordered_edges);
00093 
00094 //  Adds the start_edge to the list of boundary_edges and then attempts to find the
00095 //  next edge by getting all of the edges belonging to the second point on this
00096 //  edge and searching for an unmarked (-1) boundary edge.  Does this until it can't
00097 //  find another edge.
00098 
00099 
00100   // mark all edges connected to points of boundary edges with -2
00101   // NOTE: using negative marks, since as boundary edges are added to the ordered list they
00102   // get marked with the order in which they are found
00103 
00104   // TODO - this seems very inefficient
00105   int i;
00106   int j;
00107   int k;
00108   DLIList<CubitFacetEdge*> pt_edge_list;
00109   CubitFacetEdge* cur_edge;
00110   unordered_edges.reset();
00111   for (i=unordered_edges.size(); i>0; i--)
00112   {
00113     cur_edge = unordered_edges.get_and_step();
00114     for (j=0; j<2; j++)
00115     {
00116       pt_edge_list.clean_out();
00117       cur_edge->point(j)->edges(pt_edge_list);
00118       pt_edge_list.reset();
00119       for (k=pt_edge_list.size(); k>0; k--)
00120         pt_edge_list.get_and_step()->marked(-2);
00121     }
00122   }
00123 
00124   // mark all boundary edges with -1
00125   unordered_edges.reset();
00126   for (i=unordered_edges.size(); i>0; i--)
00127     unordered_edges.get_and_step()->marked(-1);
00128 
00129 
00130 
00131 
00132   CubitPoint *edge_pt1, *edge_pt2, *pt2, *originalpt1;
00133   CubitFacetEdge *start_edge;
00134   CubitFacetEdge *this_edge;
00135   CubitBoolean keepgoing;
00136 
00137   int i_found_some = 0;
00138   unordered_edges.reset();
00139   start_edge = unordered_edges.get();
00140 
00141   // find the orientation of the first edge with respect to one of the facets
00142   // then order the edges accordingly
00143   facets.reset();
00144   int e_index;
00145   int start_edge_sense = 0;
00146   for (i=facets.size(); i>0; i--)
00147   {
00148     CubitFacet* p_facet = facets.get_and_step();
00149     if ( (e_index = p_facet->edge_index(start_edge)) >= 0 )
00150     {
00151       start_edge_sense = p_facet->edge_use(e_index);
00152       break;
00153     }
00154   }
00155 
00156 
00157   start_edge->marked(i_found_some);
00158   i_found_some += 1;
00159   if (1 == start_edge_sense)
00160   {
00161     originalpt1 = start_edge->point(0);
00162     point_edge_chain.append(originalpt1);
00163     point_edge_chain.append(start_edge);
00164     pt2 = start_edge->point(1);
00165   }
00166   else
00167   {
00168     assert(-1 == start_edge_sense);
00169     originalpt1 = start_edge->point(1);
00170     point_edge_chain.append(originalpt1);
00171     point_edge_chain.append(start_edge);
00172     pt2 = start_edge->point(0);
00173   }
00174 
00175 
00176 //  Look for an edge having pt2 as a point and also being on the boundary.
00177   pt_edge_list.clean_out();
00178   pt2->edges(pt_edge_list);
00179 
00180   keepgoing = CUBIT_TRUE;
00181   pt_edge_list.reset();
00182   while ( keepgoing == CUBIT_TRUE ) {
00183     keepgoing = CUBIT_FALSE;
00184     for ( i = pt_edge_list.size(); i > 0; i-- ) {
00185       this_edge = pt_edge_list.get_and_step();
00186       if ( this_edge->marked() == -1 ) {
00187         i_found_some += 1;
00188         this_edge->marked(i_found_some);
00189         point_edge_chain.append(pt2);
00190         point_edge_chain.append(this_edge);
00191 
00192         edge_pt1 = this_edge->point(0);
00193         edge_pt2 = this_edge->point(1);
00194         if (pt2 == edge_pt1)
00195         {
00196           pt2 = edge_pt2;
00197         }
00198         else
00199         {
00200           assert(pt2 == edge_pt2);
00201           pt2 = edge_pt1;
00202         }
00203 
00204 
00205           keepgoing = CUBIT_TRUE;
00206           pt_edge_list.clean_out();
00207         pt2->edges(pt_edge_list);
00208           break;
00209       }
00210     }
00211   }
00212   
00213   // clear marks
00214   for (i=unordered_edges.size(); i>0; i--)
00215   {
00216     cur_edge = unordered_edges.get_and_step();
00217     for (j=0; j<2; j++)
00218     {
00219       pt_edge_list.clean_out();
00220       cur_edge->point(j)->edges(pt_edge_list);
00221       pt_edge_list.reset();
00222       for (k=pt_edge_list.size(); k>0; k--)
00223         pt_edge_list.get_and_step()->marked(0);
00224     }
00225   }
00226 
00227   assert(pt2 == originalpt1);
00228 }
00229 
00230 //===========================================================================
00231 //Function Name: partial_chain
00232 //Description:   given an ordered point - edge boundary and a start and end
00233 //               point on the boundary, return the point - edge chain between
00234 //               the two points, inclusive.
00235 //Author: bwhanks
00236 //Date: 2003
00237 //===========================================================================
00238 CubitStatus FacetDataUtil::partial_chain(DLIList<FacetEntity*> &point_edge_chain,
00239                                          FacetEntity* point1,
00240                                          FacetEntity* point2,
00241                                          DLIList<FacetEntity*> &chain_between)
00242 {
00243   // make sure the edges_between list is empty
00244   assert(chain_between.size() == 0);
00245   assert(point1 != point2);
00246 
00247   // find the start point in the list
00248   int pt1_index = point_edge_chain.where_is_item(point1);
00249 
00250   if (-1 == pt1_index)
00251     return CUBIT_FAILURE;
00252 
00253   point_edge_chain.reset();
00254   point_edge_chain.step(pt1_index);
00255 
00256   CubitBoolean b_done = CUBIT_FALSE;
00257   while (!b_done)
00258   {
00259     if (point_edge_chain.get() == point2)
00260       b_done = CUBIT_TRUE;
00261 
00262     chain_between.append(point_edge_chain.get_and_step());
00263   }
00264 
00265   return CUBIT_SUCCESS;
00266 }
00267 
00268 //===========================================================================
00269 //Function Name: get_facet_points
00270 //Description:   return a unique list of the points from a given set of facets
00271 //Author: bwhanks
00272 //Date: 2003
00273 //===========================================================================
00274 void FacetDataUtil::get_facet_points(DLIList<CubitFacet*> &cubit_facets,
00275                                      DLIList<CubitPoint*> &facet_points)
00276 {
00277   int i;
00278   DLIList<CubitPoint*> cubit_points(cubit_facets.size() * 3);
00279   for( i = cubit_facets.size(); i--; )
00280   {
00281     CubitFacet* facet = cubit_facets.step_and_get();
00282     for( int j = 0; j < 3; j++ )
00283     {
00284       CubitPoint* pt = dynamic_cast<CubitPoint*>(facet->point(j));
00285       assert(!!pt);
00286       pt->marked(0);
00287       cubit_points.append(pt);
00288     }
00289   }
00290   for( i = cubit_points.size(); i--; )
00291   {
00292     CubitPoint* pt = cubit_points.step_and_get();
00293     pt->marked( pt->marked() + 1);
00294   }
00295   for( i = cubit_points.size(); i--; )
00296   {
00297     CubitPoint* pt = cubit_points.step_and_get();
00298     pt->marked( pt->marked() - 1 );
00299     if( pt->marked() > 0 )
00300       cubit_points.change_to(0);
00301   }
00302   cubit_points.remove_all_with_value(0);
00303 
00304   facet_points = cubit_points;
00305 }
00306 
00307 //===========================================================================
00308 //Function Name: get_boundary_points
00309 //Description:   return the boundary points from a list of facets (unordered)
00310 //               assumes edges exist on the facets
00311 //Author: bwhanks
00312 //Date: 2003
00313 //===========================================================================
00314 void FacetDataUtil::get_boundary_points(DLIList<CubitFacet*> &facet_list,
00315                                         DLIList<CubitPoint*> &point_list)
00316 {
00317   int ii, jj;
00318   CubitPoint *pt;
00319   CubitFacetEdge *edge;
00320   CubitFacet *facet;
00321   DLIList<CubitFacetEdge *>edge_list;
00322   for(ii=0; ii<facet_list.size(); ii++)
00323   {
00324     facet = facet_list.get_and_step();
00325     for(jj=0; jj<3; jj++)
00326     {
00327       edge = facet->edge( jj );
00328       if (1 == edge->num_adj_facets())
00329       {
00330         edge_list.append(edge);
00331         edge->point( 0 )->marked( 0 );
00332         edge->point( 1 )->marked( 0 );
00333       }
00334     }
00335   }
00336   for(ii=0; ii<edge_list.size(); ii++)
00337   {
00338     edge = edge_list.get_and_step();
00339     pt = edge->point( 0 );
00340     if (pt->marked() == 0)
00341     {
00342       pt->marked( 1 );
00343       point_list.append( pt );
00344     }
00345     pt = edge->point( 1 );
00346     if (pt->marked() == 0)
00347     {
00348       pt->marked( 1 );
00349       point_list.append( pt );
00350     }
00351   }
00352   for(ii=0; ii<point_list.size(); ii++)
00353     point_list.get_and_step()->marked(0);
00354 
00355 }
00356 
00357 //===========================================================================
00358 //Function Name: get_boundary_edges
00359 //Description: return an unordered list of edges at the boundary of a
00360 //             set of facets
00361 //Author: sjowen
00362 //Date: 1/19/2004
00363 //===========================================================================
00364 void FacetDataUtil::get_boundary_edges(DLIList<CubitFacet*> &facet_list,
00365                                        DLIList<CubitFacetEdge*> &edge_list)
00366 {
00367   int ii, jj;
00368   CubitFacetEdge *edge;
00369   CubitFacet *facet;
00370   for(ii=0; ii<facet_list.size(); ii++)
00371   {
00372     facet = facet_list.get_and_step();
00373     for(jj=0; jj<3; jj++)
00374     {
00375       edge = facet->edge( jj );
00376       if (1 == edge->num_adj_facets())
00377       {
00378         edge_list.append(edge);
00379       }
00380     }
00381   }
00382 }
00383 
00384 //===========================================================================
00385 //Function Name: get_points
00386 //Description:   get a unique set of points from facets
00387 //Author: sjowen
00388 //Date: 9/11/03
00389 //===========================================================================
00390 void FacetDataUtil::get_points(DLIList<CubitFacet*> &facet_list,
00391                                DLIList<CubitPoint*> &point_list)
00392 {
00393   CubitFacet *facet;
00394   CubitPoint *pt;
00395   int ii, jj;
00396   for(ii=0; ii<facet_list.size(); ii++)
00397   {
00398     facet = facet_list.get_and_step();
00399     facet->point( 0 )->marked( 0 );
00400     facet->point( 1 )->marked( 0 );
00401     facet->point( 2 )->marked( 0 );
00402   }
00403 
00404   for (ii=0; ii<facet_list.size(); ii++)
00405   {
00406     facet = facet_list.get_and_step();
00407     for(jj=0; jj<3; jj++)
00408     {
00409       pt = facet->point(jj);
00410       if (pt->marked() == 0)
00411       {
00412         pt->marked(1);
00413         point_list.append(pt);
00414       }
00415     }
00416   }
00417 
00418   for(ii=0; ii<facet_list.size(); ii++)
00419   {
00420     facet = facet_list.get_and_step();
00421     facet->point( 0 )->marked( 0 );
00422     facet->point( 1 )->marked( 0 );
00423     facet->point( 2 )->marked( 0 );
00424   }
00425 }
00426 
00427 //===========================================================================
00428 //Function Name: copy_facets
00429 //Description:  make a complete copy of facets, points and edges
00430 //Note:  copies edges and points with their "feature" flag
00431 //Author: sjowen
00432 //Date: 9/11/03
00433 //===========================================================================
00434 void FacetDataUtil::copy_facets(DLIList<CubitFacet*> &old_facet_list,
00435                                 DLIList<CubitFacet*> &new_facet_list,
00436                                 DLIList<CubitPoint*> &new_point_list,
00437                                 DLIList<CubitFacetEdge*> &new_edge_list)
00438 {
00439   // get a unique set of points from the facets
00440 
00441   DLIList<CubitPoint *> old_point_list;
00442   get_points(old_facet_list, old_point_list);
00443   CubitPoint **point_array = new CubitPoint* [old_point_list.size()];
00444 
00445   //- copy the points
00446 
00447   int ii;
00448   old_point_list.reset();
00449   CubitPoint *new_point, *the_point;
00450   for(ii=0; ii<old_point_list.size(); ii++)
00451   {
00452     the_point = old_point_list.get_and_step();
00453     new_point = new CubitPointData( the_point->coordinates() );
00454     the_point->marked( ii );
00455     new_point_list.append( new_point );
00456     point_array[ii] = new_point;
00457     if (the_point->is_feature())
00458       new_point->set_as_feature();
00459   }
00460 
00461   //- copy the facets
00462 
00463   int jj, idx;
00464   CubitFacet *new_facet, *the_facet;
00465   CubitPoint *points[3];
00466 
00467   old_facet_list.reset();
00468   for (ii=0; ii<old_facet_list.size(); ii++)
00469   {
00470     the_facet = old_facet_list.get_and_step();
00471     for (jj=0; jj<3; jj++)
00472     {
00473       idx = the_facet->point(jj)->marked();
00474       points[jj] = point_array[idx];
00475     }
00476     new_facet = new CubitFacetData( points[0], points[1], points[2] );
00477     new_facet_list.append( new_facet );
00478   }
00479 
00480   //- copy the edges
00481 
00482   int idx0, idx1;
00483   CubitFacetEdge *new_edge;
00484   CubitFacetEdge *old_edge;
00485   DLIList<CubitFacetEdge *>old_edge_list;
00486   get_edges(old_facet_list, old_edge_list);
00487   for(ii=0; ii<old_edge_list.size(); ii++)
00488   {
00489     old_edge = old_edge_list.get_and_step();
00490     idx0 = old_edge->point(0)->marked();
00491     idx1 = old_edge->point(1)->marked();
00492     new_edge = new CubitFacetEdgeData( point_array[idx0], point_array[idx1] );
00493     if (old_edge->is_feature())
00494       new_edge->set_as_feature();
00495     new_edge_list.append( new_edge );
00496   }
00497 
00498   delete [] point_array;
00499 
00500 }
00501 
00502 //===========================================================================
00503 //Function Name: get_edges
00504 //Description:  Populates the edge list from the list of facets - creates the
00505 //              edges if necessary
00506 //Author: sjowen
00507 //Date: 9/11/03
00508 //===========================================================================
00509 void FacetDataUtil::get_edges(
00510   DLIList<CubitFacet *> &facet_list,
00511   DLIList<CubitFacetEdge *> &edge_list )
00512 {
00513   int i, j;
00514   CubitPoint *p0, *p1;
00515   CubitFacet *facet_ptr;
00516   CubitFacetEdge *edge_ptr;
00517   DLIList<CubitFacet *> adj_facet_list;
00518 
00519   // mark the edges and create any that are missing
00520   facet_list.reset();  //have to reset this list to that the CubitFacetEdgeData's
00521                          //get constructed correctly
00522   for ( i = 0; i < facet_list.size(); i++)
00523   {
00524     facet_ptr = facet_list.get_and_step();
00525     for (j=0; j<3; j++) {
00526       edge_ptr = facet_ptr->edge(j);
00527       if (!(edge_ptr))
00528       {
00529         facet_ptr->get_edge_pts(j, p0, p1);
00530         edge_ptr = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 );
00531       }
00532       edge_ptr->set_flag( 0 );
00533     }
00534   }
00535 
00536   // create a unique list of edges
00537 
00538   for ( i = 0; i < facet_list.size(); i++)
00539   {
00540     facet_ptr = facet_list.get_and_step();
00541     for (j=0; j<3; j++)
00542     {
00543       edge_ptr = facet_ptr->edge(j);
00544       if(edge_ptr && 0 == edge_ptr->get_flag())
00545       {
00546         edge_ptr->set_flag( 1 );
00547         edge_list.append( edge_ptr );
00548       }
00549     }
00550   }
00551 
00552   // reset the flags on the edges
00553 
00554   for ( i = 0; i < facet_list.size(); i++)
00555   {
00556     facet_ptr = facet_list.get_and_step();
00557     for (j=0; j<3; j++)
00558     {
00559       edge_ptr = facet_ptr->edge(j);
00560       if( edge_ptr )
00561         edge_ptr->set_flag( 0 );
00562     }
00563   }
00564 }
00565 
00566 //============================================================================
00567 // Function: quality
00568 // Author: sjowen
00569 // Description: this is the S.H. Lo metric for triangles that also takes into
00570 //               account a surface normal.
00571 // Date: 2/2003
00572 //============================================================================
00573 double FacetDataUtil::quality(CubitVector &c1, CubitVector &c2, CubitVector &c3,
00574                               CubitVector &surf_normal)
00575 {
00576 #define TWO_ROOT_THREE  3.46410161514
00577    double area2, alpha;
00578    double length1, length2, length3;
00579    CubitVector edge1, edge2, edge3;
00580 
00581    // create edges from the vertices
00582 
00583    edge1 = c3 - c2;
00584    edge2 = c3 - c1;
00585    edge3 = c2 - c1;
00586 
00587    // compute twice the area
00588 
00589    CubitVector normal = edge3 * edge2;
00590    area2 = normal.length();
00591 
00592    length1 = edge1.length_squared();
00593    length2 = edge2.length_squared();
00594    length3 = edge3.length_squared();
00595 
00596    alpha = TWO_ROOT_THREE * area2 / (length1 + length2 + length3);
00597 
00598    // modify the alpha metric by the dot product of the triangle normal
00599    // with the surface normal.
00600 
00601    if (fabs(area2) < CUBIT_RESABS)
00602      alpha = 0.0;
00603    else
00604    {
00605      normal /= area2;
00606      double dot = normal % surf_normal;
00607      double penalty = pow(dot, 5);
00608      alpha *= penalty;
00609    }
00610 
00611    return alpha;
00612 }
00613 
00614 //================================================================================
00615 // Description: compares length of two edges.
00616 // Notes:       used for DLIList sort
00617 // Author     : Steve Owen
00618 // Date       : 9/27/2003
00619 //================================================================================
00620 int FacetDataUtil::edge_compare(CubitFacetEdge *&ea, CubitFacetEdge *&eb)
00621 {
00622   double la = ea->length();
00623   double lb = eb->length();
00624   if (la < lb)
00625     return -1;
00626   else if (lb < la)
00627     return 1;
00628   return 0;
00629 }
00630 
00631 //================================================================================
00632 // Description: collapse edges that are smaller than 10% the average length
00633 // Notes:       non_manifold_only=true indicates that only edges that are attached
00634 //              to more than two edges will be candidates for collapse.
00635 // Author     : Steve Owen
00636 // Date       : 9/27/2003
00637 //================================================================================
00638 CubitStatus FacetDataUtil::collapse_short_edges(
00639   DLIList<CubitFacet*> &facet_list,
00640   CubitBoolean non_manifold_only)
00641 {
00642 #define COLLAPSE_TOLERANCE 0.3
00643 
00644   CubitStatus rv = CUBIT_SUCCESS;
00645   int ncollapse = 0;
00646 
00647   // get the edges
00648 
00649   DLIList <CubitFacetEdge *>edge_list;
00650   DLIList <CubitPoint *> point_list;
00651   DLIList <CubitFacet *> one_facet;
00652   DLIList <CubitFacetEdge *> facet_edges;
00653   FacetDataUtil::get_edges( facet_list, edge_list );
00654   FacetDataUtil::get_points( facet_list, point_list );
00655 
00656   // determine average length and get the collapse threshold
00657 
00658   int ii, jj, kk;
00659   double len;
00660   double tot_len = 0.0;
00661   for(ii=0; ii<point_list.size(); ii++)
00662     point_list.get_and_step()->marked(0);
00663   CubitFacetEdge *edge;
00664   for(ii=0; ii<edge_list.size(); ii++)
00665   {
00666     edge = edge_list.get_and_step();
00667     len = edge->length();
00668     tot_len += len;
00669     edge->marked(0);
00670   }
00671   len = tot_len / edge_list.size();
00672   double collapse_tol = COLLAPSE_TOLERANCE * len;
00673   //check(edge_list, facet_list);
00674 
00675   // get a list of the edges that qualify for collapse
00676 
00677   DLIList<CubitFacetEdge *>short_edges;
00678   for(ii=0; ii<edge_list.size(); ii++)
00679   {
00680     edge = edge_list.get_and_step();
00681     if (non_manifold_only && edge->num_adj_facets() == 2)
00682       continue;
00683     len = edge->length();
00684     if (len < collapse_tol)
00685     {
00686       short_edges.append(edge);
00687     }
00688   }
00689   //sort them
00690 
00691   short_edges.sort(FacetDataUtil::edge_compare);
00692 
00693   // main loop
00694 
00695   int nedges = short_edges.size();
00696   for(ii=0; ii<nedges; ii++)
00697   {
00698     edge = short_edges.get_and_step();
00699     if (edge->marked() == 1)
00700       continue;
00701     len = edge->length();
00702 
00703     bool collapse = true;
00704     CubitPoint *pt[2];
00705     CubitPoint *pt1, *pt2;
00706     pt[0] = edge->point(0);
00707     pt[1] = edge->point(1);
00708 
00709     // compute a new candidate location for the merged points
00710 
00711     CubitVector new_location;
00712     CubitVector cpt[2];
00713     cpt[0] = pt[0]->coordinates();
00714     cpt[1] = pt[1]->coordinates();
00715     new_location = (cpt[0] + cpt[1]) * 0.5;
00716 
00717     for (jj=0; jj<2 && collapse; jj++)
00718     {
00719       DLIList<CubitFacet *> adjfacets;
00720       pt[jj]->facets( adjfacets );
00721 
00722       // check all facets adjacent this point that don't contain the edge
00723       // to make sure the resulting facet will be valid (we aren't inverting anything)
00724 
00725       for(kk=0; kk<adjfacets.size() && collapse; kk++)
00726       {
00727         CubitFacet *facet = adjfacets.get_and_step();
00728         pt1 = facet->next_node( pt[jj] );
00729         pt2 = facet->next_node( pt1 );
00730         int eidx = facet->edge_index( edge );
00731         if (eidx < 0)
00732           // don't check facets that have the current edge - they'll be deleted anyway
00733         {
00734 
00735           CubitVector cpt1 = pt1->coordinates();
00736           CubitVector cpt2 = pt2->coordinates();
00737           CubitVector norm = facet->normal();
00738           double q0 = FacetDataUtil::quality(cpt[jj], cpt1, cpt2, norm);
00739           double q1 = FacetDataUtil::quality(new_location, cpt1, cpt2, norm);
00740           if (!(q1 > 0.0 || q1 > q0))
00741           {
00742             collapse = false;
00743           }
00744         }
00745       }
00746     }
00747 
00748     if (collapse)
00749     {
00750       DLIList<CubitFacet *> new_facets;
00751       CubitPoint *collpt = pt[0];
00752       CubitPoint *delpt = pt[1];
00753       DLIList<CubitFacetEdge *> adjedges;
00754       CubitFacetEdge *adjedge;
00755       delpt->edges( adjedges );
00756       CubitFacet *facet;
00757 
00758 
00759       int mydebug = 0;
00760       if (mydebug)
00761       {
00762         dcolor(4);
00763         draw_edge( edge );
00764         dview();
00765       }
00766 
00767       collpt->set(new_location);
00768 
00769       // delete all facets adjacent to the delpt.
00770 
00771       DLIList<CubitFacet *> adjfacets;
00772       delpt->facets( adjfacets );
00773 
00774       for(jj=0; jj<adjfacets.size(); jj++)
00775       {
00776         facet = adjfacets.get_and_step();
00777         pt1 = facet->next_node(delpt);
00778         pt2 = facet->next_node(pt1);
00779         int eidx = facet->edge_index( edge );
00780         facet_list.move_to(facet);
00781         delete facet;
00782         facet = NULL;
00783         if (eidx >= 0)
00784         {
00785           //if this facet is adjecnt the edge, then just remove it from the list
00786           facet_list.extract();
00787         }
00788         else
00789         {
00790 
00791           // get or create edges as needed
00792 
00793           CubitFacetEdge *e[3];
00794           e[0] = collpt->get_edge( pt1 );
00795           e[1] = pt1->get_edge( pt2 );
00796           e[2] = pt2->get_edge( collpt );
00797           for (kk=0; kk<3; kk++)
00798           {
00799             if (!(e[kk]))
00800             {
00801               switch (kk)
00802               {
00803               case 0: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( collpt, pt1 ); break;
00804               case 1: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt1, pt2 ); break;
00805               case 2: e[kk] = (CubitFacetEdge *) new CubitFacetEdgeData( pt2, collpt ); break;
00806               }
00807               edge_list.append( e[kk] );
00808             }
00809           }
00810 
00811           // create a new facet with the points from the old facet and the collpt
00812 
00813           facet = new CubitFacetData( e[0], e[1], e[2] );
00814           new_facets.append(facet);
00815 
00816           // create edges on the facet
00817 
00818           facet_list.change_to( facet );
00819         }
00820       }
00821 
00822       for(jj=0; jj<adjedges.size(); jj++)
00823       {
00824         adjedge = adjedges.get_and_step();
00825         adjedge->marked(1);  // mark it for deletion later
00826         assert(adjedge->num_adj_facets() == 0);
00827       }
00828       assert(delpt->num_adj_facets() == 0);
00829       ncollapse++;
00830 
00831       //check(edge_list, facet_list);
00832     }
00833 
00834   }
00835 
00836   PRINT_INFO("Collapsed %d short edges in triangulation\n", ncollapse);
00837 
00838   // delete points and edges that aren't used
00839   if (ncollapse > 0)
00840   {
00841     for(ii=0; ii<edge_list.size(); ii++)
00842     {
00843       edge = edge_list.get_and_step();
00844       if (edge->marked())
00845       {
00846         assert(edge->num_adj_facets() == 0);
00847         delete edge;
00848       }
00849       else if(edge->num_adj_facets() < 2){
00850         PRINT_ERROR("Unexpected result while collapsing an edge.\n");
00851         return CUBIT_FAILURE;
00852           //assert(edge->num_adj_facets() >= 2);
00853       }
00854     }
00855     CubitPoint *point;
00856     for(ii=0; ii<point_list.size(); ii++)
00857     {
00858       point = point_list.get_and_step();
00859       if (point->num_adj_facets() == 0)
00860       {
00861         delete point;
00862       }
00863     }
00864   }
00865 
00866   return rv;
00867 }
00868 
00869 //===========================================================================
00870 //  Function: check
00871 //  Purpose:  debugging only
00872 //  Date:     10/2003
00873 //  Author:   sjowen
00874 //===========================================================================
00875 void FacetDataUtil::check(DLIList<CubitFacetEdge *> &edge_list,
00876                           DLIList<CubitFacet *> &facet_list)
00877 {
00878 
00879   CubitBox box;
00880   CubitFacetEdge *edge;
00881   int ii;
00882   int nedges = 0;
00883   for(ii=0; ii<edge_list.size(); ii++)
00884   {
00885     edge = edge_list.get_and_step();
00886     if (edge->marked() == 1)
00887       continue;
00888     int nadj = edge->num_adj_facets();
00889     if (nadj <= 1)
00890     {
00891       CubitVector v0 = edge->point(0)->coordinates();
00892       CubitVector v1 = edge->point(1)->coordinates();
00893       CubitVector min(CUBIT_MIN(v0.x(), v1.x()), CUBIT_MIN(v0.y(), v1.y()), CUBIT_MIN(v0.z(), v1.z()));
00894       CubitVector max(CUBIT_MAX(v0.x(), v1.x()), CUBIT_MAX(v0.y(), v1.y()), CUBIT_MAX(v0.z(), v1.z()));
00895       CubitBox ebox(min, max);
00896       if (nedges == 0)
00897         box.reset(min, max);
00898       else
00899         box |= ebox;
00900 //      dcolor(3);
00901 //      dfldraw(facet_list);
00902       dcolor(4);
00903       dedraw(edge);
00904       dpoint(v0);
00905       dpoint(v1);
00906       nedges++;
00907     }
00908   }
00909   if (nedges > 0)
00910   {
00911     dzoom(box);
00912     dview();
00913   }
00914 }
00915 
00916 //===========================================================================
00917 //  Function: draw_edge
00918 //  Purpose:
00919 //  Date:     10/2003
00920 //  Author:   sjowen
00921 //===========================================================================
00922 void FacetDataUtil::draw_edge( CubitFacetEdge *edge )
00923 {
00924   DLIList<CubitFacet *>adjfacets;
00925   edge->facets( adjfacets );
00926   int ii,jj;
00927   CubitFacet *facet;
00928   CubitBox box;
00929   for(jj=0; jj<2; jj++)
00930   {
00931     CubitPoint *p = edge->point(jj);
00932     adjfacets.clean_out();
00933     p->facets( adjfacets );
00934     for(ii=0; ii<adjfacets.size(); ii++)
00935     {
00936       facet = adjfacets.get_and_step();
00937       if (jj==0 && ii==0)
00938         box = facet->bounding_box();
00939       else
00940         box |= facet->bounding_box();
00941       dfdraw(facet);
00942     }
00943     dpoint(p->coordinates());
00944     dpoint(p->coordinates());
00945   }
00946   dzoom(box);
00947 }
00948 
00949 //=============================================================================
00950 //Function:  is_point_in_polyhedron
00951 //Description: point-in-polyhedron test; polyhedron must be water-tight,
00952 //             manifold, triangle-tiled.  Casts a random ray in positive
00953 //             x, y, and z.  Counts crossings.  Starts over with a recast
00954 //             if a triangle is perpendicular to the ray or if the ray
00955 //             hits a triangle edge or vertex.
00956 //             Also tests for point on polyhedron.
00957 //Author: John Fowler
00958 //Date: 9/30/03
00959 //=============================================================================
00960 CubitStatus FacetDataUtil::is_point_in_polyhedron(
00961                                      DLIList<CubitFacet *> &tfacet_list,
00962                                      CubitVector &point_coords,
00963                                      CubitPointContainment &is_point_in)
00964 {
00965 unsigned int i;
00966 CubitBox bbox;
00967 CubitFacet *facet;
00968 CubitVector bbox_min, bbox_max, ray;
00969 CubitStatus status;
00970 CubitPointContainment pt_status;
00971 bool is_outside, recast, is_on_plane;
00972 double xpt, ypt, zpt;
00973 double rayx, rayy, rayz;
00974 int number_of_recasts;
00975 
00976   point_coords.get_xyz(xpt, ypt, zpt);
00977   recast = true;
00978   number_of_recasts = 0;
00979   while ( (recast == true) && (number_of_recasts < 10) ) {
00980     recast = false;
00981     is_outside = true;
00982     random_positive_ray(ray); // a random positively-pointing ray
00983     ray.get_xyz(rayx,rayy,rayz);
00984     for ( i = tfacet_list.size(); i > 0; i-- ) {
00985       facet = tfacet_list.get_and_step();
00986       bbox = facet->bounding_box();
00987       bbox_min = bbox.minimum();
00988       bbox_max = bbox.maximum();
00989       //  Because the ray is positive in direction, discard bounding boxes
00990       //  that are entirely < the starting point.
00991       if ( (xpt-bbox_max.x()) > CUBIT_RESABS ) continue;
00992       if ( (ypt-bbox_max.y()) > CUBIT_RESABS ) continue;
00993       if ( (zpt-bbox_max.z()) > CUBIT_RESABS ) continue;
00994       if ( ray_intersects_boundingbox(point_coords,ray,bbox) == false )
00995         continue;
00996       CubitPlane plane = facet->plane();
00997       CubitVector normal = plane.normal();
00998       double xnorm, ynorm, znorm;
00999       xnorm = normal.x();
01000       ynorm = normal.y();
01001       znorm = normal.z();
01002       //  Intersect the ray with the facet plane.  If ray is perpendicular to
01003       //  facet plane and point is on it, recast the ray and try again.
01004       double denominator = rayx*xnorm + rayy*ynorm + rayz*znorm;
01005       double distanc = xnorm*xpt + ynorm*ypt + znorm*zpt + plane.coefficient();
01006       if ( fabs(denominator) < GEOMETRY_RESABS )
01007       {
01008         if ( fabs(distanc) < GEOMETRY_RESABS ) {
01009           recast = true;
01010       break;
01011     } else continue;  // point is not on plane and ray is parallel to plane
01012       }
01013       double t, xintpt, yintpt, zintpt;
01014       t = -distanc;
01015       t /= denominator;
01016       if ( fabs(t) < GEOMETRY_RESABS ) is_on_plane = true;
01017       else if ( t < GEOMETRY_RESABS ) continue;
01018       else is_on_plane = false;
01019       xintpt = xpt + t*rayx;
01020       yintpt = ypt + t*rayy;
01021       zintpt = zpt + t*rayz;
01022       CubitPoint *pt;
01023       //  We need to project the triangle onto 2D.  Use the smaller components of
01024       //  the normal to detemine a good projection.
01025       double x0, y0, x1, y1, x2, y2;
01026       if ( (fabs(xnorm) >= fabs(ynorm)) && (fabs(xnorm) >= fabs(znorm)) ){  //  Use y,z
01027         pt = facet->point(0);
01028         x0 = pt->y(); y0 = pt->z();
01029         pt = facet->point(1);
01030         x1 = pt->y(); y1 = pt->z();
01031         pt = facet->point(2);
01032         x2 = pt->y(); y2 = pt->z();
01033         status = pt_in_tri_2d(yintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status);
01034       } else if (fabs(ynorm) >= fabs(znorm)) {  //  Use z,x
01035         pt = facet->point(0);
01036         x0 = pt->x(); y0 = pt->z();
01037         pt = facet->point(1);
01038         x1 = pt->x(); y1 = pt->z();
01039         pt = facet->point(2);
01040         x2 = pt->x(); y2 = pt->z();
01041         status = pt_in_tri_2d(xintpt,zintpt,x0,y0,x1,y1,x2,y2,pt_status);
01042       } else {  // Use x,y
01043         pt = facet->point(0);
01044         x0 = pt->x(); y0 = pt->y();
01045         pt = facet->point(1);
01046         x1 = pt->x(); y1 = pt->y();
01047         pt = facet->point(2);
01048         x2 = pt->x(); y2 = pt->y();
01049         status = pt_in_tri_2d(xintpt,yintpt,x0,y0,x1,y1,x2,y2,pt_status);
01050       }
01051 
01052       if ( status == CUBIT_FAILURE ) {
01053         recast = true;
01054     break;
01055       }
01056       if ( pt_status == CUBIT_PNT_OUTSIDE ) continue;
01057       //  Is the point on the triangle?
01058       if ( is_on_plane == true ) {
01059         is_point_in = CUBIT_PNT_BOUNDARY;
01060         return CUBIT_SUCCESS;
01061       }
01062       if ( pt_status == CUBIT_PNT_INSIDE ) is_outside = ! is_outside;
01063       else if ( pt_status == CUBIT_PNT_BOUNDARY ) {
01064         recast = true;
01065         break;
01066       }
01067     }
01068     if ( recast == true ) {
01069       tfacet_list.reset();
01070       number_of_recasts += 1;
01071     }
01072   }
01073   if ( recast == true ) {
01074     PRINT_ERROR("Number of recasts in point-in-polygon exceeded 10.\n");
01075     return CUBIT_FAILURE;
01076   }
01077   if ( is_outside == false ) is_point_in = CUBIT_PNT_INSIDE;
01078   else is_point_in = CUBIT_PNT_OUTSIDE;
01079 
01080   return CUBIT_SUCCESS;
01081 }
01082 
01083 //===========================================================================
01084 //  Function: pt_in_tri_2d
01085 //  Purpose:
01086 //  Date:     10/2003
01087 //  Author:   John Fowler
01088 //===========================================================================
01089 CubitStatus FacetDataUtil::pt_in_tri_2d(double xpt, double ypt,
01090                        double x0, double y0,
01091                double x1, double y1,
01092                double x2, double y2,
01093                CubitPointContainment &is_point_in)
01094 {
01095 //  From Schneider & Eberly, "Geometric Tools for COmputer Graphics",
01096 //  Chap. 13.3.1.  If triangle is needle-thin, CUBIT_FAILURE might be
01097 //  returned, in wich case is_point_in is undefined.
01098 
01099 double c0, c1, c2;
01100 double e0x, e1x, e2x, e0y, e1y, e2y;
01101 double n0x, n1x, n2x, n0y, n1y, n2y;
01102 double denom0, denom1, denom2;
01103 
01104   e0x = x1 - x0; e0y = y1 - y0;
01105   e1x = x2 - x1; e1y = y2 - y1;
01106   e2x = x0 - x2; e2y = y0 - y2;
01107   n0x = e0y; n0y = -e0x;
01108   n1x = e1y; n1y = -e1x;
01109   n2x = e2y; n2y = -e2x;
01110   denom0 = n1x*e0x + n1y*e0y;
01111   if ( fabs(denom0) < CUBIT_RESABS ) {
01112     PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
01113     return CUBIT_FAILURE;
01114   }
01115   denom1 = n2x*e1x + n2y*e1y;
01116   if ( fabs(denom1) < CUBIT_RESABS ) {
01117     PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
01118     return CUBIT_FAILURE;
01119   }
01120   denom2 = n0x*e2x + n0y*e2y;
01121   if ( fabs(denom2) < CUBIT_RESABS ) {
01122     PRINT_ERROR("Failure in pt_in_tri_2d; needle-thin triangle encountered.\n");
01123     return CUBIT_FAILURE;
01124   }
01125 
01126   c0 = -( n1x*(xpt-x1) + n1y*(ypt-y1) )/denom0;
01127   c1 = -( n2x*(xpt-x2) + n2y*(ypt-y2) )/denom1;
01128   c2 = -( n0x*(xpt-x0) + n0y*(ypt-y0) )/denom2;
01129 
01130   if ( (c0 > 0.0) && (c1 > 0.0) && (c2 > 0.0) ) is_point_in = CUBIT_PNT_INSIDE;
01131   else if ( (c0 < 0.0) || (c1 < 0.0) || (c2 < 0.0) ) is_point_in = CUBIT_PNT_OUTSIDE;
01132   else is_point_in = CUBIT_PNT_BOUNDARY;
01133 
01134   return CUBIT_SUCCESS;
01135 
01136 }
01137 
01138 //===========================================================================
01139 //  Function: random_positive_ray
01140 //  Purpose:
01141 //  Date:     10/2003
01142 //  Author:   John Fowler
01143 //===========================================================================
01144 void FacetDataUtil::random_positive_ray(CubitVector& ray)
01145 {
01146   double temp;
01147   double rayx = 0.0, rayy = 0.0, rayz = 0.0;
01148 
01149   temp = 0.0;
01150   while ( temp < 1.e-6 ) {
01151     rayx = (double(rand())/(RAND_MAX+1.0));
01152     rayy = (double(rand())/(RAND_MAX+1.0));
01153     rayz = (double(rand())/(RAND_MAX+1.0));
01154     temp = sqrt(rayx*rayx + rayy*rayy + rayz*rayz);
01155   }
01156   rayx /= temp;
01157   rayy /= temp;
01158   rayz /= temp;
01159 
01160   ray.set(rayx,rayy,rayz);
01161 
01162 }
01163 
01164 //===========================================================================
01165 //  Function: ray_intersects_boundingbox
01166 //  Purpose:
01167 //  Date:     10/2003
01168 //  Author:   John Fowler
01169 //===========================================================================
01170 bool FacetDataUtil::ray_intersects_boundingbox(CubitVector& point, CubitVector& ray, const CubitBox& bbox)
01171 {
01172 double t, xtest, ytest, ztest;
01173 double xdir, ydir, zdir, xpt, ypt, zpt, xmin, ymin, zmin, xmax, ymax, zmax;
01174 CubitVector bbox_min, bbox_max;
01175 
01176   point.get_xyz(xpt,ypt,zpt);
01177   ray.get_xyz(xdir,ydir,zdir);
01178   bbox_min = bbox.minimum();
01179   bbox_max = bbox.maximum();
01180   bbox_min.get_xyz(xmin,ymin,zmin);
01181   bbox_max.get_xyz(xmax,ymax,zmax);
01182   xmin -= GEOMETRY_RESABS;  //  So we don't miss any.
01183   ymin -= GEOMETRY_RESABS;
01184   zmin -= GEOMETRY_RESABS;
01185   xmax += GEOMETRY_RESABS;
01186   ymax += GEOMETRY_RESABS;
01187   zmax += GEOMETRY_RESABS;
01188 
01189  //  Notice that we are only interested in bboxes on the non-negative side of t.
01190   if ( fabs(xdir) > CUBIT_RESABS ) {
01191     // test xmin plane
01192     t = (xmin - xpt)/xdir;
01193     if ( t >= 0.0 ) {
01194       ytest = ypt + t*ydir;
01195       ztest = zpt + t*zdir;
01196       if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) )
01197         return true;
01198     }
01199     // test xmax plane
01200     t = (xmax - xpt)/xdir;
01201     if ( t > 0.0 ) {
01202       ytest = ypt + t*ydir;
01203       ztest = zpt + t*zdir;
01204       if ( (ytest >= ymin) && (ytest <= ymax) && (ztest >= zmin) && (ztest <= zmax) )
01205         return true;
01206     }
01207   }
01208   if ( fabs(ydir) > CUBIT_RESABS ) {
01209     // test ymin plane
01210     t = (ymin - ypt)/ydir;
01211     if ( t >= 0.0 ) {
01212       xtest = xpt + t*xdir;
01213       ztest = zpt + t*zdir;
01214       if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) )
01215         return true;
01216     }
01217     // test ymax plane
01218 
01219     t = (ymax - ypt)/ydir;
01220     if ( t > 0.0 ) {
01221       xtest = xpt + t*xdir;
01222       ztest = zpt + t*zdir;
01223       if ( (xtest >= xmin) && (xtest <= xmax) && (ztest >= zmin) && (ztest <= zmax) )
01224         return true;
01225     }
01226   }
01227   if ( fabs(zdir) > CUBIT_RESABS ) {
01228     // test zmin plane
01229     t = (zmin - zpt)/zdir;
01230     if ( t > 0.0 ) {
01231       xtest = xpt + t*xdir;
01232       ytest = ypt + t*ydir;
01233       if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) )
01234         return true;
01235     }
01236     // test zmax plane
01237     t = (zmax - zpt)/zdir;
01238     if ( t > 0.0 ) {
01239       xtest = xpt + t*xdir;
01240       ytest = ypt + t*ydir;
01241       if ( (xtest >= xmin) && (xtest <= xmax) && (ytest >= ymin) && (ytest <= ymax) )
01242         return true;
01243     }
01244   }
01245 
01246   return false;
01247 }
01248 
01249 //===========================================================================
01250 //  Function: write_facets
01251 //  Purpose:  write a list of facets to a cubit facet file
01252 //  Date:     11/28/2002
01253 //  Author:   sjowen
01254 //===========================================================================
01255 CubitStatus FacetDataUtil::write_facets( const char *file_name, DLIList<CubitFacet *> &facet_list)
01256 {
01257   FILE *fp = fopen(file_name, "w");
01258   if (!fp)
01259   {
01260     PRINT_ERROR("Couldn't open file %s for writing a facet file.\n", file_name);
01261     return CUBIT_FAILURE;
01262   }
01263 
01264   DLIList<CubitPoint*> point_list;
01265   get_points(facet_list, point_list);
01266 
01267   fprintf(fp, "%d %d\n", point_list.size(), facet_list.size());
01268   CubitPoint *pt;
01269   int ii;
01270   for (ii=1; ii<=point_list.size(); ii++)
01271   {
01272     pt = point_list.get_and_step();
01273     pt->set_id(ii);
01274     fprintf(fp, "%d %f %f %f\n", ii, pt->x(), pt->y(), pt->z() );
01275   }
01276 
01277   CubitFacet *facet;
01278   for (ii=1; ii<=facet_list.size(); ii++)
01279   {
01280     facet = facet_list.get_and_step();
01281     fprintf(fp, "%d %d %d %d\n", ii, facet->point(0)->id(),
01282              facet->point(1)->id(), facet->point(2)->id());
01283   }
01284 
01285   fclose(fp);
01286   return CUBIT_SUCCESS;
01287 
01288 }
01289 
01290 //=============================================================================
01291 //Function:  split_into_shells (PUBLIC)
01292 //Description: split this set of facets into multiple surfaces where there are
01293 //             may be disjoint regions.
01294 //Author: sjowen
01295 //Date: 8/27/2003
01296 //=============================================================================
01297 CubitStatus FacetDataUtil::split_into_shells(
01298   DLIList<CubitFacet *> &tfacet_list,
01299   DLIList<CubitQuadFacet *> &qfacet_list,
01300   DLIList<DLIList<CubitFacet *> *> &shell_list,
01301   CubitBoolean &is_water_tight)
01302 {
01303   CubitStatus stat = CUBIT_SUCCESS;
01304     //need to init this variable otherwise the caller must have.
01305   is_water_tight = CUBIT_TRUE;
01306 
01307   // combine the quads and tri lists
01308 
01309   DLIList <CubitFacet *> facet_list = tfacet_list;
01310   int ii;
01311   CubitQuadFacet *qfacet_ptr;
01312   for (ii=0; ii<qfacet_list.size(); ii++)
01313   {
01314     qfacet_ptr = qfacet_list.get_and_step();
01315     facet_list.append(qfacet_ptr->get_tri_facet( 0 ));
01316     facet_list.append(qfacet_ptr->get_tri_facet( 1 ));
01317   }
01318 
01319   // mark all the facets to begin with
01320 
01321   CubitFacet *facet_ptr;
01322   for (ii=0; ii<facet_list.size(); ii++)
01323   {
01324     facet_ptr = facet_list.get_and_step();
01325     facet_ptr->marked( 1 );
01326   }
01327 
01328   // populate the facet edge lists
01329 
01330   DLIList<CubitFacetEdge *> edge_list;
01331   FacetDataUtil::get_edges( facet_list, edge_list );
01332 
01333   // some debug stuff to draw the facets
01334 
01335   int mydebug=0;
01336   if (mydebug)
01337   {
01338     for (ii=0; ii<facet_list.size(); ii++)
01339     {
01340       facet_ptr = facet_list.get_and_step();
01341       GfxDebug::draw_facet(facet_ptr,CUBIT_YELLOW_INDEX);
01342     }
01343     GfxDebug::flush();
01344     GfxDebug::mouse_xforms();
01345   }
01346 
01347   // Go through the surfaceElemList and pull facets off one by one as we
01348   // determine which surface it belongs to.  Continue until we have depleted
01349   // the list
01350 
01351   int jj;
01352   int num_surfs_created = 0;
01353   int num_facets_remaining = facet_list.size();
01354   while( num_facets_remaining > 0)
01355   {
01356     // create a new shell to hold the face info
01357 
01358     num_surfs_created++;
01359     DLIList<CubitFacet *> *shell_ptr = new DLIList<CubitFacet *>;
01360 
01361     // start with the first facet and create a list of all elements
01362     // attached to the facet
01363 
01364     CubitBoolean shell_is_water_tight = CUBIT_TRUE;
01365     CubitFacet *start_facet_ptr = facet_list.get_and_step();
01366     stat = get_adj_facets_on_shell( start_facet_ptr, shell_ptr,
01367                                     shell_is_water_tight, mydebug );
01368     if (stat != CUBIT_SUCCESS)
01369       return stat;
01370     if (!shell_is_water_tight)
01371       is_water_tight = CUBIT_FALSE;
01372 
01373     shell_list.append( shell_ptr );
01374 
01375     // remove the facets in this shell from the facet list
01376 
01377     for( jj = facet_list.size(); jj > 0; jj-- )
01378     {
01379       facet_ptr = facet_list.get();
01380       if (facet_ptr->marked() == 0)
01381       {
01382         facet_list.change_to( NULL );
01383       }
01384       facet_list.step();
01385     }
01386     facet_list.remove_all_with_value( NULL );
01387     num_facets_remaining = facet_list.size();
01388   }
01389 
01390   return CUBIT_SUCCESS;
01391 }
01392 
01393 //=============================================================================
01394 //Function:  get_adj_facets_on_shell (PRIVATE)
01395 //Description: non recursive function that creates a list of all facets connected
01396 //             the passed in face that are on the same surface
01397 //Author: sjowen
01398 //Date: 12/22/00
01399 //=============================================================================
01400 CubitStatus FacetDataUtil::get_adj_facets_on_shell(
01401   CubitFacet *start_facet_ptr,
01402   DLIList<CubitFacet *> *shell_ptr,
01403   CubitBoolean &is_water_tight,
01404   int mydebug)
01405 {
01406   int found = 0;
01407   int ii, jj;
01408   CubitStatus stat = CUBIT_SUCCESS;
01409   DLIList<CubitFacet*> temp_list;
01410   CubitFacet *facet_ptr = NULL;
01411   CubitFacet *adj_facet_ptr = NULL;
01412   DLIList<CubitFacetEdge *>edge_list;
01413   CubitFacetEdge *edge_ptr = NULL;
01414   DLIList<CubitFacet *>adj_facet_list;
01415 
01416   // add this facet to the list
01417 
01418   temp_list.append( start_facet_ptr );
01419   start_facet_ptr->marked( 0 );
01420 
01421   while (temp_list.size())
01422   {
01423     facet_ptr = temp_list.pop();
01424     if (facet_ptr->marked() == 0)
01425     {
01426       shell_ptr->append( facet_ptr );
01427       if (mydebug)
01428       {
01429         GfxDebug::draw_facet(facet_ptr, CUBIT_RED_INDEX);
01430         GfxDebug::flush();
01431       }
01432       edge_list.clean_out();
01433       facet_ptr->edges( edge_list );
01434       for (ii=0; ii<edge_list.size(); ii++)
01435       {
01436         edge_ptr = edge_list.get_and_step();
01437         adj_facet_list.clean_out();
01438         edge_ptr->facets( adj_facet_list );
01439         found = 0;
01440 
01441         for (jj=0; jj<adj_facet_list.size() && !found; jj++)
01442         {
01443           adj_facet_ptr = adj_facet_list.get_and_step();
01444           if (adj_facet_ptr != facet_ptr)
01445           {
01446 
01447             // go to its neighbor if it is part of the surface
01448 
01449             if (adj_facet_ptr->marked() == 1)
01450             {
01451               temp_list.append( adj_facet_ptr );
01452               adj_facet_ptr->marked( 0 );
01453               found = 1;
01454             }
01455           }
01456 
01457         }
01458         if (is_water_tight && adj_facet_list.size() == 1)
01459         {
01460           is_water_tight = CUBIT_FALSE;
01461         }
01462       }
01463     }
01464   }
01465 
01466   return stat;
01467 }
01468 
01469 //=============================================================================
01470 //Function:  stitch_facets (PRIVATE)
01471 //Description: attempt to merge facets to form a watertight model
01472 //Author: sjowen
01473 //Date: 9/9/03
01474 //=============================================================================
01475 CubitStatus FacetDataUtil::stitch_facets(
01476   DLIList<DLIList<CubitFacet *> *> &shell_list,
01477   double tol,
01478   CubitBoolean &is_water_tight,
01479   CubitBoolean write_result)
01480 {
01481 
01482   CubitStatus rv = CUBIT_SUCCESS;
01483   int npmerge = 0;
01484   int nemerge = 0;
01485   DLIList<CubitPoint*> unmerged_points;
01486   is_water_tight = CUBIT_FALSE;
01487 
01488   rv = merge_coincident_vertices( shell_list, tol, npmerge, nemerge, unmerged_points );
01489   if (rv != CUBIT_SUCCESS)
01490     return rv;
01491 
01492   int nnomerge = unmerged_points.size();
01493   if (nnomerge == 0)
01494   {
01495     is_water_tight = CUBIT_TRUE;
01496   }
01497   else
01498   {
01499     rv = merge_colinear_vertices( shell_list, tol, unmerged_points,
01500                                   npmerge, nemerge, nnomerge );
01501     if (rv != CUBIT_SUCCESS)
01502       return rv;
01503 
01504     if (nnomerge == 0)
01505     {
01506       is_water_tight = CUBIT_TRUE;
01507       int mydebug = 0;
01508       if (mydebug)  // make sure its really water-tight
01509       {
01510         DLIList<CubitFacet *> *shell_ptr;
01511         DLIList<CubitFacetEdge *>boundary_edges;
01512         for (int ii=0; ii<shell_list.size(); ii++)
01513         {
01514           shell_ptr = shell_list.get_and_step();
01515           FacetDataUtil::get_boundary_edges(*shell_ptr, boundary_edges);
01516         }
01517         if (boundary_edges.size() > 0)
01518         {
01519           PRINT_ERROR("Not Water-tight!\n");
01520         }
01521       }
01522     }
01523   }
01524 
01525   if (write_result)
01526   {
01527     if (npmerge > 0 || nemerge > 0)
01528     {
01529       PRINT_INFO("%d facet vertices and %d facet edges were successfully merged.\n",
01530                  npmerge, nemerge);
01531     }
01532     if (is_water_tight)
01533     {
01534       PRINT_INFO("Facets are water-tight.\n");
01535     }
01536     else
01537     {
01538       PRINT_INFO("%d facet vertices on model boundary detected that could not be merged.\n", nnomerge);
01539     }
01540   }
01541 
01542   return rv;
01543 }
01544 
01545 //=============================================================================
01546 //Function:  merge_colinear_vertices (PRIVATE)
01547 //Description: check if any vertices fall on a free facet edge.  If so - split
01548 //             the  adjacent facet to merge
01549 //Author: sjowen
01550 //Date: 1/19/2004
01551 //=============================================================================
01552 CubitStatus FacetDataUtil::merge_colinear_vertices(
01553   DLIList<DLIList<CubitFacet *> *> &shell_list,
01554   double tol,
01555   DLIList<CubitPoint *> &merge_point_list,  // points to attempt to merge
01556   int &npmerge,    // return number of vertices merged
01557   int &nemerge,    // return number of edges merged
01558   int &nnomerge)   // return number of vertices in list NOT merged
01559 {
01560   nnomerge = 0;
01561   int mydebug = 0;
01562 
01563   int ii, jj, kk, ll, mm, pt_shell_id, edge_shell_id;
01564   RTree <CubitFacetEdge*> r_tree(tol);
01565   shell_list.reset();
01566   DLIList<CubitFacet *> *shell_ptr = NULL;
01567   CubitPoint *pt;
01568   CubitFacetEdge *edge;
01569   DLIList<CubitFacetEdge *>boundary_edges;
01570   for (ii=0; ii<shell_list.size(); ii++)
01571   {
01572     shell_ptr = shell_list.get_and_step();
01573 
01574     // get the boundary edges from the shell - these are candidates for merging.
01575     // note that this won't merge internal facets
01576 
01577     DLIList<CubitFacetEdge *>shell_boundary_edges;
01578     FacetDataUtil::get_boundary_edges(*shell_ptr, shell_boundary_edges);    
01579 
01580     // mark each of the edges with a shell id so we know when to merge shells
01581     // and add them to the kdtree for fast spatial searching
01582     edge_shell_id = ii+1;
01583     for(jj=0; jj<shell_boundary_edges.size(); jj++)
01584     {
01585       edge = shell_boundary_edges.get_and_step();
01586       edge->point(0)->marked(edge_shell_id);
01587       edge->point(1)->marked(edge_shell_id);
01588       edge->marked(edge_shell_id);
01589       r_tree.add(edge);
01590       boundary_edges.append(edge);
01591     }
01592     for(jj=0; jj<shell_ptr->size(); jj++)
01593       shell_ptr->get_and_step()->marked( edge_shell_id );
01594   }  
01595 
01596   // find points in merge_point_list that are colinear with edges in boundary_edges
01597 
01598   CubitBox ptbox;
01599   CubitVector ptmin, ptmax, coord;
01600   DLIList<CubitFacetEdge *>close_edges;
01601   CubitFacetEdge *close_edge;
01602   CubitFacet *facet;
01603   CubitPoint *p0, *p1;
01604   DLIList<CubitPoint*>adj_pt_list;
01605   DLIList<CubitPoint*>del_points;
01606   for(ii=0; ii<merge_point_list.size(); ii++)
01607   {
01608     pt = merge_point_list.get_and_step();
01609     if (pt->marked() < 0)  // has already been merged
01610       continue;   
01611 
01612     // find the closest edges in the rtree
01613 
01614     coord = pt->coordinates();
01615     ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol );
01616     ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol );
01617     ptbox.reset( ptmin, ptmax );
01618     close_edges.clean_out();
01619     r_tree.find(ptbox, close_edges);
01620 
01621 
01622     //remove any close edges that already share the merge point
01623     DLIList<CubitFacetEdge*> adj_edges;
01624     for (jj=close_edges.size(); jj--; )
01625     {
01626       close_edge = close_edges.get();
01627 
01628       if (close_edge->point(0) == pt || close_edge->point(1) == pt)
01629       {
01630         close_edges.change_to( NULL );
01631         adj_edges.append( close_edge );
01632       }
01633 
01634       close_edges.step();
01635     }
01636     close_edges.remove_all_with_value( NULL );
01637 
01638     if( close_edges.size() == 0 && adj_edges.size() > 0 )
01639     {
01640       //use a coareser tolerance to get some edges
01641       //one tenth the average length of attached edges
01642       double temp_tol = 0;
01643       for( int i=adj_edges.size(); i--; )
01644         temp_tol += adj_edges.get_and_step()->length();
01645 
01646       temp_tol /= adj_edges.size();
01647       temp_tol *= 0.1;      
01648 
01649       //bump up tolerance to get more edges
01650       ptmin.set( coord.x() - temp_tol, coord.y() - temp_tol, coord.z() - temp_tol );
01651       ptmax.set( coord.x() + temp_tol, coord.y() + temp_tol, coord.z() + temp_tol );
01652       ptbox.reset( ptmin, ptmax );
01653       close_edges.clean_out();
01654       r_tree.find(ptbox, close_edges);
01655     }
01656         
01657 
01658     // We did find something - go try to merge
01659 
01660     CubitBoolean was_merged = CUBIT_FALSE;
01661     for (jj=0; jj<close_edges.size() && !was_merged; jj++)
01662     {
01663       // test the next edge on the list
01664 
01665       close_edge = close_edges.get_and_step();
01666 
01667       // make sure the edge does not contain the merge point
01668 
01669       if (close_edge->point(0) == pt || close_edge->point(1) == pt)
01670         continue;
01671     
01672       // check to see if the edge is within tolerance of the merge point
01673 
01674       CubitVector loc_on_edge;
01675       CubitBoolean is_outside_edge;
01676       double dist = close_edge->dist_to_edge(pt->coordinates(),
01677         loc_on_edge, is_outside_edge);
01678 
01679       // allow for some surface curvature. permit the point to be close to
01680       // the edge but not on.  May want to modify this factor if it not closing
01681       // the facets correctly.  If it's too big, it may get edges that aren't
01682       // really adjacent.
01683       double edge_tol = 0.1 * close_edge->length();
01684       if (is_outside_edge || dist > edge_tol)
01685         continue;
01686 
01687       // go merge the point with the edge
01688       was_merged = CUBIT_TRUE;
01689 
01690       if (mydebug)
01691       {
01692         DLIList<CubitFacet *> fl;
01693         pt->facets( fl );
01694         dcolor(CUBIT_YELLOW_INDEX);
01695         dfldraw(fl);
01696         dcolor(CUBIT_BLUE_INDEX);
01697         dpoint(pt->coordinates());
01698         CubitFacet *f = close_edge->adj_facet(0);
01699         dcolor(CUBIT_RED_INDEX);
01700         dfdraw(f);
01701         dview();
01702       }
01703 
01704       // remove close_edge from the rtree
01705     
01706       r_tree.remove( close_edge );
01707       edge_shell_id = close_edge->marked();
01708       close_edge->marked(0);
01709 
01710       // split the edge
01711 
01712       assert(1 == close_edge->num_adj_facets());  // assumes we are splitting a boundary facet
01713       facet = close_edge->adj_facet(0);
01714       CubitFacetData *dfacet = dynamic_cast<CubitFacetData *>(facet);
01715       CubitPoint *new_pt = dfacet->split_edge(close_edge->point(0),
01716                                               close_edge->point(1),
01717                                               pt->coordinates());
01718       int facet_tool_id = facet->tool_id();
01719       new_pt->marked(edge_shell_id);
01720 
01721       // add any new facets to the shell and create missing edges
01722 
01723       for (ll=0; ll<edge_shell_id; ll++)
01724         shell_ptr = shell_list.get_and_step();
01725       DLIList<CubitFacet *>adj_facets;
01726       new_pt->facets( adj_facets );
01727       for (ll=0; ll<adj_facets.size(); ll++)
01728       {
01729         facet = adj_facets.get_and_step();
01730         if (!facet->marked())
01731         {
01732           facet->marked(edge_shell_id);
01733           shell_ptr->append(facet);
01734           for (mm=0; mm<3; mm++) {
01735             if (!(edge = facet->edge(mm)))
01736             {
01737               facet->get_edge_pts(mm, p0, p1);
01738               edge = (CubitFacetEdge *) new CubitFacetEdgeData( p0, p1 );
01739               edge->marked( 0 );
01740             }
01741           }
01742           facet->set_tool_id(facet_tool_id);
01743         }
01744       }
01745 
01746       // merge the points,
01747                                      
01748       merge_points( pt, new_pt, nemerge, &r_tree );
01749       npmerge++;
01750 
01751       // add any new edges to the rtree
01752 
01753       DLIList<CubitFacetEdge *> adj_edges;
01754       pt->edges( adj_edges );
01755       for (kk=0; kk<adj_edges.size(); kk++)
01756       {
01757         CubitFacetEdge *adj_edge = adj_edges.get_and_step();
01758         if (!adj_edge->marked() && adj_edge->num_adj_facets() == 1)
01759         {
01760           adj_edge->marked(pt->marked());
01761           r_tree.add(adj_edge);
01762         }
01763       }
01764 
01765       // see if shells need to merge and then merge
01766 
01767       pt_shell_id = pt->marked();
01768       if (pt_shell_id != edge_shell_id)
01769       {
01770 
01771         // get the shell containing the close point.  Nullify the
01772         // pointer in the shell list and move all of its facets
01773         // to the other shell.
01774 
01775         int delete_shell = edge_shell_id;
01776         DLIList<CubitFacet *> *delete_shell_ptr = NULL;
01777         shell_list.reset();
01778         for (ll=0; ll<delete_shell; ll++)
01779           delete_shell_ptr = shell_list.get_and_step();
01780         shell_list.back();
01781         shell_list.change_to(NULL);
01782 
01783         if(!delete_shell_ptr)
01784           return CUBIT_FAILURE;
01785 
01786         // mark all the points on the delete_shell as now being part of
01787         // the other shell.
01788 
01789         for(ll=0; ll<delete_shell_ptr->size(); ll++)
01790         {
01791           facet = delete_shell_ptr->get_and_step();
01792           facet->marked( pt_shell_id );
01793           facet->point( 0 )->marked( pt_shell_id );
01794           facet->point( 1 )->marked( pt_shell_id );
01795           facet->point( 2 )->marked( pt_shell_id );
01796           facet->edge( 0 )->marked( pt_shell_id );
01797           facet->edge( 1 )->marked( pt_shell_id );
01798           facet->edge( 2 )->marked( pt_shell_id );
01799         }
01800 
01801         // append the two lists together
01802 
01803         shell_list.reset();
01804         for (ll=0; ll<pt_shell_id; ll++)
01805           shell_ptr = shell_list.get_and_step();
01806         *shell_ptr += (*delete_shell_ptr);
01807         delete delete_shell_ptr;
01808       }
01809 
01810       // set the marked flag to negative to indicate that it has been
01811       // merged and it needs to be deleted.
01812 
01813       del_points.append(new_pt);
01814       new_pt->marked( -new_pt->marked() );
01815       pt->marked( -pt->marked() );
01816     } // close_edges
01817    
01818     if (!was_merged)
01819     {
01820       nnomerge++;
01821       if (mydebug)
01822       {
01823         dcolor(CUBIT_BLUE_INDEX);
01824         dpdraw(pt);
01825         dcolor(CUBIT_RED_INDEX);
01826         CubitVector mmin(-1e10, -1e10, -1e10);
01827         CubitVector mmax(1e10, 1e10, 1e10);
01828         ptbox.reset(mmin, mmax);
01829         r_tree.find(ptbox, close_edges);
01830         for(int zz=0; zz<close_edges.size(); zz++)
01831         {
01832           edge = close_edges.get_and_step();
01833           dedraw(edge);
01834           CubitVector loc_on_edge;
01835           CubitBoolean is_on_edge;
01836           double dist = edge->dist_to_edge(pt->coordinates(), loc_on_edge, is_on_edge);
01837           PRINT_INFO("edge %d dist = %f is_on_edge = %d\n", edge->id(), dist, is_on_edge);
01838         }
01839         dview();
01840       }
01841     }
01842   } // merge_point_list
01843 
01844   // compress the shell list
01845 
01846   shell_list.remove_all_with_value(NULL);
01847 
01848   // delete points that were merged
01849 
01850   for (ii=0; ii<del_points.size(); ii++)
01851   {
01852     pt = del_points.get_and_step();
01853     if (pt->marked() < 0)
01854     {
01855       assert( pt->num_adj_facets() == 0 );
01856       delete pt;
01857     }
01858   }
01859 
01860   return CUBIT_SUCCESS;
01861 }
01862 
01863 //=============================================================================
01864 //Function:  merge_points (PRIVATE)
01865 //Description: merge two cubit points where it has been determined that they
01866 //             are coincident.  Also handle merging their adjacent edges where
01867 //             appropriate
01868 //Author: sjowen
01869 //Date: 1/19/2004
01870 //=============================================================================
01871 CubitStatus FacetDataUtil::merge_points(
01872   CubitPoint *pt0, CubitPoint *pt1,
01873   int &nemerge, RTree <CubitFacetEdge*> *r_tree)  // number of edges we had to merge top do this
01874 {
01875   int mydebug = 0;
01876 
01877   // merge the points
01878   pt0->merge_points( pt1, CUBIT_TRUE );
01879   //pt0->set_as_feature();
01880 
01881   if (mydebug)
01882   {
01883     DLIList<CubitFacet *>adj_facets;
01884     pt0->facets( adj_facets );
01885     dcolor(CUBIT_RED_INDEX);
01886     dfldraw(adj_facets);
01887   }
01888 
01889   // merge edges
01890 
01891   int ll, mm;
01892   bool edge_merged;
01893   do {
01894     edge_merged = false;
01895     CubitFacetEdge *edge, *other_edge;
01896 
01897     DLIList<CubitFacetEdge *> adj_edges;
01898     pt0->edges( adj_edges );
01899     for(ll=0; ll<adj_edges.size() && !edge_merged; ll++)
01900     {
01901       edge = adj_edges.get_and_step();
01902       for(mm=0; mm<adj_edges.size() && !edge_merged; mm++)
01903       {
01904         other_edge = adj_edges.get_and_step();
01905         if (other_edge != edge &&
01906             edge->other_point(pt0) == other_edge->other_point(pt0))
01907         {
01908           CubitFacetEdgeData *dedge = dynamic_cast<CubitFacetEdgeData*>(edge);
01909           CubitFacetEdgeData *dother_edge = dynamic_cast<CubitFacetEdgeData*>(other_edge);
01910           // mbrewer (11/16/2005 for Bug 5049)
01911           if(r_tree){
01912 //            r_tree->remove(dother_edge);
01913              CubitBoolean temp_bool = r_tree->remove(dother_edge);
01914              if(!temp_bool){
01915                PRINT_DEBUG_139("FacetDataUtil:  D_OTHER_EDGE did not exist in RTREE.\n");
01916              }
01917           }
01918           if (dedge->merge_edges( dother_edge ) == CUBIT_SUCCESS)
01919           {            
01920             nemerge++;
01921             edge_merged = true;
01922             dedge->set_as_feature();
01923           }
01924         }
01925       }
01926     }
01927   } while (edge_merged);
01928   return CUBIT_SUCCESS;
01929 }
01930 
01931 
01932 CubitStatus FacetDataUtil::merge_coincident_vertices( DLIList<CubitPoint*> &points )
01933 {
01934   points.reset();
01935   CubitPoint *surviving_point = points.pop();
01936   while( points.size() )
01937   {    
01938     int nemerge = 0;
01939     merge_points( surviving_point, points.pop(), nemerge );   
01940   }
01941 
01942   return CUBIT_SUCCESS;
01943 }
01944 
01945 
01946 
01947 //=============================================================================
01948 //Function:  merge_coincident_vertices (PRIVATE)
01949 //Description: merge vertices (and connected facets and edges) if they are
01950 //             within tolerance.
01951 //Author: sjowen
01952 //Date: 9/9/03
01953 //=============================================================================
01954 CubitStatus FacetDataUtil::merge_coincident_vertices(
01955   DLIList<DLIList<CubitFacet *> *> &shell_list,
01956   double tol,
01957   int &npmerge,    // return number of vertices merged
01958   int &nemerge,    // return number of edges merged
01959   DLIList<CubitPoint *> &unmerged_points)   // return the vertices on boundary NOT merged
01960 {
01961   int mydebug = 0;
01962   npmerge = 0;
01963   nemerge = 0;
01964   int ii, jj, kk, ll, shell_id;
01965   KDDTree <CubitPoint*> kd_tree(tol, false);
01966   CubitPoint::set_box_tol( tol );
01967   shell_list.reset();
01968   DLIList<CubitFacet *> *shell_ptr = NULL;
01969   CubitPoint *pt;
01970   DLIList<CubitPoint *>boundary_points;
01971   DLIList<CubitPoint *> del_points;
01972   for (ii=0; ii<shell_list.size(); ii++)
01973   {
01974     shell_ptr = shell_list.get_and_step();
01975 
01976     // get the boundary points from the shell - these are candidates for merging.
01977     // note that this won't merge internal facets
01978 
01979     DLIList<CubitPoint *>shell_boundary_points;
01980     FacetDataUtil::get_boundary_points(*shell_ptr, shell_boundary_points);
01981 
01982     // mark each of the points with a shell id so we know when to merge shells
01983     // and add them to the kdtree for fast spatial searching
01984 
01985     shell_id = ii+1;
01986     for(jj=0; jj<shell_boundary_points.size(); jj++)
01987     {
01988       pt = shell_boundary_points.get_and_step();
01989       pt->marked(shell_id);
01990       kd_tree.add(pt);
01991       boundary_points.append(pt);
01992     }
01993   }
01994   kd_tree.balance();
01995 
01996   // find points that are coincident
01997 
01998   CubitBox ptbox;
01999   CubitVector ptmin, ptmax, coord;
02000   DLIList<CubitPoint *>close_points;
02001   CubitPoint *close_pt = NULL;
02002   CubitFacet *facet;
02003   DLIList<CubitPoint*>adj_pt_list;
02004 
02005   for(ii=0; ii<boundary_points.size(); ii++)
02006   {
02007     pt = boundary_points.get_and_step();
02008     if (pt->marked() < 0)  // has already been merged
02009       continue;
02010 
02011     // find the closest points in the kdtree
02012 
02013     coord = pt->coordinates();
02014     ptmin.set( coord.x() - tol, coord.y() - tol, coord.z() - tol );
02015     ptmax.set( coord.x() + tol, coord.y() + tol, coord.z() + tol );
02016     ptbox.reset( ptmin, ptmax );
02017     close_points.clean_out();
02018     kd_tree.find(ptbox, close_points);
02019 
02020     // if it didn't find anything to merge with, then we aren't water-tight
02021 
02022     CubitBoolean was_merged = CUBIT_FALSE;
02023 
02024     // We did find something - go try to merge
02025 
02026     for (jj=0; jj<close_points.size(); jj++)
02027     {
02028       close_pt = close_points.get_and_step();
02029       if (close_pt == pt)
02030         continue;
02031       if (close_pt->marked() < 0)  // has already been merged
02032         continue;
02033       assert(close_points.size() >= 1);
02034 
02035       // make sure this point is not already one of its neighbors
02036       // so we don't collapse a triangle
02037 
02038       CubitBoolean is_adjacent = CUBIT_FALSE;
02039       adj_pt_list.clean_out();
02040       close_pt->adjacent_points( adj_pt_list );
02041       for (kk=0; kk<adj_pt_list.size() && !is_adjacent; kk++)
02042       {
02043         if (adj_pt_list.get_and_step() == pt)
02044           is_adjacent = CUBIT_TRUE;
02045       }
02046       if (!is_adjacent)
02047       {
02048         // merge the points
02049 
02050         merge_points( pt, close_pt, nemerge );
02051         npmerge++;
02052         was_merged = CUBIT_TRUE;
02053 
02054         // see if shells need to merge and then merge
02055 
02056         shell_id = pt->marked();
02057         if (shell_id != close_pt->marked())
02058         {
02059 
02060           // get the shell containing the close point.  Nullify the
02061           // pointer in the shell list and move all of its facets
02062           // to the other shell.
02063 
02064           int delete_shell = close_pt->marked();
02065           DLIList<CubitFacet *> *delete_shell_ptr = NULL;
02066           shell_list.reset();
02067           for (ll=0; ll<delete_shell; ll++)
02068             delete_shell_ptr = shell_list.get_and_step();
02069           shell_list.back();
02070           shell_list.change_to(NULL);
02071 
02072           // mark all the points on the delete_shell as now being part of
02073           // the other shell.
02074 
02075           for(ll=0; ll<delete_shell_ptr->size(); ll++)
02076           {
02077             facet = delete_shell_ptr->get_and_step();
02078             facet->point( 0 )->marked( shell_id );
02079             facet->point( 1 )->marked( shell_id );
02080             facet->point( 2 )->marked( shell_id );
02081           }
02082 
02083           // append the two lists together
02084 
02085           shell_list.reset();
02086           for (ll=0; ll<shell_id; ll++)
02087             shell_ptr = shell_list.get_and_step();
02088           *shell_ptr += (*delete_shell_ptr);
02089           delete delete_shell_ptr;
02090         }
02091 
02092         // set the marked flag to negative to indicate that it has been
02093         // merged and it need to be deleted.
02094 
02095         if (close_pt->marked() > 0)
02096           close_pt->marked( -close_pt->marked() );
02097         del_points.append( close_pt );
02098       }
02099     }
02100     if (was_merged)
02101     {
02102       if (pt->marked() > 0)
02103         pt->marked( -pt->marked() );
02104     }
02105     else
02106     {
02107       // check to see if it was already merged
02108       if (close_points.size() == 1 && close_pt == pt)
02109       {
02110         CubitFacetEdge *edge_ptr;
02111         DLIList<CubitFacetEdge *>adj_edges;
02112         pt->edges(adj_edges);
02113         CubitBoolean on_boundary = CUBIT_FALSE;
02114         for(kk=0; kk<adj_edges.size() && !on_boundary; kk++)
02115         {
02116           edge_ptr = adj_edges.get_and_step();
02117           if (edge_ptr->num_adj_facets() == 1)
02118             on_boundary = CUBIT_TRUE;
02119         }
02120         if (on_boundary)
02121         {
02122             //PRINT_INFO("Merging 'boundary' points.\n");
02123             //if (pt->marked() > 0) pt->marked( -pt->marked() );
02124           unmerged_points.append(pt);
02125         }
02126         else
02127         {
02128           if (pt->marked() > 0) pt->marked( -pt->marked() );
02129         }
02130       }
02131       else
02132       {
02133         // otherwise save it as an unmerged point to be handled later
02134         unmerged_points.append(pt);
02135       }
02136     }
02137   }
02138 
02139   // compress the shell list
02140 
02141   shell_list.remove_all_with_value(NULL);
02142 
02143   // delete points that were merged
02144 
02145   for (ii=0; ii<del_points.size(); ii++)
02146   {
02147     pt = del_points.get_and_step();
02148     if (pt->marked() < 0)
02149     {
02150       assert( pt->num_adj_facets() == 0 );
02151       delete pt;
02152     }
02153   }
02154 
02155   //double-check that these are still boundary points.
02156   //found case where two shells were tied together by a single facet point.
02157   //this point was initially deemed an unmerged boundary point but later
02158   //adjacent boundary edges got merged so it should not be a boundary 
02159   //point anymore.
02160   for( int k=0; k<unmerged_points.size(); k++ )
02161   {
02162     DLIList<CubitFacetEdge *>adj_edges;
02163     unmerged_points[k]->edges(adj_edges);
02164     CubitBoolean on_boundary = CUBIT_FALSE;
02165     for(kk=0; kk<adj_edges.size(); kk++)
02166     {
02167       CubitFacetEdge *edge_ptr = adj_edges.get_and_step();
02168       if (edge_ptr->num_adj_facets() == 1)
02169       {
02170         on_boundary = CUBIT_TRUE;
02171         break;
02172       }
02173     }
02174     if( CUBIT_FALSE == on_boundary )
02175       unmerged_points[k] = NULL;
02176   }
02177   unmerged_points.remove_all_with_value(NULL);
02178   
02179   if (mydebug)
02180   {
02181     CubitFacetEdge *edge;
02182     for (ii=0; ii<shell_list.size(); ii++)
02183     {
02184       shell_ptr = shell_list.get_and_step();
02185       dcolor(CUBIT_GREEN_INDEX);
02186       dfldraw(*shell_ptr);
02187       dcolor(CUBIT_RED_INDEX);
02188       for(jj=0; jj<shell_ptr->size(); jj++)
02189       {
02190         facet = shell_ptr->get_and_step();
02191         for(kk=0; kk<3; kk++)
02192         {
02193           edge = facet->edge(kk);
02194           DLIList<FacetEntity *> myfacet_list;
02195           edge->get_parents( myfacet_list );
02196           assert(myfacet_list.size() == edge->num_adj_facets());
02197           if (myfacet_list.size() != 2)
02198           {
02199             dedraw( edge );      
02200           }
02201         }
02202       }
02203     }
02204     dcolor(CUBIT_BLUE_INDEX);
02205     dpldraw(unmerged_points);
02206     dview();
02207   }
02208 
02209   return CUBIT_SUCCESS;
02210 
02211 }
02212 
02213 //=============================================================================
02214 //Function:  delete_facets (PUBLIC)
02215 //Description: delete the facets and all associated edges and points from
02216 //             a list of lists of facets (shell_list)
02217 //Author: sjowen
02218 //Date: 1/21/2004
02219 //=============================================================================
02220 void FacetDataUtil::delete_facets(DLIList<DLIList<CubitFacet*>*> &shell_list)
02221 {
02222   int ii;
02223   for (ii=0; ii<shell_list.size(); ii++)
02224   {
02225     DLIList<CubitFacet*> *facet_list_ptr = shell_list.get_and_step();
02226     delete_facets( *facet_list_ptr );
02227   }
02228 }
02229 
02230 //=============================================================================
02231 //Function:  delete_facets (PUBLIC)
02232 //Description: delete the facets and all associated edges and points from
02233 //             a list of facets
02234 //Author: sjowen
02235 //Date: 1/21/2004
02236 //=============================================================================
02237 void FacetDataUtil::delete_facets(DLIList<CubitFacet*> &facet_list)
02238 {
02239   int ii;
02240   CubitFacet *facet_ptr;
02241   for (ii=0; ii<facet_list.size(); ii++)
02242   {
02243     facet_ptr = facet_list.get_and_step();
02244     delete_facet( facet_ptr );
02245   }
02246 }
02247 
02248 //=============================================================================
02249 //Function:  delete_facet (PUBLIC)
02250 //Description: delete a single facet and its underlying edges and points if
02251 //             they are no longer attached to anything
02252 //Author: sjowen
02253 //Date: 1/21/2004
02254 //=============================================================================
02255 void FacetDataUtil::delete_facet(CubitFacet *facet_ptr)
02256 {
02257   DLIList<CubitPoint *>point_list;
02258   DLIList<CubitFacetEdge *>edge_list;
02259   facet_ptr->points(point_list);
02260   facet_ptr->edges(edge_list);
02261 
02262   delete facet_ptr;
02263 
02264   CubitFacetEdge *edge_ptr;
02265   CubitPoint *point_ptr;
02266   int ii;
02267 
02268   for (ii=0; ii<edge_list.size(); ii++)
02269   {
02270     edge_ptr = edge_list.get_and_step();
02271     if (edge_ptr->num_adj_facets() == 0)
02272       delete edge_ptr;
02273   }
02274 
02275   for (ii=0; ii<3; ii++)
02276   {
02277     point_ptr = point_list.get_and_step();
02278     if (point_ptr->num_adj_facets() == 0)
02279       delete point_ptr;
02280   }
02281 
02282 }
02283 
02284 
02285 void FacetDataUtil::destruct_facet_no_delete(CubitFacet *facet_ptr)
02286 {
02287   CubitFacetData* facet_d_ptr = dynamic_cast<CubitFacetData*>(facet_ptr);
02288   if(!facet_d_ptr){
02289     PRINT_ERROR("Can't work with Facet pointer that isn't a facet data object.\n");
02290     return;
02291   }
02292   
02293   DLIList<CubitPoint *>point_list;
02294   DLIList<CubitFacetEdge *>edge_list;
02295   facet_ptr->points(point_list);
02296   facet_ptr->edges(edge_list);
02297   
02298   facet_d_ptr->destruct_facet_internals();
02299 
02300   CubitFacetEdge *edge_ptr;
02301   CubitPoint *point_ptr;
02302   int ii;
02303 
02304   for (ii=0; ii<edge_list.size(); ii++)
02305   {
02306     edge_ptr = edge_list.get_and_step();
02307     if (edge_ptr->num_adj_facets() == 0)
02308       delete edge_ptr;
02309   }
02310 
02311   for (ii=0; ii<3; ii++)
02312   {
02313     point_ptr = point_list.get_and_step();
02314     if (point_ptr->num_adj_facets() == 0)
02315       delete point_ptr;
02316   }
02317 
02318 }
02319 
02320 //=============================================================================
02321 //Function:  intersect_facet (PUBLIC)
02322 //Description: determine intersection of a segment with a facet
02323 //             returns CUBIT_PNT_UNKNOWN: if segment is in plane of facet
02324 //                     CUBIT_PNT_OUTSIDE: if segment does not intersect
02325 //                     CUBIT_PNT_INSIDE: if segment intersects inside facet
02326 //                     CUBIT_PNT_BOUNDARY: if segment intersects a vertex or edge
02327 //Author: sjowen
02328 //Date: 1/30/2004
02329 //=============================================================================
02330 CubitPointContainment FacetDataUtil::intersect_facet(
02331   CubitVector &start, CubitVector &end, // start and end points of vector
02332   CubitFacet *facet_ptr,      // the facet to intersect
02333   CubitVector &qq,            // return the intersection point
02334   CubitVector &ac,    // area coordinates of qq if is in or on facet
02335   CubitBoolean bound) // if true, only check for intersections between the end points.
02336 {
02337 
02338   CubitPlane fplane = facet_ptr->plane();
02339   double dstart = fplane.distance(start);
02340   double dend = fplane.distance(end);
02341 
02342   // points are both in the plane of the facet - can't handle this case
02343 
02344   if (fabs(dstart) < GEOMETRY_RESABS &&
02345       fabs(dend) < GEOMETRY_RESABS)
02346   {
02347     return CUBIT_PNT_UNKNOWN;
02348   }
02349 
02350   // one point is on the plane
02351 
02352   if (fabs(dstart) < GEOMETRY_RESABS)
02353   {
02354     qq = start;
02355   }
02356   else if (fabs(dend) < GEOMETRY_RESABS)
02357   {
02358     qq = end;
02359   }
02360 
02361   // points are both on the same side of the plane
02362   else if(dstart*dend > 0.0 &&
02363           (bound || fabs(dstart-dend) < CUBIT_RESABS) )
02364   {
02365     return CUBIT_PNT_OUTSIDE;
02366   }
02367   // points are on opposite sides of plane: if bound == false then compute intersection with plane
02368 
02369   else
02370   {
02371     CubitVector dir = end-start;
02372     dir.normalize();
02373     qq = fplane.intersect(start, dir);
02374   }
02375 
02376   FacetEvalTool::facet_area_coordinate( facet_ptr, qq, ac );
02377    
02378 //mod mbrewer ... the original code would call a point
02379     // on the boundary if any area coordinate was near
02380     // zero, regardless of whether another area coordinate
02381     // was negative... making it outside.
02382 //   if (fabs(ac.x()) < GEOMETRY_RESABS ||
02383 //       fabs(ac.y()) < GEOMETRY_RESABS ||
02384 //       fabs(ac.z()) < GEOMETRY_RESABS)
02385 //   {
02386 //     return CUBIT_PNT_BOUNDARY;
02387 //   }
02388   if ( (fabs(ac.x()) < GEOMETRY_RESABS && (ac.y() > -GEOMETRY_RESABS &&
02389                                            ac.z() > -GEOMETRY_RESABS) )||
02390        (fabs(ac.y()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
02391                                            ac.z() > -GEOMETRY_RESABS) )||
02392        (fabs(ac.z()) < GEOMETRY_RESABS && (ac.x() > -GEOMETRY_RESABS &&
02393                                            ac.y() > -GEOMETRY_RESABS) ) ){
02394     return CUBIT_PNT_BOUNDARY;
02395   }   
02396   else if (ac.x() < 0.0 || ac.y() < 0.0 || ac.z() < 0.0)
02397   {
02398     return CUBIT_PNT_OUTSIDE;
02399   }
02400 
02401   return CUBIT_PNT_INSIDE;
02402 }
02403 
02404 
02405 //=============================================================================
02406 //Function:  get_bbox_of_points (PUBLIC)
02407 //Description: Find the bounding box of a list of CubitPoints
02408 //Author: jdfowle
02409 //Date: 12/15/03
02410 //=============================================================================
02411 CubitStatus FacetDataUtil::get_bbox_of_points(DLIList<CubitPoint*>& point_list, CubitBox& bbox)
02412 {
02413 double x, y, z, min[3], max[3];
02414 int i;
02415 CubitPoint *point;
02416   min[0] = min[1] = min[2] = CUBIT_DBL_MAX;
02417   max[0] = max[1] = max[2] = -CUBIT_DBL_MAX + 1.;
02418 
02419   for ( i = 0; i < point_list.size(); i++ ) {
02420     point = point_list.get_and_step();
02421     x = point->x();
02422     if ( min[0] > x ) min[0] = x;
02423     if ( max[0] < x ) max[0] = x;
02424     y = point->y();
02425     if ( min[1] > y ) min[1] = y;
02426     if ( max[1] < y ) max[1] = y;
02427     z = point->z();
02428     if ( min[2] > z ) min[2] = z;
02429     if ( max[2] < z ) max[2] = z;
02430   }
02431   bbox.reset(min,max);
02432 
02433   return CUBIT_SUCCESS;
02434 }
02435 
02436 //=============================================================================
02437 //Function:  squared_distance_to_segment (PUBLIC)
02438 //Description: get square of distance from point to closest point on a line segment;
02439 //  returns closest point.  Taken from "Geometric Tools for Computer Graphics",
02440 // by Schneider & Eberly, sec. 6.1.
02441 //Author: jdfowle
02442 //Date: 03/08/03
02443 //=============================================================================
02444 CubitVector FacetDataUtil::squared_distance_to_segment(CubitVector &p, CubitVector &p0, 
02445                                                       CubitVector &p1, double &distance2)
02446 {
02447 CubitVector YmPO, D;
02448 double t;
02449 
02450   D = p1 - p0;
02451   YmPO = p - p0;
02452   t = D.x()*YmPO.x() + D.y()*YmPO.y() + D.z()*YmPO.z();
02453   
02454   if ( t < 0.0 ) {
02455     distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z();
02456     return p0;
02457   }
02458   
02459   double DdD;
02460   DdD = D.x()*D.x() + D.y()*D.y() + D.z()*D.z();
02461   if ( t >= DdD ) {
02462     CubitVector YmP1;
02463     YmP1 = p - p1;
02464     distance2 = YmP1.x()*YmP1.x() + YmP1.y()*YmP1.y() + YmP1.z()*YmP1.z();
02465     return p1;
02466   }
02467   
02468   //  closest point is interior to segment
02469   distance2 = YmPO.x()*YmPO.x() + YmPO.y()*YmPO.y() + YmPO.z()*YmPO.z() - t*t/DdD;
02470   return p0 + (t/DdD)*(p1 - p0);
02471 }
02472 
02473 //=============================================================================
02474 //Function:  get_bbox_intersections (PUBLIC)
02475 //Description: Get the intersection of the line defined by point1 and point2 with
02476 //bbox.  Returns 0,1 or 2 for the number of intersections.  A line
02477 //in one of the planes of the box will return 0.  Returns -1 for failure.
02478 //Author mborden
02479 //Date: 04/05/07
02480 //=============================================================================
02481 int FacetDataUtil::get_bbox_intersections(CubitVector& point1,
02482                                           CubitVector& point2,
02483                                           const CubitBox& bbox,
02484                                           CubitVector& intersection_1,
02485                                           CubitVector& intersection_2)
02486 {
02487   int debug = 0;
02488   if( debug )
02489   {
02490     GfxDebug::draw_point( point1, CUBIT_RED_INDEX );
02491     GfxDebug::draw_point( point2, CUBIT_BLUE_INDEX );
02492     GfxDebug::flush();
02493   }
02494   
02495   double coords[6];
02496   coords[0] = bbox.min_x();
02497   coords[1] = bbox.max_x();
02498   coords[2] = bbox.min_y();
02499   coords[3] = bbox.max_y();
02500   coords[4] = bbox.min_z();
02501   coords[5] = bbox.max_z();
02502 
02503   DLIList<CubitVector*> intersections;
02504   
02505   int ii;
02506   for( ii = 0; ii < 3; ii++ )
02507   {
02508       //Define four points for each plane.
02509     double box_points[4][3];
02510 
02511       //ii = 0 -> x-planes
02512       //ii = 1 -> y_planes
02513       //ii = 2 -> z_planes
02514 
02515       //Only the coordinates for the plane we are in
02516       //change.  The other two are constant for the
02517       //jj loops below.
02518     box_points[0][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
02519     box_points[1][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
02520     box_points[2][(ii + 1) % 3] = coords[((ii*2)+3) % 6];
02521     box_points[3][(ii + 1) % 3] = coords[((ii*2)+2) % 6];
02522 
02523     box_points[0][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
02524     box_points[1][(ii + 2) % 3] = coords[((ii*2)+4) % 6];
02525     box_points[2][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
02526     box_points[3][(ii + 2) % 3] = coords[((ii*2)+5) % 6];
02527       
02528     int jj;
02529     for( jj = 0; jj < 2; jj++ )
02530     {
02531       CubitPoint* points[4];
02532       int kk;
02533       for( kk = 0; kk < 4; kk++ )
02534       {
02535         box_points[kk][ii] = coords[(ii*2)+jj];
02536         points[kk] = new CubitPointData( box_points[kk][0], box_points[kk][1], box_points[kk][2] );
02537       }
02538       
02539         //Create two facets for this plane to check for intersections.
02540       CubitFacet* facets[2];
02541       facets[0] = new CubitFacetData( points[0], points[1], points[3] );
02542       facets[1] = new CubitFacetData( points[1], points[2], points[3] );
02543 
02544       for( kk = 0; kk < 2; kk++ )
02545       {
02546         CubitVector intersection;
02547         CubitVector area_coord;
02548 
02549           //Make sure the points are not parrellel with the facet.
02550         CubitVector dir = point2 - point1;
02551         CubitVector normal = facets[kk]->normal();
02552         if( fabs(dir % normal) < CUBIT_RESABS )
02553             continue;
02554         
02555         CubitPointContainment contain = intersect_facet( point1, point2, facets[kk],
02556                                                          intersection, area_coord, CUBIT_FALSE );
02557         if( CUBIT_PNT_UNKNOWN == contain )
02558         {
02559             //The points are in a plane.  Return 0.
02560           delete facets[0];
02561           delete facets[1];
02562           int ll;
02563           for( ll = 0; ll < 4; ll++ )
02564               delete points[ll];
02565           for( ll = intersections.size(); ll > 0; ll-- )
02566               delete intersections.get_and_step();
02567 
02568           return 0;
02569         }
02570         if( CUBIT_PNT_BOUNDARY == contain ||
02571             CUBIT_PNT_INSIDE == contain )
02572         {
02573             //The point intersects the facet so it's inside the box's surface.
02574           CubitVector* new_intersection = new CubitVector;
02575           *new_intersection = intersection;
02576           intersections.append( new_intersection );
02577 
02578           if( debug )
02579           {
02580             GfxDebug::draw_point( *new_intersection, CUBIT_CYAN_INDEX );
02581             GfxDebug::flush();
02582           }
02583           
02584           break;          
02585         }
02586       }
02587       
02588       delete facets[0];
02589       delete facets[1];
02590       for( kk = 0; kk < 4; kk++ )
02591           delete points[kk];      
02592     }
02593   }
02594 
02595     //Check for duplicate intersections.
02596   intersections.reset();
02597   for( ii = 0; ii < intersections.size(); ii++ )
02598   {
02599     CubitVector* base_vec = intersections.next(ii);
02600     if( NULL == base_vec )
02601         continue;
02602     
02603     int jj;
02604     for( jj = ii+1; jj < intersections.size(); jj++ )
02605     {
02606       CubitVector* compare_vec = intersections.next(jj);
02607       if( NULL != compare_vec )
02608       {
02609         if( base_vec->distance_between_squared( *compare_vec ) < GEOMETRY_RESABS * GEOMETRY_RESABS )
02610         {
02611           intersections.step(jj);
02612           delete intersections.get();
02613           intersections.change_to( NULL );
02614           intersections.reset();
02615         }
02616       }
02617     }
02618   }
02619   intersections.remove_all_with_value( NULL );
02620 
02621   
02622   if( intersections.size() > 2 )
02623   {
02624     assert( intersections.size() <= 2 );
02625     return -1;
02626   }
02627   else if( intersections.size() > 0 )
02628   {
02629     intersection_1 = *intersections.get();
02630     if( intersections.size() > 1 )
02631         intersection_2 = *intersections.next();
02632   }
02633   
02634     //Delete memory.
02635   for( ii = intersections.size(); ii > 0; ii-- )
02636       delete intersections.get_and_step();
02637   
02638   return intersections.size();
02639 }
02640 
02641 
02642 //=============================================================================
02643 //Function:  mark_facets (PUBLIC)
02644 //Description: mark facets and their children.  assumes facets have points and edges
02645 //Author sjowen
02646 //Date: 09/18/09
02647 //=============================================================================
02648 void FacetDataUtil::mark_facets( DLIList<FacetEntity *> &facet_list, int mark_value )
02649 {
02650   int ifacet;
02651   FacetEntity *facet_ptr;
02652   for (ifacet = 0; ifacet<facet_list.size(); ifacet++ )
02653   {
02654     facet_ptr = facet_list.get_and_step();
02655     CubitFacet *cfacet_ptr = dynamic_cast<CubitFacet *> (facet_ptr);
02656     if( cfacet_ptr )
02657     {
02658       cfacet_ptr->marked(mark_value);
02659       for (int ii=0; ii<3; ii++)
02660       {
02661         cfacet_ptr->point(ii)->marked(mark_value);
02662         cfacet_ptr->edge(ii)->marked(mark_value);
02663       }
02664     }
02665     else
02666     {
02667       CubitFacetEdge *edge_ptr = dynamic_cast<CubitFacetEdge*>(facet_ptr);
02668       if( edge_ptr )
02669       {
02670         edge_ptr->marked(mark_value);
02671         for (int ii=0; ii<2; ii++)        
02672           edge_ptr->point(ii)->marked(mark_value);                  
02673       }
02674     }
02675   }  
02676 }
02677 
02678 //==================================================================================
02679 // Description: identifies all the facets that contain given two cubit points
02680 //
02681 //
02682 // Notes:  
02683 // Author: william roshan quadros
02684 // Date: 3/30/2011
02685 //===================================================================================
02686 CubitStatus FacetDataUtil::find_facet( DLIList<CubitFacet *> temp_split_facets, CubitPoint *pnt0, CubitPoint *pnt1, DLIList<CubitFacet *>  &select_facets )
02687 {
02688   int i;
02689   CubitFacet *ptr_facet;
02690   for( i = 0; i < temp_split_facets.size(); i++ )
02691   {
02692     ptr_facet = temp_split_facets.get_and_step();
02693 
02694     if( ptr_facet->contains( pnt0 ) && ptr_facet->contains( pnt1 ) )
02695     {
02696       select_facets.append( ptr_facet);
02697     }
02698   }
02699 
02700   if( select_facets.size() )
02701     return CUBIT_SUCCESS;
02702   else
02703     return CUBIT_FAILURE;
02704 }
02705 
02706 
02707 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines