MBErrorCode delete_degenerate_tris( MBRange tris ) { MBErrorCode result; for(MBRange::iterator i=tris.begin(); i!=tris.end(); i++) { result = delete_degenerate_tris( *i ); assert(MB_SUCCESS == result); } return MB_SUCCESS; }
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; }
int main(int argc, char **argv) { //open moab instance MBInterface *MBI(); //for unit testing purposes, we don't care about the output. Just PASS or FAIL. bool verbose=false; // ****************************************************************** // Load the h5m file and create tags. // ****************************************************************** clock_t start_time; start_time = clock(); // load file and get tolerance from the iter file MBErrorCode result; std::string filename = "iter_imprinted.h5m"; //set filename MBEntityHandle input_set; result = MBI()->create_meshset( MESHSET_SET, input_set ); //create handle to meshset if(MB_SUCCESS != result) { return result; } result = MBI()->load_file( filename.c_str(), &input_set ); //load the file into the meshset if(MB_SUCCESS != result) { // failed to load the file std::cout << "could not load file" << std::endl; return result; } /// get faceting tolerance /// double facet_tolerance; MBTag faceting_tol_tag; //get faceting tolerance handle from file result = MBI()->tag_get_handle( "FACETING_TOL", 1, MB_TYPE_DOUBLE, faceting_tol_tag , moab::MB_TAG_SPARSE|moab::MB_TAG_CREAT ); if(gen::error(MB_SUCCESS!=result, "could not get the faceting tag handle")) return result; //get the faceting tolerance of any entity MBRange file_set; result = MBI()->get_entities_by_type_and_tag( 0, MBENTITYSET, &faceting_tol_tag, NULL, 1, file_set ); //get facetint tolerance value result = MBI()->tag_get_data( faceting_tol_tag, &file_set.front(), 1, &facet_tolerance ); if(gen::error(MB_SUCCESS!=result, "could not get the faceting tolerance")) return result; // create tags on geometry MBTag geom_tag, id_tag; result = MBI()->tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag, moab::MB_TAG_DENSE|moab::MB_TAG_CREAT ); if(gen::error(MB_SUCCESS != result, "could not get GEOM_DIMENSION_TAG_NAME handle")) return result; result = MBI()->tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, id_tag, moab::MB_TAG_DENSE|moab::MB_TAG_CREAT ); if(gen::error(MB_SUCCESS != result, "could not get GLOBAL_ID_TAG_NAME handle")) return result; // get surface and volume sets MBRange surf_sets, vol_sets; // MBRange of set of surfaces and volumes // surface sets int dim = 2; void* input_dim[] = {&dim}; result = MBI()->get_entities_by_type_and_tag( input_set, MBENTITYSET, &geom_tag, input_dim, 1, surf_sets); if(MB_SUCCESS != result) { return result; } // volume sets dim = 3; result = MBI()->get_entities_by_type_and_tag( input_set, MBENTITYSET, &geom_tag, input_dim, 1, vol_sets); if(MB_SUCCESS != result) { return result; } //vertex sets dim= 0; MBRange verts; result = MBI()->get_entities_by_dimension(input_set, dim, verts, false); if(gen::error(MB_SUCCESS!=result, " could not get vertices from the mesh")) return result; if(gen::error(MB_SUCCESS!=result, "could not get vertex coordinates")) return result; if(verbose) { std::cout<< "number of verticies= " << verts.size() << std::endl; std::cout<< "number of surfaces= " << surf_sets.size() << std::endl; std::cout<< "number of volumes= " << vol_sets.size() << std::endl; } //initialize booleans to pass to make_mesh_watertight bool check_topology, test, sealed; check_topology=false; test=true; // initialize boolean for each set of tests bool test_set_result=true; //seal mesh and make sure it is entirely sealed // seal the model using make_watertight result=mw_func::make_mesh_watertight (input_set, facet_tolerance, false); if(gen::error(MB_SUCCESS!=result, "could not make the mesh watertight")) return result; // Lastly Check to see if make_watertight fixed the model result=cw_func::check_mesh_for_watertightness( input_set, facet_tolerance, sealed, test); if(gen::error(MB_SUCCESS!=result, "could not check model for watertightness")) return result; if(sealed) { std::cout << "PASS" << std::endl; } else { std::cout << "FAIL" << std::endl; test_set_result=false; } exit(0); }
bool CamalPaveDriver::prepareCGMEvaluator() { // // we will have to mesh every geo edge separately, and we have to ensure that the number of mesh edges // for a face is even. // pretty tough to do. Initially, we have to decide loops, number of edges on each face, etc // first build //int err; // get the triangles and the vertices from moab set /*iBase_EntityHandle *triangles = NULL; int triangles_alloc = 0; iBase_EntityHandle *vert_adj = NULL; int vert_adj_alloc = 0, vert_adj_size; int numTriangles; int * offsets = NULL, offsets_alloc = 0, indices_size; int * indices = NULL, indices_alloc = 0, offsets_size; iMesh_getAdjEntIndices(_meshIface, _set, iBase_FACE, iMesh_TRIANGLE, iBase_VERTEX, &triangles, &triangles_alloc, &numTriangles, &vert_adj, &vert_adj_alloc, &vert_adj_size, &indices, &indices_alloc, &indices_size, &offsets, &offsets_alloc, &offsets_size, &err); ERRORR("Couldn't get connectivity for triangles.", 1);*/ MBRange triangles; MBErrorCode rval = _mb->get_entities_by_type( 0 /* root set, as above, we know */, MBTRI, triangles); // get all the nodes MBRange vertices; rval = _mb->get_adjacencies(triangles, 0, false, vertices, MBInterface::UNION); // first, create CubitPointData list, from the coordinates in one array /* get the coordinates in one array */ /*int vert_coords_alloc = 0, vertex_coord_size; double * xyz = NULL; iMesh_getVtxArrCoords(_meshIface, vert_adj, vert_adj_size, iBase_INTERLEAVED, &xyz, &vert_coords_alloc, &vertex_coord_size, &err); ERRORR("Couldn't get coordinates for vertices.", 1);*/ // here, we use Cholla from CGM // we need to replace it with something equivalent, but simpler // the first try would be some tags in MOAB // create the cubit point data // initialize CGM AppUtil::instance()->startup(0, NULL); CGMApp::instance()->startup(0, NULL); // Initialize the GeometryTool GeometryQueryTool *gqt = GeometryQueryTool::instance(); FacetModifyEngine *fme = FacetModifyEngine::instance(); int vert_adj_size = vertices.size(); int numTriangles = triangles.size(); DLIList<CubitFacet*> f_list(numTriangles); DLIList<CubitPoint*> p_list(vert_adj_size); double * xyz = new double [3*vert_adj_size]; rval = _mb-> get_coords(vertices, xyz); //std::map<MBEntityHandle, CubitPoint *> mapPoints; //MBRange::iterator it = vertices.begin(); for (int i = 0; i < vert_adj_size; i++/*, it++*/) { double * pCoord = &xyz[3 * i]; CubitPointData * newPoint = new CubitPointData(pCoord[0], pCoord[1], pCoord[2]); p_list.append(newPoint); //mapPoints[*it] = newPoint;// or maybe we should use finding the index in MBRange?? } // yes // define all the triangles, to see what we have for (MBRange::iterator it = triangles.begin(); it!=triangles.end(); it++) { MBEntityHandle tri = *it; int nnodes; const MBEntityHandle * conn3;// _mb->get_connectivity(tri, conn3, nnodes); assert(nnodes == 3); int vtri[3];// indices for triangles int ii = 0; for (ii = 0; ii < 3; ii++) vtri[ii] = vertices.index(conn3[ii]); // vtri[ii] = indices[offsets[j] + ii]; CubitFacetData * triangle = new CubitFacetData(p_list[vtri[0]], p_list[vtri[1]], p_list[vtri[2]]); f_list.append(triangle); } DLIList<LoopSM*> my_loops; DLIList<Surface*> surf_list; CubitStatus result; //double angle = 0.01;// very small, negligible; is this radians or degrees? result = fme->build_facet_surface(NULL, f_list, p_list, _angle, 4, true, false, surf_list); if (surf_list.size() == 0 || result != CUBIT_SUCCESS) { PRINT_ERROR("Problems building mesh based surfaces.\n"); return result; } else PRINT_INFO("Constructed %d surfaces.\n", surf_list.size()); //Now build the shell. If we had it set up right this would be //in a loop. We need to store list of DLBlockSurfaceLists on each //blockvolumemesh to store the shell information. But that will //be saved for later. ShellSM *shell_ptr; result = fme->make_facet_shell(surf_list, shell_ptr); if (shell_ptr == NULL || result != CUBIT_SUCCESS) { PRINT_ERROR("Problems building mesh based shell entity.\n"); return result; } #if 1 DLIList<ShellSM*> shell_list; shell_list.append(shell_ptr); Lump *lump_ptr; result = fme->make_facet_lump(shell_list, lump_ptr); if (lump_ptr == NULL || result != CUBIT_SUCCESS) { PRINT_ERROR("Problems building mesh based lump entity.\n"); return result; } DLIList<Lump*> lump_list; lump_list.append(lump_ptr); BodySM *bodysm_ptr; Body *body_ptr; result = fme->make_facet_body(lump_list, bodysm_ptr); body_ptr = GeometryQueryTool::instance()->make_Body(bodysm_ptr); if (body_ptr == NULL || result != CUBIT_SUCCESS) { PRINT_ERROR("Problems building mesh based body entity.\n"); return result; } if (!body_ptr) { exit(1); } PRINT_INFO("Body successfully created.\n"); #endif PRINT_INFO("Number of vertices = %d\n", gqt->num_ref_vertices()); PRINT_INFO("Number of edges = %d\n", gqt->num_ref_edges()); PRINT_INFO("Number of faces = %d\n", gqt->num_ref_faces()); // print vertex positions DLIList<RefVertex*> verts; gqt->ref_vertices(verts); int i; for (i = 0; i < verts.size(); i++) { RefVertex * vert = verts[i]; CubitVector coords = vert->coordinates(); PRINT_INFO("Vertex %d: %4.2f, %4.2f, %4.2f.\n", vert->id(), coords.x(), coords.y(), coords.z()); } // print edges and faces DLIList<RefEdge*> refEdges; gqt->ref_edges(refEdges); for (i = 0; i < refEdges.size(); i++) { RefEdge * edg = refEdges[i]; PRINT_INFO("Edge %d: %d %d\n", edg->id(), edg->start_vertex()->id(), edg->end_vertex ()->id() ); } DLIList<RefFace*> refFaces; gqt->ref_faces(refFaces); for (i = 0; i < refFaces.size(); i++) { RefFace * face = refFaces[i]; DLIList< Loop * > loop_list ; face->ordered_loops (loop_list ) ; DLIList< RefEdge * > ordered_edge_list; loop_list[0]->ordered_ref_edges (ordered_edge_list); //DLIList< RefVertex* > *listV = ref_vert_loop_list[0]; PRINT_INFO("face %d: loop 0 size %d\n", face->id(), ordered_edge_list.size() ); for (int j=0; j<ordered_edge_list.size(); j++) { PRINT_INFO(" %d", ordered_edge_list[j]->id() ); } PRINT_INFO("\n"); } return true; }
// we do not merge edges, just vert. check the verts MBErrorCode test_zipping(const double FACET_TOL, const std::vector< std::vector<MBEntityHandle> > arcs ) { MBErrorCode result; // make sure each arc has the same number of edges for(unsigned int i=1; i<arcs.size(); i++) { if(arcs[0].size() != arcs[i].size()) { std::cout << "The curve has " << arcs[0].size() << " edges but arc " << i << " has " << arcs[i].size() << " edges." << std::endl; gen::print_arcs( arcs ); return MB_FAILURE; } } // loop over every edge of the curve (first arc) for(unsigned int i=0; i<arcs[0].size()-1; i++) { // check for degenerate edge if(arcs[0][i] == arcs[0][i+1]) { std::cout << "degenerate edge at pos " << i << " and " << i+1 << " with verts " << arcs[0][i] << " and " << arcs[0][i+1] << std::endl; return MB_FAILURE; } // check for edge of zero dist double d = gen::dist_between_verts( arcs[0][i], arcs[0][i+1] ); if(FACET_TOL >= d) { std::cout << "edge length=" << d << " betwee pos " << i << " and " << i+1 << " with verts " << arcs[0][i] << " and " << arcs[0][i+1] << std::endl; return MB_FAILURE; } // loop over every arc for( unsigned int j=0; j<arcs.size(); j++) { // make sure vertices match if(arcs[0][i]!=arcs[j][i] || arcs[0][i+1]!=arcs[j][i+1]) { std::cout << "arc " << j << " vertices do not match curve vertices, pos= " << i << "/" << arcs[j].size() << std::endl; return MB_FAILURE; } } // make sure triangles have area MBRange tris; result = MBI()->get_adjacencies( &(arcs[0][i]), 2, 2, false, tris ); assert(MB_SUCCESS == result); for(MBRange::iterator k=tris.begin(); k!=tris.end(); k++) { // We know that there are not degenerate edges along the curve. // Sometimes degenerate tris are created due to merging curve endpts. // here we do not remove tri from the surf meshset, but we should if( gen::triangle_degenerate(*k) ) { //result = MBI()->delete_entities( &(*k), 1); //assert(MB_SUCCESS == result); std::cout << " arc=" << 0 << " pos=" << i << " vert=" << arcs[0][i] << " degenerate triangle" << std::endl; gen::print_triangle(*k, false); //print_edge( edge ); //continue; return MB_FAILURE; } double area; result = gen::triangle_area( *k, area ); assert(MB_SUCCESS == result); // I found a valid tri on a curve with only one edge (1e-5 long) // that had an area of 1e-11. if(1e-8 > area) { std::cout << " arc=" << 0 << " pos=" << i << " vert=" << arcs[0][i] << " small triangle " << std::endl; gen::print_triangle(*k, false); //print_edge( edge ); gen::print_arcs( arcs ); //if(0.0 >= area) return MB_FAILURE; } } } return MB_SUCCESS; }
MBErrorCode t_joint( MBTag normal_tag, const MBEntityHandle vert0, const MBEntityHandle vert1, const MBEntityHandle vert2 ) { struct triangles { MBEntityHandle before_tri; const MBEntityHandle *before; MBCartVect before_norm; MBEntityHandle after0[3]; MBEntityHandle after1[3]; MBCartVect after0_norm; MBCartVect after1_norm; MBEntityHandle surf_set; }; // Get all of the old information before changing anything. // This is important because once the // new connectivity is set stuff becomes stale. // get the edge // get endpoints of the edge MBErrorCode result; MBEntityHandle endpts[2] = { vert0, vert2 }; MBRange tris; result = MBI()->get_adjacencies( endpts, 2, 2, true, tris ); assert(MB_SUCCESS == result); //std::cout << "t_joint: tris.size()=" << tris.size() << std::endl; //MBI()->list_entities( tris ); triangles joints[tris.size()]; for(unsigned int i=0; i<tris.size(); i++) { joints[i].before_tri = tris[i]; // Find the surface set that the tri is in. MBRange surf_sets; result = MBI()->get_adjacencies( &joints[i].before_tri, 1, 4, false, surf_sets); assert(MB_SUCCESS == result); //std::cout << "t_joint: " << surf_sets.size() << " surface sets found for triangle" // << std::endl; // Check to make sure we found a set if(1 != surf_sets.size()) { std::cout << " t_joint: " << surf_sets.size() << " surface sets found for triangle " << joints[i].before_tri << std::endl; assert(1 == surf_sets.size()); //if(1!=surf_sets.size()) return MB_FAILURE; } joints[i].surf_set = surf_sets.front(); //std::cout << "t_joint: surf id=" << gen::geom_id_by_handle( joints[i].surf_set ) // << std::endl; //gen::print_triangle( joints[i].before_tri, false ); // get old connectivity int n_verts; result = MBI()->get_connectivity( joints[i].before_tri, joints[i].before, n_verts); if(MB_SUCCESS != result) std::cout << "result=" << result << std::endl; assert(MB_SUCCESS == result); if(3 != n_verts) std::cout << "n_verts=" << n_verts << std::endl; assert(3 == n_verts); // test to make sure not degenerate //if(conn[0]==conn[1] || conn[1]==conn[2] || conn[2]==conn[0]) { if( gen::triangle_degenerate( joints[i].before_tri )) { std::cout << " t_joint: degenerate input triangle" << std::endl; gen::print_triangle( joints[i].before_tri, false); return MB_FAILURE; } // make new connectivity for(int j=0; j<3; j++) { joints[i].after0[j] = (joints[i].before[j]==endpts[0]) ? vert1 : joints[i].before[j]; joints[i].after1[j] = (joints[i].before[j]==endpts[1]) ? vert1 : joints[i].before[j]; } // test to make sure not degenerate //if(conn0[0]==conn0[1] || conn0[1]==conn0[2] || conn0[2]==conn0[0]) { if(gen::triangle_degenerate( joints[i].after0[0], joints[i].after0[1], joints[i].after0[2])) { std::cout << " t_joint: degenerate output triangle 1" << std::endl; gen::print_triangle( joints[i].before_tri, false ); // return MB_FAILURE; } // test to make sure not degenerate //if(conn1[0]==conn1[1] || conn1[1]==conn1[2] || conn1[2]==conn1[0]) { if(gen::triangle_degenerate( joints[i].after1[0], joints[i].after1[1], joints[i].after1[2])) { std::cout << " t_joint: degenerate output triangle 2" << std::endl; gen::print_triangle( joints[i].before_tri, false ); //gen::print_triangle( *i, true ); //return MB_FAILURE; } // set the new connectivity on the original triangle result = MBI()->set_connectivity( joints[i].before_tri, joints[i].after0, 3 ); assert(MB_SUCCESS == result); // set the new connectivity on the new triangle MBEntityHandle new_tri; result = MBI()->create_element( MBTRI, joints[i].after1, 3, new_tri ); assert(MB_SUCCESS == result); // copy the original normal to the new triangle MBCartVect normal; result = MBI()->tag_get_data( normal_tag, &joints[i].before_tri, 1, &normal); assert(MB_SUCCESS == result); result = MBI()->tag_set_data( normal_tag, &new_tri, 1, &normal); assert(MB_SUCCESS == result); // add the new triangle to the same surface set as the original result = MBI()->add_entities( joints[i].surf_set, &new_tri, 1); assert(MB_SUCCESS == result); // catch-all to remove degenerate tris result = zip::delete_degenerate_tris( joints[i].before_tri ); if(gen::error(MB_SUCCESS!=result,"could not delete degenerate tri")) return result; result = zip::delete_degenerate_tris( new_tri ); if(gen::error(MB_SUCCESS!=result,"could not delete degenerate tri")) return result; //gen::print_triangle( tri, false ); //gen::print_triangle( new_tri, false ); } 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; } }