MBErrorCode build_obbs(moab::OrientedBoxTreeTool *obbTree, MBRange &surfs, MBRange &volumes) { MBErrorCode rval = MB_SUCCESS; for (MBRange::iterator i = surfs.begin(); i != surfs.end(); ++i) { MBEntityHandle root; MBRange tris; rval = MBI()->get_entities_by_dimension( *i, 2, tris ); if (MB_SUCCESS != rval) return rval; if (tris.empty()) std::cerr << "WARNING: Surface " << *i << " has no facets." << std::endl; rval = obbTree->build( tris, root ); if (MB_SUCCESS != rval) return rval; #pragma omp critical rval = MBI()->add_entities( root, &*i, 1 ); if (MB_SUCCESS != rval) return rval; } return MB_SUCCESS; }
/* Accepts a range of inverted tris. Refacets affected surface so that no tris are inverted. */ MBErrorCode remove_inverted_tris(MBTag normal_tag, MBRange tris, const bool debug ) { MBErrorCode result; bool failures_occur = false; while(!tris.empty()) { /* Get a group of triangles to re-facet. They must be adjacent to each other and in the same surface. */ MBRange tris_to_refacet; tris_to_refacet.insert( tris.front() ); MBRange surf_set; result = MBI()->get_adjacencies( tris_to_refacet, 4, false, surf_set ); assert(MB_SUCCESS == result); if(1 != surf_set.size()) { std::cout << "remove_inverted_tris: tri is in " << surf_set.size() << " surfaces" << std::endl; return MB_FAILURE; } // get all tris in the surface MBRange surf_tris; result = MBI()->get_entities_by_type( surf_set.front(), MBTRI, surf_tris ); assert(MB_SUCCESS == result); /* Find all of the adjacent inverted triangles of the same surface. Keep searching until a search returns no new triangles. */ bool search_again = true; while(search_again) { // Here edges are being created. Remember to delete them. Outside of this // function. Skinning gets bogged down if unused MBEdges (from other // surfaces) accumulate. MBRange tri_edges; result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges, MBInterface::UNION ); assert(MB_SUCCESS == result); MBRange connected_tris; result = MBI()->get_adjacencies( tri_edges, 2, false, connected_tris, MBInterface::UNION ); assert(MB_SUCCESS == result); result = MBI()->delete_entities( tri_edges ); assert(MB_SUCCESS == result); MBRange tris_to_refacet2 = intersect( tris_to_refacet, connected_tris ); tris_to_refacet2 = intersect( tris_to_refacet, surf_tris ); if(tris_to_refacet.size() == tris_to_refacet2.size()) search_again = false; tris_to_refacet.swap( tris_to_refacet2 ); } // Remove the inverted tris that will be refaceted. tris = subtract( tris, tris_to_refacet ); // do edges already exist? MBRange temp; result = MBI()->get_entities_by_type(0, MBEDGE, temp ); assert(MB_SUCCESS == result); if(!temp.empty()) MBI()->list_entities( temp ); assert(temp.empty()); // keep enlarging patch until we have tried to refacet the entire surface int counter=0; while(true) { // do edges already exist? temp.clear(); result = MBI()->get_entities_by_type(0, MBEDGE, temp ); assert(MB_SUCCESS == result); if(!temp.empty()) MBI()->list_entities( temp ); assert(temp.empty()); counter++; // Only try enlarging each patch a few times if(48 == counter) { failures_occur = true; if(debug) std::cout << "remove_inverted_tris: ear clipping failed, counter=" << counter << std::endl; break; } // THIS PROVIDES A BAD EXIT. MUST FIX // get the edges of the patch of inverted tris MBRange tri_edges; result = MBI()->get_adjacencies( tris_to_refacet, 1, true, tri_edges, MBInterface::UNION ); assert(MB_SUCCESS == result); // get all adjacent tris to the patch of inverted tris in the surface MBRange adj_tris; result = MBI()->get_adjacencies( tri_edges, 2, false, adj_tris, MBInterface::UNION ); assert(MB_SUCCESS == result); result = MBI()->delete_entities( tri_edges ); assert(MB_SUCCESS == result); tris_to_refacet = intersect( surf_tris, adj_tris ); if(tris_to_refacet.empty()) continue; //gen::print_triangles( tris_to_refacet ); // get an area-weighted normal of the adj_tris MBCartVect plane_normal(0,0,0); //for(unsigned int i=0; i<tris_to_refacet.size(); i++) { for(MBRange::iterator i=tris_to_refacet.begin(); i!=tris_to_refacet.end(); i++) { MBCartVect norm; result = MBI()->tag_get_data( normal_tag, &(*i), 1, &norm); assert(MB_SUCCESS == result); double area; result = gen::triangle_area( *i, area ); assert(MB_SUCCESS == result); if(debug) std::cout << "norm=" << norm << " area=" << area << std::endl; //plane_normal += norm*area; plane_normal += norm; } plane_normal.normalize(); // do edges already exist? temp.clear(); result = MBI()->get_entities_by_type(0, MBEDGE, temp ); assert(MB_SUCCESS == result); if(!temp.empty()) MBI()->list_entities( temp ); assert(temp.empty()); // skin the tris MBRange unordered_edges; //MBSkinner tool(MBI()); //result = tool.find_skin( tris_to_refacet, 1, unordered_edges, false ); result = gen::find_skin( tris_to_refacet, 1, unordered_edges, false ); assert(MB_SUCCESS == result); if(unordered_edges.empty()) { // do edges already exist? MBRange temp; result = MBI()->get_entities_by_type(0, MBEDGE, temp ); assert(MB_SUCCESS == result); if(!temp.empty()) MBI()->list_entities( temp ); assert(temp.empty()); continue; } //std::cout << "remove_inverted_tris: surf_id=" // << gen::geom_id_by_handle(surf_set.front()) << std::endl; //result = MBI()->list_entities( tris_to_refacet ); //assert(MB_SUCCESS == result); // assemble into a polygon std::vector<MBEntityHandle> polygon_of_verts; result = arc::order_verts_by_edge( unordered_edges, polygon_of_verts ); if(debug) gen::print_loop( polygon_of_verts ); //assert(MB_SUCCESS == result); if(MB_SUCCESS != result) { if(debug) std::cout << "remove_inverted_tris: couldn't order polygon by edge" << std::endl; return MB_FAILURE; } // remember to remove edges result = MBI()->delete_entities( unordered_edges ); assert(MB_SUCCESS == result); // remove the duplicate endpt polygon_of_verts.pop_back(); // the polygon should have at least 3 verts if(3 > polygon_of_verts.size()) { if(debug) std::cout << "remove_inverted_tris: polygon has too few points" << std::endl; return MB_FAILURE; } // orient the polygon with the triangles (could be backwards) // get the first adjacent tri MBEntityHandle edge[2] = { polygon_of_verts[0], polygon_of_verts[1] }; MBRange one_tri; result = MBI()->get_adjacencies( edge, 2, 2, false, one_tri ); assert(MB_SUCCESS == result); one_tri = intersect( tris_to_refacet, one_tri ); assert(1 == one_tri.size()); const MBEntityHandle *conn; int n_conn; result = MBI()->get_connectivity( one_tri.front(), conn, n_conn ); assert(MB_SUCCESS == result); assert(3 == n_conn); if( (edge[0]==conn[1] && edge[1]==conn[0]) || (edge[0]==conn[2] && edge[1]==conn[1]) || (edge[0]==conn[0] && edge[1]==conn[2]) ) { reverse( polygon_of_verts.begin(), polygon_of_verts.end() ); if(debug) std::cout << "remove_inverted_tris: polygon reversed" << std::endl; } /* facet the polygon. Returns MB_FAILURE if it fails to facet the polygon. */ MBRange new_tris; result = gen::ear_clip_polygon( polygon_of_verts, plane_normal, new_tris ); // break if the refaceting is successful if(MB_SUCCESS == result) { // summarize tri area for(MBRange::iterator i=new_tris.begin(); i!=new_tris.end(); i++) { double area; result = gen::triangle_area( *i, area ); assert(MB_SUCCESS == result); if(debug) std::cout << " new tri area=" << area << std::endl; } // check the new normals std::vector<MBCartVect> new_normals; result = gen::triangle_normals( new_tris, new_normals ); if(MB_SUCCESS != result) return result; // test the new triangles std::vector<int> inverted_tri_indices; std::vector<MBCartVect> normals ( new_normals.size(), plane_normal ); result = zip::test_normals( normals, new_normals, inverted_tri_indices ); assert(MB_SUCCESS == result); if(inverted_tri_indices.empty()) { // remove the tris that were re-faceted tris = subtract( tris, tris_to_refacet ); result = MBI()->remove_entities( surf_set.front(), tris_to_refacet ); assert(MB_SUCCESS == result); result = MBI()->delete_entities( tris_to_refacet ); assert(MB_SUCCESS == result); // add the new tris to the surf set result = MBI()->add_entities( surf_set.front(), new_tris ); assert(MB_SUCCESS == result); // put the new normals on the new tris result = gen::save_normals( new_tris, normal_tag ); assert(MB_SUCCESS == result); if(debug) std::cout << "remove_inverted_tris: success fixing a patch" << std::endl; break; } } // remember to delete the tris that were created from the failed ear clipping else { result = MBI()->delete_entities( new_tris ); assert(MB_SUCCESS == result); } // If the entire surface could not be ear clipped, give up if (tris_to_refacet.size() == surf_tris.size()) { if(debug) std::cout << "remove_inverted_tris: ear clipping entire surface failed" << std::endl; return MB_FAILURE; } } // loop until the entire surface has attempted to be refaceted } // loop over each patch of inverted tris if(failures_occur) { if(debug) std::cout << "remove_inverted_facets: at least one failure occured" << std::endl; return MB_FAILURE; } else { return MB_SUCCESS; } }