cgma
PartitionSurface.cpp
Go to the documentation of this file.
00001 #include "PartitionLump.hpp"
00002 #include "PartitionSurface.hpp"
00003 #include "PartitionLoop.hpp"
00004 #include "PartitionShell.hpp"
00005 #include "PartitionCurve.hpp"
00006 #include "VirtualQueryEngine.hpp"
00007 #include "PartitionEngine.hpp"
00008 #include "PartSurfFacetTool.hpp"
00009 #include "PartitionTool.hpp"
00010 
00011 #include "CubitFacetData.hpp"
00012 #include "TDVGFacetOwner.hpp"
00013 #include "GMem.hpp"
00014 #include "CubitPoint.hpp"
00015 #include "CubitPointData.hpp"
00016 #include "CubitFacetEdgeData.hpp"
00017 #include "CubitTransformMatrix.hpp"
00018 #include "GfxDebug.hpp"
00019 
00020 #include "RefVertex.hpp"
00021 
00022 void PartitionSurface::draw_facets( int color ) const
00023 {
00024   DLIList<CubitFacetData*> facets;
00025   get_facet_data(facets);
00026   int i;
00027   for ( i = facets.size(); i--; ) {
00028     CubitFacet* facet = facets.step_and_get();
00029     for ( int j = 0; j < 3; j++ )
00030       if ( facet->edge(j) )
00031         facet->edge(j)->marked(0);
00032   }
00033   for ( i = facets.size(); i--; ) {
00034     CubitFacet* facet = facets.step_and_get();
00035     for ( int j = 0; j < 3; j++ )
00036       if ( facet->edge(j) )
00037         facet->edge(j)->marked(facet->edge(j)->marked()+1);
00038   }
00039   
00040   
00041   for ( i = facets.size(); i--; ) {
00042     CubitFacetData* facet = facets.step_and_get();
00043     CubitVector pts[3] = {facet->point(0)->coordinates(),
00044                           facet->point(1)->coordinates(),
00045                           facet->point(2)->coordinates()};
00046     for ( int j = 0; j < 3; j++ )
00047     {
00048       CubitVector p1 = pts[j];
00049       CubitVector p2 = pts[(j+1)%3];
00050       int c = color == CUBIT_RED_INDEX ? color - 1 : CUBIT_RED_INDEX;
00051       CubitFacetEdge* edge = facet->edge((j+2)%3);
00052       if (!edge) continue;
00053       
00054       switch( edge->marked() ) {
00055           case 1: c = color + 1; break;
00056           case 2: c = color; break;
00057           default : c = color == CUBIT_RED_INDEX ? color - 1 : CUBIT_RED_INDEX;
00058        
00059         if (edge->marked()==1 && !TDVGFacetOwner::get(edge))
00060           PRINT_WARNING("Boundary edge in surface facetting not owned by a curve.\n");
00061       }
00062     
00063       GfxDebug::draw_line( (float)p1.x(), (float)p1.y(), (float)p1.z(), 
00064                       (float)p2.x(), (float)p2.y(), (float)p2.z(), c );
00065     }
00066     
00067     
00068     CubitVector center = ( pts[0] + pts[1] + pts[2] ) / 3.0;
00069     CubitVector normal = (pts[1] - pts[0]) * (pts[2] - pts[0]);
00070     double len = normal.length();
00071     if ( len > GEOMETRY_RESABS ) {
00072         normal /= sqrt(len);
00073 //      if ( len > 1e-2 )
00074 //        normal /= len;
00075 //      else
00076 //        normal.length(1.0);
00077 
00078         GfxDebug::draw_vector( center, center + normal, color );
00079     } else {
00080       GfxDebug::draw_point( center, color + 1 );
00081     }
00082   }
00083   GfxDebug::flush();
00084 
00085   for ( i = facets.size(); i--; ) {
00086     CubitFacet* facet = facets.step_and_get();
00087     for ( int j = 0; j < 3; j++ )
00088       if ( facet->edge(j) )
00089         facet->edge(j)->marked(0);
00090   }
00091 }
00092 
00093 void PartitionSurface::print_debug_info( const char* prefix ,
00094                                          bool print_sub_entity_set ) const
00095 {
00096   if( !prefix ) prefix = "";
00097   PRINT_INFO("%sPartitionSurface %p\n", prefix, (void*)this );
00098   PartitionLoop* loop = 0;
00099   while( (loop = next_loop(loop)) )
00100   {
00101     PRINT_INFO("%s  Loop %p:\n", prefix, (void*)loop );
00102     PartitionCoEdge* coedge = loop->first_coedge();
00103     do
00104     {
00105       PRINT_INFO("%s    CoEdge %p %s -> Curve %p\n",
00106         prefix, (void*)coedge, coedge->sense() == CUBIT_FORWARD ? "FORWARD" :
00107                         coedge->sense() == CUBIT_REVERSED ? "REVERSE" :
00108                         "UNKNOWN", (void*)coedge->get_curve() );
00109       coedge = loop->next_coedge(coedge);
00110     } while( coedge != loop->first_coedge() );
00111   }
00112 
00113   char buffer[128];
00114   sprintf(buffer,"%s  ",prefix);
00115   if( print_sub_entity_set )
00116     sub_entity_set().print_debug_info(buffer);
00117 } 
00118 
00119 PartitionSurface::PartitionSurface()
00120   : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0)
00121 {}
00122 
00123 PartitionSurface::PartitionSurface( PartitionLump* lump )
00124   : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0)
00125 {
00126   lump->sub_entity_set().add_lower_order( this );
00127 }
00128 
00129 PartitionSurface::~PartitionSurface()
00130 {
00131   while( firstLoop )
00132     remove( firstLoop );
00133   
00134   while( firstCoSurf )
00135   {
00136     PartitionCoSurf* cos = firstCoSurf;
00137     if( cos->get_shell() )
00138       cos->get_shell()->remove( cos );
00139     remove( cos );
00140     delete cos;
00141     assert( firstCoSurf != cos );
00142   }
00143   
00144     // delete facets
00145   DLIList<CubitPoint*> facet_points(3);
00146   DLIList<CubitFacetEdge*> facet_edges(3);
00147   while( facetList.size() )
00148   {
00149     CubitFacet* facet = facetList.pop();
00150     facet_edges.clean_out();
00151     facet->edges(facet_edges);
00152     facet_points.clean_out();
00153     facet->points(facet_points);
00154     TDVGFacetOwner::remove(facet);
00155     delete facet;
00156     
00157     PartitionCurve* curve;
00158     while( facet_edges.size() )
00159     {
00160       CubitFacetEdge* edge = facet_edges.pop();
00161       if( edge && !edge->num_adj_facets() ) {
00162         if ( TDVGFacetOwner::get(edge) ) {
00163           curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
00164           curve->remove_facet_data();
00165         }
00166         delete edge;
00167       }
00168     }
00169     
00170     PartitionPoint* ppoint;
00171     while( facet_points.size() )
00172     {
00173       CubitPoint* point = facet_points.pop();
00174       if( point && !point->num_adj_facets() ) {
00175         if ( TDVGFacetOwner::get(point) ) {
00176           ppoint = dynamic_cast<PartitionPoint*>(TDVGFacetOwner::get(point));
00177           if( ppoint )
00178             ppoint->facet_point(0);
00179         }
00180         delete point;
00181       }
00182     }
00183   }
00184 }
00185 
00186 CubitStatus PartitionSurface::add( PartitionLoop* loop )
00187 {
00188   if( loop->mySurface )
00189     return CUBIT_FAILURE;
00190   
00191   loop->mySurface = this;
00192   loop->nextInSurface = firstLoop;
00193   firstLoop = loop;
00194   return CUBIT_SUCCESS;
00195 }
00196   
00197   
00198 CubitStatus PartitionSurface::remove( PartitionLoop* loop )
00199 {
00200   if( loop->mySurface != this )
00201     return CUBIT_FAILURE;
00202   
00203   if( firstLoop == loop )
00204   {
00205     firstLoop = loop->nextInSurface;
00206   }
00207   else
00208   {
00209     PartitionLoop* prev = firstLoop;
00210     while( prev && prev->nextInSurface != loop )
00211       prev = prev->nextInSurface;
00212     
00213     if( !prev )
00214     {
00215       assert(0);
00216       return CUBIT_FAILURE;
00217     }
00218     
00219     prev->nextInSurface = loop->nextInSurface;
00220   }
00221   
00222   loop->mySurface = 0;
00223   loop->nextInSurface = 0;
00224   return CUBIT_SUCCESS;
00225 }
00226 
00227 int PartitionSurface::num_loops() const
00228 {
00229   int count = 0;
00230   for( PartitionLoop* loop = firstLoop; loop; loop = loop->nextInSurface )
00231     count++;
00232   return count;
00233 }
00234 
00235 CubitStatus PartitionSurface::add( PartitionCoSurf* cosurf )
00236 {
00237   if( cosurf->mySurface )
00238     return CUBIT_FAILURE;
00239   
00240   cosurf->mySurface = this;
00241   cosurf->surfaceNext = firstCoSurf;
00242   firstCoSurf = cosurf;
00243   return CUBIT_SUCCESS;
00244 }
00245 
00246 CubitStatus PartitionSurface::remove( PartitionCoSurf* cosurf )
00247 {
00248   if( cosurf->mySurface != this )
00249     return CUBIT_FAILURE;
00250   
00251   if( cosurf == firstCoSurf )
00252   {
00253     firstCoSurf = cosurf->surfaceNext;
00254   }
00255   else
00256   {
00257     PartitionCoSurf* prev = firstCoSurf;
00258     while( prev && prev->surfaceNext != cosurf )
00259       prev = prev->surfaceNext;
00260     
00261     if( !prev ) { assert(prev != NULL); return CUBIT_FAILURE; }
00262     
00263     prev->surfaceNext = cosurf->surfaceNext;
00264   }
00265   
00266   cosurf->mySurface = 0;
00267   cosurf->surfaceNext = 0;
00268   return CUBIT_SUCCESS;
00269 }
00270 
00271 PartitionCoSurf* PartitionSurface::find_first( const PartitionShell* shell ) const
00272 {
00273   PartitionCoSurf* cos = firstCoSurf;
00274   while( cos && cos->get_shell() != shell )
00275     cos = cos->surfaceNext;
00276   return cos;
00277 }
00278 
00279 
00280 PartitionCoSurf* PartitionSurface::find_first( const PartitionLump* lump ) const
00281 {
00282   PartitionCoSurf* cos = firstCoSurf;
00283   while( cos && (!cos->get_shell() || cos->get_shell()->get_lump() != lump ) )
00284     cos = cos->surfaceNext;
00285   return cos;
00286 }
00287 
00288 PartitionCoSurf* PartitionSurface::find_next( const PartitionCoSurf* prev ) const
00289 {
00290   if( prev->mySurface != this )
00291     return 0;
00292   PartitionCoSurf* cos = prev->surfaceNext;
00293   while( cos && cos->get_shell() != prev->get_shell() )
00294     cos = cos->surfaceNext;
00295   return cos;
00296 }
00297 
00298 PartitionCoSurf* PartitionSurface::find_first( const PartitionShell* shell,
00299                                                CubitSense sense ) const
00300 {
00301   PartitionCoSurf* cos = firstCoSurf;
00302   while( cos && (cos->get_shell() != shell || cos->sense() != sense) )
00303     cos = cos->surfaceNext;
00304   return cos;
00305 }
00306 
00307 //-------------------------------------------------------------------------
00308 // Purpose       : Get child point bridges
00309 //
00310 // Special Notes : 
00311 //
00312 // Creator       : Jason Kraftcheck
00313 //
00314 // Creation Date : 
00315 //-------------------------------------------------------------------------
00316 void PartitionSurface::get_points( DLIList<PartitionPoint*>& list ) const
00317 {
00318   PartitionLoop* loop = 0;
00319   while ( (loop = next_loop(loop)) ) 
00320   {
00321     PartitionCoEdge* coedge = loop->first_coedge();
00322     do 
00323     {
00324       PartitionCurve* curve = coedge->get_curve();
00325 
00326       list.append( curve->start_point() );
00327       list.append( curve->end_point() );
00328       
00329       coedge = loop->next_coedge(coedge);
00330     } while( coedge != loop->first_coedge() );
00331   }
00332   
00333   list.reset();
00334   int i;
00335   for ( i = list.size(); i--; )
00336     list.get_and_step()->mark = 1;
00337   
00338   for ( i = list.size(); i--; )
00339   {
00340     list.back();
00341     if( list.get()->mark )
00342       list.get()->mark = 0;
00343     else  
00344       list.change_to(0);
00345   }
00346   list.remove_all_with_value(0);
00347 }
00348 
00349 
00350     
00351 
00352 GeometryQueryEngine* PartitionSurface::get_geometry_query_engine() const
00353 {
00354   return VirtualQueryEngine::instance();
00355 }
00356 
00357 void PartitionSurface::get_children_virt( DLIList<TopologyBridge*>& list )
00358 {
00359   for( PartitionLoop* loop = firstLoop; loop; loop = loop->nextInSurface )
00360     list.append( loop );
00361 }
00362 
00363 void PartitionSurface::get_parents_virt( DLIList<TopologyBridge*>& result_list )
00364 {
00365   Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity());
00366   if( ! real_surf )
00367   { 
00368     for( PartitionCoSurf* cos = firstCoSurf; cos; cos = cos->surfaceNext )
00369       if( cos->get_shell() )
00370         result_list.append_unique( cos->get_shell() );
00371   }
00372   else
00373   {
00374     int i;
00375     DLIList<TopologyBridge*> real_surf_shells, tmp_list;
00376     real_surf->get_parents_virt( real_surf_shells );
00377     
00378       // get real volumes from real shells
00379     DLIList<TopologyBridge*> real_surf_vols(real_surf_shells.size());
00380     real_surf_shells.reset();
00381     for( i = real_surf_shells.size(); i--; )
00382     {
00383       tmp_list.clean_out();
00384       real_surf_shells.get_and_step()->get_parents_virt( tmp_list );
00385       assert(tmp_list.size() == 1);
00386       real_surf_vols.append(tmp_list.get());
00387     }
00388 
00389       // replace real volumes with owning partition volumes (if any)
00390     DLIList<TopologyBridge*> vol_list(real_surf_vols.size());
00391     real_surf_vols.reset();
00392     for( i = real_surf_vols.size(); i--; )
00393     {
00394       TopologyBridge* vol_bridge = real_surf_vols.get_and_step();
00395       SubEntitySet* set = dynamic_cast<SubEntitySet*>(vol_bridge->owner());
00396       if( set )
00397       {
00398         tmp_list.clean_out();
00399         set->get_owners(tmp_list);
00400         vol_list += tmp_list;
00401       }
00402       else
00403         vol_list.append(vol_bridge);
00404     }
00405     
00406       // for each volume, get all child shells that are parents of this
00407     vol_list.reset();
00408     DLIList<TopologyBridge*> vol_shells;
00409     for( i = vol_list.size(); i--; )
00410     {
00411       vol_shells.clean_out();
00412       vol_list.get_and_step()->get_children( vol_shells, false, layer() );
00413       vol_shells.reset();
00414       for( int j = vol_shells.size(); j--; )
00415       {
00416         TopologyBridge* shell = vol_shells.get_and_step();
00417         tmp_list.clean_out();
00418         shell->get_children( tmp_list, false, layer() );
00419         if( tmp_list.is_in_list(this) )
00420           result_list.append(shell);
00421       }
00422     }
00423   }
00424 }
00425 
00426 CubitSense PartitionSurface::get_shell_sense( ShellSM* shell_ptr ) const
00427 {
00428   if( PartitionShell* pshell = dynamic_cast<PartitionShell*>(shell_ptr) )
00429     return pshell->find_sense( this );
00430   
00431   Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity());
00432   if( real_surf )
00433   { 
00434     DLIList<TopologyBridge*> list(2);
00435     real_surf->get_parents_virt( list );
00436     if( list.is_in_list( shell_ptr ) )
00437       return real_surf->get_shell_sense( shell_ptr );
00438   }
00439   
00440   return CUBIT_UNKNOWN;
00441 }
00442 
00443 
00444 void PartitionSurface::append_simple_attribute_virt(const CubitSimpleAttrib& csa)
00445 { sub_entity_set().add_attribute( this, csa ); }
00446 void PartitionSurface::remove_simple_attribute_virt(const CubitSimpleAttrib& csa)
00447 { sub_entity_set().rem_attribute( this, csa ); }
00448 void PartitionSurface::remove_all_simple_attribute_virt()
00449 { sub_entity_set().rem_all_attrib( this ); }
00450 CubitStatus PartitionSurface::get_simple_attribute(DLIList<CubitSimpleAttrib>& list)
00451 { 
00452   sub_entity_set().get_attributes( this, list ); 
00453   return CUBIT_SUCCESS;
00454 }
00455 CubitStatus PartitionSurface::get_simple_attribute(const CubitString& name,
00456                                        DLIList<CubitSimpleAttrib>& list)
00457 { 
00458   sub_entity_set().get_attributes( this, name.c_str(), list ); 
00459   return CUBIT_SUCCESS;
00460 }
00461 
00462 void PartitionSurface::reverse_loops()
00463 {
00464   PartitionLoop* loop = 0;
00465   while( (loop = next_loop(loop)) )
00466     loop->reverse();
00467 }
00468 
00469 CubitBox PartitionSurface::bounding_box() const
00470 {
00471   int i, j;
00472   CubitFacet* facet;
00473   for ( i = 0; i< facetList.size(); i++ ) {
00474     facet = facetList.next(i);
00475     facet->point(0)->marked(1);
00476     facet->point(1)->marked(1);
00477     facet->point(2)->marked(1);
00478   }
00479   
00480   facet = facetList.get();
00481   CubitBox result(facet->point(0)->coordinates());
00482   facet->point(0)->marked(0);
00483   
00484   for ( i = 0; i< facetList.size(); i++ ) {
00485     facet = facetList.next(i);
00486     for ( j = 0; j < 3; j++ ) {
00487       if ( facet->point(j)->marked() ) {
00488         facet->point(j)->marked(0);
00489         result |= facet->point(j)->coordinates();
00490       }
00491     }
00492   }
00493   
00494   return result;
00495 }
00496 
00497   
00498   
00499 
00500 double PartitionSurface::measure()
00501 { 
00502   double result = 0.;
00503   for ( int i = facetList.size(); i--; )
00504     result += facetList.step_and_get()->area();
00505   return result;
00506 }
00507 
00508 GeometryType PartitionSurface::geometry_type()
00509 {
00510   return FACET_SURFACE_TYPE;
00511 }
00512 
00513 void PartitionSurface::closest_point_trimmed( CubitVector f, CubitVector& r )
00514 { 
00515   closest_facet( f, r );
00516 }
00517 
00518 CubitStatus PartitionSurface::closest_point_along_vector(CubitVector& from_point, 
00519                                           CubitVector& along_vector,
00520                                           CubitVector& point_on_surface)
00521 {
00522   return CUBIT_FAILURE;
00523 }
00524 
00525 CubitStatus PartitionSurface::get_point_normal( CubitVector &, CubitVector & )
00526 {
00527   return CUBIT_FAILURE;
00528 }
00529 
00530 CubitStatus PartitionSurface::move_to_geometry( CubitVector& pos )
00531 {
00532   const CubitVector copy(pos);
00533   return closest_point( copy, &pos );
00534 }
00535 
00536 CubitStatus PartitionSurface::closest_point_uv_guess(  
00537     CubitVector const& location,
00538     double&, double&,
00539     CubitVector* closest_location,
00540     CubitVector* unit_normal )
00541 {
00542   return closest_point(location, closest_location, unit_normal);
00543 }
00544 
00545 
00546 CubitStatus PartitionSurface::closest_point( const CubitVector& position,
00547                                              CubitVector* closest,
00548                                              CubitVector* normal,
00549                                              CubitVector* curvature1,
00550                                              CubitVector* curvature2 )
00551 {
00552   if ( closest || normal )
00553   {
00554     CubitVector tmp_closest;
00555     CubitFacet* facet = closest_facet( position, tmp_closest );
00556     if ( closest )
00557       *closest = tmp_closest;
00558     if ( normal )
00559       *normal = facet->normal();
00560   }
00561   
00562   if( curvature1 )
00563     curvature1->set( 0.0, 0.0, 0.0 );
00564   if( curvature2 )
00565     curvature2->set( 0.0, 0.0, 0.0 );
00566   
00567   return CUBIT_SUCCESS;
00568 }
00569 
00570 CubitStatus PartitionSurface::principal_curvatures( 
00571                                        const CubitVector& ,
00572                                        double&, double& ,
00573                                        CubitVector* )
00574 {
00575   return CUBIT_FAILURE;
00576 }
00577 
00578 CubitVector PartitionSurface::position_from_u_v( double , double  )
00579 {
00580   return CubitVector(0.0,0.0,0.0);
00581 }
00582 
00583 CubitStatus PartitionSurface::u_v_from_position( const CubitVector& ,
00584                                                  double&, double &,
00585                                                  CubitVector* )
00586 {
00587   return CUBIT_FAILURE;
00588 }
00589 
00590 CubitBoolean PartitionSurface::is_periodic()
00591 {
00592   return CUBIT_FALSE;
00593 }
00594 
00595 CubitBoolean PartitionSurface::is_periodic_in_U( double& )
00596 {
00597   return  CUBIT_FALSE;
00598 }
00599 
00600 CubitBoolean PartitionSurface::is_periodic_in_V( double& )
00601 {
00602   return CUBIT_FALSE;
00603 }
00604 
00605 CubitBoolean PartitionSurface::is_singular_in_U( double )
00606 {
00607   return CUBIT_FALSE;
00608 }
00609 
00610 CubitBoolean PartitionSurface::is_singular_in_V( double )
00611 {
00612   return  CUBIT_FALSE;
00613 }
00614 
00615 CubitBoolean PartitionSurface::is_closed_in_U()
00616 {
00617   return CUBIT_FALSE;
00618 }
00619 
00620 CubitBoolean PartitionSurface::is_closed_in_V()
00621 {
00622   return  CUBIT_FALSE;
00623 }
00624 
00625 CubitStatus PartitionSurface::uv_derivitives( double , double , 
00626                                               CubitVector& ,
00627                                               CubitVector&  )
00628 {
00629   return CUBIT_FAILURE;
00630 }
00631 
00632 CubitBoolean PartitionSurface::is_parametric()
00633 {
00634   return CUBIT_FALSE;
00635 }
00636 
00637 CubitBoolean PartitionSurface::get_param_range_U( double& , double&  )
00638 {
00639   return CUBIT_FALSE;
00640 }
00641 
00642 CubitBoolean PartitionSurface::get_param_range_V( double&, double& )
00643 {
00644   return CUBIT_FALSE;
00645 }
00646 
00647 CubitBoolean PartitionSurface::is_position_on( CubitVector& position )
00648 {
00649   const double tolsqr = GEOMETRY_RESABS * GEOMETRY_RESABS;
00650   CubitVector closest;
00651   closest_facet( position, closest );
00652   double distsqr = (position - closest).length_squared();
00653   return (CubitBoolean)(distsqr < tolsqr);
00654 }
00655 
00656 CubitPointContainment PartitionSurface::point_containment( const CubitVector& point )
00657 {
00658   PartitionCurve* curve = 0;
00659   CubitPointContainment result = point_containment( point, curve );
00660   if ( curve ) {
00661     CubitVector curve_closest;
00662     curve->closest_point( point, curve_closest );
00663     if ( (point - curve_closest).length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS )
00664       result = CUBIT_PNT_BOUNDARY;
00665   }
00666   return result;
00667 }
00668 
00669 CubitPointContainment PartitionSurface::point_containment( const CubitVector& point,
00670                                                        PartitionCurve*& curve )
00671 {
00672   CubitVector facet_pos;
00673   CubitFacet* facet = closest_facet(point, facet_pos);
00674   
00675   int i;
00676   double tol = 10*GEOMETRY_RESABS;
00677   int closest_edge = -1;
00678   CubitPoint* closest_point = 0;
00679   double closest_dist_sqr = CUBIT_DBL_MAX;
00680   CubitVector closest_pos;
00681   CubitFacetEdge* edge;
00682   
00683     // Find closest edge/point on facet
00684   for ( i = 0; i < 3; i++ ) 
00685   {
00686     edge = facet->edge(i);
00687     
00688     CubitVector start = edge->point(0)->coordinates();
00689     CubitVector end   = edge->point(1)->coordinates();
00690     CubitVector dir = end - start;
00691     double len_sqr = dir.length_squared();
00692     double t = (dir % (point - start)) / len_sqr;
00693     double len = sqrt(len_sqr);
00694     double dist_from_start = t * len;
00695     double dist_from_end   = (1.0 - t) * len;
00696     CubitPoint* facet_point = 0;
00697     CubitVector pos;
00698     if ( dist_from_start < tol ) 
00699     {
00700       pos = start;
00701       facet_point = edge->point(0);
00702     }
00703     else if( dist_from_end < tol ) 
00704     {
00705       pos = end;
00706       facet_point = edge->point(1);
00707     }
00708     else 
00709       pos = t * dir + start;
00710      
00711     double dist_sqr = (pos - point).length_squared();
00712     if ( dist_sqr < closest_dist_sqr ) 
00713     {
00714       closest_edge = i;
00715       closest_point = facet_point;
00716       closest_dist_sqr = dist_sqr;
00717       closest_pos = pos;
00718     }
00719   }
00720   
00721   edge = facet->edge(closest_edge);
00722   
00723     // If closest to an edge (not a point) ...
00724   if ( !closest_point ) 
00725   {
00726       // If the edge is not on the boundary of the surface facets...
00727     curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
00728     if ( !curve || curve->is_nonmanifold(this) )
00729       return CUBIT_PNT_INSIDE;  // not a boundary edge
00730   
00731       // If within tolerance of boundary
00732     if ( (point - closest_pos).length_squared() < tol*tol )
00733       return CUBIT_PNT_BOUNDARY;
00734     
00735       // Check which side of the edge the point is on
00736     CubitVector dir = edge->point(1)->coordinates() - edge->point(0)->coordinates();
00737     if ( facet->edge_use(closest_edge) == -1 )
00738       dir = -dir;
00739     double dot = facet->normal() % ((closest_pos - point) * dir);
00740     if ( dot < 0.0 )
00741       return CUBIT_PNT_OUTSIDE;
00742     else
00743       return CUBIT_PNT_INSIDE;
00744   }
00745   
00746   
00747     // Get two boundary edges adjacent to point
00748   DLIList<CubitFacetEdge*> edge_list;
00749   closest_point->edges( edge_list );
00750   for ( i = edge_list.size(); i--; )
00751   {
00752     edge = edge_list.step_and_get();
00753     curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(edge));
00754     if ( !curve || !curve->is_in_surface(this,true) )
00755       edge_list.change_to(0);
00756   }
00757   edge_list.remove_all_with_value(0);
00758   
00759   if (!edge_list.size())
00760     return CUBIT_PNT_INSIDE;
00761 
00762   if (edge_list.size() > 2) 
00763   {
00764     // This is a special case.  The point was closest to an
00765     // intersection of more than two curves on the surface boundary
00766     // (for example the point where a circular hole is tangent to
00767     //  the boundary of the surface.).  If the input position is closest
00768     //  to such a point it must be outside the surface (or on the boundary).
00769     // However, a little work is required to decide which curve to pass back.
00770     DLIList<PartitionCurve*> curve_list;
00771     while (edge_list.size())
00772     {
00773       PartitionEntity* owner = TDVGFacetOwner::get(edge_list.pop());
00774       curve_list.append_unique( dynamic_cast<PartitionCurve*>(owner) );
00775     }
00776     assert( !! TDVGFacetOwner::get(closest_point) );
00777     closest_dist_sqr = CUBIT_DBL_MAX;
00778     curve = 0;
00779     while (curve_list.size())
00780     {
00781       PartitionCurve* temp_curve = curve_list.pop();
00782       temp_curve->closest_point( point, closest_pos );
00783       if ( (point - closest_pos).length_squared() < closest_dist_sqr )
00784       {
00785         curve = temp_curve;
00786         closest_dist_sqr = (point - closest_pos).length_squared();
00787       }
00788     }
00789     
00790     if ( (point - closest_point->coordinates()).length_squared() < tol*tol )
00791       return CUBIT_PNT_BOUNDARY;
00792     else
00793       return CUBIT_PNT_OUTSIDE;
00794   }
00795     
00796      
00797   
00798   assert(edge_list.size() == 2);
00799   CubitFacetEdge *bdy_edges[2] = {edge_list.get(), edge_list.next()};
00800   
00801   
00802     // need to pass back a curve
00803   curve = dynamic_cast<PartitionCurve*>(TDVGFacetOwner::get(bdy_edges[0]));
00804   
00805     // If within tolerance of boundary
00806   if ( (point - closest_pos).length_squared() < tol*tol )
00807     return CUBIT_PNT_BOUNDARY;
00808 
00809     // Fill arrays for each of two boundary edges
00810   CubitFacet* bdy_facets[2] = {0,0};      // adjacent facet
00811   bool inside_facets[2] = {false,false};  // inside/outside of facet
00812   CubitPoint* start_pts[2], *end_pts[2];  // edge points
00813   for ( int j = 0; j < 2; j++ )
00814   {
00815     for ( i = 0; i < bdy_edges[j]->num_adj_facets(); i++ )
00816     {
00817       CubitFacet* facet = bdy_edges[j]->adj_facet(i);
00818       if ( TDVGFacetOwner::get(facet) == this ) 
00819       {
00820         bdy_facets[j] = facet;
00821         break;
00822       }
00823     }
00824     assert(!!bdy_facets[j]);
00825     
00826     int index = bdy_facets[j]->edge_index(bdy_edges[j]);
00827     if ( bdy_facets[j]->edge_use(index) < 0 ) {
00828       start_pts[j] = bdy_edges[j]->point(1);
00829       end_pts[j] = bdy_edges[j]->point(0);
00830     } else {
00831       start_pts[j] = bdy_edges[j]->point(0);
00832       end_pts[j] = bdy_edges[j]->point(1);
00833     }   
00834     CubitVector dir = end_pts[j]->coordinates() - start_pts[j]->coordinates(); 
00835     double dot = facet->normal() % ((closest_pos - point) * dir);
00836     inside_facets[j] = dot > 0.0;
00837   }
00838   
00839     // mean normal for facets
00840   CubitVector normal = bdy_facets[0]->normal();
00841   normal += bdy_facets[1]->normal();
00842   
00843     // cross product of edge vectors
00844     // if we had edges in wrong order, need to reverse
00845     // crossproduct
00846   CubitVector cross;
00847   CubitVector dir1 = end_pts[0]->coordinates() - start_pts[0]->coordinates();
00848   CubitVector dir2 = end_pts[1]->coordinates() - start_pts[1]->coordinates();
00849   if ( end_pts[0] == closest_point && start_pts[1] == closest_point )
00850   {
00851     cross = dir1 * dir2;
00852   }
00853   else
00854   {
00855     assert( start_pts[0] == closest_point && end_pts[1] == closest_point );
00856     cross = dir2 * dir1;
00857   }
00858   
00859   bool convex = (cross % normal) > 0.0;
00860   if ( convex )
00861     return inside_facets[0] && inside_facets[1] ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE;
00862   else
00863     return inside_facets[0] || inside_facets[1] ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE;
00864 }
00865 
00866 
00867 
00868 
00869 CubitPointContainment PartitionSurface::point_containment( double , double )
00870 {
00871   return CUBIT_PNT_UNKNOWN;
00872 }
00873 /*
00874 CubitPointContainment PartitionSurface::point_containment( 
00875             CubitVector& point, double u, double v )
00876 {
00877   return point_containment( point );
00878 }
00879 */
00880 CubitSense PartitionSurface::get_geometry_sense()
00881 { 
00882   return geometry_sense;
00883 }
00884 
00885 void PartitionSurface::reverse_sense()
00886 {
00887   reverse_loops();
00888   if( owner() )
00889     owner()->notify_reversed(this);
00890 
00891   if(geometry_sense == CUBIT_FORWARD)
00892     geometry_sense = CUBIT_REVERSED;
00893   else
00894     geometry_sense = CUBIT_FORWARD;
00895 
00896   int j;
00897   DLIList<CubitFacetData*> surf_facets;
00898   this->get_facet_data( surf_facets );
00899   for(j=surf_facets.size(); j--;)
00900     surf_facets.get_and_step()->flip();
00901 }
00902 
00903 PartitionSurface::PartitionSurface( PartitionSurface* split_from )
00904   : geometry_sense(CUBIT_FORWARD), firstLoop(0), firstCoSurf(0)
00905 {
00906   split_from->sub_entity_set().add_lower_order( this );
00907 }
00908   
00909 PartitionSurface* PartitionSurface::copy()
00910 {
00911   return new PartitionSurface(this);
00912 }
00913 
00914 PartitionSurface* PartitionSurface::split( DLIList<CubitFacetData*>& facets )
00915 {
00916   int i;
00917   bool okay = true;
00918   
00919     // mark facets
00920   for( i = facets.size(); i--; )
00921     facets.get_and_step()->marked(0);
00922   for( i = facetList.size(); i--; )
00923     facetList.get_and_step()->marked(1);
00924     
00925     // make sure all facets in passed list are in my list,
00926     // and clear the marks
00927   for( i = facets.size(); i--; ) {
00928     CubitFacetData* facet = facets.get_and_step();
00929     if( facet->marked() )
00930       facet->marked(0);
00931     else
00932       okay = false;
00933   }
00934   
00935   if (!okay) {
00936     for( i = facetList.size(); i--; )
00937       facetList.get_and_step()->marked(0);
00938     assert(okay);
00939     return 0;
00940   }
00941   
00942   for( i = facetList.size(); i--; ) {
00943     if( facetList.step_and_get()->marked() )
00944       facetList.get()->marked(0);
00945     else
00946       facetList.change_to(0);
00947   }
00948   facetList.remove_all_with_value(0);
00949   
00950   PartitionSurface* result = copy();
00951   result->set_facet_data(facets);
00952   return result;
00953 }
00954 
00955 CubitStatus PartitionSurface::combine( PartitionSurface* other_surf )
00956 {
00957   for ( int i = other_surf->facetList.size(); i--;  )
00958     TDVGFacetOwner::set(other_surf->facetList.step_and_get(),this);
00959   facetList += other_surf->facetList;
00960   other_surf->facetList.clean_out();
00961   return CUBIT_SUCCESS;
00962 }
00963 
00964 void PartitionSurface::get_facet_data( DLIList<CubitFacetData*>& result_list ) const
00965 {
00966   result_list = facetList;
00967 }
00968 
00969 void PartitionSurface::set_facet_data( const DLIList<CubitFacetData*>&  new_list )
00970 {
00971   int i;
00972   
00973   for ( i = facetList.size(); i--; )
00974     TDVGFacetOwner::remove(facetList.step_and_get());
00975   facetList = new_list;
00976   for ( i = facetList.size(); i--; )
00977     TDVGFacetOwner::set(facetList.step_and_get(),this);
00978 }  
00979   
00980 void PartitionSurface::notify_split( FacetEntity* old_tri, FacetEntity* new_tri )
00981 {
00982   if ( dynamic_cast<CubitFacetEdge*>(old_tri) )
00983     return;
00984   
00985   CubitFacetData* new_ptr = dynamic_cast<CubitFacetData*>(new_tri);
00986 #ifndef NDEBUG
00987   CubitFacetData* old_ptr = dynamic_cast<CubitFacetData*>(old_tri);
00988   assert(old_ptr && new_ptr && facetList.is_in_list(old_ptr));
00989 #endif
00990   TDVGFacetOwner::set(new_ptr,this);
00991   facetList.append(new_ptr);
00992 }
00993 
00994 CubitStatus PartitionSurface::init_facet_data()
00995 {
00996   Surface* real_surf = dynamic_cast<Surface*>(partitioned_entity());
00997   //assert(are_marks_cleared());
00998 
00999   CubitStatus res = CUBIT_SUCCESS;
01000   GMem gMem;
01001   
01002   // TODO - tolerance arguments are defaulted.  Do we need to specify?
01003   res = real_surf->get_geometry_query_engine()->
01004     get_graphics(real_surf, &gMem, PartitionTool::instance()->get_faceting_tolerance() );
01005   if( !res )
01006     return CUBIT_FAILURE;
01007 
01008   // Work around  bug w/ coincident facet points
01009   // for blend surfaces.  Consolidate coincident points.
01010   int old_count = gMem.pointListCount;
01011   gMem.consolidate_points(GEOMETRY_RESABS);
01012   if( old_count != gMem.pointListCount ) {
01013     PRINT_WARNING("Possible invalid facetting for surface.  "
01014                   "Coincident points found.\n");
01015   }
01016 
01017   DLIList<CubitFacetData*> surf_facets;
01018   CubitPointData** point_array = new CubitPointData*[gMem.pointListCount];
01019 
01020   // create CubitFacetData from GMem
01021   int i;
01022    
01023   CubitVector ipos, opos;
01024   for ( i = 0; i < gMem.pointListCount; i++ ) {
01025     ipos.set( gMem.point_list()[i].x, gMem.point_list()[i].y, gMem.point_list()[i].z );
01026     if( real_surf->closest_point( ipos, &opos ) )
01027       ipos = opos;
01028     point_array[i] = new CubitPointData( ipos );
01029   }
01030 
01031   int junk = 0;
01032   bool fail_out = false;
01033   CubitPoint *p1, *p2, *p3;
01034   for ( i = 0; i < gMem.fListCount; i += 4 ) 
01035   {
01036     if(gMem.facet_list()[i] != 3)
01037       fail_out = true;
01038     else
01039     {
01040       p1 = point_array[ gMem.facet_list()[i+1] ];
01041       p2 = point_array[ gMem.facet_list()[i+2] ];
01042       p3 = point_array[ gMem.facet_list()[i+3] ];
01043 
01044       if(p1 == p2 || p1 == p3 || p2 == p3)
01045         fail_out = true;
01046     }
01047     if(fail_out == true)
01048     {
01049       PRINT_ERROR("Non-triangular facet encountered.  Aborting.\n");
01050       while (surf_facets.size())
01051         delete surf_facets.pop();
01052       for (i = 0; i < gMem.pointListCount; i++)
01053         delete point_array[i];
01054       delete [] point_array;
01055       return CUBIT_FAILURE;
01056     }
01057     else
01058     {
01059       CubitFacetData* facet = new CubitFacetData(p1, p2, p3, &junk );
01060       surf_facets.append(facet);
01061     }
01062   }
01063   
01064   delete [] point_array; 
01065 
01066   if(geometry_sense == CUBIT_REVERSED)
01067   {
01068     for(i=surf_facets.size(); i--;)
01069       surf_facets.get_and_step()->flip();
01070   }
01071   
01072 /*  
01073     // Make sure facet orientation is consistant
01074   DLIList<CubitFacet*> facets(surf_facets.size());
01075   for ( i = surf_facets.size(); i--; )
01076   {
01077     CubitFacet* facet = surf_facets.step_and_get();
01078     facet->marked(1);
01079     facets.append(facet);
01080   }
01081   bool reversed_some = false;
01082   while ( facets.size() )
01083   {
01084     CubitFacet* facet = facets.pop();
01085     facet->marked(0);
01086     bool reversed[3] = {false,false,false};
01087     CubitFacet* neighbors[3] = {0,0,0};
01088     for ( i = 0; i < 3; i++ )
01089     {
01090       CubitFacetEdge* edge = facet->edge(i);
01091       CubitFacet* other = edge->other_facet(facet);
01092       if( other && other != facet )
01093       {
01094         neighbors[i] = other;
01095         int index = other->edge_index(edge);
01096         if ( facet->edge_use(i) == other->edge_use(index) )
01097           reversed[i] = true;
01098       }
01099     }
01100     
01101     if ( !(reversed[0] || reversed[1] || reversed[2]) )
01102       continue;
01103 
01104     facet->flip();
01105     reversed_some = true;
01106     reversed[0] = !reversed[0];
01107     reversed[1] = !reversed[1];
01108     reversed[2] = !reversed[2];
01109     
01110     for ( i = 0; i < 3; i++ )
01111     {
01112       if( neighbors[i] && reversed[i] && !neighbors[i]->marked() )
01113       {
01114         neighbors[i]->marked(1);
01115         facets.append( neighbors[i] );
01116       }
01117     }
01118   }
01119   
01120   if( reversed_some ) 
01121   {
01122     PRINT_WARNING("Possible invalid facetting for surface.  "
01123                   "Inconsistent facet orientation.\n");
01124   }
01125   
01126     // pick a facet and compare to surface normal to see
01127     // if we have them all backwards
01128   surf_facets.reset();
01129   CubitFacet* facet = surf_facets.get();  
01130   CubitVector pts[3] = { facet->point(0)->coordinates(),
01131                          facet->point(1)->coordinates(),
01132                          facet->point(2)->coordinates()};
01133   CubitVector facet_norm = (pts[1] - pts[0]) * (pts[2] - pts[0]);
01134   CubitVector facet_cent = (pts[0] + pts[1] + pts[2]) / 3.0;
01135   CubitVector surf_norm;
01136   real_surf->closest_point( facet_cent, 0, &surf_norm );
01137   if ( facet_norm % surf_norm < 0 )
01138   {
01139     PRINT_WARNING("Possible invalid facetting for surface.  "
01140                   "Backwards facets.\n");
01141     for ( i = surf_facets.size(); i--; )
01142       surf_facets.step_and_get()->flip();
01143   }    
01144 */
01145   
01146   PartSurfFacetTool tool(this);
01147   return tool.init_facet_data(surf_facets);
01148 }
01149 
01150 
01151 void PartitionSurface::replace_facets( DLIList<CubitFacetData*> &dead_facets,
01152                                        DLIList<CubitFacetData*> &new_facets)
01153 {
01154   int i;
01155   facetList -= dead_facets;
01156   facetList += new_facets;
01157   
01158   for( i = dead_facets.size(); i--; )
01159     TDVGFacetOwner::remove( dead_facets.step_and_get() );
01160 
01161   for( i = new_facets.size(); i--; )
01162     TDVGFacetOwner::set( new_facets.step_and_get(), this );
01163 
01164   // TODO - memory management - where should the facets get deleted
01165 }
01166 
01167 //-------------------------------------------------------------------------
01168 // Purpose       : Find closest facet and point on facet
01169 //
01170 // Special Notes : 
01171 //
01172 // Creator       : Jason Kraftcheck
01173 //
01174 // Creation Date : 03/28/03
01175 //-------------------------------------------------------------------------
01176 CubitFacet* PartitionSurface::closest_facet( const CubitVector& input_position,
01177                                              CubitVector& result_position)
01178 {
01179   return PartSurfFacetTool::closest_facet( input_position, facetList, result_position );
01180 }
01181 
01182 
01183 //-------------------------------------------------------------------------
01184 // Purpose       : Save geometry in an attribute
01185 //
01186 // Special Notes : 
01187 //
01188 // Creator       : Jason Kraftcheck
01189 //
01190 // Creation Date : 01/21/03
01191 //-------------------------------------------------------------------------
01192 CubitStatus PartitionSurface::save( CubitSimpleAttrib& attrib )
01193 {
01194   assert(dynamic_cast<Lump*>(partitioned_entity()) != 0);
01195   
01196   int i;
01197   int id = sub_entity_set().get_id(this);
01198   if( id <= 0 ) return CUBIT_FAILURE;
01199   
01200     // get facets
01201   DLIList<CubitFacetData*> facets;
01202   get_facet_data( facets );
01203   
01204     // get list of points from facets
01205   DLIList<CubitPoint*> points(facets.size()*3), facet_points(3);
01206   facets.reset();
01207   for( i = facets.size(); i--; )
01208   {
01209     facet_points.clean_out();
01210     facets.get_and_step()->points(facet_points);
01211     points += facet_points;
01212   }
01213   
01214   for( i = points.size(); i--; )
01215     points.step_and_get()->marked(0);
01216   for( i = points.size(); i--; )
01217   {
01218     CubitPoint* pt = points.step_and_get();
01219     pt->marked(pt->marked()+1);
01220   }
01221   points.last();
01222   for( i = points.size(); i--; )
01223   {
01224     if( points.get()->marked() > 1 )
01225     {
01226       points.get()->marked( points.get()->marked() - 1 );
01227       points.change_to(0);
01228     }
01229     points.back();
01230   }
01231   points.remove_all_with_value(0);
01232   
01233     // construct position list
01234   DLIList<CubitVector*> pt_list(points.size());
01235   points.reset();
01236   for( i = 0; i < points.size(); i++ )
01237   {
01238     CubitPoint* pt = points.get_and_step();
01239     pt_list.append( new CubitVector(pt->coordinates()) );
01240     pt->marked(i);
01241   }
01242   
01243     // connect facet connectivity list
01244   DLIList<int> facetlist( facets.size() * 3 );
01245   facets.reset();
01246   for( i = facets.size(); i--; )
01247   {
01248     facet_points.clean_out();
01249     facets.get_and_step()->points(facet_points);
01250     facet_points.reset();
01251     for( int j = facet_points.size(); j--; )
01252       facetlist.append( facet_points.get_and_step()->marked() );
01253   }
01254   
01255   DLIList<int> facet_point_owners;
01256   DLIList<CubitFacetEdge*> pt_edges;
01257   points.reset();
01258   for ( i = points.size(); i--; )
01259   {
01260     CubitPoint* pt = points.get_and_step();
01261     PartitionEntity* owner = TDVGFacetOwner::get(pt);
01262     if (!owner)
01263     {
01264       pt->edges(pt_edges);
01265       while ( pt_edges.size() )
01266       {
01267         CubitFacetEdge* edge = pt_edges.pop();
01268         PartitionEntity* tmp = TDVGFacetOwner::get(edge);
01269         if ( tmp )
01270         {
01271           assert(!owner || owner == tmp);
01272           owner = tmp;
01273         }
01274       }
01275     }
01276     if ( !owner )
01277       owner = this;
01278 
01279     int set_id, ent_id;
01280     if( &(owner->sub_entity_set()) == &(sub_entity_set()) )
01281     {
01282       set_id = 0;
01283       ent_id = sub_entity_set().get_id( owner );
01284     }
01285     else
01286     {
01287       set_id = owner->sub_entity_set().get_unique_id();
01288       ent_id = owner->sub_entity_set().get_id(owner);
01289     }
01290     facet_point_owners.append( set_id );
01291     facet_point_owners.append( ent_id );
01292   }
01293   
01294     // clean up point marks
01295   for( i = points.size(); i--; )
01296     points.step_and_get()->marked(0);
01297   
01298   DLIList<int> topo_list;
01299   get_save_topology( topo_list );
01300   
01301   return sub_entity_set().save_geometry( id, 2, &pt_list, &facetlist, &topo_list, 
01302                                          &facet_point_owners, attrib );
01303 }
01304 
01305 //-------------------------------------------------------------------------
01306 // Purpose       : Get topology connectivity list for use in saving
01307 //
01308 // Special Notes : 
01309 //
01310 // Creator       : Jason Kraftcheck
01311 //
01312 // Creation Date : 01/21/03
01313 //-------------------------------------------------------------------------
01314 CubitStatus PartitionSurface::get_save_topology( DLIList<int>& topo_list )
01315 {
01316   PartitionLoop* loop = 0;
01317   while( (loop = next_loop(loop)) )
01318   {
01319     topo_list.append(loop->num_coedges());
01320     PartitionCoEdge* coedge = loop->first_coedge();
01321     do
01322     {
01323       int set_id, crv_id;
01324       PartitionCurve* curve = coedge->get_curve();
01325       if( &(curve->sub_entity_set()) == &(sub_entity_set()) )
01326       {
01327         set_id = 0;
01328         crv_id = sub_entity_set().get_id( curve );
01329       }
01330       else
01331       {
01332         set_id = curve->sub_entity_set().get_unique_id();
01333         crv_id = curve->sub_entity_set().get_id(curve);
01334       }
01335 
01336       if( coedge->sense() == CUBIT_REVERSED )
01337         crv_id *= -1;
01338       topo_list.append(set_id);
01339       topo_list.append(crv_id);
01340     } while( (coedge = loop->next_coedge(coedge)) != loop->first_coedge() );
01341   }
01342 
01343   return CUBIT_SUCCESS;
01344 }
01345     
01346 
01347 void PartitionSurface::interior_facet_points( DLIList<CubitPoint*>& list ) const
01348 {
01349   
01350   DLIList<CubitPoint*> point_list(facetList.size() * 3);
01351   DLIList<CubitFacetEdge*> edge_list;
01352   int i;
01353   for( i = 0; i < facetList.size(); i++ )
01354   {
01355     CubitFacetData* facet = facetList.next(i);
01356     for( int j = 0; j < 3; j++ )
01357     {
01358       CubitPoint* pt = facet->point(j);
01359       if( TDVGFacetOwner::get(pt) )
01360         continue;  // not interior - on a vertex
01361       
01362       edge_list.clean_out();
01363       pt->edges( edge_list );
01364       bool skip = false;
01365       for( int k = edge_list.size(); k--; )
01366         if( TDVGFacetOwner::get(edge_list.step_and_get()) )
01367           skip = true; // not interior - on a curve
01368         
01369       if( !skip )
01370         point_list.append(pt);
01371     }
01372   }
01373   
01374     // uniquify list
01375   for( i = point_list.size(); i--; )
01376     point_list.step_and_get()->marked(1);
01377   for( i = point_list.size(); i--; )
01378     if( point_list.step_and_get()->marked() )
01379       point_list.get()->marked(0);
01380     else
01381       point_list.change_to(0);
01382   point_list.remove_all_with_value(0);
01383   list = point_list;
01384 }  
01385   
01386 
01387 void PartitionSurface::transform( const CubitTransformMatrix& xform )
01388 {
01389   int i;
01390   
01391   DLIList<CubitPoint*> points;
01392   interior_facet_points(points);
01393   for(i = points.size(); i--; )
01394   {
01395     CubitPoint* pt = points.step_and_get();
01396     pt->set( xform * pt->coordinates() );
01397   }
01398   
01399   double det = xform.sub_matrix( 3, 3 ).determinant();
01400   if (det < 0.0)
01401   {
01402     for (i = 0; i < facetList.size(); i++)
01403       facetList.next(i)->flip();
01404   
01405     PartitionLoop* loop = 0;
01406     while ((loop = next_loop(loop)))
01407       loop->reverse();
01408   }
01409   
01410   for (i = 0; i < facetList.size(); i++ )
01411   {
01412     facetList.next(i)->update_plane();
01413   }
01414   
01415 }
01416       
01417   
01418 
01419 PartitionSurface* PartitionSurface::construct( const CubitSimpleAttrib& attrib,
01420                                                PartitionLump* vol )
01421 {
01422     // construct surface and read attrib data
01423   PartitionSurface* new_surf = new PartitionSurface;
01424   DLIList<CubitVector*> facet_points;
01425   DLIList<int> facets, curve_conn, point_owners;
01426   vol->sub_entity_set().
01427     add_lower_order( new_surf, attrib, 2, facet_points, facets, curve_conn, point_owners );
01428   
01429   if( facets.size() % 3 != 0 )
01430   {
01431     assert( !(facets.size() % 3 ) );
01432     delete new_surf;
01433     return 0;
01434   }
01435   
01436     // create loops and coedges
01437   DLIList<PartitionCurve*> curve_list;
01438   int i = curve_conn.size();
01439   curve_conn.reset();
01440   bool okay = true;
01441   while( okay && i > 0 )
01442   {
01443     int k = curve_conn.get_and_step();
01444     i--;
01445     
01446     if( k <= 0 || i < 2*k )
01447       { okay = false; break; }
01448     
01449     PartitionLoop* new_loop = new PartitionLoop();
01450     PartitionCoEdge* prev_coedge = 0;
01451     new_surf->add( new_loop );
01452     
01453     for( int j = 0; okay && j < k; j++ )
01454     {
01455       int set_id = curve_conn.get_and_step();
01456       int ent_id = curve_conn.get_and_step();
01457       i -= 2;
01458       
01459       CubitSense sense = CUBIT_FORWARD;
01460       if( ent_id < 0 )
01461       {
01462         sense = CUBIT_REVERSED;
01463         ent_id = -ent_id;
01464       }
01465       
01466       PartitionEntity* ent = PartitionEngine::instance()
01467         .entity_from_id( set_id, ent_id, vol->sub_entity_set() );
01468       PartitionCurve* curve = dynamic_cast<PartitionCurve*>(ent);
01469       
01470       if( !curve )
01471         { okay = false; break;  }
01472       
01473       curve_list.append( curve );
01474       PartitionCoEdge* coedge = new PartitionCoEdge( new_surf, sense );
01475       new_loop->insert_after( coedge, prev_coedge );
01476       prev_coedge = coedge;
01477       curve->add( coedge );
01478     }
01479   }
01480   
01481   if( !okay )
01482   {
01483     PartitionEngine::instance().destroy_surface( new_surf );
01484     return 0;
01485   }
01486   
01487     // construct facet points
01488   CubitPointData** points = new CubitPointData*[facet_points.size()];
01489   facet_points.reset();
01490   point_owners.reset();
01491   for( i = 0; i < facet_points.size(); i++ )
01492   {
01493     CubitVector* pt = facet_points.get_and_step();
01494     points[i] = new CubitPointData(*pt);
01495     delete pt;
01496     
01497     int set_id = point_owners.get_and_step();
01498     int ent_id = point_owners.get_and_step();
01499     PartitionEntity* owner = PartitionEngine::instance()
01500       .entity_from_id( set_id, ent_id, vol->sub_entity_set() );
01501     
01502     if ( !owner )
01503     {
01504       okay = false;
01505       break;
01506     }
01507     
01508     if ( owner != new_surf )
01509     {
01510       if ( !dynamic_cast<PartitionPoint*>(owner) &&
01511            !dynamic_cast<PartitionCurve*>(owner) )
01512       {
01513         okay = false;
01514         break;
01515       }
01516       TDVGFacetOwner::set(points[i], owner);
01517     }
01518   }
01519   
01520   if ( !okay )
01521   {
01522     for ( i = 0; i < facet_points.size(); i++ )
01523       delete points[i];
01524     delete [] points;
01525     PartitionEngine::instance().destroy_surface( new_surf );
01526     return 0;
01527   }
01528     
01529     // construct facets
01530   facets.reset();
01531   DLIList<CubitFacetData*> facet_list;
01532   int junk = 0;
01533   for( i = 0; i < facets.size(); i += 3 )
01534   {
01535     CubitFacetData* facet = new CubitFacetData(
01536                                     points[facets.next(0)],
01537                                     points[facets.next(1)],
01538                                     points[facets.next(2)], &junk );
01539     facet_list.append(facet);
01540     facets.step(3);
01541     
01542       // set edge owners to this surface as a kind of mark
01543       // (will use this a little later)
01544     for ( int j = 0; j < 3; j++ )
01545       TDVGFacetOwner::set( facet->edge(j), new_surf );
01546   } 
01547   
01548     // Seam facet points on vertices
01549   for ( i = 0; i < facet_points.size(); i++ )
01550   {
01551     PartitionEntity* ent = TDVGFacetOwner::get(points[i]);
01552     PartitionPoint* vertex = dynamic_cast<PartitionPoint*>(ent);
01553     if (!vertex) continue;
01554     
01555     if ( !vertex->facet_point() )
01556       vertex->facet_point(points[i]);
01557     else if ( vertex->facet_point() != points[i] )
01558     {
01559       vertex->facet_point()->merge_points(points[i]);
01560       points[i] = vertex->facet_point();
01561     }
01562   }
01563   
01564     // done with point list -- delete it
01565   delete [] points;
01566 
01567     // seam facet edges with curves
01568   DLIList<CubitFacetEdge*> pt_edges;
01569   DLIList<CubitFacetEdgeData*> curve_edges;
01570   while ( curve_list.size() )
01571   {
01572     curve_edges.clean_out();
01573     PartitionCurve* curve = curve_list.pop();
01574     CubitPoint* pt = curve->start_point()->facet_point();
01575     if (!pt) {okay = false; break;}
01576 
01577     //For periodic curves, you can easily set up 'curve_edges'
01578     //in the opposite order.  When finding the first edge, I added 
01579     //the logic in the if(find_correct_direction_on_periodics) block.  It
01580     //looks at the first facet edge in the curve and finds the appropriate
01581     //facet edge sharing the same point that has the smallest angle between.
01582     //This approach assure that we are appending the facet edges to the list
01583     //'curve_edges' in the same orientation as the facet edges on the curve.  
01584     bool find_correct_direction_on_periodics = false;     
01585     PartitionPoint* start_vtx = curve->start_point();
01586     PartitionPoint* end_vtx = curve->end_point();
01587     CubitPointData* start_point = start_vtx->facet_point();
01588     CubitPointData* end_point = end_vtx->facet_point();
01589     if( start_vtx == end_vtx && start_point == end_point )
01590       find_correct_direction_on_periodics = true;          
01591     
01592     double smallest_angle = CUBIT_DBL_MAX;
01593     bool debug = false;
01594 
01595     do {
01596 
01597       if( smallest_angle != CUBIT_DBL_MAX )
01598         find_correct_direction_on_periodics = false;
01599 
01600       CubitFacetEdge *edge = 0, *pt_edge = 0;
01601       pt_edges.clean_out();
01602       pt->edges(pt_edges);
01603       while ( pt_edges.size() )
01604       {
01605         CubitFacetEdge* tmp_edge = pt_edges.pop();
01606         if ( TDVGFacetOwner::get(tmp_edge) != new_surf )
01607           continue;
01608           
01609         PartitionEntity* owner = TDVGFacetOwner::get(tmp_edge->other_point(pt));
01610         if ( owner == curve )
01611         {
01612           if( find_correct_direction_on_periodics )
01613           {            
01614             CubitPoint* start_point = pt;
01615            
01616             DLIList<CubitFacetEdgeData*> curve_edges;
01617             curve->get_facet_data(curve_edges);
01618             curve_edges.reset();
01619             CubitFacetEdge *first_facet_edge = curve_edges.get();
01620             CubitPoint *real_next_point = first_facet_edge->other_point(start_point);
01621             CubitPoint *possible_next_point = tmp_edge->other_point(start_point);
01622 
01623             CubitVector v1 = real_next_point->coordinates() - start_point->coordinates();
01624             CubitVector v2 = possible_next_point->coordinates() - start_point->coordinates();
01625 
01626             double angle = v1.interior_angle(v2);
01627 
01628             if( angle < smallest_angle )
01629             {
01630               smallest_angle = angle;
01631               edge = tmp_edge;   
01632             }
01633           }
01634           else
01635           {
01636             edge = tmp_edge;
01637           }
01638         }
01639         else if ( owner == curve->end_point() )
01640         {
01641           pt_edge = tmp_edge;
01642         }
01643       }
01644       
01645       if ( !edge ) 
01646         edge = pt_edge;
01647       else
01648       {
01649         //so we don't traverse backwards
01650         TDVGFacetOwner::set(edge->other_point(pt), 0);
01651       }
01652         
01653       CubitFacetEdgeData* edge_d = dynamic_cast<CubitFacetEdgeData*>(edge);
01654       if (!edge_d) 
01655       {
01656         okay = false; 
01657         break;
01658       }
01659       
01660       if( debug )
01661       {
01662         pt->debug_draw(4);
01663         GfxDebug::mouse_xforms();
01664         edge_d->debug_draw(5);
01665         GfxDebug::mouse_xforms();
01666         edge_d->other_point(pt)->debug_draw(6);
01667         GfxDebug::mouse_xforms();
01668       }
01669 
01670       curve_edges.append(edge_d);
01671       pt = edge_d->other_point(pt);
01672     } while (pt != curve->end_point()->facet_point());
01673     
01674     if( !okay || !PartSurfFacetTool::seam_curve( curve_edges, curve, facet_list ) ) 
01675     {
01676       okay = false;
01677       break;
01678     }
01679   }
01680     
01681     // clean up any owner pointers on edges that were being
01682     // used as a kind of mark
01683   for ( i = facet_list.size(); i--; )
01684   {
01685     CubitFacet* facet = facet_list.get_and_step();
01686     for ( int j = 0; j < 3; j++ )
01687       if ( TDVGFacetOwner::get(facet->edge(j)) == new_surf )
01688         TDVGFacetOwner::set(facet->edge(j), 0);
01689   }
01690     
01691     // set surface facets
01692   new_surf->set_facet_data( facet_list );
01693   
01694   if (!okay)
01695   {
01696     PartitionEngine::instance().destroy_surface( new_surf );
01697     return 0;
01698   }
01699 
01700   return new_surf;
01701 }
01702 
01703 
01704 CubitStatus PartitionSurface::notify_moving_point( CubitPoint* point, 
01705                                            const CubitVector& new_pos )
01706 {
01707   DLIList<CubitFacetData*> old_facets, new_facets;
01708   if (!PartSurfFacetTool::fix_move_point(point, new_pos, facetList, old_facets, new_facets, this))
01709     return CUBIT_FAILURE;
01710   
01711   assert( !old_facets.size() == !new_facets.size() );
01712   if (old_facets.size())
01713     replace_facets( old_facets, new_facets );
01714   return CUBIT_SUCCESS;
01715 }
01716 
01717 void PartitionSurface::notify_destroyed( CubitFacetData* facet )
01718 {
01719   facetList.move_to(facet);
01720   assert(facetList.size() && facetList.get() == facet);
01721   facetList.extract();
01722 }
01723 
01724 
01725 CubitStatus PartitionSurface::evaluate( double u, double v,
01726                                         CubitVector *position,                                   
01727                                         CubitVector *normal,
01728                                         CubitVector *curvature1,
01729                                         CubitVector *curvature2 )
01730 {
01731   return CUBIT_FAILURE;
01732 }
01733 
01734 CubitStatus PartitionSurface::get_projected_distance_on_surface( CubitVector *pos1,
01735                                                                  CubitVector *pos2, 
01736                                                                  double &distance )
01737 {
01738   return CUBIT_FAILURE;
01739 }
01740 
01741 CubitStatus PartitionSurface::get_sphere_params
01742 (
01743   CubitVector &center,
01744   double &radius
01745 ) const
01746 {
01747   PRINT_ERROR("Currently, Cubit is unable to determine sphere parameters for PartitionSurfaces.\n");
01748   return CUBIT_FAILURE;
01749 }
01750 
01751 CubitStatus PartitionSurface::get_cone_params
01752 (
01753    CubitVector &center,
01754    CubitVector &normal,
01755    CubitVector &major_axis,
01756    double &radius_ratio,
01757    double &sine_angle,
01758    double &cos_angle
01759 ) const
01760 {
01761   PRINT_ERROR("Currently, Cubit is unable to determine cone parameters for PartitionSurfaces.\n");
01762   return CUBIT_FAILURE;
01763 }
01764 
01765 CubitStatus PartitionSurface::get_torus_params
01766 (
01767   CubitVector &center,
01768   CubitVector &normal,
01769   double &major_radius,
01770   double &minor_radius
01771 ) const
01772 {
01773   PRINT_ERROR("Currently, Cubit is unable to determine torus parameters for PartitionSurface.\n");
01774   return CUBIT_FAILURE;
01775 }
01776 
01777 CubitStatus PartitionSurface::get_nurb_params
01778 (
01779   bool &rational,
01780   int &degree_u,
01781   int &degree_v,
01782   int &num_cntrl_pts_u,
01783   int &num_cntrl_pts_v,
01784   DLIList<CubitVector> &cntrl_pts,
01785   DLIList<double> &cntrl_pt_weights,
01786   DLIList<double> &u_knots,
01787   DLIList<double> &v_knots
01788 ) const
01789 {
01790   PRINT_ERROR("Currently, Cubit is unable to determine nurbs parameters for PartitionSurface.\n");
01791   return CUBIT_FAILURE;
01792 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines