//------------------------------------------------------------------------------ // Initialize the dual center //------------------------------------------------------------------------------ void initAttrs( Polyhedron & poly ) { // assign IDs to vertices int vID = 0; for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->id() = vID++; vi->label() = DEFAULT_LABEL; vi->nCuts() = 0; } cerr << "Total number of vertices = " << vID << endl; // assign IDs to faces: the dual vertex and the dual coordinates-the center coordinates int fID = 0; for ( Facet_iterator fi = poly.facets_begin(); fi != poly.facets_end(); ++fi ) { fi->id() = fID++; // fi->label() = DEFAULT_LABEL; fi->piece() = NO_INDEX; Vector3 sum( 0.0, 0.0, 0.0 ); Halfedge_facet_circulator hfc = fi->facet_begin(); do { sum = sum + ( hfc->vertex()->point() - CGAL::ORIGIN ); } while ( ++hfc != fi->facet_begin() ); sum = sum / ( double )CGAL::circulator_size( hfc ); fi->center() = CGAL::ORIGIN + sum; // cerr << " Barycenter No. " << fid-1 << " : " << bary[ fid-1 ] << endl; } cerr << "Total number of facets = " << fID << endl; // initialize the halfedge IDs for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) { hi->id() = NO_INDEX; } // assign the same IDs to the identical/ opposite halfedges int eID = 0; for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) { if ( hi->id() == NO_INDEX ) { assert( hi->opposite()->id() == NO_INDEX ); hi->id() = eID; hi->opposite()->id() = eID; eID++; hi->label() = hi->opposite()->label() = DEFAULT_LABEL; hi->match() = hi->opposite()->match() = DEFAULT_LABEL; hi->cycle() = hi->opposite()->cycle() = NO_INDEX; hi->weight() = hi->opposite()->weight() = 0.0; hi->connect() = hi->opposite()->connect() = true; hi->visit() = hi->opposite()->visit() = false; // We individually handle hi->fixed } } cerr << "Total number of edges = " << eID << endl; }
void initWeights( Polyhedron & poly ) { // assign the same IDs to the identical/ opposite halfedges for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) { hi->fixed() = false; } }
int main() { Polyhedron P; Build_triangle<HalfedgeDS> triangle; P.delegate( triangle); CGAL_assertion( P.is_triangle( P.halfedges_begin())); return 0; }
void renewAttrs( Polyhedron & poly ) { // assign IDs to vertices for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->nCuts() = 0; } // assign IDs to faces: the dual vertex and the dual coordinates-the center coordinates for ( Facet_iterator fi = poly.facets_begin(); fi != poly.facets_end(); ++fi ) { fi->piece() = NO_INDEX; Vector3 sum( 0.0, 0.0, 0.0 ); Halfedge_facet_circulator hfc = fi->facet_begin(); do { sum = sum + ( hfc->vertex()->point() - CGAL::ORIGIN ); } while ( ++hfc != fi->facet_begin() ); sum = sum / ( double )CGAL::circulator_size( hfc ); fi->center() = CGAL::ORIGIN + sum; } // assign the same IDs to the identical/ opposite halfedges for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) { hi->label() = DEFAULT_LABEL; hi->match() = DEFAULT_LABEL; hi->cycle() = NO_INDEX; hi->connect() = true; hi->visit() = false; hi->path() = NO_INDEX; hi->orient() = true; // We individually handle hi->fixed } }
void mergeColinear(Polyhedron& p) { int vertBefore = p.size_of_vertices(); bool colinearFound = true; while (colinearFound) { colinearFound = false; // Set temporarily to false, if merge degments then set true int percCount = 1; for (Polyhedron::Halfedge_iterator hit = p.halfedges_begin(); hit != p.halfedges_end(); ++hit,++percCount){ if (CGAL::circulator_size(hit->vertex_begin()) == 1) { std::cerr << "WARNING: Loose edge, but how??"<<std::endl; while (CGAL::circulator_size(hit->vertex_begin()) == 1) hit = p.join_vertex(hit->opposite()); break; } if ((CGAL::circulator_size(hit->vertex_begin()) == 2) && // if only two he connected to vertex (hit->facet_degree()>3 && hit->opposite()->facet_degree()>3)) { // if faces are not triangles // prob faster Vector_3 cur(hit->prev()->vertex()->point(),hit->vertex()->point()); Vector_3 nex(hit->vertex()->point(),hit->next()->vertex()->point()); if ( is_colinear(cur,nex)) { // check if colinear std::cout << "\rVertices before/after: "<<vertBefore<<" -> "<< p.size_of_vertices()<<". ("<<100*percCount/p.size_of_halfedges()<<"%)"; p.join_vertex(hit->opposite()); // move cur to prev point colinearFound = true; break; } } } } std::cout << "\rVertices before/after: "<<vertBefore<<" -> "<< p.size_of_vertices()<<". (100%)" << std::endl; }
/** * Set the label on all edges to be CHANNEL, RIDGE, or TRANSVERSE. */ void label_all_edges(Polyhedron& p) { for (Halfedge_iterator i = p.halfedges_begin(); i != p.halfedges_end(); ++i) { // type is not initialized by the constructor, so we initialize it here. i->type = NO_TYPE; i->type = edge_type(i); } }
void mergeCoplanar(Polyhedron& p,bool step2) { int facetsBefore = p.size_of_facets(); p.normalize_border(); if(!p.size_of_border_halfedges()) { // Calculate normals only once in advace! so all tris should be coplanar with the original std::transform( p.facets_begin(), p.facets_end(),p.planes_begin(),Plane_equation()); // Calculate plane equations (only works on tri<- = bs)=true bool coplanarFound = true; std::vector<Polyhedron::Halfedge_handle> skipHEs; while (coplanarFound) { coplanarFound = false; // Set coplanarFound false int percCount = 1; for (Polyhedron::Halfedge_iterator hit = p.halfedges_begin(); hit != p.halfedges_end(); ++hit,++percCount){ // Loop through all halfedges if (is_coplanar(hit,true)){ // If coplanar and equals semantics Polyhedron::Halfedge_handle removeMe = hit; while (CGAL::circulator_size(removeMe->vertex_begin()) < 3) // Mover handle to beginning of linestring removeMe = removeMe->next(); bool jcnh = false; if (!step2) jcnh = joinCreatesNoHole (hit); else jcnh = joinCreatesNoHole2(hit); if (jcnh){ // If no holes will be created std::cout << "\rFacets before/after: "<<facetsBefore<<" -> "<< p.size_of_facets()<<". ("<<100*percCount/p.size_of_halfedges()<<"%)"; while (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3) // Join vertexes until at the other end of linestring if (removeMe->facet_degree()>3 && removeMe->opposite()->facet_degree()>3) removeMe = (p.join_vertex(removeMe))->next()->opposite(); else // One of the faces turned into a triangle ->remove center vertex break; if (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3) // Remove remained of the border p.erase_center_vertex(removeMe->opposite()); // if two segments remain remove center point else p.join_facet(removeMe); // if one segment remains join facets coplanarFound = true; break; } else { // simplify border, but how to do this safely? not optimal solution implemented. Should do: add inward offseted point of intersection etc. if (std::find(skipHEs.begin(), skipHEs.end(),hit)!=skipHEs.end()) { // Skip if hit in skipList while (CGAL::circulator_size(removeMe->opposite()->vertex_begin()) < 3) { // Join vertexes until at the other end of linestring if (removeMe->facet_degree()>3 && removeMe->opposite()->facet_degree()>3) if (triDoesNotIntersectFacet(removeMe)) // if tri reMe,reME->prev does not intersect left or right facet removeMe = (p.join_vertex(removeMe))->next()->opposite(); // remove removeME else { skipHEs.push_back(removeMe); skipHEs.push_back(removeMe->opposite()); removeMe = removeMe->prev(); // move removeME one halfedge back } else break; // stop if only a triangle remains or at other end } skipHEs.push_back(removeMe); skipHEs.push_back(removeMe->opposite()); } } } } } } //if (!step2) mergeCoplanar(p,true); //else std::cout << "\rFacets before/after: "<<facetsBefore<<" -> "<< p.size_of_facets()<<". (100%)"<<std::endl; }
double shortest_edge(Polyhedron& p) { double shortest = std::numeric_limits<double>::max(); for (typename Polyhedron::Halfedge_iterator halfedge = p.halfedges_begin(); halfedge != p.halfedges_end(); halfedge++) { const double length = get_edge_length<Polyhedron>(halfedge); shortest = std::min(shortest, length); } return shortest; }
/* Simplificate a mesh using CGALs Triangulated Surface Mesh Simplification (http://doc.cgal.org/latest/Surface_mesh_simplification/index.html#Chapter_Triangulated_Surface_Mesh_Simplification) */ const char* CGALSimplificateSurface(const char* inputMeshFile, const char* outputMeshFile, int stopnr, std::vector<double> box = std::vector<double>()) { vtkSmartPointer<vtkPolyData> inputPoly = IOHelper::VTKReadPolyData(inputMeshFile); Polyhedron polyhedron; VTKPolydataToCGALPolyhedron_converter(inputPoly, &polyhedron); //create stop predicate CGAL::Surface_mesh_simplification::Count_stop_predicate<Polyhedron> stop(stopnr); Constrains_map constrains_map ; //if box contains exactly six values, use region inside box to mark non-removable edges if(box.size()==6) { int totalEdges=0; int constrainedEdges=0; log_debug()<<"bounding box given"<<std::endl; //iterate over all edges, edges inside box will be marked as non-removable for(Polyhedron::Halfedge_iterator eb = polyhedron.halfedges_begin(), ee = polyhedron.halfedges_end() ; eb != ee ; ++ eb ) { Point currentPoint = eb->vertex()->point(); //test if edge vertex is within box if( (currentPoint[0]>=box[0]) && (currentPoint[1]>=box[1]) && (currentPoint[2]>=box[2]) && (currentPoint[0]<=box[3]) && (currentPoint[1]<=box[4]) && (currentPoint[2]<=box[5])) { //add to map of non-removable edges constrains_map.set_is_constrained(eb,true); constrainedEdges++; } totalEdges++; } log_debug()<<"total edges: "<<totalEdges<<" constrained: "<<constrainedEdges<<std::endl; } //simplificate mesh int r = CGAL::Surface_mesh_simplification::edge_collapse (polyhedron,stop, CGAL::vertex_index_map(boost::get(CGAL::vertex_external_index,polyhedron)) .edge_index_map (boost::get(CGAL::edge_external_index ,polyhedron)) .edge_is_border_map(constrains_map) ); log_debug()<<"Edges removed: "<<r<<std::endl; //now create polydata-object vtkSmartPointer<vtkPolyData> vtkpoly = vtkSmartPointer<vtkPolyData>::New(); //convert polyhedron to polydata CGALPolyhedronToVTKPolydata_converter(&polyhedron, vtkpoly); //write polydata to disk bool result = IOHelper::VTKWritePolyData(outputMeshFile,vtkpoly); return outputMeshFile; }
//------------------------------------------------------------------------------ // Compute and store the results of dual graphs into appropriate variables // // computeDual( mesh, whole, bary, mid ); //------------------------------------------------------------------------------ void computeDual( Polyhedron & poly, Graph & dual, vector< Point3 > & bary, vector< Point3 > & mid ) { // initialize the array of face barycenters: refer to the point at which the gravitational forces exerted by 2 objects are equal bary.clear(); bary.resize( poly.size_of_facets() ); // initialize the dual graph with dual vertices dual.clear(); int fid = 0; for ( Facet_iterator fi = poly.facets_begin(); fi != poly.facets_end(); ++fi ) { // add a vertex: each face equals to each dual vertex add_vertex( dual ); bary[ fid++ ] = fi->center(); // cerr << " Barycenter No. " << fid-1 << " : " << bary[ fid-1 ] << endl; } int size_of_edges = poly.size_of_halfedges() / 2; //redundant // initialize the array of midpoints mid.clear(); mid.resize( size_of_edges ); // initialize the array of lengths // length.clear(); // length.resize( size_of_edges ); // construct the connecitivity of the dual graph for ( Halfedge_iterator hi = poly.halfedges_begin(); hi != poly.halfedges_end(); ++hi ) { int origID = hi->facet()->id(); // the face int destID = hi->opposite()->facet()->id(); // the neighbor face Point3 origCoord = hi->vertex()->point(); Point3 destCoord = hi->opposite()->vertex()->point(); Vector3 dispVec = origCoord - destCoord; Point3 midCoord = destCoord + 0.5 * dispVec; // double curLength = sqrt( dispVec.squared_length() ); // the length between two connected vertices #ifdef DEBUG cerr << origID << " -- " << destID << endl; #endif // DEBUG if ( origID < destID ) add_edge( origID, destID, hi->id(), dual ); mid[ hi->id() ] = midCoord; hi->mid() = hi->opposite()->mid() = midCoord; hi->weight() = hi->opposite()->weight() = 1.0; } }
int main() { Polyhedron P; Build_triangle<HalfedgeDS> triangle; P.delegate( triangle); CGAL_assertion( P.is_triangle( P.halfedges_begin())); CGAL::set_pretty_mode(std::cout); std::cout << "Success creating two triangles: " << std::endl; std::cout << "The polyhedron created at this stage" << P << std::endl; running_iterators(P); return 0; }
static void remove_short_edges(Polyhedron& p, const double threshold) { while (true) { bool removed = false; for (typename Polyhedron::Halfedge_iterator halfedge = p.halfedges_begin(); halfedge != p.halfedges_end(); halfedge++) { if (get_edge_length<Polyhedron>(halfedge) < threshold) { remove_edge<Polyhedron>(p, halfedge); removed = true; break; } } if (!removed) break; } }