cgma
|
00001 #include "PartitionShell.hpp" 00002 #include "PartitionLump.hpp" 00003 #include "PartitionSurface.hpp" 00004 #include "VirtualQueryEngine.hpp" 00005 #include "CubitFacetData.hpp" 00006 00007 PartitionShell::PartitionShell( ) 00008 : myLump(0), lumpNext(0), firstCoSurf(0) 00009 { } 00010 00011 PartitionShell::~PartitionShell() 00012 { 00013 assert( !myLump ); 00014 remove_all_surfaces(); 00015 } 00016 00017 CubitStatus PartitionShell::add( PartitionCoSurf* cosurf ) 00018 { 00019 if( cosurf->myShell || cosurf->shellNext ) 00020 { 00021 assert(!cosurf->myShell && !cosurf->shellNext); 00022 return CUBIT_FAILURE; 00023 } 00024 00025 cosurf->myShell = this; 00026 cosurf->shellNext = firstCoSurf; 00027 firstCoSurf = cosurf; 00028 return CUBIT_SUCCESS; 00029 } 00030 00031 CubitStatus PartitionShell::remove( PartitionCoSurf* cosurf ) 00032 { 00033 if( cosurf->myShell != this ) 00034 { 00035 assert( cosurf->myShell == this ); 00036 return CUBIT_FAILURE; 00037 } 00038 00039 if( cosurf == firstCoSurf ) 00040 { 00041 firstCoSurf->shellNext = cosurf->shellNext; 00042 firstCoSurf = firstCoSurf->shellNext; 00043 } 00044 else 00045 { 00046 PartitionCoSurf* prev = firstCoSurf; 00047 while( prev && prev->shellNext != cosurf ) 00048 prev = prev->shellNext; 00049 00050 if( !prev ) { assert(0); return CUBIT_FAILURE; } 00051 00052 prev->shellNext = cosurf->shellNext; 00053 } 00054 00055 cosurf->myShell = 0; 00056 cosurf->shellNext = 0; 00057 return CUBIT_SUCCESS; 00058 } 00059 00060 PartitionCoSurf* PartitionShell::add( PartitionSurface* surf, CubitSense sense ) 00061 { 00062 PartitionCoSurf* new_cos = new PartitionCoSurf( sense ); 00063 if( !surf->add(new_cos) || !this->add(new_cos) ) 00064 { 00065 delete new_cos; 00066 new_cos = 0; 00067 } 00068 return new_cos; 00069 } 00070 00071 PartitionCoSurf* PartitionShell::find_first( const PartitionSurface* surf ) const 00072 { 00073 PartitionCoSurf* cos = firstCoSurf; 00074 while( cos && cos->get_surface() != surf ) 00075 cos = cos->shellNext; 00076 return cos; 00077 } 00078 PartitionCoSurf* PartitionShell::find_next( const PartitionCoSurf* prev ) const 00079 { 00080 PartitionCoSurf* cos = prev->shellNext; 00081 while( cos && cos->get_surface() != prev->get_surface() ) 00082 cos = cos->shellNext; 00083 return cos; 00084 } 00085 CubitSense PartitionShell::find_sense( const PartitionSurface* surf ) const 00086 { 00087 PartitionCoSurf* cos = find_first( surf ); 00088 if( ! cos ) 00089 return CUBIT_UNKNOWN; 00090 00091 CubitSense result = cos->sense(); 00092 while( (cos = find_next( cos )) ) 00093 if( cos->sense() != result ) 00094 return CUBIT_UNKNOWN; 00095 00096 return result; 00097 } 00098 00099 00100 00101 00102 void PartitionShell::remove_all_surfaces( DLIList<PartitionSurface*>* list ) 00103 { 00104 while( PartitionCoSurf* cosurf = firstCoSurf ) 00105 { 00106 if( cosurf->get_surface() ) 00107 { 00108 if( list ) 00109 list->append( cosurf->get_surface() ); 00110 cosurf->get_surface()->remove( cosurf ); 00111 } 00112 remove( cosurf ); 00113 delete cosurf; 00114 } 00115 00116 if( list ) 00117 list->uniquify_ordered(); 00118 } 00119 00120 void PartitionShell::get_parents_virt( DLIList<TopologyBridge*>& parents ) 00121 { 00122 if( myLump ) 00123 parents.append( myLump ); 00124 } 00125 00126 void PartitionShell::get_children_virt( DLIList<TopologyBridge*>& children ) 00127 { 00128 PartitionCoSurf* cos = 0; 00129 while( (cos = next_co_surface( cos )) ) 00130 if( cos->get_surface() ) 00131 children.append_unique( cos->get_surface() ); 00132 } 00133 00134 int PartitionShell::layer() const { return get_lump()->layer(); } 00135 00136 GeometryQueryEngine* PartitionShell::get_geometry_query_engine() const 00137 { 00138 return VirtualQueryEngine::instance(); 00139 } 00140 00141 void PartitionShell::append_simple_attribute_virt( const CubitSimpleAttrib& ) 00142 { } 00143 void PartitionShell::remove_simple_attribute_virt( const CubitSimpleAttrib& ) 00144 { } 00145 void PartitionShell::remove_all_simple_attribute_virt() 00146 { } 00147 CubitStatus PartitionShell::get_simple_attribute( DLIList<CubitSimpleAttrib>& ) 00148 { return CUBIT_FAILURE; } 00149 CubitStatus PartitionShell::get_simple_attribute( const CubitString&, 00150 DLIList<CubitSimpleAttrib>& ) 00151 { return CUBIT_FAILURE; } 00152 00153 void PartitionShell::print_debug_info( const char* /*prefix*/ ) const 00154 { 00155 } 00156 00157 //------------------------------------------------------------------------- 00158 // Purpose : Determine point containment. 00159 // 00160 // Special Notes : 00161 // 00162 // Creator : Jason Kraftcheck 00163 // 00164 // Creation Date : 02/23/03 00165 //------------------------------------------------------------------------- 00166 CubitPointContainment PartitionShell::point_containment( const CubitVector& pt ) 00167 { 00168 // Find closest cosurface to passed point 00169 PartitionCoSurf* cosurf = 0; 00170 PartitionCoSurf* closest = 0; 00171 double dist_to_closest = CUBIT_DBL_MAX; 00172 CubitVector pt_on_surface; 00173 while( (cosurf = next_co_surface(cosurf)) ) 00174 { 00175 PartitionSurface* surf = cosurf->get_surface(); 00176 00177 // Ignore surfaces that occur more than once in the 00178 // shell. 00179 bool skip = false; 00180 PartitionCoSurf* surf_cosurf = 0; 00181 while( (surf_cosurf = surf->next_co_surface(surf_cosurf)) ) 00182 { 00183 if( surf_cosurf->get_shell() == this && surf_cosurf != cosurf ) 00184 { 00185 skip = true; 00186 break; 00187 } 00188 } 00189 00190 if( skip ) 00191 continue; 00192 00193 surf->closest_point_trimmed( pt, pt_on_surface ); 00194 double dist_sqr = (pt - pt_on_surface).length_squared(); 00195 if( dist_sqr < dist_to_closest ) 00196 { 00197 closest = cosurf; 00198 dist_to_closest = dist_sqr; 00199 } 00200 } 00201 00202 if( !closest ) 00203 return CUBIT_PNT_UNKNOWN; // already printed error messages above 00204 00205 if( dist_to_closest < (GEOMETRY_RESABS*GEOMETRY_RESABS) ) // point is on shell 00206 return CUBIT_PNT_BOUNDARY; 00207 00208 CubitVector normal; 00209 closest->get_surface()->closest_point_trimmed( pt, pt_on_surface ); 00210 closest->get_surface()->closest_point( pt_on_surface, 0, &normal ); 00211 if( closest->sense() == CUBIT_REVERSED ) 00212 normal *= -1.0; 00213 00214 pt_on_surface -= pt; 00215 if ( pt_on_surface.length_squared() < GEOMETRY_RESABS*GEOMETRY_RESABS ) 00216 return CUBIT_PNT_BOUNDARY; 00217 00218 return (normal % pt_on_surface) > 0.0 ? CUBIT_PNT_INSIDE : CUBIT_PNT_OUTSIDE; 00219 } 00220 00221 bool PartitionShell::is_nonmanifold( PartitionSurface* surf ) const 00222 { 00223 int count = 0; 00224 PartitionCoSurf* cosurf = 0; 00225 while ((cosurf = surf->next_co_surface( cosurf ))) 00226 if (cosurf->get_shell() == this) 00227 count++; 00228 00229 return count != 1; 00230 } 00231 00232 CubitStatus PartitionShell::mass_properties( CubitVector& centroid, 00233 double& volume ) 00234 { 00235 PartitionCoSurf* cosurf = 0; 00236 DLIList<CubitFacetData*> facets; 00237 CubitVector p1, p2, p3, normal; 00238 const CubitVector p0(0.0, 0.0, 0.0); 00239 centroid.set(0.0, 0.0, 0.0 ); 00240 volume = 0.0; 00241 00242 while ((cosurf = next_co_surface( cosurf ))) 00243 { 00244 if (is_nonmanifold( cosurf->get_surface() )) 00245 continue; 00246 00247 facets.clean_out(); 00248 cosurf->get_surface()->get_facet_data( facets ); 00249 00250 for (int i = facets.size(); i--; ) 00251 { 00252 CubitFacet* facet = facets.step_and_get(); 00253 p1 = facet->point(0)->coordinates(); 00254 p2 = facet->point(1)->coordinates(); 00255 p3 = facet->point(2)->coordinates(); 00256 normal = (p3 - p1) * (p2 - p1); 00257 00258 double two_area = normal.length(); 00259 if (two_area > CUBIT_RESABS ) 00260 { 00261 if (cosurf->sense() == CUBIT_REVERSED) 00262 normal = -normal; 00263 00264 normal /= two_area; 00265 00266 double height = normal % (p0 - p1); 00267 double vol = two_area * height; 00268 00269 volume += vol; 00270 centroid += vol * (p0 + p1 + p2 + p3); 00271 } 00272 } 00273 } 00274 00275 if (volume > CUBIT_RESABS) 00276 centroid /= 4.0 * volume; 00277 volume /= 6.0; 00278 return CUBIT_SUCCESS; 00279 } 00280