cgma
|
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