MeshKit
1.0
|
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 }