MOAB: Mesh Oriented datABase  (version 5.5.0)
merge_test.cpp
Go to the documentation of this file.
1 #include <vector>
2 #include <utility>
3 #include <iostream>
4 using namespace std;
5 using namespace moab;
6 
7 #include "moab/Core.hpp"
8 #include "moab/Interface.hpp"
9 #include "moab/Range.hpp"
10 
12 
14 {
15  public:
16  unsigned int node;
17  unsigned int edge;
18  unsigned int quad;
19  unsigned int tri;
20  unsigned int hex;
21  unsigned int tet;
22 
23  EntityCount();
24 
25  ErrorCode get_counts();
26  ErrorCode create_adjacencies( Range& entities, int adj_dim );
27  void copy_counts( EntityCount& count );
28  void print();
29 };
30 
32 {
33  node = 0;
34  edge = 0;
35  quad = 0;
36  tri = 0;
37  hex = 0;
38  tet = 0;
39 }
40 
42 {
43  node = count.node;
44  edge = count.edge;
45  quad = count.quad;
46  tri = count.tri;
47  hex = count.hex;
48  tet = count.tet;
49 }
50 
52 {
54  int do_create = edge == 0;
55 
56  if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
57  node = entities.size();
58 
59  entities.clear();
60  if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
61  hex = entities.size();
62  if( hex > 0 && do_create )
63  {
64  if( create_adjacencies( entities, 2 ) != MB_SUCCESS ) return MB_FAILURE;
65  if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
66  }
67 
68  entities.clear();
69  if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
70  quad = entities.size();
71  if( quad > 0 && do_create )
72  {
73 
74  if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
75  }
76 
77  entities.clear();
78  if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
79  tet = entities.size();
80  if( tet > 0 && do_create )
81  {
82  if( create_adjacencies( entities, 2 ) != MB_SUCCESS ) return MB_FAILURE;
83  if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
84  }
85 
86  entities.clear();
87  if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
88  tri = entities.size();
89  if( tri > 0 && do_create )
90  {
91  if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
92  }
93 
94  entities.clear();
95  if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
96  edge = entities.size();
97 
98  return MB_SUCCESS;
99 }
100 
102 {
103  ErrorCode result;
104  Range::iterator iter;
105  std::vector< EntityHandle > adjacencies;
106 
107  for( iter = entities.begin(); iter != entities.end(); ++iter )
108  {
109  result = gMB->get_adjacencies( &*iter, 1, adj_dim, true, adjacencies );
110  if( result != MB_SUCCESS ) break;
111  }
112 
113  return result;
114 }
115 
117 {
118  std::cout << " Vertices: " << node << std::endl;
119  cout << " Edges: " << edge << endl;
120  if( quad > 0 ) cout << " Quad Elements: " << quad << endl;
121  if( hex > 0 ) cout << " Hex Elements: " << hex << endl;
122  if( tri > 0 ) cout << " Tri Elements: " << tri << endl;
123  if( tet > 0 ) cout << " Tet Elements: " << tet << endl;
124 }
125 
126 bool points_are_coincident( const double* first, const double* second )
127 {
128  double diff[3];
129  diff[0] = first[0] - second[0];
130  diff[1] = first[1] - second[1];
131  diff[2] = first[2] - second[2];
132  double length = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
133 
134  if( fabs( length ) < .001 ) return true;
135 
136  return false;
137 }
138 
139 // dumb n^2 coincident node algorithm
140 ErrorCode find_coincident_nodes( Range vertices, std::vector< std::pair< EntityHandle, EntityHandle > >& coin_nodes )
141 {
142  double first_coords[3], second_coords[3];
143  Range::iterator iter, jter;
144  std::pair< EntityHandle, EntityHandle > coincident_pair;
145  ErrorCode result;
146 
147  for( iter = vertices.begin(); iter != vertices.end(); ++iter )
148  {
149  result = gMB->get_coords( &*iter, 1, first_coords );
150  if( result != MB_SUCCESS ) return result;
151 
152  for( jter = iter; jter != vertices.end(); ++jter )
153  {
154  if( *iter != *jter )
155  {
156  result = gMB->get_coords( &*jter, 1, second_coords );
157  if( result != MB_SUCCESS ) return result;
158 
159  if( points_are_coincident( first_coords, second_coords ) )
160  {
161  coincident_pair.first = *iter;
162  coincident_pair.second = *jter;
163  coin_nodes.push_back( coincident_pair );
164  }
165  }
166  }
167  }
168  return MB_SUCCESS;
169 }
170 
171 ErrorCode find_coincident_edges( Range entities, std::vector< std::pair< EntityHandle, EntityHandle > >& coin_edges )
172 {
173  double coords1[3], coords2[3], coords3[3];
174  Range::iterator iter, jter;
175  std::vector< EntityHandle > conn( 2 );
176  std::pair< EntityHandle, EntityHandle > coincident_pair;
177 
178  for( iter = entities.begin(); iter != entities.end(); ++iter )
179  {
180  if( gMB->get_connectivity( &*iter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
181 
182  // Get the coordinates for the edge endpoints.
183  if( gMB->get_coords( &conn[0], 1, coords1 ) != MB_SUCCESS ) return MB_FAILURE;
184 
185  if( gMB->get_coords( &conn[1], 1, coords2 ) != MB_SUCCESS ) return MB_FAILURE;
186 
187  for( jter = iter; jter != entities.end(); ++jter )
188  {
189  if( *iter != *jter )
190  {
191  // Edges should be the same sense to merge.
192  if( gMB->get_connectivity( &*jter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
193 
194  if( gMB->get_coords( &conn[0], 1, coords3 ) != MB_SUCCESS ) return MB_FAILURE;
195 
196  if( points_are_coincident( coords1, coords3 ) )
197  {
198  if( gMB->get_coords( &conn[1], 1, coords3 ) != MB_SUCCESS ) return MB_FAILURE;
199 
200  if( points_are_coincident( coords2, coords3 ) )
201  {
202  coincident_pair.first = *iter;
203  coincident_pair.second = *jter;
204  coin_edges.push_back( coincident_pair );
205  }
206  }
207  }
208  }
209  }
210 
211  return MB_SUCCESS;
212 }
213 
215  int num_nodes,
216  std::vector< std::pair< EntityHandle, EntityHandle > >& coin )
217 {
218  double coords1[8][3], coords2[8][3];
219  Range::iterator iter, jter;
220  std::vector< EntityHandle > conn( 8 );
221  std::pair< EntityHandle, EntityHandle > coincident_pair;
222  int i = 0, j = 0, ii = 0;
223 
224  for( iter = entities.begin(); iter != entities.end(); ++iter )
225  {
226  // Get the coordinates for the element corners.
227  if( gMB->get_connectivity( &*iter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
228  for( ii = 0; ii < num_nodes; ii++ )
229  {
230  if( gMB->get_coords( &conn[ii], 1, coords1[ii] ) != MB_SUCCESS ) return MB_FAILURE;
231  }
232 
233  for( jter = iter; jter != entities.end(); ++jter )
234  {
235  if( *iter != *jter )
236  {
237  // Elements should be the same sense to merge.
238  if( gMB->get_connectivity( &*jter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
239 
240  if( gMB->get_coords( &conn[0], 1, coords2[0] ) != MB_SUCCESS ) return MB_FAILURE;
241 
242  // Find if first node is coincident before testing the rest.
243  for( i = 0; i < num_nodes; i++ )
244  {
245  if( points_are_coincident( coords1[i], coords2[0] ) ) break;
246  }
247 
248  if( i < num_nodes )
249  {
250  for( ii = 1; ii < num_nodes; ii++ )
251  {
252  if( gMB->get_coords( &conn[ii], 1, coords2[ii] ) != MB_SUCCESS ) return MB_FAILURE;
253  }
254 
255  for( j = 1; j < num_nodes; j++ )
256  {
257  if( !points_are_coincident( coords1[j], coords2[( j + i ) % num_nodes] ) ) break;
258  }
259 
260  if( j == num_nodes )
261 
262  {
263  coincident_pair.first = *iter;
264  coincident_pair.second = *jter;
265  coin.push_back( coincident_pair );
266  }
267  }
268  }
269  }
270  }
271 
272  return MB_SUCCESS;
273 }
274 
276 {
277  Range entities;
278  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
279 
280  if( curr_count.node > 0 )
281  {
282  if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
283  find_coincident_nodes( entities, coincident );
284  diff_count.node = coincident.size();
285  entities.clear();
286  coincident.clear();
287  }
288  if( curr_count.edge > 0 )
289  {
290  if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
291  find_coincident_edges( entities, coincident );
292  diff_count.edge = coincident.size();
293  entities.clear();
294  coincident.clear();
295  }
296  if( curr_count.quad > 0 )
297  {
298  if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
299  find_coincident_elements( entities, 4, coincident );
300  diff_count.quad = coincident.size();
301  entities.clear();
302  coincident.clear();
303  }
304  if( curr_count.tri > 0 )
305  {
306  if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
307  find_coincident_elements( entities, 3, coincident );
308  diff_count.tri = coincident.size();
309  entities.clear();
310  coincident.clear();
311  }
312  if( curr_count.tet > 0 )
313  {
314  if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
315  find_coincident_elements( entities, 4, coincident );
316  diff_count.tet = coincident.size();
317  entities.clear();
318  coincident.clear();
319  }
320  if( curr_count.hex > 0 )
321  {
322  if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
323  find_coincident_elements( entities, 8, coincident );
324  diff_count.hex = coincident.size();
325  entities.clear();
326  coincident.clear();
327  }
328 
329  return MB_SUCCESS;
330 }
331 
332 ErrorCode merge_top_down( EntityCount& init_count, EntityCount& curr_count )
333 {
334  Range entities;
335  EntityCount diff_count;
336  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
337 
338  // Find how many objects of each type need to be merged.
339  if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
340 
341  // Find the top level object to merge.
342  if( diff_count.hex > 0 )
343  {
344  if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
345  find_coincident_elements( entities, 8, coincident );
346  }
347  else if( diff_count.quad > 0 )
348  {
349  if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
350  find_coincident_elements( entities, 4, coincident );
351  }
352  else if( diff_count.tet > 0 )
353  {
354  if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
355  find_coincident_elements( entities, 4, coincident );
356  }
357  else if( diff_count.tri > 0 )
358 
359  {
360  if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
361  find_coincident_elements( entities, 3, coincident );
362  }
363  else if( diff_count.edge > 0 )
364  {
365  if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
366  find_coincident_edges( entities, coincident );
367  }
368 
369  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
370  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
371  gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
372 
373  // Get the new entity totals.
374  curr_count.get_counts();
375 
376  // Make sure we didn't merge anything.
377  if( init_count.node != curr_count.node || init_count.edge != curr_count.edge ||
378  init_count.quad != curr_count.quad || init_count.tri != curr_count.tri || init_count.hex != curr_count.hex ||
379  init_count.tet != curr_count.tet )
380  {
381  cout << "***ERROR: Merged top down when not using auto merge.***" << endl;
382  return MB_FAILURE;
383  }
384 
385  return MB_SUCCESS;
386 }
387 
388 ErrorCode merge_nodes( EntityCount& init_count, EntityCount& curr_count )
389 {
390  cout << "Merging Coincident Nodes:" << endl;
391 
392  // Get the list of vertices from the database.
393  Range vertices;
394  ErrorCode result = gMB->get_entities_by_type( 0, MBVERTEX, vertices );
395  if( result != MB_SUCCESS ) return result;
396 
397  // find the coincident node pairs
398  std::vector< std::pair< EntityHandle, EntityHandle > > coincident_nodes;
399  find_coincident_nodes( vertices, coincident_nodes );
400 
401  // merge the coincident nodes
402  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
403  for( iter = coincident_nodes.begin(); iter != coincident_nodes.end(); ++iter )
404  {
405  cout << " Coincident nodes: " << ( *iter ).first << "-" << ( *iter ).second << endl;
406  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
407  if( result != MB_SUCCESS ) return result;
408  }
409 
410  // Get the reduced list of vertices.
411  curr_count.get_counts();
412 
413  // Make sure the coincident nodes were all merged.
414  if( init_count.node - curr_count.node != coincident_nodes.size() )
415  {
416  cout << "***ERROR: Not all coincident nodes were merged.***" << endl;
417  return MB_FAILURE;
418  }
419 
420  init_count.node = curr_count.node;
421 
422  // Make sure we didn't merge anything else.
423  if( init_count.edge != curr_count.edge || init_count.quad != curr_count.quad || init_count.tri != curr_count.tri ||
424  init_count.hex != curr_count.hex || init_count.tet != curr_count.tet )
425  {
426  cout << "***ERROR: Merged other objects when merging nodes.***" << endl;
427  return MB_FAILURE;
428  }
429 
430  return MB_SUCCESS;
431 }
432 
433 ErrorCode merge_edges( EntityCount& init_count, EntityCount& curr_count )
434 {
435  cout << "Merging Coincident Edges:" << endl;
436 
437  // Get the list of entities from the database.
438  Range entities;
440  if( result != MB_SUCCESS ) return result;
441 
442  // find the coincident edge pairs
443  std::vector< std::pair< EntityHandle, EntityHandle > > coincident_edges;
444  find_coincident_edges( entities, coincident_edges );
445 
446  // merge the coincident edges
447  unsigned long id1, id2;
448  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
449  for( iter = coincident_edges.begin(); iter != coincident_edges.end(); ++iter )
450  {
451  id1 = gMB->id_from_handle( ( *iter ).first );
452  id2 = gMB->id_from_handle( ( *iter ).second );
453  cout << " Coincident edges: " << id1 << "-" << id2 << endl;
454  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
455  if( result != MB_SUCCESS ) return result;
456  }
457 
458  // Get the reduced list of edges.
459  curr_count.get_counts();
460 
461  // Make sure the coincident edges were all merged.
462  if( init_count.edge - curr_count.edge != coincident_edges.size() )
463  {
464  cout << "***ERROR: Not all coincident edges were merged.***" << endl;
465  return MB_FAILURE;
466  }
467 
468  init_count.edge = curr_count.edge;
469 
470  // Make sure we didn't merge anything else.
471  if( init_count.node != curr_count.node || init_count.quad != curr_count.quad || init_count.tri != curr_count.tri ||
472  init_count.hex != curr_count.hex || init_count.tet != curr_count.tet )
473  {
474  cout << "***ERROR: Merged other objects when merging edges.***" << endl;
475  return MB_FAILURE;
476  }
477 
478  return MB_SUCCESS;
479 }
480 
481 ErrorCode merge_2D_elem( EntityCount& init_count, EntityCount& curr_count )
482 {
483  cout << "Merging Coincident 2D Elements:" << endl;
484 
485  // Get the list of tris from the database.
486  Range entities;
488  if( result != MB_SUCCESS ) return result;
489 
490  // find the coincident tri pairs
491  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
492  find_coincident_elements( entities, 3, coincident );
493 
494  // merge the coincident tris
495  unsigned long id1, id2;
496  unsigned int tri_diff = coincident.size();
497  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
498  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
499  {
500  id1 = gMB->id_from_handle( ( *iter ).first );
501  id2 = gMB->id_from_handle( ( *iter ).second );
502  cout << " Coincident tris: " << id1 << "-" << id2 << endl;
503  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
504 
505  if( result != MB_SUCCESS ) return result;
506  }
507 
508  // Get the list of quads from the database.
509  entities.clear();
510  result = gMB->get_entities_by_type( 0, MBQUAD, entities );
511  if( result != MB_SUCCESS ) return result;
512 
513  // find the coincident tri pairs
514  coincident.clear();
515  find_coincident_elements( entities, 4, coincident );
516 
517  // merge the coincident tris
518  unsigned int quad_diff = coincident.size();
519  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
520  {
521  id1 = gMB->id_from_handle( ( *iter ).first );
522  id2 = gMB->id_from_handle( ( *iter ).second );
523  cout << " Coincident quads: " << id1 << "-" << id2 << endl;
524  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
525  if( result != MB_SUCCESS ) return result;
526  }
527 
528  // Get the reduced list of faces.
529  curr_count.get_counts();
530 
531  // Make sure the coincident faces were all merged.
532  if( init_count.tri - curr_count.tri != tri_diff )
533  {
534  cout << "***ERROR: Not all coincident tris were merged.***" << endl;
535  return MB_FAILURE;
536  }
537  if( init_count.quad - curr_count.quad != quad_diff )
538  {
539  cout << "***ERROR: Not all coincident quads were merged.***" << endl;
540  return MB_FAILURE;
541  }
542 
543  init_count.tri = curr_count.tri;
544  init_count.quad = curr_count.quad;
545 
546  // Make sure we didn't merge anything else.
547  if( init_count.node != curr_count.node || init_count.edge != curr_count.edge || init_count.hex != curr_count.hex ||
548  init_count.tet != curr_count.tet )
549  {
550  cout << "***ERROR: Merged other objects when merging faces.***" << endl;
551  return MB_FAILURE;
552  }
553 
554  return MB_SUCCESS;
555 }
556 
557 ErrorCode merge_3D_elem( EntityCount& init_count, EntityCount& curr_count )
558 {
559  cout << "Merging Coincident 3D Elements:" << endl;
560 
561  // Get the list of tets from the database.
562  Range entities;
564  if( result != MB_SUCCESS ) return result;
565 
566  // find the coincident tet pairs
567  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
568  find_coincident_elements( entities, 4, coincident );
569 
570  // merge the coincident tets
571  unsigned long id1, id2;
572  unsigned int tet_diff = coincident.size();
573  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
574  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
575  {
576  id1 = gMB->id_from_handle( ( *iter ).first );
577  id2 = gMB->id_from_handle( ( *iter ).second );
578  cout << " Coincident tets: " << id1 << "-" << id2 << endl;
579  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
580  if( result != MB_SUCCESS ) return result;
581  }
582 
583  // Get the list of hexs from the database.
584  entities.clear();
585  result = gMB->get_entities_by_type( 0, MBHEX, entities );
586  if( result != MB_SUCCESS ) return result;
587 
588  // find the coincident hex pairs
589  coincident.clear();
590  find_coincident_elements( entities, 8, coincident );
591 
592  // merge the coincident tris
593  unsigned int hex_diff = coincident.size();
594  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
595  {
596  id1 = gMB->id_from_handle( ( *iter ).first );
597  id2 = gMB->id_from_handle( ( *iter ).second );
598  cout << " Coincident hexs: " << id1 << "-" << id2 << endl;
599  result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
600  if( result != MB_SUCCESS ) return result;
601  }
602 
603  // Get the reduced list of elements.
604  curr_count.get_counts();
605 
606  // Make sure the coincident elements were all merged.
607  if( init_count.tet - curr_count.tet != tet_diff )
608  {
609  cout << "***ERROR: Not all coincident tets were merged.***" << endl;
610  return MB_FAILURE;
611  }
612  if( init_count.hex - curr_count.hex != hex_diff )
613  {
614  cout << "***ERROR: Not all coincident hexs were merged.***" << endl;
615  return MB_FAILURE;
616  }
617 
618  init_count.tet = curr_count.tet;
619  init_count.hex = curr_count.hex;
620 
621  // Make sure we didn't merge anything else.
622  if( init_count.node != curr_count.node || init_count.edge != curr_count.edge ||
623  init_count.quad != curr_count.quad || init_count.tri != curr_count.tri )
624  {
625  cout << "***ERROR: Merged other objects when merging elements.***" << endl;
626  return MB_FAILURE;
627  }
628 
629  return MB_SUCCESS;
630 }
631 
632 ErrorCode read_file( std::string& file_name, EntityCount& counts )
633 {
634  // Make sure the database is empty.
635  gMB->delete_mesh();
636 
637  // Read the model from the file.
638  if( gMB->load_mesh( file_name.c_str(), 0 ) != MB_SUCCESS )
639  {
640  cout << "***ERROR: Unable to load mesh file.***" << endl;
641  return MB_FAILURE;
642  }
643 
644  // Get the number of each entity types in the mesh.
645  if( counts.get_counts() != MB_SUCCESS )
646  {
647  cout << "***ERROR: Unable to get entity list counts.***" << endl;
648  return MB_FAILURE;
649  }
650 
651  return MB_SUCCESS;
652 }
653 
654 ErrorCode write_file( std::string& file_name )
655 {
656  // get the block tag
657  ErrorCode result;
658  Range block_range;
659  Tag block_tag;
660 
661  if( gMB->tag_get_handle( "MATERIAL_SET", block_tag ) == MB_SUCCESS )
662  {
663  // get all the blocks
664  result = gMB->get_entities_by_type_and_tag( 0, MBENTITYSET, &block_tag, 0, 1, block_range );
665  if( result != MB_SUCCESS ) return result;
666  }
667 
668  // transfer range contents into vectors
669  std::vector< EntityHandle > output_list;
670 
671  Range::iterator range_iter, end_iter;
672  range_iter = block_range.begin();
673  end_iter = block_range.end();
674 
675  for( ; range_iter != end_iter; ++range_iter )
676  {
677  int id;
678  result = gMB->tag_get_handle( "MATERIAL_SET", block_tag );
679  if( result != MB_SUCCESS ) return result;
680 
681  result = gMB->tag_get_data( block_tag, &*range_iter, 1, &id );
682  if( result != MB_SUCCESS ) return result;
683 
684  // if(id != 2)
685  output_list.push_back( *range_iter );
686  }
687 
688  // write the file
689  static std::string mrg_splice( ".mrg" );
690  file_name.insert( file_name.size() - 2, mrg_splice );
691  result = gMB->write_mesh( file_name.c_str(), &output_list[0], output_list.size() );
692 
693  return result;
694 }
695 
696 ErrorCode process_td_auto_merge( std::string& file_name )
697 {
698  EntityCount init_count;
699  EntityCount curr_count;
700  EntityCount diff_count;
701 
702  // Read in the mesh and get the number of entities of each type.
703  if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
704 
705  // Copy the initial counts into the current count object.
706  curr_count.copy_counts( init_count );
707 
708  // Print out the list of initial objects.
709  cout << "Initial Entities:" << endl;
710  curr_count.print();
711 
712  // Try auto merging from the top down.
713  Range entities;
714  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
715 
716  // Find how many objects of each type need to be merged.
717  if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
718 
719  // Find the top level object to merge.
720  if( diff_count.hex > 0 )
721  {
722  if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
723  find_coincident_elements( entities, 8, coincident );
724  }
725  else if( diff_count.quad > 0 )
726  {
727  if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
728  find_coincident_elements( entities, 4, coincident );
729  }
730  else if( diff_count.tet > 0 )
731  {
732  if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
733  find_coincident_elements( entities, 4, coincident );
734  }
735  else if( diff_count.tri > 0 )
736  {
737  if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
738  find_coincident_elements( entities, 3, coincident );
739  }
740  else if( diff_count.edge > 0 )
741  {
742  if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
743  find_coincident_edges( entities, coincident );
744  }
745  else if( diff_count.node > 0 )
746  {
747  if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
748  find_coincident_nodes( entities, coincident );
749  }
750 
751  cout << "Merging coincident entities(top down)..." << endl;
752  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
753  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
754  gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
755 
756  // Get the new entity totals.
757  if( curr_count.get_counts() != MB_SUCCESS )
758  {
759  cout << "***ERROR: Unable to get entity list counts.***" << endl;
760  return MB_FAILURE;
761  }
762 
763  // Make sure we merged everything.
764  if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
765  init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
766  init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
767  {
768  cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
769  curr_count.print();
770  return MB_FAILURE;
771  }
772 
773  // Print out the final list of objects.
774  cout << "Final Entities:" << endl;
775  curr_count.print();
776 
777  return MB_SUCCESS;
778 }
779 
780 ErrorCode process_mo_auto_merge( std::string& file_name )
781 {
782  EntityCount init_count;
783  EntityCount curr_count;
784  EntityCount diff_count;
785 
786  // Read in the mesh and get the number of entities of each type.
787  if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
788 
789  // Copy the initial counts into the current count object.
790  curr_count.copy_counts( init_count );
791 
792  // Print out the list of initial objects.
793  cout << "Initial Entities:" << endl;
794  curr_count.print();
795 
796  // Try auto merging from the middle out.
797  Range entities;
798  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
799 
800  // Find how many objects of each type need to be merged.
801  if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
802 
803  // Start merge at the edge level if present.
804  if( diff_count.edge > 0 )
805  {
806  if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
807  find_coincident_edges( entities, coincident );
808  }
809  else
810  {
811  if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
812  find_coincident_nodes( entities, coincident );
813  }
814 
815  cout << "Merging coincident entities(middle out)..." << endl;
816  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
817  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
818 
819  gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
820 
821  // Get the new entity totals.
822  if( curr_count.get_counts() != MB_SUCCESS )
823  {
824  cout << "***ERROR: Unable to get entity list counts.***" << endl;
825  return MB_FAILURE;
826  }
827 
828  // Make sure we merged everything.
829  if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
830  init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
831  init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
832  {
833  cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
834  curr_count.print();
835  return MB_FAILURE;
836  }
837 
838  // Print out the final list of objects.
839  cout << "Final Entities:" << endl;
840  curr_count.print();
841 
842  return MB_SUCCESS;
843 }
844 
845 ErrorCode process_bu_auto_merge( std::string& file_name )
846 {
847  EntityCount init_count;
848  EntityCount curr_count;
849  EntityCount diff_count;
850 
851  // Read in the mesh and get the number of entities of each type.
852  if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
853 
854  // Copy the initial counts into the current count object.
855  curr_count.copy_counts( init_count );
856 
857  // Print out the list of initial objects.
858  cout << "Initial Entities:" << endl;
859  curr_count.print();
860 
861  // Try auto merging from the bottom up.
862  Range entities;
863  std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
864 
865  // Find how many objects of each type need to be merged.
866  if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
867 
868  // Start merging from the nodes and go up.
869  if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
870  find_coincident_nodes( entities, coincident );
871 
872  cout << "Merging coincident entities(bottom up)..." << endl;
873  std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
874  for( iter = coincident.begin(); iter != coincident.end(); ++iter )
875  gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
876 
877  // Get the new entity totals.
878  if( curr_count.get_counts() != MB_SUCCESS )
879  {
880  cout << "***ERROR: Unable to get entity list counts.***" << endl;
881  return MB_FAILURE;
882  }
883 
884  // Make sure we merged everything.
885  if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
886  init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
887  init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
888  {
889  cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
890  curr_count.print();
891 
892  return MB_FAILURE;
893  }
894 
895  // Print out the final list of objects.
896  cout << "Final Entities:" << endl;
897  curr_count.print();
898 
899  return MB_SUCCESS;
900 }
901 
902 ErrorCode process_merge( std::string& file_name )
903 {
904  EntityCount init_count;
905  EntityCount curr_count;
906 
907  // Read in the mesh and get the number of entities of each type.
908  if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
909 
910  // Copy the initial counts into the current count object.
911  curr_count.copy_counts( init_count );
912 
913  // Print out the list of initial objects.
914  cout << "Initial Entities:" << endl;
915  curr_count.print();
916 
917  // Try to merge elements before nodes (should fail).
918  if( merge_top_down( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
919 
920  // Merge the nodes.
921  if( merge_nodes( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
922 
923  // Next, merge the edges.
924  if( merge_edges( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
925 
926  // Now, merge the 2D elements.
927  if( merge_2D_elem( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
928 
929  // Finally, merge the 3D elements.
930  if( merge_3D_elem( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
931 
932  // Print out the final list of objects.
933  if( curr_count.get_counts() != MB_SUCCESS )
934  {
935  cout << "***ERROR: Unable to get entity list counts.***" << endl;
936  return MB_FAILURE;
937  }
938  cout << "Final Entities:" << endl;
939  curr_count.print();
940 
941  // write the file out (modifies name)
942  return write_file( file_name );
943 }
944 
945 int main()
946 {
947  ErrorCode result;
948  std::string test_files[] = {
949  std::string( "test/2barcase1.g" ), std::string( "test/2barcase2.g" ), std::string( "test/2hexcase1.g" ),
950  std::string( "test/2hexcase2.g" ), std::string( "test/2hexcase3.g" ), std::string( "test/2hexcase4.g" ),
951  std::string( "test/2hexcase5.g" ), std::string( "test/2quadcase1.g" ), std::string( "test/2quadcase2.g" ),
952  std::string( "test/2quadcase3.g" ), std::string( "test/2quadcase4.g" ), std::string( "test/2tetcase1.g" ),
953  std::string( "test/2tetcase2.g" ), std::string( "test/2tetcase3.g" ), std::string( "test/2tetcase4.g" ),
954  std::string( "test/2tricase1.g" ), std::string( "test/2tricase2.g" ), std::string( "test/2tricase3.g" ) };
955 
956  // Create the MB database instance.
957  gMB = new Core();
958 
959  // Loop through the list of test files.
960  unsigned int i;
961  cout << "---Starting Top Down Auto Merge Tests---" << endl << endl;
962  for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
963  {
964  cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
965  result = process_td_auto_merge( test_files[i] );
966  if( result == MB_SUCCESS )
967  cout << "---Success---";
968  else
969  cout << "---Failure---";
970  cout << endl << endl;
971  }
972 
973  cout << "---Starting Bottom Up Auto Merge Tests---" << endl << endl;
974  for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
975  {
976  cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
977  result = process_bu_auto_merge( test_files[i] );
978  if( result == MB_SUCCESS )
979 
980  cout << "---Success---";
981  else
982  cout << "---Failure---";
983  cout << endl << endl;
984  }
985 
986  cout << "---Starting Middle Out Auto Merge Tests---" << endl << endl;
987  for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
988  {
989  cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
990  result = process_mo_auto_merge( test_files[i] );
991  if( result == MB_SUCCESS )
992  cout << "---Success---";
993  else
994  cout << "---Failure---";
995 
996  cout << endl << endl;
997  }
998 
999  cout << "---Starting Merge Tests---" << endl << endl;
1000  for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
1001  {
1002  cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
1003  result = process_merge( test_files[i] );
1004  if( result == MB_SUCCESS )
1005  cout << "---Success---";
1006  else
1007  cout << "---Failure---";
1008  cout << endl << endl;
1009  }
1010 
1011  // Destroy the MB database instance.
1012  delete gMB;
1013  gMB = NULL;
1014 }