MOAB: Mesh Oriented datABase  (version 5.4.1)
merge_test.cpp
Go to the documentation of this file.
00001 #include <vector>
00002 #include <utility>
00003 #include <iostream>
00004 using namespace std;
00005 using namespace moab;
00006 
00007 #include "moab/Core.hpp"
00008 #include "moab/Interface.hpp"
00009 #include "moab/Range.hpp"
00010 
00011 Interface* gMB = 0;
00012 
00013 class EntityCount
00014 {
00015   public:
00016     unsigned int node;
00017     unsigned int edge;
00018     unsigned int quad;
00019     unsigned int tri;
00020     unsigned int hex;
00021     unsigned int tet;
00022 
00023     EntityCount();
00024 
00025     ErrorCode get_counts();
00026     ErrorCode create_adjacencies( Range& entities, int adj_dim );
00027     void copy_counts( EntityCount& count );
00028     void print();
00029 };
00030 
00031 EntityCount::EntityCount()
00032 {
00033     node = 0;
00034     edge = 0;
00035     quad = 0;
00036     tri  = 0;
00037     hex  = 0;
00038     tet  = 0;
00039 }
00040 
00041 void EntityCount::copy_counts( EntityCount& count )
00042 {
00043     node = count.node;
00044     edge = count.edge;
00045     quad = count.quad;
00046     tri  = count.tri;
00047     hex  = count.hex;
00048     tet  = count.tet;
00049 }
00050 
00051 ErrorCode EntityCount::get_counts()
00052 {
00053     Range entities;
00054     int do_create = edge == 0;
00055 
00056     if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00057     node = entities.size();
00058 
00059     entities.clear();
00060     if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00061     hex = entities.size();
00062     if( hex > 0 && do_create )
00063     {
00064         if( create_adjacencies( entities, 2 ) != MB_SUCCESS ) return MB_FAILURE;
00065         if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
00066     }
00067 
00068     entities.clear();
00069     if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
00070     quad = entities.size();
00071     if( quad > 0 && do_create )
00072     {
00073 
00074         if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
00075     }
00076 
00077     entities.clear();
00078     if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
00079     tet = entities.size();
00080     if( tet > 0 && do_create )
00081     {
00082         if( create_adjacencies( entities, 2 ) != MB_SUCCESS ) return MB_FAILURE;
00083         if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
00084     }
00085 
00086     entities.clear();
00087     if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
00088     tri = entities.size();
00089     if( tri > 0 && do_create )
00090     {
00091         if( create_adjacencies( entities, 1 ) != MB_SUCCESS ) return MB_FAILURE;
00092     }
00093 
00094     entities.clear();
00095     if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
00096     edge = entities.size();
00097 
00098     return MB_SUCCESS;
00099 }
00100 
00101 ErrorCode EntityCount::create_adjacencies( Range& entities, int adj_dim )
00102 {
00103     ErrorCode result;
00104     Range::iterator iter;
00105     std::vector< EntityHandle > adjacencies;
00106 
00107     for( iter = entities.begin(); iter != entities.end(); ++iter )
00108     {
00109         result = gMB->get_adjacencies( &*iter, 1, adj_dim, true, adjacencies );
00110         if( result != MB_SUCCESS ) break;
00111     }
00112 
00113     return result;
00114 }
00115 
00116 void EntityCount::print()
00117 {
00118     std::cout << "   Vertices: " << node << std::endl;
00119     cout << "   Edges: " << edge << endl;
00120     if( quad > 0 ) cout << "   Quad Elements: " << quad << endl;
00121     if( hex > 0 ) cout << "   Hex Elements: " << hex << endl;
00122     if( tri > 0 ) cout << "   Tri Elements: " << tri << endl;
00123     if( tet > 0 ) cout << "   Tet Elements: " << tet << endl;
00124 }
00125 
00126 bool points_are_coincident( const double* first, const double* second )
00127 {
00128     double diff[3];
00129     diff[0]       = first[0] - second[0];
00130     diff[1]       = first[1] - second[1];
00131     diff[2]       = first[2] - second[2];
00132     double length = diff[0] * diff[0] + diff[1] * diff[1] + diff[2] * diff[2];
00133 
00134     if( fabs( length ) < .001 ) return true;
00135 
00136     return false;
00137 }
00138 
00139 // dumb n^2 coincident node algorithm
00140 ErrorCode find_coincident_nodes( Range vertices, std::vector< std::pair< EntityHandle, EntityHandle > >& coin_nodes )
00141 {
00142     double first_coords[3], second_coords[3];
00143     Range::iterator iter, jter;
00144     std::pair< EntityHandle, EntityHandle > coincident_pair;
00145     ErrorCode result;
00146 
00147     for( iter = vertices.begin(); iter != vertices.end(); ++iter )
00148     {
00149         result = gMB->get_coords( &*iter, 1, first_coords );
00150         if( result != MB_SUCCESS ) return result;
00151 
00152         for( jter = iter; jter != vertices.end(); ++jter )
00153         {
00154             if( *iter != *jter )
00155             {
00156                 result = gMB->get_coords( &*jter, 1, second_coords );
00157                 if( result != MB_SUCCESS ) return result;
00158 
00159                 if( points_are_coincident( first_coords, second_coords ) )
00160                 {
00161                     coincident_pair.first  = *iter;
00162                     coincident_pair.second = *jter;
00163                     coin_nodes.push_back( coincident_pair );
00164                 }
00165             }
00166         }
00167     }
00168     return MB_SUCCESS;
00169 }
00170 
00171 ErrorCode find_coincident_edges( Range entities, std::vector< std::pair< EntityHandle, EntityHandle > >& coin_edges )
00172 {
00173     double coords1[3], coords2[3], coords3[3];
00174     Range::iterator iter, jter;
00175     std::vector< EntityHandle > conn( 2 );
00176     std::pair< EntityHandle, EntityHandle > coincident_pair;
00177 
00178     for( iter = entities.begin(); iter != entities.end(); ++iter )
00179     {
00180         if( gMB->get_connectivity( &*iter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
00181 
00182         // Get the coordinates for the edge endpoints.
00183         if( gMB->get_coords( &conn[0], 1, coords1 ) != MB_SUCCESS ) return MB_FAILURE;
00184 
00185         if( gMB->get_coords( &conn[1], 1, coords2 ) != MB_SUCCESS ) return MB_FAILURE;
00186 
00187         for( jter = iter; jter != entities.end(); ++jter )
00188         {
00189             if( *iter != *jter )
00190             {
00191                 // Edges should be the same sense to merge.
00192                 if( gMB->get_connectivity( &*jter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
00193 
00194                 if( gMB->get_coords( &conn[0], 1, coords3 ) != MB_SUCCESS ) return MB_FAILURE;
00195 
00196                 if( points_are_coincident( coords1, coords3 ) )
00197                 {
00198                     if( gMB->get_coords( &conn[1], 1, coords3 ) != MB_SUCCESS ) return MB_FAILURE;
00199 
00200                     if( points_are_coincident( coords2, coords3 ) )
00201                     {
00202                         coincident_pair.first  = *iter;
00203                         coincident_pair.second = *jter;
00204                         coin_edges.push_back( coincident_pair );
00205                     }
00206                 }
00207             }
00208         }
00209     }
00210 
00211     return MB_SUCCESS;
00212 }
00213 
00214 ErrorCode find_coincident_elements( Range entities,
00215                                     int num_nodes,
00216                                     std::vector< std::pair< EntityHandle, EntityHandle > >& coin )
00217 {
00218     double coords1[8][3], coords2[8][3];
00219     Range::iterator iter, jter;
00220     std::vector< EntityHandle > conn( 8 );
00221     std::pair< EntityHandle, EntityHandle > coincident_pair;
00222     int i = 0, j = 0, ii = 0;
00223 
00224     for( iter = entities.begin(); iter != entities.end(); ++iter )
00225     {
00226         // Get the coordinates for the element corners.
00227         if( gMB->get_connectivity( &*iter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
00228         for( ii = 0; ii < num_nodes; ii++ )
00229         {
00230             if( gMB->get_coords( &conn[ii], 1, coords1[ii] ) != MB_SUCCESS ) return MB_FAILURE;
00231         }
00232 
00233         for( jter = iter; jter != entities.end(); ++jter )
00234         {
00235             if( *iter != *jter )
00236             {
00237                 // Elements should be the same sense to merge.
00238                 if( gMB->get_connectivity( &*jter, 1, conn ) != MB_SUCCESS ) return MB_FAILURE;
00239 
00240                 if( gMB->get_coords( &conn[0], 1, coords2[0] ) != MB_SUCCESS ) return MB_FAILURE;
00241 
00242                 // Find if first node is coincident before testing the rest.
00243                 for( i = 0; i < num_nodes; i++ )
00244                 {
00245                     if( points_are_coincident( coords1[i], coords2[0] ) ) break;
00246                 }
00247 
00248                 if( i < num_nodes )
00249                 {
00250                     for( ii = 1; ii < num_nodes; ii++ )
00251                     {
00252                         if( gMB->get_coords( &conn[ii], 1, coords2[ii] ) != MB_SUCCESS ) return MB_FAILURE;
00253                     }
00254 
00255                     for( j = 1; j < num_nodes; j++ )
00256                     {
00257                         if( !points_are_coincident( coords1[j], coords2[( j + i ) % num_nodes] ) ) break;
00258                     }
00259 
00260                     if( j == num_nodes )
00261 
00262                     {
00263                         coincident_pair.first  = *iter;
00264                         coincident_pair.second = *jter;
00265                         coin.push_back( coincident_pair );
00266                     }
00267                 }
00268             }
00269         }
00270     }
00271 
00272     return MB_SUCCESS;
00273 }
00274 
00275 ErrorCode coincident_counts( EntityCount& curr_count, EntityCount& diff_count )
00276 {
00277     Range entities;
00278     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00279 
00280     if( curr_count.node > 0 )
00281     {
00282         if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00283         find_coincident_nodes( entities, coincident );
00284         diff_count.node = coincident.size();
00285         entities.clear();
00286         coincident.clear();
00287     }
00288     if( curr_count.edge > 0 )
00289     {
00290         if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
00291         find_coincident_edges( entities, coincident );
00292         diff_count.edge = coincident.size();
00293         entities.clear();
00294         coincident.clear();
00295     }
00296     if( curr_count.quad > 0 )
00297     {
00298         if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
00299         find_coincident_elements( entities, 4, coincident );
00300         diff_count.quad = coincident.size();
00301         entities.clear();
00302         coincident.clear();
00303     }
00304     if( curr_count.tri > 0 )
00305     {
00306         if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
00307         find_coincident_elements( entities, 3, coincident );
00308         diff_count.tri = coincident.size();
00309         entities.clear();
00310         coincident.clear();
00311     }
00312     if( curr_count.tet > 0 )
00313     {
00314         if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
00315         find_coincident_elements( entities, 4, coincident );
00316         diff_count.tet = coincident.size();
00317         entities.clear();
00318         coincident.clear();
00319     }
00320     if( curr_count.hex > 0 )
00321     {
00322         if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00323         find_coincident_elements( entities, 8, coincident );
00324         diff_count.hex = coincident.size();
00325         entities.clear();
00326         coincident.clear();
00327     }
00328 
00329     return MB_SUCCESS;
00330 }
00331 
00332 ErrorCode merge_top_down( EntityCount& init_count, EntityCount& curr_count )
00333 {
00334     Range entities;
00335     EntityCount diff_count;
00336     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00337 
00338     // Find how many objects of each type need to be merged.
00339     if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
00340 
00341     // Find the top level object to merge.
00342     if( diff_count.hex > 0 )
00343     {
00344         if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00345         find_coincident_elements( entities, 8, coincident );
00346     }
00347     else if( diff_count.quad > 0 )
00348     {
00349         if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
00350         find_coincident_elements( entities, 4, coincident );
00351     }
00352     else if( diff_count.tet > 0 )
00353     {
00354         if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
00355         find_coincident_elements( entities, 4, coincident );
00356     }
00357     else if( diff_count.tri > 0 )
00358 
00359     {
00360         if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
00361         find_coincident_elements( entities, 3, coincident );
00362     }
00363     else if( diff_count.edge > 0 )
00364     {
00365         if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
00366         find_coincident_edges( entities, coincident );
00367     }
00368 
00369     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00370     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00371         gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00372 
00373     // Get the new entity totals.
00374     curr_count.get_counts();
00375 
00376     // Make sure we didn't merge anything.
00377     if( init_count.node != curr_count.node || init_count.edge != curr_count.edge ||
00378         init_count.quad != curr_count.quad || init_count.tri != curr_count.tri || init_count.hex != curr_count.hex ||
00379         init_count.tet != curr_count.tet )
00380     {
00381         cout << "***ERROR: Merged top down when not using auto merge.***" << endl;
00382         return MB_FAILURE;
00383     }
00384 
00385     return MB_SUCCESS;
00386 }
00387 
00388 ErrorCode merge_nodes( EntityCount& init_count, EntityCount& curr_count )
00389 {
00390     cout << "Merging Coincident Nodes:" << endl;
00391 
00392     // Get the list of vertices from the database.
00393     Range vertices;
00394     ErrorCode result = gMB->get_entities_by_type( 0, MBVERTEX, vertices );
00395     if( result != MB_SUCCESS ) return result;
00396 
00397     // find the coincident node pairs
00398     std::vector< std::pair< EntityHandle, EntityHandle > > coincident_nodes;
00399     find_coincident_nodes( vertices, coincident_nodes );
00400 
00401     // merge the coincident nodes
00402     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00403     for( iter = coincident_nodes.begin(); iter != coincident_nodes.end(); ++iter )
00404     {
00405         cout << "   Coincident nodes: " << ( *iter ).first << "-" << ( *iter ).second << endl;
00406         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00407         if( result != MB_SUCCESS ) return result;
00408     }
00409 
00410     // Get the reduced list of vertices.
00411     curr_count.get_counts();
00412 
00413     // Make sure the coincident nodes were all merged.
00414     if( init_count.node - curr_count.node != coincident_nodes.size() )
00415     {
00416         cout << "***ERROR: Not all coincident nodes were merged.***" << endl;
00417         return MB_FAILURE;
00418     }
00419 
00420     init_count.node = curr_count.node;
00421 
00422     // Make sure we didn't merge anything else.
00423     if( init_count.edge != curr_count.edge || init_count.quad != curr_count.quad || init_count.tri != curr_count.tri ||
00424         init_count.hex != curr_count.hex || init_count.tet != curr_count.tet )
00425     {
00426         cout << "***ERROR: Merged other objects when merging nodes.***" << endl;
00427         return MB_FAILURE;
00428     }
00429 
00430     return MB_SUCCESS;
00431 }
00432 
00433 ErrorCode merge_edges( EntityCount& init_count, EntityCount& curr_count )
00434 {
00435     cout << "Merging Coincident Edges:" << endl;
00436 
00437     // Get the list of entities from the database.
00438     Range entities;
00439     ErrorCode result = gMB->get_entities_by_type( 0, MBEDGE, entities );
00440     if( result != MB_SUCCESS ) return result;
00441 
00442     // find the coincident edge pairs
00443     std::vector< std::pair< EntityHandle, EntityHandle > > coincident_edges;
00444     find_coincident_edges( entities, coincident_edges );
00445 
00446     // merge the coincident edges
00447     unsigned long id1, id2;
00448     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00449     for( iter = coincident_edges.begin(); iter != coincident_edges.end(); ++iter )
00450     {
00451         id1 = gMB->id_from_handle( ( *iter ).first );
00452         id2 = gMB->id_from_handle( ( *iter ).second );
00453         cout << "   Coincident edges: " << id1 << "-" << id2 << endl;
00454         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00455         if( result != MB_SUCCESS ) return result;
00456     }
00457 
00458     // Get the reduced list of edges.
00459     curr_count.get_counts();
00460 
00461     // Make sure the coincident edges were all merged.
00462     if( init_count.edge - curr_count.edge != coincident_edges.size() )
00463     {
00464         cout << "***ERROR: Not all coincident edges were merged.***" << endl;
00465         return MB_FAILURE;
00466     }
00467 
00468     init_count.edge = curr_count.edge;
00469 
00470     // Make sure we didn't merge anything else.
00471     if( init_count.node != curr_count.node || init_count.quad != curr_count.quad || init_count.tri != curr_count.tri ||
00472         init_count.hex != curr_count.hex || init_count.tet != curr_count.tet )
00473     {
00474         cout << "***ERROR: Merged other objects when merging edges.***" << endl;
00475         return MB_FAILURE;
00476     }
00477 
00478     return MB_SUCCESS;
00479 }
00480 
00481 ErrorCode merge_2D_elem( EntityCount& init_count, EntityCount& curr_count )
00482 {
00483     cout << "Merging Coincident 2D Elements:" << endl;
00484 
00485     // Get the list of tris from the database.
00486     Range entities;
00487     ErrorCode result = gMB->get_entities_by_type( 0, MBTRI, entities );
00488     if( result != MB_SUCCESS ) return result;
00489 
00490     // find the coincident tri pairs
00491     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00492     find_coincident_elements( entities, 3, coincident );
00493 
00494     // merge the coincident tris
00495     unsigned long id1, id2;
00496     unsigned int tri_diff = coincident.size();
00497     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00498     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00499     {
00500         id1 = gMB->id_from_handle( ( *iter ).first );
00501         id2 = gMB->id_from_handle( ( *iter ).second );
00502         cout << "   Coincident tris: " << id1 << "-" << id2 << endl;
00503         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00504 
00505         if( result != MB_SUCCESS ) return result;
00506     }
00507 
00508     // Get the list of quads from the database.
00509     entities.clear();
00510     result = gMB->get_entities_by_type( 0, MBQUAD, entities );
00511     if( result != MB_SUCCESS ) return result;
00512 
00513     // find the coincident tri pairs
00514     coincident.clear();
00515     find_coincident_elements( entities, 4, coincident );
00516 
00517     // merge the coincident tris
00518     unsigned int quad_diff = coincident.size();
00519     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00520     {
00521         id1 = gMB->id_from_handle( ( *iter ).first );
00522         id2 = gMB->id_from_handle( ( *iter ).second );
00523         cout << "   Coincident quads: " << id1 << "-" << id2 << endl;
00524         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00525         if( result != MB_SUCCESS ) return result;
00526     }
00527 
00528     // Get the reduced list of faces.
00529     curr_count.get_counts();
00530 
00531     // Make sure the coincident faces were all merged.
00532     if( init_count.tri - curr_count.tri != tri_diff )
00533     {
00534         cout << "***ERROR: Not all coincident tris were merged.***" << endl;
00535         return MB_FAILURE;
00536     }
00537     if( init_count.quad - curr_count.quad != quad_diff )
00538     {
00539         cout << "***ERROR: Not all coincident quads were merged.***" << endl;
00540         return MB_FAILURE;
00541     }
00542 
00543     init_count.tri  = curr_count.tri;
00544     init_count.quad = curr_count.quad;
00545 
00546     // Make sure we didn't merge anything else.
00547     if( init_count.node != curr_count.node || init_count.edge != curr_count.edge || init_count.hex != curr_count.hex ||
00548         init_count.tet != curr_count.tet )
00549     {
00550         cout << "***ERROR: Merged other objects when merging faces.***" << endl;
00551         return MB_FAILURE;
00552     }
00553 
00554     return MB_SUCCESS;
00555 }
00556 
00557 ErrorCode merge_3D_elem( EntityCount& init_count, EntityCount& curr_count )
00558 {
00559     cout << "Merging Coincident 3D Elements:" << endl;
00560 
00561     // Get the list of tets from the database.
00562     Range entities;
00563     ErrorCode result = gMB->get_entities_by_type( 0, MBTET, entities );
00564     if( result != MB_SUCCESS ) return result;
00565 
00566     // find the coincident tet pairs
00567     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00568     find_coincident_elements( entities, 4, coincident );
00569 
00570     // merge the coincident tets
00571     unsigned long id1, id2;
00572     unsigned int tet_diff = coincident.size();
00573     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00574     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00575     {
00576         id1 = gMB->id_from_handle( ( *iter ).first );
00577         id2 = gMB->id_from_handle( ( *iter ).second );
00578         cout << "   Coincident tets: " << id1 << "-" << id2 << endl;
00579         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00580         if( result != MB_SUCCESS ) return result;
00581     }
00582 
00583     // Get the list of hexs from the database.
00584     entities.clear();
00585     result = gMB->get_entities_by_type( 0, MBHEX, entities );
00586     if( result != MB_SUCCESS ) return result;
00587 
00588     // find the coincident hex pairs
00589     coincident.clear();
00590     find_coincident_elements( entities, 8, coincident );
00591 
00592     // merge the coincident tris
00593     unsigned int hex_diff = coincident.size();
00594     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00595     {
00596         id1 = gMB->id_from_handle( ( *iter ).first );
00597         id2 = gMB->id_from_handle( ( *iter ).second );
00598         cout << "   Coincident hexs: " << id1 << "-" << id2 << endl;
00599         result = gMB->merge_entities( ( *iter ).first, ( *iter ).second, false, true );
00600         if( result != MB_SUCCESS ) return result;
00601     }
00602 
00603     // Get the reduced list of elements.
00604     curr_count.get_counts();
00605 
00606     // Make sure the coincident elements were all merged.
00607     if( init_count.tet - curr_count.tet != tet_diff )
00608     {
00609         cout << "***ERROR: Not all coincident tets were merged.***" << endl;
00610         return MB_FAILURE;
00611     }
00612     if( init_count.hex - curr_count.hex != hex_diff )
00613     {
00614         cout << "***ERROR: Not all coincident hexs were merged.***" << endl;
00615         return MB_FAILURE;
00616     }
00617 
00618     init_count.tet = curr_count.tet;
00619     init_count.hex = curr_count.hex;
00620 
00621     // Make sure we didn't merge anything else.
00622     if( init_count.node != curr_count.node || init_count.edge != curr_count.edge ||
00623         init_count.quad != curr_count.quad || init_count.tri != curr_count.tri )
00624     {
00625         cout << "***ERROR: Merged other objects when merging elements.***" << endl;
00626         return MB_FAILURE;
00627     }
00628 
00629     return MB_SUCCESS;
00630 }
00631 
00632 ErrorCode read_file( std::string& file_name, EntityCount& counts )
00633 {
00634     // Make sure the database is empty.
00635     gMB->delete_mesh();
00636 
00637     // Read the model from the file.
00638     if( gMB->load_mesh( file_name.c_str(), 0 ) != MB_SUCCESS )
00639     {
00640         cout << "***ERROR: Unable to load mesh file.***" << endl;
00641         return MB_FAILURE;
00642     }
00643 
00644     // Get the number of each entity types in the mesh.
00645     if( counts.get_counts() != MB_SUCCESS )
00646     {
00647         cout << "***ERROR: Unable to get entity list counts.***" << endl;
00648         return MB_FAILURE;
00649     }
00650 
00651     return MB_SUCCESS;
00652 }
00653 
00654 ErrorCode write_file( std::string& file_name )
00655 {
00656     // get the block tag
00657     ErrorCode result;
00658     Range block_range;
00659     Tag block_tag;
00660 
00661     if( gMB->tag_get_handle( "MATERIAL_SET", block_tag ) == MB_SUCCESS )
00662     {
00663         // get all the blocks
00664         result = gMB->get_entities_by_type_and_tag( 0, MBENTITYSET, &block_tag, 0, 1, block_range );
00665         if( result != MB_SUCCESS ) return result;
00666     }
00667 
00668     // transfer range contents into vectors
00669     std::vector< EntityHandle > output_list;
00670 
00671     Range::iterator range_iter, end_iter;
00672     range_iter = block_range.begin();
00673     end_iter   = block_range.end();
00674 
00675     for( ; range_iter != end_iter; ++range_iter )
00676     {
00677         int id;
00678         result = gMB->tag_get_handle( "MATERIAL_SET", block_tag );
00679         if( result != MB_SUCCESS ) return result;
00680 
00681         result = gMB->tag_get_data( block_tag, &*range_iter, 1, &id );
00682         if( result != MB_SUCCESS ) return result;
00683 
00684         // if(id != 2)
00685         output_list.push_back( *range_iter );
00686     }
00687 
00688     // write the file
00689     static std::string mrg_splice( ".mrg" );
00690     file_name.insert( file_name.size() - 2, mrg_splice );
00691     result = gMB->write_mesh( file_name.c_str(), &output_list[0], output_list.size() );
00692 
00693     return result;
00694 }
00695 
00696 ErrorCode process_td_auto_merge( std::string& file_name )
00697 {
00698     EntityCount init_count;
00699     EntityCount curr_count;
00700     EntityCount diff_count;
00701 
00702     // Read in the mesh and get the number of entities of each type.
00703     if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
00704 
00705     // Copy the initial counts into the current count object.
00706     curr_count.copy_counts( init_count );
00707 
00708     // Print out the list of initial objects.
00709     cout << "Initial Entities:" << endl;
00710     curr_count.print();
00711 
00712     // Try auto merging from the top down.
00713     Range entities;
00714     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00715 
00716     // Find how many objects of each type need to be merged.
00717     if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
00718 
00719     // Find the top level object to merge.
00720     if( diff_count.hex > 0 )
00721     {
00722         if( gMB->get_entities_by_type( 0, MBHEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00723         find_coincident_elements( entities, 8, coincident );
00724     }
00725     else if( diff_count.quad > 0 )
00726     {
00727         if( gMB->get_entities_by_type( 0, MBQUAD, entities ) != MB_SUCCESS ) return MB_FAILURE;
00728         find_coincident_elements( entities, 4, coincident );
00729     }
00730     else if( diff_count.tet > 0 )
00731     {
00732         if( gMB->get_entities_by_type( 0, MBTET, entities ) != MB_SUCCESS ) return MB_FAILURE;
00733         find_coincident_elements( entities, 4, coincident );
00734     }
00735     else if( diff_count.tri > 0 )
00736     {
00737         if( gMB->get_entities_by_type( 0, MBTRI, entities ) != MB_SUCCESS ) return MB_FAILURE;
00738         find_coincident_elements( entities, 3, coincident );
00739     }
00740     else if( diff_count.edge > 0 )
00741     {
00742         if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
00743         find_coincident_edges( entities, coincident );
00744     }
00745     else if( diff_count.node > 0 )
00746     {
00747         if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00748         find_coincident_nodes( entities, coincident );
00749     }
00750 
00751     cout << "Merging coincident entities(top down)..." << endl;
00752     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00753     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00754         gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
00755 
00756     // Get the new entity totals.
00757     if( curr_count.get_counts() != MB_SUCCESS )
00758     {
00759         cout << "***ERROR: Unable to get entity list counts.***" << endl;
00760         return MB_FAILURE;
00761     }
00762 
00763     // Make sure we merged everything.
00764     if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
00765         init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
00766         init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
00767     {
00768         cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
00769         curr_count.print();
00770         return MB_FAILURE;
00771     }
00772 
00773     // Print out the final list of objects.
00774     cout << "Final Entities:" << endl;
00775     curr_count.print();
00776 
00777     return MB_SUCCESS;
00778 }
00779 
00780 ErrorCode process_mo_auto_merge( std::string& file_name )
00781 {
00782     EntityCount init_count;
00783     EntityCount curr_count;
00784     EntityCount diff_count;
00785 
00786     // Read in the mesh and get the number of entities of each type.
00787     if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
00788 
00789     // Copy the initial counts into the current count object.
00790     curr_count.copy_counts( init_count );
00791 
00792     // Print out the list of initial objects.
00793     cout << "Initial Entities:" << endl;
00794     curr_count.print();
00795 
00796     // Try auto merging from the middle out.
00797     Range entities;
00798     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00799 
00800     // Find how many objects of each type need to be merged.
00801     if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
00802 
00803     // Start merge at the edge level if present.
00804     if( diff_count.edge > 0 )
00805     {
00806         if( gMB->get_entities_by_type( 0, MBEDGE, entities ) != MB_SUCCESS ) return MB_FAILURE;
00807         find_coincident_edges( entities, coincident );
00808     }
00809     else
00810     {
00811         if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00812         find_coincident_nodes( entities, coincident );
00813     }
00814 
00815     cout << "Merging coincident entities(middle out)..." << endl;
00816     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00817     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00818 
00819         gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
00820 
00821     // Get the new entity totals.
00822     if( curr_count.get_counts() != MB_SUCCESS )
00823     {
00824         cout << "***ERROR: Unable to get entity list counts.***" << endl;
00825         return MB_FAILURE;
00826     }
00827 
00828     // Make sure we merged everything.
00829     if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
00830         init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
00831         init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
00832     {
00833         cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
00834         curr_count.print();
00835         return MB_FAILURE;
00836     }
00837 
00838     // Print out the final list of objects.
00839     cout << "Final Entities:" << endl;
00840     curr_count.print();
00841 
00842     return MB_SUCCESS;
00843 }
00844 
00845 ErrorCode process_bu_auto_merge( std::string& file_name )
00846 {
00847     EntityCount init_count;
00848     EntityCount curr_count;
00849     EntityCount diff_count;
00850 
00851     // Read in the mesh and get the number of entities of each type.
00852     if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
00853 
00854     // Copy the initial counts into the current count object.
00855     curr_count.copy_counts( init_count );
00856 
00857     // Print out the list of initial objects.
00858     cout << "Initial Entities:" << endl;
00859     curr_count.print();
00860 
00861     // Try auto merging from the bottom up.
00862     Range entities;
00863     std::vector< std::pair< EntityHandle, EntityHandle > > coincident;
00864 
00865     // Find how many objects of each type need to be merged.
00866     if( coincident_counts( curr_count, diff_count ) != MB_SUCCESS ) return MB_FAILURE;
00867 
00868     // Start merging from the nodes and go up.
00869     if( gMB->get_entities_by_type( 0, MBVERTEX, entities ) != MB_SUCCESS ) return MB_FAILURE;
00870     find_coincident_nodes( entities, coincident );
00871 
00872     cout << "Merging coincident entities(bottom up)..." << endl;
00873     std::vector< std::pair< EntityHandle, EntityHandle > >::iterator iter;
00874     for( iter = coincident.begin(); iter != coincident.end(); ++iter )
00875         gMB->merge_entities( ( *iter ).first, ( *iter ).second, true, true );
00876 
00877     // Get the new entity totals.
00878     if( curr_count.get_counts() != MB_SUCCESS )
00879     {
00880         cout << "***ERROR: Unable to get entity list counts.***" << endl;
00881         return MB_FAILURE;
00882     }
00883 
00884     // Make sure we merged everything.
00885     if( init_count.node - curr_count.node != diff_count.node || init_count.edge - curr_count.edge != diff_count.edge ||
00886         init_count.quad - curr_count.quad != diff_count.quad || init_count.tri - curr_count.tri != diff_count.tri ||
00887         init_count.hex - curr_count.hex != diff_count.hex || init_count.tet - curr_count.tet != diff_count.tet )
00888     {
00889         cout << "***ERROR: Not all coincident objects merged automatically.***" << endl;
00890         curr_count.print();
00891 
00892         return MB_FAILURE;
00893     }
00894 
00895     // Print out the final list of objects.
00896     cout << "Final Entities:" << endl;
00897     curr_count.print();
00898 
00899     return MB_SUCCESS;
00900 }
00901 
00902 ErrorCode process_merge( std::string& file_name )
00903 {
00904     EntityCount init_count;
00905     EntityCount curr_count;
00906 
00907     // Read in the mesh and get the number of entities of each type.
00908     if( read_file( file_name, init_count ) != MB_SUCCESS ) return MB_FAILURE;
00909 
00910     // Copy the initial counts into the current count object.
00911     curr_count.copy_counts( init_count );
00912 
00913     // Print out the list of initial objects.
00914     cout << "Initial Entities:" << endl;
00915     curr_count.print();
00916 
00917     // Try to merge elements before nodes (should fail).
00918     if( merge_top_down( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
00919 
00920     // Merge the nodes.
00921     if( merge_nodes( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
00922 
00923     // Next, merge the edges.
00924     if( merge_edges( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
00925 
00926     // Now, merge the 2D elements.
00927     if( merge_2D_elem( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
00928 
00929     // Finally, merge the 3D elements.
00930     if( merge_3D_elem( init_count, curr_count ) != MB_SUCCESS ) return MB_FAILURE;
00931 
00932     // Print out the final list of objects.
00933     if( curr_count.get_counts() != MB_SUCCESS )
00934     {
00935         cout << "***ERROR: Unable to get entity list counts.***" << endl;
00936         return MB_FAILURE;
00937     }
00938     cout << "Final Entities:" << endl;
00939     curr_count.print();
00940 
00941     // write the file out (modifies name)
00942     return write_file( file_name );
00943 }
00944 
00945 int main()
00946 {
00947     ErrorCode result;
00948     std::string test_files[] = {
00949         std::string( "test/2barcase1.g" ),  std::string( "test/2barcase2.g" ),  std::string( "test/2hexcase1.g" ),
00950         std::string( "test/2hexcase2.g" ),  std::string( "test/2hexcase3.g" ),  std::string( "test/2hexcase4.g" ),
00951         std::string( "test/2hexcase5.g" ),  std::string( "test/2quadcase1.g" ), std::string( "test/2quadcase2.g" ),
00952         std::string( "test/2quadcase3.g" ), std::string( "test/2quadcase4.g" ), std::string( "test/2tetcase1.g" ),
00953         std::string( "test/2tetcase2.g" ),  std::string( "test/2tetcase3.g" ),  std::string( "test/2tetcase4.g" ),
00954         std::string( "test/2tricase1.g" ),  std::string( "test/2tricase2.g" ),  std::string( "test/2tricase3.g" ) };
00955 
00956     // Create the MB database instance.
00957     gMB = new Core();
00958 
00959     // Loop through the list of test files.
00960     unsigned int i;
00961     cout << "---Starting Top Down Auto Merge Tests---" << endl << endl;
00962     for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
00963     {
00964         cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
00965         result = process_td_auto_merge( test_files[i] );
00966         if( result == MB_SUCCESS )
00967             cout << "---Success---";
00968         else
00969             cout << "---Failure---";
00970         cout << endl << endl;
00971     }
00972 
00973     cout << "---Starting Bottom Up Auto Merge Tests---" << endl << endl;
00974     for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
00975     {
00976         cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
00977         result = process_bu_auto_merge( test_files[i] );
00978         if( result == MB_SUCCESS )
00979 
00980             cout << "---Success---";
00981         else
00982             cout << "---Failure---";
00983         cout << endl << endl;
00984     }
00985 
00986     cout << "---Starting Middle Out Auto Merge Tests---" << endl << endl;
00987     for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
00988     {
00989         cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
00990         result = process_mo_auto_merge( test_files[i] );
00991         if( result == MB_SUCCESS )
00992             cout << "---Success---";
00993         else
00994             cout << "---Failure---";
00995 
00996         cout << endl << endl;
00997     }
00998 
00999     cout << "---Starting Merge Tests---" << endl << endl;
01000     for( i = 0; i < ( sizeof( test_files ) / sizeof( std::string ) ); i++ )
01001     {
01002         cout << "---Testing:\"" << test_files[i] << "\"---" << endl;
01003         result = process_merge( test_files[i] );
01004         if( result == MB_SUCCESS )
01005             cout << "---Success---";
01006         else
01007             cout << "---Failure---";
01008         cout << endl << endl;
01009     }
01010 
01011     // Destroy the MB database instance.
01012     delete gMB;
01013     gMB = NULL;
01014 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines