MOAB: Mesh Oriented datABase
(version 5.2.1)
|
00001 #include "moab/Interface.hpp" 00002 #include "TestUtil.hpp" 00003 #include "moab/Core.hpp" 00004 #include "moab/Types.hpp" 00005 #include "MBTagConventions.hpp" 00006 #include "moab/GeomTopoTool.hpp" 00007 #include <iostream> 00008 #include <map> 00009 #include <set> 00010 00011 using namespace moab; 00012 00013 Tag category_tag; 00014 Tag geom_tag; 00015 Tag name_tag; 00016 Tag obj_name_tag; 00017 Tag dim_tag, id_tag; 00018 00019 bool check_tree( Interface* mbi, GeomTopoTool* GTT, std::map< int, std::set< int > >& ref_map ); 00020 ErrorCode get_all_handles( Interface* mbi ); 00021 Range get_children_by_dimension( Interface* mbi, EntityHandle parent, int desired_dimension ); 00022 void heappermute( Interface* mbi, int v[], int n, std::map< int, std::set< int > > ref_map, int len ); 00023 void swap( int* x, int* y ); 00024 void get_cube_info( int cube_id, std::vector< double >& scale, std::vector< double >& trans ); 00025 void test_two_cubes(); 00026 void test_three_cubes(); 00027 void test_four_cubes(); 00028 00029 ErrorCode build_cube( Interface* mbi, std::vector< double > scale_vec, std::vector< double > trans_vec, int object_id, 00030 EntityHandle& volume ) 00031 { 00032 GeomTopoTool* GTT = new GeomTopoTool( mbi ); 00033 00034 ErrorCode rval; 00035 00036 // Define a 1x1x1 cube centered at orgin 00037 00038 // coordinates of each corner 00039 const double coords[] = { 0.5, -0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5, -0.5, -0.5, -0.5, -0.5, 00040 0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5 }; 00041 00042 // connectivity of 2 triangles per 00043 // each face of the cube 00044 const int connectivity[] = { 00045 0, 3, 1, 3, 2, 1, // -Z 00046 0, 1, 4, 5, 4, 1, // +X 00047 1, 2, 6, 6, 5, 1, // +Y 00048 6, 2, 3, 7, 6, 3, // -X 00049 0, 4, 3, 7, 3, 4, // -Y 00050 4, 5, 7, 5, 6, 7 // +Z 00051 }; 00052 00053 // Create the geometry 00054 const int num_verts = 8; 00055 const int num_tris = 12; 00056 EntityHandle verts[num_verts], tris[num_tris], surf; 00057 00058 rval = mbi->create_meshset( MESHSET_SET, surf );MB_CHK_ERR( rval ); 00059 /* 00060 // scale coords 00061 int i; 00062 double scaled_coords[24]; 00063 for ( i = 0; i < num_verts; i++ ) 00064 { 00065 scaled_coords[3*i] = coords[3*i]*scale_vec[0]; 00066 scaled_coords[3*i+1] = coords[3*i+1]*scale_vec[1]; 00067 scaled_coords[3*i+2] = coords[3*i+2]*scale_vec[2]; 00068 } 00069 00070 // translate coords 00071 double trans_coords[24]; 00072 for ( i = 0; i < num_verts; i++ ) 00073 { 00074 trans_coords[3*i] = scaled_coords[3*i] + trans_vec[0]; 00075 trans_coords[3*i+1] = scaled_coords[3*i+1] + trans_vec[1]; 00076 trans_coords[3*i+2] = scaled_coords[3*i+2] + trans_vec[2]; 00077 } 00078 */ 00079 // transform coords-- scale and translate 00080 double trans_coords[24]; 00081 for( int i = 0; i < num_verts; i++ ) 00082 { 00083 trans_coords[3 * i] = coords[3 * i] * scale_vec[0] + trans_vec[0]; 00084 trans_coords[3 * i + 1] = coords[3 * i + 1] * scale_vec[1] + trans_vec[1]; 00085 trans_coords[3 * i + 2] = coords[3 * i + 2] * scale_vec[2] + trans_vec[2]; 00086 } 00087 00088 // create vertices and add to meshset 00089 for( int i = 0; i < num_verts; ++i ) 00090 { 00091 rval = mbi->create_vertex( trans_coords + 3 * i, verts[i] );MB_CHK_ERR( rval ); 00092 00093 rval = mbi->add_entities( surf, &verts[i], 1 );MB_CHK_ERR( rval ); 00094 } 00095 00096 // create triangles and add to meshset 00097 for( int i = 0; i < num_tris; ++i ) 00098 { 00099 const EntityHandle conn[] = { verts[connectivity[3 * i]], verts[connectivity[3 * i + 1]], 00100 verts[connectivity[3 * i + 2]] }; 00101 rval = mbi->create_element( MBTRI, conn, 3, tris[i] );MB_CHK_ERR( rval ); 00102 00103 rval = mbi->add_entities( surf, &tris[i], 1 );MB_CHK_ERR( rval ); 00104 } 00105 00106 // set name, id, geom, and category tags for SURFACE 00107 rval = mbi->tag_set_data( name_tag, &surf, 1, "Surface\0" );MB_CHK_ERR( rval ); 00108 std::string object_name; 00109 rval = mbi->tag_set_data( obj_name_tag, &surf, 1, object_name.c_str() );MB_CHK_ERR( rval ); 00110 rval = mbi->tag_set_data( id_tag, &surf, 1, &object_id );MB_CHK_ERR( rval ); 00111 int two = 2; 00112 rval = mbi->tag_set_data( geom_tag, &surf, 1, &( two ) );MB_CHK_ERR( rval ); 00113 rval = mbi->tag_set_data( category_tag, &surf, 1, "Surface\0" );MB_CHK_ERR( rval ); 00114 00115 // create volume meshset associated with surface meshset 00116 // EntityHandle volume; 00117 rval = mbi->create_meshset( MESHSET_SET, volume );MB_CHK_ERR( rval ); 00118 00119 // set name, id, geom, and category tags for VOLUME 00120 rval = mbi->tag_set_data( name_tag, &volume, 1, "Volume\0" );MB_CHK_ERR( rval ); 00121 rval = mbi->tag_set_data( obj_name_tag, &surf, 1, object_name.c_str() );MB_CHK_ERR( rval ); 00122 rval = mbi->tag_set_data( id_tag, &volume, 1, &( object_id ) );MB_CHK_ERR( rval ); 00123 int three = 3; 00124 rval = mbi->tag_set_data( geom_tag, &volume, 1, &( three ) );MB_CHK_ERR( rval ); 00125 rval = mbi->tag_set_data( category_tag, &volume, 1, "Volume\0" );MB_CHK_ERR( rval ); 00126 00127 // set surface as child of volume 00128 rval = mbi->add_parent_child( volume, surf );MB_CHK_ERR( rval ); 00129 00130 // set sense tag 00131 rval = GTT->set_sense( surf, volume, SENSE_FORWARD );MB_CHK_ERR( rval ); 00132 00133 delete GTT; 00134 00135 return MB_SUCCESS; 00136 } 00137 00138 int main() 00139 { 00140 int result = 0; 00141 00142 result += RUN_TEST( test_two_cubes ); 00143 result += RUN_TEST( test_three_cubes ); 00144 result += RUN_TEST( test_four_cubes ); 00145 00146 return result; 00147 } 00148 00149 ErrorCode get_all_handles( Interface* mbi ) 00150 { 00151 ErrorCode rval; 00152 00153 rval = mbi->tag_get_handle( NAME_TAG_NAME, NAME_TAG_SIZE, MB_TYPE_OPAQUE, name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( rval ); 00154 00155 rval = mbi->tag_get_handle( "OBJECT_NAME", 32, MB_TYPE_OPAQUE, obj_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( rval ); 00156 00157 int negone = -1; 00158 rval = mbi->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, MB_TAG_SPARSE | MB_TAG_CREAT, 00159 &negone );MB_CHK_ERR( rval ); 00160 00161 id_tag = mbi->globalId_tag(); 00162 00163 rval = mbi->tag_get_handle( CATEGORY_TAG_NAME, CATEGORY_TAG_SIZE, MB_TYPE_OPAQUE, category_tag, 00164 MB_TAG_SPARSE | MB_TAG_CREAT ); 00165 00166 MB_CHK_ERR( rval ); 00167 return MB_SUCCESS; 00168 } 00169 00170 /* This function tests that the tree built by generate_hierarchy is the same 00171 as the reference tree 00172 */ 00173 bool check_tree( Interface* mbi, GeomTopoTool* GTT, std::map< int, std::set< int > >& ref_map ) 00174 { 00175 ErrorCode rval; 00176 int vol_id; 00177 std::set< int > test_set; 00178 00179 Range vols; 00180 rval = GTT->get_gsets_by_dimension( 3, vols ); 00181 if( ref_map.size() != vols.size() ) { return false; } 00182 00183 // go through volumes, create sets of children 00184 for( Range::iterator it = vols.begin(); it != vols.end(); ++it ) 00185 { 00186 // get vol id 00187 rval = mbi->tag_get_data( id_tag, &( *it ), 1, &vol_id );MB_CHK_ERR( rval ); 00188 00189 // check if test vol in ref map 00190 if( ref_map.find( vol_id ) == ref_map.end() ) { return false; } 00191 00192 // put range of child surfaces into set 00193 Range child_surfs; 00194 test_set.clear(); 00195 child_surfs = get_children_by_dimension( mbi, *it, 2 ); 00196 00197 for( Range::iterator j = child_surfs.begin(); j != child_surfs.end(); ++j ) 00198 { 00199 int child_id; 00200 00201 rval = mbi->tag_get_data( id_tag, &( *j ), 1, &child_id );MB_CHK_ERR( rval ); 00202 test_set.insert( child_id ); 00203 } 00204 00205 // compare sets 00206 if( test_set != ref_map[vol_id] ) { return false; } 00207 } 00208 00209 return true; 00210 } 00211 00212 Range get_children_by_dimension( Interface* mbi, EntityHandle parent, int desired_dimension ) 00213 { 00214 ErrorCode rval; 00215 Range all_children, desired_children; 00216 Range::iterator it; 00217 int actual_dimension; 00218 00219 all_children.clear(); 00220 rval = mbi->get_child_meshsets( parent, all_children );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to get child meshsets", all_children ); 00221 00222 for( it = all_children.begin(); it != all_children.end(); ++it ) 00223 { 00224 rval = mbi->tag_get_data( geom_tag, &( *it ), 1, &actual_dimension );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to get geom tag from child meshset", all_children ); 00225 if( actual_dimension == desired_dimension ) { desired_children.insert( *it ); } 00226 } 00227 00228 return desired_children; 00229 } 00230 00231 /* This function contains info for the scale and translation vectors of 00232 four different cubes that will be used in the hierarchy testing 00233 */ 00234 void get_cube_info( int cube_id, std::vector< double >& scale, std::vector< double >& trans ) 00235 { 00236 scale.clear(); 00237 trans.clear(); 00238 00239 if( cube_id == 1 ) 00240 { 00241 scale.push_back( 1 ); 00242 scale.push_back( 1 ); 00243 scale.push_back( 1 ); 00244 trans.push_back( 0 ); 00245 trans.push_back( 0 ); 00246 trans.push_back( 0 ); 00247 } 00248 if( cube_id == 2 ) 00249 { 00250 scale.push_back( 4 ); 00251 scale.push_back( 4 ); 00252 scale.push_back( 4 ); 00253 trans.push_back( 0 ); 00254 trans.push_back( 0 ); 00255 trans.push_back( 0 ); 00256 } 00257 if( cube_id == 3 ) 00258 { 00259 scale.push_back( 8 ); 00260 scale.push_back( 8 ); 00261 scale.push_back( 8 ); 00262 trans.push_back( 0 ); 00263 trans.push_back( 0 ); 00264 trans.push_back( 0 ); 00265 } 00266 if( cube_id == 4 ) 00267 { 00268 scale.push_back( 40 ); 00269 scale.push_back( 40 ); 00270 scale.push_back( 40 ); 00271 trans.push_back( 0 ); 00272 trans.push_back( 0 ); 00273 trans.push_back( 0 ); 00274 } 00275 } 00276 00277 /* 00278 * One large cube that contains a smaller one. 00279 */ 00280 void test_two_cubes() 00281 { 00282 ErrorCode rval; 00283 00284 Interface* mbi = new Core(); 00285 00286 // get all handles (dimension, id, sense) 00287 rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval ); 00288 00289 int len = 2; 00290 int num[2] = { 1, 2 }; 00291 00292 // build reference map 00293 std::map< int, std::set< int > > ref_map; 00294 ref_map[1].insert( 1 ); 00295 ref_map[2].insert( 2 ); 00296 ref_map[2].insert( 1 ); 00297 00298 heappermute( mbi, num, len, ref_map, len ); 00299 00300 delete mbi; 00301 } 00302 00303 /* 00304 * One large cube that contains two others. 00305 * The two inner cubes are siblings. 00306 */ 00307 void test_three_cubes() 00308 { 00309 ErrorCode rval; 00310 00311 Interface* mbi = new Core(); 00312 00313 // get all handles (dimension, id, sense) 00314 rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval ); 00315 00316 int len = 3; 00317 int num[3] = { 1, 2, 3 }; 00318 00319 // build reference map 00320 std::map< int, std::set< int > > ref_map; 00321 ref_map[1].insert( 1 ); 00322 ref_map[2].insert( 2 ); 00323 ref_map[2].insert( 1 ); 00324 ref_map[3].insert( 3 ); 00325 ref_map[3].insert( 2 ); 00326 00327 heappermute( mbi, num, len, ref_map, len ); 00328 00329 delete mbi; 00330 } 00331 00332 /* 00333 * Four nested cubes of decreasing size; one placed inside the next 00334 */ 00335 void test_four_cubes() 00336 { 00337 ErrorCode rval; 00338 00339 Interface* mbi = new Core(); 00340 00341 // get all handles (dimension, id, sense) 00342 rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval ); 00343 00344 int len = 4; 00345 int num[4] = { 1, 2, 3, 4 }; 00346 00347 // build reference map 00348 std::map< int, std::set< int > > ref_map; 00349 ref_map[1].insert( 1 ); 00350 ref_map[2].insert( 2 ); 00351 ref_map[2].insert( 1 ); 00352 ref_map[3].insert( 3 ); 00353 ref_map[3].insert( 2 ); 00354 ref_map[4].insert( 4 ); 00355 ref_map[4].insert( 3 ); 00356 00357 heappermute( mbi, num, len, ref_map, len ); 00358 00359 delete mbi; 00360 } 00361 00362 /* Heap's algorithm generates all possible permutations of n objects 00363 This function is a modification of code found here: 00364 http://www.sanfoundry.com/c-program-implement-heap-algorithm-permutation-n-numbers 00365 */ 00366 void heappermute( Interface* mbi, int v[], int n, std::map< int, std::set< int > > ref_map, int len ) 00367 { 00368 00369 ErrorCode rval; 00370 std::vector< double > scale, trans; 00371 EntityHandle vol; 00372 Range flat_vols; 00373 00374 if( n == 1 ) 00375 { 00376 // build cubes 00377 flat_vols.clear(); 00378 for( int i = 0; i < len; i++ ) 00379 { 00380 get_cube_info( v[i], scale, trans ); 00381 build_cube( mbi, scale, trans, v[i], vol ); 00382 flat_vols.insert( vol ); 00383 } 00384 00385 // construct the topology 00386 GeomTopoTool* GTT = new GeomTopoTool( mbi ); 00387 // first build obbs-- necessary for topology construction 00388 rval = GTT->construct_obb_trees();MB_CHK_ERR_RET( rval ); 00389 rval = GTT->restore_topology_from_geometric_inclusion( flat_vols );MB_CHK_ERR_RET( rval ); 00390 00391 // test the topology 00392 bool result = check_tree( mbi, GTT, ref_map ); 00393 CHECK_EQUAL( 1, result ); 00394 delete GTT; 00395 00396 // delete the geometry so new one can be built; 00397 rval = mbi->delete_mesh();MB_CHK_ERR_RET( rval ); 00398 } 00399 00400 else 00401 { 00402 for( int i = 0; i < n; i++ ) 00403 { 00404 heappermute( mbi, v, n - 1, ref_map, len ); 00405 if( n % 2 == 1 ) { swap( &v[0], &v[n - 1] ); } 00406 00407 else 00408 { 00409 swap( &v[i], &v[n - 1] ); 00410 } 00411 } 00412 } 00413 } 00414 00415 void swap( int* x, int* y ) 00416 { 00417 int temp; 00418 00419 temp = *x; 00420 *x = *y; 00421 *y = temp; 00422 }