MOAB: Mesh Oriented datABase  (version 5.5.0)
restore_topo_geom_incl_test.cpp
Go to the documentation of this file.
1 #include "moab/Interface.hpp"
2 #include "TestUtil.hpp"
3 #include "moab/Core.hpp"
4 #include "moab/Types.hpp"
5 #include "MBTagConventions.hpp"
6 #include "moab/GeomTopoTool.hpp"
7 #include <iostream>
8 #include <map>
9 #include <set>
10 
11 using namespace moab;
12 
18 
19 bool check_tree( Interface* mbi, GeomTopoTool* GTT, std::map< int, std::set< int > >& ref_map );
21 Range get_children_by_dimension( Interface* mbi, EntityHandle parent, int desired_dimension );
22 void heappermute( Interface* mbi, int v[], int n, std::map< int, std::set< int > > ref_map, int len );
23 void swap( int* x, int* y );
24 void get_cube_info( int cube_id, std::vector< double >& scale, std::vector< double >& trans );
25 void test_two_cubes();
26 void test_three_cubes();
27 void test_four_cubes();
28 
30  std::vector< double > scale_vec,
31  std::vector< double > trans_vec,
32  int object_id,
33  EntityHandle& volume )
34 {
35  GeomTopoTool* GTT = new GeomTopoTool( mbi );
36 
37  ErrorCode rval;
38 
39  // Define a 1x1x1 cube centered at orgin
40 
41  // coordinates of each corner
42  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,
43  0.5, -0.5, 0.5, 0.5, 0.5, 0.5, -0.5, 0.5, 0.5, -0.5, -0.5, 0.5 };
44 
45  // connectivity of 2 triangles per
46  // each face of the cube
47  const int connectivity[] = {
48  0, 3, 1, 3, 2, 1, // -Z
49  0, 1, 4, 5, 4, 1, // +X
50  1, 2, 6, 6, 5, 1, // +Y
51  6, 2, 3, 7, 6, 3, // -X
52  0, 4, 3, 7, 3, 4, // -Y
53  4, 5, 7, 5, 6, 7 // +Z
54  };
55 
56  // Create the geometry
57  const int num_verts = 8;
58  const int num_tris = 12;
59  EntityHandle verts[num_verts], tris[num_tris], surf;
60 
61  rval = mbi->create_meshset( MESHSET_SET, surf );MB_CHK_ERR( rval );
62  /*
63  // scale coords
64  int i;
65  double scaled_coords[24];
66  for ( i = 0; i < num_verts; i++ )
67  {
68  scaled_coords[3*i] = coords[3*i]*scale_vec[0];
69  scaled_coords[3*i+1] = coords[3*i+1]*scale_vec[1];
70  scaled_coords[3*i+2] = coords[3*i+2]*scale_vec[2];
71  }
72 
73  // translate coords
74  double trans_coords[24];
75  for ( i = 0; i < num_verts; i++ )
76  {
77  trans_coords[3*i] = scaled_coords[3*i] + trans_vec[0];
78  trans_coords[3*i+1] = scaled_coords[3*i+1] + trans_vec[1];
79  trans_coords[3*i+2] = scaled_coords[3*i+2] + trans_vec[2];
80  }
81  */
82  // transform coords-- scale and translate
83  double trans_coords[24];
84  for( int i = 0; i < num_verts; i++ )
85  {
86  trans_coords[3 * i] = coords[3 * i] * scale_vec[0] + trans_vec[0];
87  trans_coords[3 * i + 1] = coords[3 * i + 1] * scale_vec[1] + trans_vec[1];
88  trans_coords[3 * i + 2] = coords[3 * i + 2] * scale_vec[2] + trans_vec[2];
89  }
90 
91  // create vertices and add to meshset
92  for( int i = 0; i < num_verts; ++i )
93  {
94  rval = mbi->create_vertex( trans_coords + 3 * i, verts[i] );MB_CHK_ERR( rval );
95 
96  rval = mbi->add_entities( surf, &verts[i], 1 );MB_CHK_ERR( rval );
97  }
98 
99  // create triangles and add to meshset
100  for( int i = 0; i < num_tris; ++i )
101  {
102  const EntityHandle conn[] = { verts[connectivity[3 * i]], verts[connectivity[3 * i + 1]],
103  verts[connectivity[3 * i + 2]] };
104  rval = mbi->create_element( MBTRI, conn, 3, tris[i] );MB_CHK_ERR( rval );
105 
106  rval = mbi->add_entities( surf, &tris[i], 1 );MB_CHK_ERR( rval );
107  }
108 
109  // set name, id, geom, and category tags for SURFACE
110  rval = mbi->tag_set_data( name_tag, &surf, 1, "Surface\0" );MB_CHK_ERR( rval );
111  std::string object_name;
112  rval = mbi->tag_set_data( obj_name_tag, &surf, 1, object_name.c_str() );MB_CHK_ERR( rval );
113  rval = mbi->tag_set_data( id_tag, &surf, 1, &object_id );MB_CHK_ERR( rval );
114  int two = 2;
115  rval = mbi->tag_set_data( geom_tag, &surf, 1, &( two ) );MB_CHK_ERR( rval );
116  rval = mbi->tag_set_data( category_tag, &surf, 1, "Surface\0" );MB_CHK_ERR( rval );
117 
118  // create volume meshset associated with surface meshset
119  // EntityHandle volume;
120  rval = mbi->create_meshset( MESHSET_SET, volume );MB_CHK_ERR( rval );
121 
122  // set name, id, geom, and category tags for VOLUME
123  rval = mbi->tag_set_data( name_tag, &volume, 1, "Volume\0" );MB_CHK_ERR( rval );
124  rval = mbi->tag_set_data( obj_name_tag, &surf, 1, object_name.c_str() );MB_CHK_ERR( rval );
125  rval = mbi->tag_set_data( id_tag, &volume, 1, &( object_id ) );MB_CHK_ERR( rval );
126  int three = 3;
127  rval = mbi->tag_set_data( geom_tag, &volume, 1, &( three ) );MB_CHK_ERR( rval );
128  rval = mbi->tag_set_data( category_tag, &volume, 1, "Volume\0" );MB_CHK_ERR( rval );
129 
130  // set surface as child of volume
131  rval = mbi->add_parent_child( volume, surf );MB_CHK_ERR( rval );
132 
133  // set sense tag
134  rval = GTT->set_sense( surf, volume, SENSE_FORWARD );MB_CHK_ERR( rval );
135 
136  delete GTT;
137 
138  return MB_SUCCESS;
139 }
140 
141 int main()
142 {
143  int result = 0;
144 
145  result += RUN_TEST( test_two_cubes );
146  result += RUN_TEST( test_three_cubes );
147  result += RUN_TEST( test_four_cubes );
148 
149  return result;
150 }
151 
153 {
154  ErrorCode rval;
155 
157 
158  rval = mbi->tag_get_handle( "OBJECT_NAME", 32, MB_TYPE_OPAQUE, obj_name_tag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_ERR( rval );
159 
160  int negone = -1;
162  &negone );MB_CHK_ERR( rval );
163 
164  id_tag = mbi->globalId_tag();
165 
168 
169  MB_CHK_ERR( rval );
170  return MB_SUCCESS;
171 }
172 
173 /* This function tests that the tree built by generate_hierarchy is the same
174  as the reference tree
175 */
176 bool check_tree( Interface* mbi, GeomTopoTool* GTT, std::map< int, std::set< int > >& ref_map )
177 {
178  ErrorCode rval;
179  int vol_id;
180  std::set< int > test_set;
181 
182  Range vols;
183  rval = GTT->get_gsets_by_dimension( 3, vols );
184  if( ref_map.size() != vols.size() )
185  {
186  return false;
187  }
188 
189  // go through volumes, create sets of children
190  for( Range::iterator it = vols.begin(); it != vols.end(); ++it )
191  {
192  // get vol id
193  rval = mbi->tag_get_data( id_tag, &( *it ), 1, &vol_id );MB_CHK_ERR( rval );
194 
195  // check if test vol in ref map
196  if( ref_map.find( vol_id ) == ref_map.end() )
197  {
198  return false;
199  }
200 
201  // put range of child surfaces into set
202  Range child_surfs;
203  test_set.clear();
204  child_surfs = get_children_by_dimension( mbi, *it, 2 );
205 
206  for( Range::iterator j = child_surfs.begin(); j != child_surfs.end(); ++j )
207  {
208  int child_id;
209 
210  rval = mbi->tag_get_data( id_tag, &( *j ), 1, &child_id );MB_CHK_ERR( rval );
211  test_set.insert( child_id );
212  }
213 
214  // compare sets
215  if( test_set != ref_map[vol_id] )
216  {
217  return false;
218  }
219  }
220 
221  return true;
222 }
223 
224 Range get_children_by_dimension( Interface* mbi, EntityHandle parent, int desired_dimension )
225 {
226  ErrorCode rval;
227  Range all_children, desired_children;
228  Range::iterator it;
229  int actual_dimension;
230 
231  all_children.clear();
232  rval = mbi->get_child_meshsets( parent, all_children );MB_CHK_SET_ERR_RET_VAL( rval, "Failed to get child meshsets", all_children );
233 
234  for( it = all_children.begin(); it != all_children.end(); ++it )
235  {
236  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 );
237  if( actual_dimension == desired_dimension )
238  {
239  desired_children.insert( *it );
240  }
241  }
242 
243  return desired_children;
244 }
245 
246 /* This function contains info for the scale and translation vectors of
247  four different cubes that will be used in the hierarchy testing
248 */
249 void get_cube_info( int cube_id, std::vector< double >& scale, std::vector< double >& trans )
250 {
251  scale.clear();
252  trans.clear();
253 
254  if( cube_id == 1 )
255  {
256  scale.push_back( 1 );
257  scale.push_back( 1 );
258  scale.push_back( 1 );
259  trans.push_back( 0 );
260  trans.push_back( 0 );
261  trans.push_back( 0 );
262  }
263  if( cube_id == 2 )
264  {
265  scale.push_back( 4 );
266  scale.push_back( 4 );
267  scale.push_back( 4 );
268  trans.push_back( 0 );
269  trans.push_back( 0 );
270  trans.push_back( 0 );
271  }
272  if( cube_id == 3 )
273  {
274  scale.push_back( 8 );
275  scale.push_back( 8 );
276  scale.push_back( 8 );
277  trans.push_back( 0 );
278  trans.push_back( 0 );
279  trans.push_back( 0 );
280  }
281  if( cube_id == 4 )
282  {
283  scale.push_back( 40 );
284  scale.push_back( 40 );
285  scale.push_back( 40 );
286  trans.push_back( 0 );
287  trans.push_back( 0 );
288  trans.push_back( 0 );
289  }
290 }
291 
292 /*
293  * One large cube that contains a smaller one.
294  */
296 {
297  ErrorCode rval;
298 
299  Interface* mbi = new Core();
300 
301  // get all handles (dimension, id, sense)
302  rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval );
303 
304  int len = 2;
305  int num[2] = { 1, 2 };
306 
307  // build reference map
308  std::map< int, std::set< int > > ref_map;
309  ref_map[1].insert( 1 );
310  ref_map[2].insert( 2 );
311  ref_map[2].insert( 1 );
312 
313  heappermute( mbi, num, len, ref_map, len );
314 
315  delete mbi;
316 }
317 
318 /*
319  * One large cube that contains two others.
320  * The two inner cubes are siblings.
321  */
323 {
324  ErrorCode rval;
325 
326  Interface* mbi = new Core();
327 
328  // get all handles (dimension, id, sense)
329  rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval );
330 
331  int len = 3;
332  int num[3] = { 1, 2, 3 };
333 
334  // build reference map
335  std::map< int, std::set< int > > ref_map;
336  ref_map[1].insert( 1 );
337  ref_map[2].insert( 2 );
338  ref_map[2].insert( 1 );
339  ref_map[3].insert( 3 );
340  ref_map[3].insert( 2 );
341 
342  heappermute( mbi, num, len, ref_map, len );
343 
344  delete mbi;
345 }
346 
347 /*
348  * Four nested cubes of decreasing size; one placed inside the next
349  */
351 {
352  ErrorCode rval;
353 
354  Interface* mbi = new Core();
355 
356  // get all handles (dimension, id, sense)
357  rval = get_all_handles( mbi );MB_CHK_ERR_RET( rval );
358 
359  int len = 4;
360  int num[4] = { 1, 2, 3, 4 };
361 
362  // build reference map
363  std::map< int, std::set< int > > ref_map;
364  ref_map[1].insert( 1 );
365  ref_map[2].insert( 2 );
366  ref_map[2].insert( 1 );
367  ref_map[3].insert( 3 );
368  ref_map[3].insert( 2 );
369  ref_map[4].insert( 4 );
370  ref_map[4].insert( 3 );
371 
372  heappermute( mbi, num, len, ref_map, len );
373 
374  delete mbi;
375 }
376 
377 /* Heap's algorithm generates all possible permutations of n objects
378  This function is a modification of code found here:
379  http://www.sanfoundry.com/c-program-implement-heap-algorithm-permutation-n-numbers
380 */
381 void heappermute( Interface* mbi, int v[], int n, std::map< int, std::set< int > > ref_map, int len )
382 {
383 
384  ErrorCode rval;
385  std::vector< double > scale, trans;
386  EntityHandle vol;
387  Range flat_vols;
388 
389  if( n == 1 )
390  {
391  // build cubes
392  flat_vols.clear();
393  for( int i = 0; i < len; i++ )
394  {
395  get_cube_info( v[i], scale, trans );
396  build_cube( mbi, scale, trans, v[i], vol );
397  flat_vols.insert( vol );
398  }
399 
400  // construct the topology
401  GeomTopoTool* GTT = new GeomTopoTool( mbi );
402  // first build obbs-- necessary for topology construction
403  rval = GTT->construct_obb_trees();MB_CHK_ERR_RET( rval );
404  rval = GTT->restore_topology_from_geometric_inclusion( flat_vols );MB_CHK_ERR_RET( rval );
405 
406  // test the topology
407  bool result = check_tree( mbi, GTT, ref_map );
408  CHECK_EQUAL( 1, result );
409  delete GTT;
410 
411  // delete the geometry so new one can be built;
412  rval = mbi->delete_mesh();MB_CHK_ERR_RET( rval );
413  }
414 
415  else
416  {
417  for( int i = 0; i < n; i++ )
418  {
419  heappermute( mbi, v, n - 1, ref_map, len );
420  if( n % 2 == 1 )
421  {
422  swap( &v[0], &v[n - 1] );
423  }
424 
425  else
426  {
427  swap( &v[i], &v[n - 1] );
428  }
429  }
430  }
431 }
432 
433 void swap( int* x, int* y )
434 {
435  int temp;
436 
437  temp = *x;
438  *x = *y;
439  *y = temp;
440 }