cgma
PartitionLump.cpp
Go to the documentation of this file.
00001 #include "PartitionLump.hpp"
00002 #include "PartitionShell.hpp"
00003 #include "PartitionSurface.hpp"
00004 #include "VirtualQueryEngine.hpp"
00005 #include "PartitionCurve.hpp"
00006 #include "PartitionBody.hpp"
00007 #include "CubitFacetData.hpp"
00008 
00009 PartitionLump::PartitionLump( Lump* real_lump )
00010   : listHead(0)
00011 {
00012   assert( dynamic_cast<SubEntitySet*>(real_lump->owner()) == 0 );
00013   new SubEntitySet( real_lump, this );
00014 }
00015 
00016 PartitionLump::PartitionLump( PartitionLump* split_from )
00017   : listHead(0)
00018 {
00019   split_from->sub_entity_set().add_partition( this );
00020 }
00021 
00022 PartitionLump::~PartitionLump()
00023 {
00024   remove_all_shells();
00025 }
00026 
00027 Lump* PartitionLump::real_lump() const
00028 {
00029   return dynamic_cast<Lump*>(partitioned_entity());
00030 }
00031 
00032 
00033 CubitStatus PartitionLump::add( PartitionShell* shell )
00034 {
00035   assert( shell->myLump == 0 );
00036   shell->lumpNext = listHead;
00037   shell->myLump = this;
00038   listHead = shell;
00039   return CUBIT_SUCCESS;
00040 }
00041 
00042 CubitStatus PartitionLump::remove( PartitionShell* shell )
00043 {
00044   if( shell->myLump != this )
00045     return CUBIT_FAILURE;
00046   
00047   if( listHead == shell )
00048   {
00049     listHead = shell->lumpNext;
00050   }
00051   else
00052   {
00053     PartitionShell* sh = listHead;
00054     while( sh && sh->lumpNext != shell )
00055       sh = sh->lumpNext;
00056     assert( sh && sh->lumpNext == shell );
00057     sh->lumpNext = shell->lumpNext;
00058   }
00059   
00060   shell->myLump = 0;
00061   shell->lumpNext = 0;
00062   return CUBIT_SUCCESS;
00063 }
00064 
00065 void PartitionLump::remove_all_shells()
00066 {
00067   while( listHead )
00068   {
00069     CubitStatus s = remove( listHead );
00070     assert( s );
00071     if (CUBIT_SUCCESS != s) {
00072       PRINT_ERROR("Failed to remove all shells.\n");
00073     }
00074   }
00075 }
00076 
00077 void PartitionLump::get_parents_virt( DLIList<TopologyBridge*>& list )
00078 {
00079   if( get_body() )
00080     list.append( get_body() );
00081   else
00082   {
00083     real_lump()->get_parents_virt( list );
00084 //    PartitionEngine::fix_up_query_results( list );
00085   }
00086 }
00087 
00088 void PartitionLump::get_children_virt( DLIList<TopologyBridge*>& list )
00089 {
00090   PartitionShell* shell = first_shell();
00091   while( shell )
00092   {
00093     list.append( shell );
00094     shell = next_shell( shell );
00095   }
00096 }
00097 
00098 GeometryQueryEngine* PartitionLump::get_geometry_query_engine() const
00099 {
00100   return VirtualQueryEngine::instance();
00101 }
00102 
00103 
00104 
00105 void PartitionLump::append_simple_attribute_virt(const CubitSimpleAttrib& csa)
00106 { sub_entity_set().add_attribute( this, csa ); }
00107 void PartitionLump::remove_simple_attribute_virt(const CubitSimpleAttrib& csa)
00108 { sub_entity_set().rem_attribute( this, csa ); }
00109 void PartitionLump::remove_all_simple_attribute_virt()
00110 { sub_entity_set().rem_all_attrib( this ); }
00111 CubitStatus PartitionLump::get_simple_attribute(DLIList<CubitSimpleAttrib>& list)
00112 { 
00113   sub_entity_set().get_attributes( this, list ); 
00114   return CUBIT_SUCCESS;
00115 }
00116 CubitStatus PartitionLump::get_simple_attribute(const CubitString& name,
00117                                        DLIList<CubitSimpleAttrib>& list)
00118 { 
00119   sub_entity_set().get_attributes( this, name.c_str(), list ); 
00120   return CUBIT_SUCCESS;
00121 }
00122 
00123 void PartitionLump::notify_split( FacetEntity* , FacetEntity* )
00124   { assert(0); }
00125 
00126 void PartitionLump::reverse_sense()
00127 {
00128   PartitionShell* shell = 0;
00129   while( (shell = next_shell(shell)) )
00130   {
00131     PartitionCoSurf* cosurf = 0;
00132     while( (cosurf = shell->next_co_surface( cosurf )) )
00133     {
00134       bool reversed = (cosurf->sense() == CUBIT_REVERSED);
00135       cosurf->sense( reversed ? CUBIT_FORWARD : CUBIT_REVERSED );
00136     }
00137   }
00138 }
00139 
00140 void PartitionLump::transform(const CubitTransformMatrix&) {;}    
00141 
00142 CubitBox PartitionLump::bounding_box() const
00143 {
00144   return real_lump() ? real_lump()->bounding_box() : CubitBox();
00145 }
00146 
00147 double PartitionLump::measure() 
00148 {
00149     // Calculate volume of this lump from surface facets.
00150     // Volume is calculated as the sum of the signed
00151     // volumes of the tetrahedrons formed by this point
00152     // with triagle.
00153   CubitVector p0 = bounding_box().center();
00154   
00155   double result = 0.0;
00156   PartitionShell* shell = 0;
00157   PartitionCoSurf* cosurf = 0;
00158   DLIList<CubitFacetData*> facets;
00159   CubitVector p1, normal;
00160   
00161     // calculate area around this point
00162   while ( (shell = next_shell(shell)) )
00163   {
00164       // mark surfaces with a count of how many times they 
00165       // occur in the shell
00166     cosurf = 0;
00167     while ( (cosurf = shell->next_co_surface(cosurf)) )
00168       cosurf->get_surface()->mark = 0;
00169     cosurf = 0;
00170     while ( (cosurf = shell->next_co_surface(cosurf)) )
00171       cosurf->get_surface()->mark++;
00172     
00173       // calculate partial area for each surface
00174     cosurf = 0;
00175     while ( (cosurf = shell->next_co_surface(cosurf)) )
00176     {
00177       PartitionSurface* surf = cosurf->get_surface();
00178       
00179         // skip non-manifold surfaces
00180       if( surf->mark > 1 ) continue;
00181       
00182       facets.clean_out();
00183       surf->get_facet_data( facets );
00184       for  ( int i = facets.size(); i--; )
00185       {
00186           // Tetrahedron volume is Ah/3
00187           // Calculate 2Ah and add to result.
00188           // Divide result by 6 when all done.
00189         
00190         CubitFacet* facet = facets.step_and_get();
00191         p1 = facet->point(0)->coordinates();
00192         normal = (facet->point(2)->coordinates() - p1) 
00193                * (facet->point(1)->coordinates() - p1);
00194         
00195           // Triangle area is 1/2 length of edge product
00196         double two_area = normal.length();
00197         
00198         if ( two_area > CUBIT_RESABS )
00199         {
00200             // Calculating signed area - need to 
00201             // reverse facet normal for reversed
00202             // cosurfaces.
00203           if ( cosurf->sense() == CUBIT_REVERSED )
00204             normal = -normal;
00205           
00206             // Make normal a unit vector.  Already
00207             // calculated length, so reuse that 
00208             // value.
00209           normal /= two_area;
00210           
00211             // This is where the signed part of the
00212             // calculation comes in.  If normal is 
00213             // in opposite direction as the vector
00214             // (p0-p1), then the height is negative.
00215           double height = normal % (p0 - p1);
00216           
00217             // Add the signed height value times 
00218             // twice the triangle area to result.
00219           result += two_area * height;
00220         }
00221       }
00222     }
00223     
00224       // clear marks
00225     cosurf = 0;
00226     while ( (cosurf = shell->next_co_surface(cosurf)) )
00227       cosurf->get_surface()->mark = 0;
00228   }
00229   
00230     // Calculated 2Ah for each tetrahedron, so divide
00231     // by 6 to get Ah/3.
00232   return result / 6.0;
00233 }
00234 
00235 PartitionBody* PartitionLump::get_body() const
00236   { return sub_entity_set().body(); }
00237 
00238 TopologyBridge* PartitionLump::find_parent_body() const
00239 {
00240   if( get_body() ) 
00241     return get_body();
00242   
00243   Lump* lump = real_lump();
00244   if(!lump) return 0;
00245   
00246   DLIList<TopologyBridge*> list;
00247   lump->get_parents_virt(list);
00248   return list.size() ? list.get() : 0;
00249 }
00250 
00251 CubitStatus PartitionLump::save( CubitSimpleAttrib& attrib )
00252 {
00253   DLIList<int> surf_list;
00254   
00255   PartitionShell* shell = 0;
00256   while( (shell = next_shell(shell)) )
00257   {
00258     PartitionCoSurf* cosurf = 0;
00259     int cosurf_count = 0;
00260     while( (cosurf = shell->next_co_surface(cosurf)) )
00261       cosurf_count++;
00262     
00263     surf_list.append(cosurf_count);
00264     cosurf = 0;
00265     while( (cosurf = shell->next_co_surface(cosurf)) )
00266     {
00267       PartitionSurface* surf = cosurf->get_surface();
00268       int set_id = 0;
00269       int surf_id = surf->sub_entity_set().get_id(surf);
00270       if( &(surf->sub_entity_set()) != &sub_entity_set() )
00271         set_id = surf->sub_entity_set().get_unique_id();
00272     
00273       if ( cosurf->sense() == CUBIT_REVERSED )
00274         surf_id = -surf_id;
00275         
00276       surf_list.append( set_id );
00277       surf_list.append( surf_id );
00278     }
00279   }
00280   
00281   int id = sub_entity_set().get_id(this);
00282   return sub_entity_set().save_geometry( id, 3, 0, 0, &surf_list, 0, attrib );
00283 }
00284 
00285 void PartitionLump::get_all_children( DLIList<PartitionEntity*>& list )
00286 {
00287   PartitionShell* shell = 0;
00288   while( (shell = next_shell(shell)) )
00289   {
00290     PartitionCoSurf* cosurf = 0;
00291     while( (cosurf = shell->next_co_surface(cosurf)) )
00292     {
00293       PartitionSurface* surface = cosurf->get_surface();
00294       list.append( surface );
00295       PartitionLoop* loop = 0;
00296       while( (loop = surface->next_loop(loop)) )
00297       {
00298         PartitionCoEdge* coedge = loop->first_coedge();
00299         do {
00300           PartitionCurve* curve = coedge->get_curve();
00301           list.append( curve );
00302           list.append( curve->start_point() );
00303           list.append( curve->end_point() );
00304           coedge = loop->next_coedge( coedge );
00305         } while( coedge != loop->first_coedge() );
00306       }
00307     }
00308   }
00309   
00310   int i;
00311   for( i = list.size(); i--; )
00312     list.step_and_get()->mark = 0;
00313   for( i = list.size(); i--; )
00314     list.step_and_get()->mark++;
00315   for( i = list.size(); i--; )
00316   {
00317     list.step_and_get()->mark--;
00318     if( list.get()->mark != 0 )
00319       list.change_to(0);
00320   }
00321   list.remove_all_with_value(0);
00322 }
00323 
00324 //-------------------------------------------------------------------------
00325 // Purpose       : Mass properties
00326 //
00327 // Special Notes : 
00328 //
00329 // Creator       : Jason Kraftcheck
00330 //
00331 // Creation Date : 05/10/04
00332 //-------------------------------------------------------------------------
00333 CubitStatus PartitionLump::mass_properties( CubitVector& centroid, double& volume )
00334 {
00335   PartitionShell* shell = 0;
00336   CubitVector s_cent;
00337   double s_vol;
00338   volume = 0.0;
00339   centroid.set( 0.0, 0.0, 0.0 );
00340   
00341   while ((shell = next_shell( shell )))
00342   {
00343     if (CUBIT_SUCCESS != shell->mass_properties( s_cent, s_vol ))
00344       return CUBIT_FAILURE;
00345     centroid += s_vol * s_cent;
00346     volume += s_vol;
00347   }
00348   
00349   if (volume > CUBIT_RESABS)
00350     centroid /= volume;
00351   else
00352     centroid.set( 0.0, 0.0, 0.0 );
00353   return CUBIT_SUCCESS;
00354 }
00355 
00356 CubitPointContainment PartitionLump::point_containment( const CubitVector& pos, double tolerance )
00357 {
00358   PartitionCoSurf* closest_surf = NULL;
00359   double closest_dist = CUBIT_DBL_MAX;
00360   CubitVector closest, normal;
00361   
00362   PartitionShell* shell = 0;
00363   while ((shell = next_shell( shell )))
00364   {
00365     PartitionCoSurf* cosurf = 0;
00366     while ((cosurf = shell->next_co_surface( cosurf )))
00367     {
00368       PartitionSurface* surf = cosurf->get_surface();
00369       if (!shell->is_nonmanifold( surf ))
00370       {
00371         surf->closest_point( pos, &closest );
00372         double dist = (pos - closest).length_squared();
00373         if (dist < closest_dist)
00374         {
00375           closest_dist = dist;
00376           closest_surf = cosurf;
00377         }
00378       }
00379     }
00380   }
00381   
00382   if (!closest_surf)
00383     return CUBIT_PNT_UNKNOWN;
00384 
00385   if( tolerance < 0 )
00386     tolerance = GEOMETRY_RESABS;
00387   
00388   closest_surf->get_surface()->closest_point( pos, &closest, &normal );
00389   if ((closest - pos).length_squared() < tolerance * tolerance )
00390     return CUBIT_PNT_BOUNDARY;
00391   
00392   if (closest_surf->sense() == CUBIT_REVERSED)
00393     normal = -normal;
00394   
00395   double dot = normal % (closest - pos);
00396   return dot < CUBIT_RESABS ? CUBIT_PNT_OUTSIDE :
00397          dot > CUBIT_RESABS ? CUBIT_PNT_INSIDE  :
00398                               CUBIT_PNT_UNKNOWN;
00399 }
00400 
00401   
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines