MeshKit  1.0
cleanup.cpp
Go to the documentation of this file.
00001 #include <iostream>
00002 #include "meshkit/cleanup.hpp"
00003 //#include "moab/AdaptiveKDTree.hpp"
00004 #include "moab/OrientedBoxTreeTool.hpp"
00005 
00006 using namespace moab;
00007 namespace cleanup {
00008   // The obbtrees are no longer valid because the triangles have been altered.
00009   //  -Surface and volume sets are tagged with tags holding the obb tree
00010   //   root handles.
00011   //  -Surface/volume set handles are added to the root meshset.
00012   // Somehow, delete the old tree without deleting the
00013   // surface and volume sets, then build a new tree.
00014   ErrorCode remove_obb_tree(bool verbose) {
00015     ErrorCode result;
00016     Range obb_entities;
00017     Tag obbTag;
00018     result = MBI()->tag_get_handle( "OBB_TREE", sizeof(EntityHandle),
00019                           MB_TYPE_HANDLE, obbTag, MB_TAG_DENSE, NULL, 0 );
00020     if(verbose)
00021     {
00022     if(gen::error(MB_SUCCESS != result, "could not get OBB tree handle")) return result;
00023     }
00024     else
00025     {
00026     if(gen::error(MB_SUCCESS != result, "")) return result;
00027     }
00028     // This gets the surface/volume sets. I don't want to delete the sets.
00029     // I want to remove the obbTag that contains the tree root handle and
00030     // delete the tree.
00031     result = MBI()->get_entities_by_type_and_tag( 0, MBENTITYSET,
00032                                                     &obbTag, 0, 1, obb_entities );
00033     assert(MB_SUCCESS == result);
00034     std::cout << "  found " << obb_entities.size() << " OBB entities" << std::endl;
00035     //gen::print_range( obb_entities );
00036     //result = MBI()->delete_entities( obb_entities );
00037  
00038     // find tree roots
00039     Range trees;
00040     OrientedBoxTreeTool tool( MBI() );
00041     Tag rootTag;
00042     for(Range::iterator i=obb_entities.begin(); i!=obb_entities.end(); i++) {
00043       EntityHandle root;
00044       result = MBI()->tag_get_data( obbTag, &(*i), 1, &root );
00045       if(gen::error(MB_SUCCESS!=result, "coule not get OBB tree data")) return result;
00046       //assert(MB_SUCCESS == result);
00047       tool.delete_tree( root );
00048     }
00049     result = MBI()->tag_delete( obbTag ); // use this for DENSE tags
00050     assert(MB_SUCCESS == result);
00051 
00052 
00053     result = MBI()->tag_get_handle ( "OBB", sizeof(double), 
00054                                   MB_TYPE_DOUBLE, rootTag, MB_TAG_SPARSE, 0, 0);
00055     assert(MB_SUCCESS==result || MB_ALREADY_ALLOCATED==result);
00056     /*    result = MBI()->get_entities_by_type_and_tag( 0, MBENTITYSET, &rootTag, 
00057                                                    NULL, 1, trees );
00058     if(MB_SUCCESS != result) std::cout << "result=" << result << std::endl;
00059     assert(MB_SUCCESS == result);
00060     //tool.find_all_trees( trees );
00061     std::cout << trees.size() << " tree(s) contained in file" << std::endl;
00062     //gen::print_range( trees );
00063   
00064     // delete the trees
00065     for (Range::iterator i = trees.begin(); i != trees.end(); ++i) {
00066       result = tool.delete_tree( *i );
00067       //if(MB_SUCCESS != result) std::cout << "result=" << result << std::endl;
00068       //assert(MB_SUCCESS == result);
00069     }
00070     */ 
00071     // Were all of the trees deleted? Perhaps some of the roots we found were
00072     // child roots that got deleted with their parents.
00073     trees.clear();
00074     result = MBI()->get_entities_by_type_and_tag( 0, MBENTITYSET, &rootTag,
00075                                                     NULL, 1, trees );
00076     assert(MB_SUCCESS == result);
00077     std::cout << "  " << trees.size() << " OBB tree(s) contained in file" << std::endl;
00078     return MB_SUCCESS;
00079   }
00080 
00081   ErrorCode delete_small_edge_and_tris( const EntityHandle vert0,
00082                                           EntityHandle &vert1,
00083                                           const double tol ) {
00084     // If the verts are the same, this is not meaningful.
00085     if(vert0 == vert1) return MB_SUCCESS;
00086     ErrorCode result = MB_SUCCESS;
00087 
00088     // If the edge is small, delete it and the adjacent tris.
00089     if(tol > gen::dist_between_verts(vert0, vert1)) {
00090       // get tris to delete
00091       Range tris;
00092       EntityHandle verts[2] = {vert0, vert1};
00093       result = MBI()->get_adjacencies( verts, 2, 2, false, tris );                   
00094       assert(MB_SUCCESS == result);
00095       result = MBI()->delete_entities( tris );
00096       assert(MB_SUCCESS == result);
00097       std::cout << "delete_small_edge_and_tris: deleted " << tris.size() 
00098                 << " tris." << std::endl;
00099       // now merge the verts, keeping the first one
00100       // IN FUTURE, AVERAGE THE LOCATIONS???????????
00101       result = MBI()->merge_entities( vert0, vert1, false, true);
00102       assert(MB_SUCCESS == result);
00103       vert1 = vert0;
00104     }
00105     return result;
00106   }
00107 
00108   ErrorCode delete_small_edges(const Range &surfaces, const double FACET_TOL) {
00109     // PROBLEM: THIS IS INVALID BECAUSE TRIS CAN HAVE LONG EDGES BUT
00110     // SMALL AREA. All three pts are in a line. This is the nature of
00111     // faceting vs. meshing.
00112     /* Remove small triangles by removing edges that are too small. 
00113     Remove small edges by merging their endpoints together, creating
00114     degenerate triangles. Delete the degenerate triangles. */
00115     ErrorCode result;
00116     for(Range::const_iterator i=surfaces.begin(); i!=surfaces.end(); i++) {
00117       std::cout << "surf_id=" << gen::geom_id_by_handle(*i) << std::endl;
00118 
00119       // get all tris
00120       Range tris;
00121       result = MBI()->get_entities_by_type( *i, MBTRI, tris );
00122       assert(MB_SUCCESS == result);
00123 
00124       // Check to ensure there area no degenerate tris
00125       for(Range::iterator j=tris.begin(); j!=tris.end(); j++) {
00126         // get endpts
00127         const EntityHandle *endpts;
00128         int n_verts;                                      
00129         result = MBI()->get_connectivity( *j, endpts, n_verts);
00130         assert(MB_SUCCESS == result);
00131         assert(3 == n_verts);
00132         assert( endpts[0]!=endpts[1] && endpts[1]!=endpts[2] );
00133       }
00134 
00135 
00136       // get the skin first, because my find_skin does not check before creating edges.
00137       Range skin_edges;
00138       //result = gen::find_skin( tris, 1, skin_edges, false );
00139       Skinner tool(MBI());
00140       result = tool.find_skin( 0 , tris, 1, skin_edges, false );
00141       assert(MB_SUCCESS == result);
00142 
00143       // create the edges
00144       Range edges;
00145       result = MBI()->get_adjacencies( tris, 1, true, edges, Interface::UNION );
00146       if(MB_SUCCESS != result) {
00147         std::cout << "result=" << result << std::endl;
00148       }
00149       assert(MB_SUCCESS == result);
00150 
00151       // get the internal edges
00152       Range internal_edges = subtract(edges, skin_edges);
00153 
00154       for(Range::iterator j=internal_edges.begin(); j!=internal_edges.end(); j++) {
00155         int n_internal_edges = internal_edges.size();
00156         std::cout << "edge=" << *j << std::endl;
00157         MBI()->list_entity( *j );
00158         assert(MB_SUCCESS == result);
00159 
00160         // get endpts
00161         const EntityHandle *endpts;
00162         int n_verts;                                      
00163         result = MBI()->get_connectivity( *j, endpts, n_verts);
00164         assert(MB_SUCCESS == result);
00165         assert(2 == n_verts);
00166 
00167         // does another edge exist w the same endpts? Why would it?
00168         Range duplicate_edges;
00169         result = MBI()->get_adjacencies( endpts, 2, 1, true, duplicate_edges );
00170         assert(MB_SUCCESS == result);
00171         if(1 < duplicate_edges.size()) MBI()->list_entities( duplicate_edges );
00172         assert(1 == duplicate_edges.size());
00173 
00174         // if the edge length is less than MERGE_TOL do nothing
00175         if(FACET_TOL < gen::dist_between_verts( endpts[0], endpts[1] )) continue; 
00176  
00177         // quick check
00178         for(Range::iterator k=internal_edges.begin(); k!=internal_edges.end(); k++) {
00179           const EntityHandle *epts;
00180           int n_vts;                                      
00181           result = MBI()->get_connectivity( *k, epts, n_vts);
00182           assert(MB_SUCCESS == result);
00183           assert(2 == n_vts);
00184           // The skin edges/verts cannot be moved, therefore both endpoints cannot 
00185           // be on the skin. If they are, continue.
00186           Range adj_edges0;
00187           result = MBI()->get_adjacencies( &epts[0], 1, 1, true, adj_edges0 );
00188           assert(MB_SUCCESS == result);
00189           if(3 > adj_edges0.size()) {
00190             std::cout << "adj_edges0.size()=" << adj_edges0.size() 
00191                       << " epts[0]=" << epts[0] << std::endl;
00192             MBI()->list_entity( epts[0] );
00193             //MBI()->write_mesh( "test_output.h5m" );
00194             assert(MB_SUCCESS == result);
00195           }
00196           assert(3 <= adj_edges0.size());
00197           Range adj_skin_edges0 = intersect( adj_edges0, skin_edges );
00198 //        bool endpt0_is_skin;
00199 //        if(adj_skin_edges0.empty()) endpt0_is_skin = false;
00200 //        else endpt0_is_skin = true;
00201 
00202           Range adj_edges1;
00203           result = MBI()->get_adjacencies( &epts[1], 1, 1, true, adj_edges1 );
00204           assert(MB_SUCCESS == result);
00205           if(3 > adj_edges1.size()) {
00206             std::cout << "adj_edges1.size()=" << adj_edges1.size() 
00207                       << " epts[1]=" << epts[1] << std::endl;
00208             MBI()->list_entity( epts[1] );
00209             //MBI()->write_mesh( "test_output.h5m" );
00210             assert(MB_SUCCESS == result);
00211           }
00212           assert(3 <= adj_edges1.size());
00213         }
00214 
00215 
00216         // The skin edges/verts cannot be moved, therefore both endpoints cannot 
00217         // be on the skin. If they are, continue.
00218         Range adj_edges0;
00219         result = MBI()->get_adjacencies( &endpts[0], 1, 1, true, adj_edges0 );
00220         assert(MB_SUCCESS == result);
00221         if(3 > adj_edges0.size()) {
00222           std::cout << "adj_edges0.size()=" << adj_edges0.size() 
00223                     << " endpts[0]=" << endpts[0] << std::endl;
00224           MBI()->list_entity( endpts[0] );
00225           //MBI()->write_mesh( "test_output.h5m" );
00226           assert(MB_SUCCESS == result);
00227         }
00228         assert(3 <= adj_edges0.size());
00229         Range adj_skin_edges0 = intersect( adj_edges0, skin_edges );
00230         bool endpt0_is_skin;
00231         if(adj_skin_edges0.empty()) endpt0_is_skin = false;
00232         else endpt0_is_skin = true;
00233 
00234         Range adj_edges1;
00235         result = MBI()->get_adjacencies( &endpts[1], 1, 1, true, adj_edges1 );
00236         assert(MB_SUCCESS == result);
00237         if(3 > adj_edges1.size()) {
00238           std::cout << "adj_edges1.size()=" << adj_edges1.size() 
00239                     << " endpts[1]=" << endpts[1] << std::endl;
00240           MBI()->list_entity( endpts[1] );
00241           //MBI()->write_mesh( "test_output.h5m" );
00242           assert(MB_SUCCESS == result);
00243         }
00244         assert(3 <= adj_edges1.size());
00245         Range adj_skin_edges1 = intersect( adj_edges1, skin_edges );
00246         bool endpt1_is_skin;
00247         if(adj_skin_edges1.empty()) endpt1_is_skin = false;
00248         else endpt1_is_skin = true;
00249         if(endpt0_is_skin && endpt1_is_skin) continue;
00250         
00251         // Keep the skin endpt, and delete the other endpt
00252         EntityHandle keep_endpt, delete_endpt;
00253         if(endpt0_is_skin) {
00254           keep_endpt   = endpts[0];
00255           delete_endpt = endpts[1];
00256         } else {
00257           keep_endpt   = endpts[1];
00258           delete_endpt = endpts[0];
00259         }
00260 
00261         // get the adjacent tris
00262         std::vector<EntityHandle> adj_tris;
00263         result = MBI()->get_adjacencies( &(*j), 1, 2, false, adj_tris );
00264         assert(MB_SUCCESS == result);
00265                 if(2 != adj_tris.size()) {
00266         std::cout << "adj_tris.size()=" << adj_tris.size() << std::endl;
00267         for(unsigned int i=0; i<adj_tris.size(); i++) gen::print_triangle( adj_tris[i], true );
00268         } 
00269         assert(2 == adj_tris.size());
00270  
00271         // When merging away an edge, a tri and 2 edges will be deleted.
00272         // Get each triangle's edge other edge the will be deleted.
00273         Range tri0_delete_edge_verts;
00274         result = MBI()->get_adjacencies( &adj_tris[0], 1, 0, true, tri0_delete_edge_verts );
00275         assert(MB_SUCCESS == result);
00276         assert(3 == tri0_delete_edge_verts.size());
00277         tri0_delete_edge_verts.erase( keep_endpt );
00278         Range tri0_delete_edge;
00279         result = MBI()->get_adjacencies( tri0_delete_edge_verts, 1, true, tri0_delete_edge );
00280         assert(MB_SUCCESS == result);
00281         assert(1 == tri0_delete_edge.size());      
00282  
00283         Range tri1_delete_edge_verts;
00284         result = MBI()->get_adjacencies( &adj_tris[1], 1, 0, true, tri1_delete_edge_verts );
00285         assert(MB_SUCCESS == result);
00286         assert(3 == tri1_delete_edge_verts.size());
00287         tri1_delete_edge_verts.erase( keep_endpt );
00288         Range tri1_delete_edge;
00289         result = MBI()->get_adjacencies( tri1_delete_edge_verts, 1, true, tri1_delete_edge );
00290         assert(MB_SUCCESS == result);
00291         assert(1 == tri1_delete_edge.size());      
00292 
00293         // When an edge is merged, it will be deleted and its to adjacent tris
00294         // will be deleted because they are degenerate. We cannot alter the skin.
00295         // How many skin edges does tri0 have?
00296         /*        Range tri_edges;
00297         result = MBI()->get_adjacencies( &adj_tris[0], 1, 1, false, tri_edges );
00298         assert(MB_SUCCESS == result);
00299         assert(3 == tri_edges.size());
00300         Range tri0_internal_edges = intersect(tri_edges, internal_edges);
00301 
00302         // Cannot merge the edge away if the tri has more than one skin edge.
00303         // Otherwise we would delete a skin edge. We already know the edges in 
00304         // edge_set are not on the skin.
00305         if(2 > tri0_internal_edges.size()) continue;
00306 
00307         // check the other tri
00308         tri_edges.clear();
00309         result = MBI()->get_adjacencies( &adj_tris[1], 1, 1, false, tri_edges );
00310         assert(MB_SUCCESS == result);
00311         assert(3 == tri_edges.size());
00312         Range tri1_internal_edges = intersect(tri_edges, internal_edges);
00313         if(2 > tri1_internal_edges.size()) continue;
00314 
00315         // Check to make sure that the internal edges are not on the skin
00316         Range temp;
00317         temp = intersect( tri0_internal_edges, skin_edges );
00318         assert(temp.empty());
00319         temp = intersect( tri1_internal_edges, skin_edges );
00320         assert(temp.empty());
00321 
00322         // We know that the edge will be merged away. Find the keep_vert and
00323         // delete_vert. The delete_vert should never be a skin vertex because the
00324         // skin must not move.
00325         Range delete_vert;
00326         result = MBI()->get_adjacencies( tri0_internal_edges, 0, false, delete_vert);
00327         assert(MB_SUCCESS == result);
00328         assert(1 == delete_vert.size());        
00329         */
00330 
00331         // *********************************************************************
00332         // Test to see if the merge would create inverted tris. Several special
00333         // cases to avoid all result in inverted tris.
00334         // *********************************************************************
00335         // get all the tris adjacent to the point the will be moved.
00336         Range altered_tris;
00337         result = MBI()->get_adjacencies( &delete_endpt, 1, 2, false, altered_tris );
00338         assert(MB_SUCCESS == result);
00339         bool inverted_tri = false;
00340         for(Range::const_iterator k=altered_tris.begin(); k!=altered_tris.end(); ++k) {
00341           const EntityHandle *conn;
00342           int n_verts;
00343           result = MBI()->get_connectivity( *k, conn, n_verts );
00344           assert(MB_SUCCESS == result);
00345           assert(3 == tris.size());
00346           EntityHandle new_conn[3];
00347           for(unsigned int i=0; i<3; ++i) {
00348             new_conn[i] = (conn[i]==delete_endpt) ? keep_endpt : conn[i];
00349           }
00350           double area;
00351           result = gen::triangle_area( new_conn, area );
00352           assert(MB_SUCCESS == result);
00353           if(0 > area) {
00354             std::cout << "inverted tri detected, area=" << area << std::endl;
00355             inverted_tri = true;
00356             break;
00357           }
00358         }
00359         if(inverted_tri) continue;      
00360 
00361         // If we got here, then the merge will occur. Delete the edge the will be
00362         // made degenerate and the edge that will be made duplicate.
00363         std::cout << "A merge will occur" << std::endl;
00364         gen::print_triangle( adj_tris[0], true );
00365         gen::print_triangle( adj_tris[1], true );
00366         //tri0_internal_edges.erase( *j );
00367         //tri1_internal_edges.erase( *j );
00368         internal_edges.erase( tri0_delete_edge.front() );
00369         internal_edges.erase( tri1_delete_edge.front() );
00370         std::cout << "merged verts=" << keep_endpt << " " << delete_endpt << std::endl;
00371         MBI()->list_entity( keep_endpt );
00372         MBI()->list_entity( delete_endpt );
00373         result = MBI()->merge_entities( keep_endpt, delete_endpt, false, true );          
00374         assert(MB_SUCCESS == result);
00375         result = MBI()->delete_entities( tri0_delete_edge );
00376         assert(MB_SUCCESS == result);
00377         result = MBI()->delete_entities( tri1_delete_edge );
00378         assert(MB_SUCCESS == result);
00379         result = MBI()->delete_entities( &(*j), 1 );
00380         assert(MB_SUCCESS == result);
00381         std::cout << "deleted edges=" << *j << " " << tri0_delete_edge.front()
00382                   << " " << tri1_delete_edge.front() << std::endl;
00383                   
00384         // delete degenerate tris                          
00385         result = MBI()->delete_entities( &adj_tris[0], 2 );                 
00386         assert(MB_SUCCESS == result);
00387         MBI()->list_entity( keep_endpt );
00388 
00389         // remove the edge from the range
00390         j = internal_edges.erase(*j) - 1; 
00391         std::cout << "next iter=" << *j << std::endl;        
00392 
00393         Range new_tris;
00394         result = MBI()->get_entities_by_type( *i, MBTRI, new_tris );
00395         assert(MB_SUCCESS == result);
00396         Range new_skin_edges;
00397         result = tool.find_skin( *i, new_tris, 1, new_skin_edges, false );
00398         assert(MB_SUCCESS == result);
00399         assert(skin_edges.size() == new_skin_edges.size());
00400         for(unsigned int k=0; k<skin_edges.size(); k++) {
00401           if(skin_edges[k] != new_skin_edges[k]) {
00402             MBI()->list_entity( skin_edges[k] );
00403             MBI()->list_entity( new_skin_edges[k] );
00404           }
00405           assert(skin_edges[k] == new_skin_edges[k]);
00406         }
00407         if (n_internal_edges != (int) internal_edges.size()+3)
00408         assert(n_internal_edges == (int) internal_edges.size()+3);
00409       }
00410   
00411       // cleanup edges
00412       result = MBI()->get_entities_by_type( 0, MBEDGE, edges );
00413       assert(MB_SUCCESS == result);
00414       result = MBI()->delete_entities( edges ); 
00415       assert(MB_SUCCESS == result);
00416    
00417     }
00418     return MB_SUCCESS;
00419   } 
00420   
00421   // Lots of edges have been created but are no longer needed.
00422   // Delete edges that are not in curves. These should be the only edges
00423   // that remain. This incredibly speeds up the watertight_check tool (100x?).
00424   ErrorCode cleanup_edges( Range curve_meshsets ) {
00425     ErrorCode result;
00426     Range edges, edges_to_keep;
00427     for(Range::iterator i=curve_meshsets.begin(); i!=curve_meshsets.end(); i++) {
00428       result = MBI()->get_entities_by_dimension( *i, 1, edges );
00429       assert(MB_SUCCESS == result);
00430       edges_to_keep.merge( edges );
00431     }
00432 
00433     Range all_edges;
00434     result = MBI()->get_entities_by_dimension( 0, 1, all_edges );
00435     assert(MB_SUCCESS == result);
00436 
00437     // delete the edges that are not in curves.
00438     //Range edges_to_delete = all_edges.subtract( edges_to_keep );
00439     Range edges_to_delete = subtract( all_edges, edges_to_keep );
00440     std::cout << "deleting " << edges_to_delete.size() << " unused edges" << std::endl;
00441     result = MBI()->delete_entities( edges_to_delete );
00442     assert(MB_SUCCESS == result);
00443     return result;
00444   }
00445  
00446   
00447 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines