void smoothMesh( Polyhedron & poly, unsigned int nTimes ) { int nV = poly.size_of_vertices(); const double lambda = SMOOTHING_LAMBDA; const double mu = SMOOTHING_MU; vector< Point3 > shrink ( nV ); vector< Point3 > expand ( nV ); for ( unsigned int k = 0; k < nTimes; ++k ) { // copy the vertex coordinates for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { shrink [ vi->id() ] = vi->point(); } // shrinking stage for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { moveVertex( vi, shrink[ vi->id() ], lambda ); } // copy back the vertex coordinates for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->point() = shrink[ vi->id() ]; expand[ vi->id() ] = shrink[ vi->id() ]; } // expanding stage for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { moveVertex( vi, expand[ vi->id() ], mu ); } // copy back the vertex coordinates for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->point() = expand[ vi->id() ]; } } }
void geometryUtils::subdivide(Polyhedron& P) { if (P.size_of_facets() == 0) return; // We use that new vertices/halfedges/facets are appended at the end. std::size_t nv = P.size_of_vertices(); Vertex_iterator last_v = P.vertices_end(); --last_v; // the last of the old vertices Edge_iterator last_e = P.edges_end(); --last_e; // the last of the old edges Facet_iterator last_f = P.facets_end(); --last_f; // the last of the old facets Facet_iterator f = P.facets_begin(); // create new center vertices do { geometryUtils::subdivide_create_center_vertex(P, f); } while (f++ != last_f); std::vector<Point_3> pts; // smooth the old vertices pts.reserve(nv); // get intermediate space for the new points ++last_v; // make it the past-the-end position again std::transform(P.vertices_begin(), last_v, std::back_inserter(pts), Smooth_old_vertex()); std::copy(pts.begin(), pts.end(), P.points_begin()); Edge_iterator e = P.edges_begin(); // flip the old edges ++last_e; // make it the past-the-end position again while (e != last_e) { Halfedge_handle h = e; ++e; // careful, incr. before flip since flip destroys current edge geometryUtils::subdivide_flip_edge(P, h); }; CGAL_postcondition(P.is_valid()); };
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 transformMesh( Polyhedron & poly, Transformation3 & map ) { for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { Point3 store = vi->point().transform( map ); vi->point() = store; } }
polyhedron cgal_to_polyhedron( const Nef_polyhedron &NP ){ Polyhedron P; polyhedron ret; if( NP.is_simple() ){ NP.convert_to_polyhedron(P); std::vector<double> coords; std::vector<int> tris; int next_id = 0; std::map< Polyhedron::Vertex*, int > vid; for( Polyhedron::Vertex_iterator iter=P.vertices_begin(); iter!=P.vertices_end(); iter++ ){ coords.push_back( CGAL::to_double( (*iter).point().x() ) ); coords.push_back( CGAL::to_double( (*iter).point().y() ) ); coords.push_back( CGAL::to_double( (*iter).point().z() ) ); vid[ &(*iter) ] = next_id++; } for( Polyhedron::Facet_iterator iter=P.facets_begin(); iter!=P.facets_end(); iter++ ){ Polyhedron::Halfedge_around_facet_circulator j = iter->facet_begin(); tris.push_back( CGAL::circulator_size(j) ); do { tris.push_back( std::distance(P.vertices_begin(), j->vertex()) ); } while ( ++j != iter->facet_begin()); } ret.initialize_load_from_mesh( coords, tris ); } else { std::cout << "resulting polyhedron is not simple!" << std::endl; } return ret; }
//------------------------------------------------------------------------------ // 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; }
//------------------------------------------------------------------------------ // Normalize the 3D triangulated mesh with the display window //------------------------------------------------------------------------------ void normalizeMesh( Polyhedron & poly, vector< Segment3 > & bone ) { Vector3 sum, ave; for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { sum = sum + ( vi->point() - CGAL::ORIGIN ); } ave = sum / ( double )poly.size_of_vertices(); for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->point() = vi->point() - ave; } cerr << " ave = " << ave << endl; Transformation3 translate( CGAL::TRANSLATION, -ave ); // fabs:absolute values-no negative values double sideMax = 0.0; for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { if ( fabs( vi->point().x() ) > sideMax ) sideMax = fabs( vi->point().x() ); if ( fabs( vi->point().y() ) > sideMax ) sideMax = fabs( vi->point().y() ); if ( fabs( vi->point().z() ) > sideMax ) sideMax = fabs( vi->point().z() ); } // sideMax: the largest number for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { vi->point() = CGAL::ORIGIN + ( vi->point() - CGAL::ORIGIN ) / sideMax; } Transformation3 scale( CGAL::SCALING, 1.0/sideMax ); Transformation3 composite = scale * translate; for ( unsigned int k = 0; k < bone.size(); ++k ) { bone[ k ] = bone[ k ].transform( composite ); } }
void modify_vertex_position() { Polyhedron P; Halfedge_handle h = P.make_tetrahedron(); if ( P.is_tetrahedron(h)) { int i(0); for(Vertex_iterator vi = P.vertices_begin(); vi != P.vertices_end(); ++vi,++i) { std::cout << "before changing vertex " << i << ": " << vi->point().x() << vi->point().y() << vi->point().z() << endl; Point_3 pt(1, 0, 0); vi->point() = pt; std::cout << "after changing vertex " << i << ": " << vi->point().x() << vi->point().y() << vi->point().z() << endl; } } }
IGL_INLINE void igl::copyleft::cgal::polyhedron_to_mesh( const Polyhedron & poly, Eigen::MatrixXd & V, Eigen::MatrixXi & F) { using namespace std; V.resize(poly.size_of_vertices(),3); F.resize(poly.size_of_facets(),3); typedef typename Polyhedron::Vertex_const_iterator Vertex_iterator; std::map<Vertex_iterator,size_t> vertex_to_index; { size_t v = 0; for( typename Polyhedron::Vertex_const_iterator p = poly.vertices_begin(); p != poly.vertices_end(); p++) { V(v,0) = p->point().x(); V(v,1) = p->point().y(); V(v,2) = p->point().z(); vertex_to_index[p] = v; v++; } } { size_t f = 0; for( typename Polyhedron::Facet_const_iterator facet = poly.facets_begin(); facet != poly.facets_end(); ++facet) { typename Polyhedron::Halfedge_around_facet_const_circulator he = facet->facet_begin(); // Facets in polyhedral surfaces are at least triangles. assert(CGAL::circulator_size(he) == 3 && "Facets should be triangles"); size_t c = 0; do { //// This is stooopidly slow // F(f,c) = std::distance(poly.vertices_begin(), he->vertex()); F(f,c) = vertex_to_index[he->vertex()]; c++; } while ( ++he != facet->facet_begin()); f++; } } }
scalarField calcCurvature(const triSurface& surf) { scalarField k(surf.points().size(), 0); Polyhedron P; buildCGALPolyhedron convert(surf); P.delegate(convert); // Info<< "Created CGAL Polyhedron with " << label(P.size_of_vertices()) // << " vertices and " << label(P.size_of_facets()) // << " facets. " << endl; // The rest of this function adapted from // CGAL-3.7/examples/Jet_fitting_3/Mesh_estimation.cpp //Vertex property map, with std::map typedef std::map<Vertex*, int> Vertex2int_map_type; typedef boost::associative_property_map< Vertex2int_map_type > Vertex_PM_type; typedef T_PolyhedralSurf_rings<Polyhedron, Vertex_PM_type > Poly_rings; typedef CGAL::Monge_via_jet_fitting<Kernel> Monge_via_jet_fitting; typedef Monge_via_jet_fitting::Monge_form Monge_form; std::vector<Point_3> in_points; //container for data points // default parameter values and global variables unsigned int d_fitting = 2; unsigned int d_monge = 2; unsigned int min_nb_points = (d_fitting + 1)*(d_fitting + 2)/2; //initialize the tag of all vertices to -1 Vertex_iterator vitb = P.vertices_begin(); Vertex_iterator vite = P.vertices_end(); Vertex2int_map_type vertex2props; Vertex_PM_type vpm(vertex2props); CGAL_For_all(vitb, vite) { put(vpm, &(*vitb), -1); }
//********************************************************************************** //returns min coordinates Vector3r MinCoord(const shared_ptr<Shape>& cm1,const State& state1){ const Se3r& se3=state1.se3; Polyhedra* A = static_cast<Polyhedra*>(cm1.get()); //move and rotate CGAL structure Polyhedron Matrix3r rot_mat = (se3.orientation).toRotationMatrix(); Vector3r trans_vec = se3.position; Transformation t_rot_trans(rot_mat(0,0),rot_mat(0,1),rot_mat(0,2), trans_vec[0],rot_mat(1,0),rot_mat(1,1),rot_mat(1,2),trans_vec[1],rot_mat(2,0),rot_mat(2,1),rot_mat(2,2),trans_vec[2],1.); Polyhedron PA = A->GetPolyhedron(); std::transform( PA.points_begin(), PA.points_end(), PA.points_begin(), t_rot_trans); Vector3r minccord = trans_vec; for(Polyhedron::Vertex_iterator vi = PA.vertices_begin(); vi != PA.vertices_end(); ++vi){ if (vi->point()[0]<minccord[0]) minccord[0]=vi->point()[0]; if (vi->point()[1]<minccord[1]) minccord[1]=vi->point()[1]; if (vi->point()[2]<minccord[2]) minccord[2]=vi->point()[2]; } return minccord; }
ofMesh & ofxCGALSkinSurface::makeSkinSurfaceMesh() { std::list<Weighted_point> l; FT shrinkfactor = shrinkFactor; for(int i=0; i<points.size(); i++) { float px = points[i].point.x; float py = points[i].point.y; float pz = points[i].point.z; float radius = points[i].radius; l.push_front(Weighted_point(Bare_point(px, py, pz), radius * radius)); } Skin_surface_3 skin_surface(l.begin(), l.end(), shrinkfactor); Polyhedron p; CGAL::mesh_skin_surface_3(skin_surface, p); if(bSubdiv == true) { CGAL::subdivide_skin_surface_mesh_3(skin_surface, p); } mesh.clear(); map<Point_3, int> point_indices; int count = 0; for (auto it=p.vertices_begin(); it!=p.vertices_end(); ++it) { auto& p = it->point(); mesh.addVertex(ofVec3f(p.x(), p.y(), p.z())); point_indices[p] = count++; } for (auto it=p.facets_begin(); it!=p.facets_end(); ++it) { mesh.addIndex(point_indices[it->halfedge()->vertex()->point()]); mesh.addIndex(point_indices[it->halfedge()->next()->vertex()->point()]); mesh.addIndex(point_indices[it->halfedge()->prev()->vertex()->point()]); } }
void ComputeGaussCurvature(Polyhedron &P) { Polyhedron::Vertex_iterator vit; for(vit=P.vertices_begin(); vit!=P.vertices_end(); vit++) ComputeGaussCurvature(vit); }
void MainWindow::parameterize(const Parameterization_method method) { QApplication::setOverrideCursor(Qt::WaitCursor); // get active polyhedron int index = getSelectedSceneItemIndex(); Polyhedron* pMesh = scene->polyhedron(index); if(pMesh == NULL) { QApplication::restoreOverrideCursor(); return; } // parameterize QTime time; time.start(); typedef CGAL::Parameterization_polyhedron_adaptor_3<Polyhedron> Adaptor; Adaptor adaptor(*pMesh); bool success = false; switch(method) { case PARAM_MVC: { std::cout << "Parameterize (MVC)..."; typedef CGAL::Mean_value_coordinates_parameterizer_3<Adaptor> Parameterizer; Parameterizer::Error_code err = CGAL::parameterize(adaptor,Parameterizer()); success = err == Parameterizer::OK; break; } case PARAM_DCP: { std::cout << "Parameterize (DCP)..."; typedef CGAL::Discrete_conformal_map_parameterizer_3<Adaptor> Parameterizer; Parameterizer::Error_code err = CGAL::parameterize(adaptor,Parameterizer()); success = err == Parameterizer::OK; } } if(success) std::cout << "ok (" << time.elapsed() << " ms)" << std::endl; else { std::cout << "failure" << std::endl; QApplication::restoreOverrideCursor(); return; } // add textured polyhedon to the scene Textured_polyhedron *pTex_polyhedron = new Textured_polyhedron(); Textured_polyhedron_builder<Polyhedron,Textured_polyhedron,Kernel> builder; builder.run(*pMesh,*pTex_polyhedron); pTex_polyhedron->compute_normals(); Polyhedron::Vertex_iterator it1; Textured_polyhedron::Vertex_iterator it2; for(it1 = pMesh->vertices_begin(), it2 = pTex_polyhedron->vertices_begin(); it1 != pMesh->vertices_end(), it2 != pTex_polyhedron->vertices_end(); it1++, it2++) { // (u,v) pair is stored per halfedge FT u = adaptor.info(it1->halfedge())->uv().x(); FT v = adaptor.info(it1->halfedge())->uv().y(); it2->u() = u; it2->v() = v; } scene->addTexPolyhedron(pTex_polyhedron, tr("%1 (parameterized)").arg(scene->polyhedronName(index)), Qt::white, scene->isPolyhedronVisible(index), scene->polyhedronRenderingMode(index)); QApplication::restoreOverrideCursor(); }
void ElPoly::DefineSkin(int NSample){ std::list<Weighted_point> l; FT shrinkfactor = 0.5; double *Plot = new double[pNType()*CUBE(NSample)]; double *Count = new double[CUBE(NSample)]; double Thre = 10.; double Radius = pEdge(0)/(double)NSample; for(int p=0;p<pNPart();p++){ int t = pType(p); int vx = (int)(pPos(p,0)/pEdge(0)*NSample); int vy = (int)(pPos(p,1)/pEdge(1)*NSample); int vz = (int)(pPos(p,2)/pEdge(2)*NSample); int vTot = (vz*NSample+vy)*NSample+vx; Plot[vTot*pNType()+t] += 1.; } double *Norm = (double *)calloc(pNType(),sizeof(double)); for(int t=0;t<pNType();t++){ for(int v=0;v<CUBE(NSample);v++){ if(Norm[t] < Plot[v*pNType()+t]) Norm[t] = Plot[v*pNType()+t]; } Norm[t] = Norm[t] <= 0. ? 1. : Norm[t]; } for(int vx=0;vx<NSample;vx++){ double x = vx*pEdge(0)/(double)NSample; for(int vy=0;vy<NSample;vy++){ double y = vy*pEdge(1)/(double)NSample; for(int vz=0;vz<NSample;vz++){ double z = vz*pEdge(2)/(double)NSample; int vTot = (vz*NSample+vy)*NSample+vx; if(Plot[vTot*pNType()] > Thre){ l.push_front(Weighted_point(Bare_point(x,y,z),Radius)); } } } } Polyhedron Polyhe; Skin_surface_3 skin_surface(l.begin(), l.end(), shrinkfactor); CGAL::mesh_skin_surface_3(skin_surface, Polyhe); // CGAL::subdivide_skin_surface_mesh_3(skin_surface, Polyhe); // std::ofstream out("mesh.off"); // out << Polyhe; glDeleteLists(Dr->Particles,1); Dr->Particles = glGenLists(1); glNewList(Dr->Particles,GL_COMPILE); // Polyhedron::Facet_iterator fcUp = Polyhe.facets_begin(); // for(;fcUp != Polyhe.facets_end(); ++fcUp){ // Polyhedron::Supports_facet_halfedge = fcUp.halfedge(); // //Halfedge_around_facet_circulator heUp = fcUp.halfedge(); // } // for (Vertex_iterator vit = Polyhe.vertices_begin();vit != Polyhe.vertices_end(); vit++){ // // Vector n = policy.normal(vit); // // n = n/sqrt(n*n); // cout << vit->point() << std::endl; // Halfedge_iterator heUp = Polyhe.halfedges_begin(); // for(;heUp != Polyhe.halfedges_end(); ++heUp){ // //Polyhedron::Halfedge_handle Half = *heUp; // Vertex_handle veUp = heUp->vertex(); // K::Point_3 pf1 = vit->point(); // } // } CGAL::Inverse_index<Vertex_handle> index(Polyhe.vertices_begin(), Polyhe.vertices_end()); for(Facet_iterator fi = Polyhe.facets_begin();fi != Polyhe.facets_end(); ++fi) { HFC hc = fi->facet_begin(); HFC hc_end = hc; Polyhedron::Vertex_handle vf1 = (*hc).vertex(); hc++; Polyhedron::Vertex_handle vf2 = (*hc).vertex(); hc++; Polyhedron::Vertex_handle vf3 = (*hc).vertex(); hc++; K::Point_3 pf1 = vf1->point(); K::Point_3 pf2 = vf2->point(); K::Point_3 pf3 = vf3->point(); Vettore v1(pf1.x(),pf1.y(),pf1.z()); Vettore v2(pf2.x(),pf2.y(),pf2.z()); Vettore v3(pf3.x(),pf3.y(),pf3.z()); Vettore vN(3); v1.Mult(InvScaleUn); v2.Mult(InvScaleUn); v3.Mult(InvScaleUn); vN = (v1-v2) ^ (v3-v2); //if(vN.Norm() > 2.*AreaMean) continue; double Sfumatura = .3*Mat->Casuale(); glColor4f(0.1,.4+Sfumatura,0.2,1.); //glColor4f(HueUp[p].r,HueUp[p].g,HueUp[p].b,HueUp[p].a); DrTria(&v1,&v2,&v3,&vN); glColor4f(1.,.0,0.,1.); DrTriaContour(&v1,&v2,&v3); // glPushMatrix();//Particle // glBegin(GL_LINES); // do { // Polyhedron::Vertex_handle vh = (*hc).vertex(); // K::Point_3 pf1 = vh->point(); // glVertex3d(pf1.x(),pf1.y(),pf1.z()); // } while (++hc != hc_end); // glEnd(); // glPopMatrix();//Particle } glEndList(); // Tr tr; // 3D-Delaunay triangulation // C2t3 c2t3 (tr); // 2D-complex in 3D-Delaunay triangulation // Surface_3 surface(sphere_function,Sphere_3(CGAL::ORIGIN, 2.)); // Surface_mesh_default_criteria_3<Tr> criteria(30., 0.1,0.1); // // meshing surface // make_surface_mesh(c2t3, surface, criteria, CGAL::Non_manifold_tag()); // std::cout << "Final number of points: " << tr.number_of_vertices() << "\n"; // DT dt; // for(int c=0;c<Gen->NChain;c++){ // if(CHAIN_IF_TYPE(Ch[c].Type,CHAIN_UP) )continue; // Point_3<K> ChPos(pPos(c,CLat1),pPos(c,CLat2),pPos(c,CNorm)); // dt.insert(ChPos); // } // Face_iterator fcTr = dt.finite_faces_begin(); // glDeleteLists(Dr->Particles,1); // Dr->Particles = glGenLists(1); // glNewList(Dr->Particles,GL_COMPILE); // for(;fcTr != dt.faces_end(); ++fcTr){ // Vertex_handle vf1 = fcTr->vertex(0), // vf2 = fcTr->vertex(1),vf3 = fcTr->vertex(2); // Point pf1 = vf1->point(); // Point pf2 = vf2->point(); // Point pf3 = vf3->point(); // Vettore v1(pf1.x() - pf2.x(),pf1.y() - pf2.y(),pf1.z()-pf2.z()); // Vettore v2(pf3.x() - pf2.x(),pf3.y() - pf2.y(),pf1.z()-pf2.z()); // Vettore vN(3); // vN = v1 ^ v2; // DrTira(v1,v2,v3,vN); // } // glEndList(); }
/* * mexFunction(): entry point for the mex function */ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { // interface to deal with input arguments from Matlab enum InputIndexType {IN_TRI, IN_X, IN_METHOD, IN_ITER, InputIndexType_MAX}; MatlabImportFilter::Pointer matlabImport = MatlabImportFilter::New(); matlabImport->ConnectToMatlabFunctionInput(nrhs, prhs); // check that we have all input arguments matlabImport->CheckNumberOfArguments(2, InputIndexType_MAX); // register the inputs for this function at the import filter MatlabInputPointer inTRI = matlabImport->RegisterInput(IN_TRI, "TRI"); MatlabInputPointer inX = matlabImport->RegisterInput(IN_X, "X"); MatlabInputPointer inMETHOD = matlabImport->RegisterInput(IN_METHOD, "METHOD"); MatlabInputPointer inITER = matlabImport->RegisterInput(IN_ITER, "ITER"); // interface to deal with outputs to Matlab enum OutputIndexType {OUT_TRI, OUT_N, OutputIndexType_MAX}; MatlabExportFilter::Pointer matlabExport = MatlabExportFilter::New(); matlabExport->ConnectToMatlabFunctionOutput(nlhs, plhs); // check number of outputs the user is asking for matlabExport->CheckNumberOfArguments(0, OutputIndexType_MAX); // register the outputs for this function at the export filter typedef MatlabExportFilter::MatlabOutputPointer MatlabOutputPointer; MatlabOutputPointer outTRI = matlabExport->RegisterOutput(OUT_TRI, "TRI"); MatlabOutputPointer outN = matlabExport->RegisterOutput(OUT_N, "N"); // if any of the inputs is empty, the output is empty too if (mxIsEmpty(prhs[IN_TRI]) || mxIsEmpty(prhs[IN_X])) { matlabExport->CopyEmptyArrayToMatlab(outTRI); matlabExport->CopyEmptyArrayToMatlab(outN); return; } // polyhedron to contain the input mesh Polyhedron mesh; PolyhedronBuilder<Polyhedron> builder(matlabImport, inTRI, inX); mesh.delegate(builder); // get size of input matrix with the points mwSize nrowsTri = mxGetM(inTRI->pm); mwSize nrowsX = mxGetM(inX->pm); #ifdef DEBUG std::cout << "Number of facets read = " << mesh.size_of_facets() << std::endl; std::cout << "Number of vertices read = " << mesh.size_of_vertices() << std::endl; #endif if (nrowsTri != mesh.size_of_facets()) { mexErrMsgTxt(("Input " + inTRI->name + ": Number of triangles read into mesh different from triangles provided at the input").c_str()); } if (nrowsX != mesh.size_of_vertices()) { mexErrMsgTxt(("Input " + inX->name + ": Number of vertices read into mesh different from vertices provided at the input").c_str()); } // sort halfedges such that the non-border edges precede the // border edges. We need to do this before any halfedge iterator // operations are valid mesh.normalize_border(); #ifdef DEBUG std::cout << "Number of border halfedges = " << mesh.size_of_border_halfedges() << std::endl; #endif // number of holes we have filled mwIndex n = 0; // a closed mesh with no holes will have no border edges. What we do // is grab a border halfedge and close the associated hole. This // makes the rest of the iterators invalid, so we have to normalize // the mesh again. Then we iterate, looking for a new border // halfedge, filling the hole, etc. // // Note that confusingly, mesh.border_halfedges_begin() gives a // pointer to the halfedge that is NOT a border in a border // edge. The border halfedge is instead // mesh.border_halfedges_begin()->opposite() while (!mesh.is_closed()) { // exit if user pressed Ctrl+C ctrlcCheckPoint(__FILE__, __LINE__); // get the first hole we can find, and close it mesh.fill_hole(mesh.border_halfedges_begin()->opposite()); // increase the counter of number of holes we have filled n++; // renormalize mesh so that halfedge iterators are again valid mesh.normalize_border(); } // split all facets to triangles CGAL::triangulate_polyhedron<Polyhedron>(mesh); // copy output with number of holes filled std::vector<double> nout(1, n); matlabExport->CopyVectorOfScalarsToMatlab<double, std::vector<double> >(outN, nout, 1); // allocate memory for Matlab outputs double *tri = matlabExport->AllocateMatrixInMatlab<double>(outTRI, mesh.size_of_facets(), 3); // extract the triangles of the solution // snippet adapted from CgalMeshSegmentation.cpp // vertices coordinates. Assign indices to the vertices by defining // a map between their handles and the index std::map<Vertex_handle, int> V; int inum = 0; for(Vertex_iterator vit = mesh.vertices_begin(); vit != mesh.vertices_end(); ++vit) { // save to internal list of vertices V[vit] = inum++; } // triangles given as (i,j,k), where each index corresponds to a vertex in x mwIndex row = 0; for (Facet_iterator fit = mesh.facets_begin(); fit != mesh.facets_end(); ++fit, ++row) { if (fit->facet_degree() != 3) { std::cerr << "Facet has " << fit->facet_degree() << " edges" << std::endl; mexErrMsgTxt("Facet does not have 3 edges"); } // go around the half-edges of the facet, to extract the vertices Halfedge_around_facet_circulator heit = fit->facet_begin(); int idx = 0; do { // extract triangle indices and save to Matlab output // note that Matlab indices go like 1, 2, 3..., while C++ indices go like 0, 1, 2... tri[row + idx * mesh.size_of_facets()] = 1 + V[heit->vertex()]; idx++; } while (++heit != fit->facet_begin()); } }
void alignMesh( Polyhedron & poly ) { int num = poly.size_of_vertices(); // initialization here is very important!! Point3 ave( 0.0, 0.0, 0.0 ); for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { ave = ave + ( vi->point() - CGAL::ORIGIN ); } ave = CGAL::ORIGIN + ( ave - CGAL::ORIGIN )/( double )num; unsigned int dim = 3; double * data = new double [ num*dim ]; int nPoints = 0; for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { data[ nPoints * dim + 0 ] = vi->point().x() - ave.x(); data[ nPoints * dim + 1 ] = vi->point().y() - ave.y(); data[ nPoints * dim + 2 ] = vi->point().z() - ave.z(); nPoints++; } assert( nPoints == ( int )num ); /***************************************** analyze the engenstructure of X^T X *****************************************/ /* define the matrix X */ gsl_matrix_view X = gsl_matrix_view_array( data, num, dim ); /* memory reallocation */ // proj = ( double * )realloc( proj, sizeof( double ) * PDIM * num ); /* calculate the covariance matrix B */ gsl_matrix * B = gsl_matrix_alloc( dim, dim ); gsl_blas_dgemm( CblasTrans, CblasNoTrans, 1.0, &(X.matrix), &(X.matrix), 0.0, B ); /* divided by the number of samples */ gsl_matrix_scale( B, 1.0/(double)num ); gsl_vector * eVal = gsl_vector_alloc( dim ); gsl_matrix * eVec = gsl_matrix_alloc( dim, dim ); gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc( dim ); // eigenanalysis of the matrix B gsl_eigen_symmv( B, eVal, eVec, w ); // release the memory of w gsl_eigen_symmv_free( w ); // sort eigenvalues in a descending order gsl_eigen_symmv_sort( eVal, eVec, GSL_EIGEN_SORT_VAL_DESC ); // #ifdef MYDEBUG for ( unsigned int i = 0; i < dim; ++i ) { cerr << "Eigenvalue No. " << i << " = " << gsl_vector_get( eVal, i ) << endl; cerr << "Eigenvector No. " << i << endl; double length = 0.0; for ( unsigned int j = 0; j < dim; ++j ) { cerr << gsl_matrix_get( eVec, i, j ) << " "; length += gsl_matrix_get( eVec, i, j )*gsl_matrix_get( eVec, i, j ); } cerr << " length = " << length << endl; } // #endif // MYDEBUG // 0 1 2, 0 2 1, Transformation3 map; map = Transformation3( gsl_matrix_get(eVec,1,0), gsl_matrix_get(eVec,0,0), gsl_matrix_get(eVec,2,0), gsl_matrix_get(eVec,1,1), gsl_matrix_get(eVec,0,1), gsl_matrix_get(eVec,2,1), gsl_matrix_get(eVec,1,2), gsl_matrix_get(eVec,0,2), gsl_matrix_get(eVec,2,2) ); if ( map.is_odd() ) { cerr << " Transformation matrix reflected" << endl; map = Transformation3( gsl_matrix_get(eVec,1,0), gsl_matrix_get(eVec,0,0), -gsl_matrix_get(eVec,2,0), gsl_matrix_get(eVec,1,1), gsl_matrix_get(eVec,0,1), -gsl_matrix_get(eVec,2,1), gsl_matrix_get(eVec,1,2), gsl_matrix_get(eVec,0,2), -gsl_matrix_get(eVec,2,2) ); } for ( unsigned int i = 0; i < dim; ++i ) { cerr << "| "; for ( unsigned int j = 0; j < dim; ++j ) { cerr << map.cartesian( i, j ) << " "; } cerr << "|" << endl; } transformMesh( poly, map ); return; }
//------------------------------------------------------------------------------ // Align the mesh //------------------------------------------------------------------------------ Vector3 principalAxis( Polyhedron & poly ) { int num = poly.size_of_vertices(); // initialization here is very important!! Point3 ave( 0.0, 0.0, 0.0 ); for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { ave = ave + ( vi->point() - CGAL::ORIGIN ); } ave = CGAL::ORIGIN + ( ave - CGAL::ORIGIN )/( double )num; unsigned int dim = 3; double * data = new double [ num*dim ]; int nPoints = 0; for ( Vertex_iterator vi = poly.vertices_begin(); vi != poly.vertices_end(); ++vi ) { data[ nPoints * dim + 0 ] = vi->point().x() - ave.x(); data[ nPoints * dim + 1 ] = vi->point().y() - ave.y(); data[ nPoints * dim + 2 ] = vi->point().z() - ave.z(); nPoints++; } assert( nPoints == ( int )num ); /***************************************** analyze the engenstructure of X^T X *****************************************/ /* define the matrix X */ gsl_matrix_view X = gsl_matrix_view_array( data, num, dim ); /* memory reallocation */ // proj = ( double * )realloc( proj, sizeof( double ) * PDIM * num ); /* calculate the covariance matrix B */ gsl_matrix * B = gsl_matrix_alloc( dim, dim ); gsl_blas_dgemm( CblasTrans, CblasNoTrans, 1.0, &(X.matrix), &(X.matrix), 0.0, B ); /* divided by the number of samples */ gsl_matrix_scale( B, 1.0/(double)num ); gsl_vector * eVal = gsl_vector_alloc( dim ); gsl_matrix * eVec = gsl_matrix_alloc( dim, dim ); gsl_eigen_symmv_workspace * w = gsl_eigen_symmv_alloc( dim ); // eigenanalysis of the matrix B gsl_eigen_symmv( B, eVal, eVec, w ); // release the memory of w gsl_eigen_symmv_free( w ); // sort eigenvalues in a descending order gsl_eigen_symmv_sort( eVal, eVec, GSL_EIGEN_SORT_VAL_DESC ); #ifdef MYDEBUG for ( unsigned int i = 0; i < dim; ++i ) { cerr << "Eigenvalue No. " << i << " = " << gsl_vector_get( eVal, i ) << endl; cerr << "Eigenvector No. " << i << endl; for ( unsigned int j = 0; j < dim; ++j ) { length += gsl_matrix_get( eVec, i, j )*gsl_matrix_get( eVec, i, j ); } cerr << " length = " << length << endl; } #endif // MYDEBUG Vector3 ref( gsl_matrix_get( eVec, 0, 0 ), gsl_matrix_get( eVec, 0, 1 ), gsl_matrix_get( eVec, 0, 2 ) ); return ref; #ifdef DEBUG gsl_vector_view eachVec = gsl_matrix_column( eigenVec, 0 ); double cosRot = gsl_matrix_get( eigenVec, 0, 1 ); double sinRot = gsl_matrix_get( eigenVec, 1, 1 ); #ifdef DEBUG cerr << " 2nd axis : " << cosRot << " , " << sinRot << endl; #endif // DEBUG Transformation2 rotate( CGAL::ROTATION, -sinRot, cosRot ); for ( unsigned int i = 0; i < subpatch.size(); ++i ) { subpatch[ i ]->triangle() = subpatch[ i ]->triangle().transform( rotate ); } #endif // DEBUG }
int main(int argc, char * argv[]) { std::cerr << "PARAMETERIZATION" << std::endl; std::cerr << " Floater parameterization" << std::endl; std::cerr << " Circle border" << std::endl; std::cerr << " OpenNL solver" << std::endl; std::cerr << " Very simple cut if model is not a topological disk" << std::endl; //*************************************** // decode parameters //*************************************** if (argc-1 != 1) { std::cerr << "Usage: " << argv[0] << " input_file.off" << std::endl; return(EXIT_FAILURE); } // File name is: const char* input_filename = argv[1]; //*************************************** // Read the mesh //*************************************** // Read the mesh std::ifstream stream(input_filename); Polyhedron mesh; stream >> mesh; if(!stream || !mesh.is_valid() || mesh.empty()) { std::cerr << "Error: cannot read OFF file " << input_filename << std::endl; return EXIT_FAILURE; } //*************************************** // Create Polyhedron adaptor //*************************************** Parameterization_polyhedron_adaptor mesh_adaptor(mesh); //*************************************** // Virtually cut mesh //*************************************** // The parameterization methods support only meshes that // are topological disks => we need to compute a "cutting" of the mesh // that makes it homeomorphic to a disk Seam seam = cut_mesh(mesh_adaptor); if (seam.empty()) { std::cerr << "Input mesh not supported: the example cutting algorithm is too simple to cut this shape" << std::endl; return EXIT_FAILURE; } // Create a second adaptor that virtually "cuts" the mesh following the 'seam' path typedef CGAL::Parameterization_mesh_patch_3<Parameterization_polyhedron_adaptor> Mesh_patch_polyhedron; Mesh_patch_polyhedron mesh_patch(mesh_adaptor, seam.begin(), seam.end()); if (!mesh_patch.is_valid()) { std::cerr << "Input mesh not supported: non manifold shape or invalid cutting" << std::endl; return EXIT_FAILURE; } //*************************************** // Floater Mean Value Coordinates parameterization //*************************************** typedef CGAL::Parameterizer_traits_3<Mesh_patch_polyhedron> Parameterizer; // Type that defines the error codes Parameterizer::Error_code err = CGAL::parameterize(mesh_patch); switch(err) { case Parameterizer::OK: // Success break; case Parameterizer::ERROR_EMPTY_MESH: // Input mesh not supported case Parameterizer::ERROR_NON_TRIANGULAR_MESH: case Parameterizer::ERROR_NO_TOPOLOGICAL_DISC: case Parameterizer::ERROR_BORDER_TOO_SHORT: std::cerr << "Input mesh not supported: " << Parameterizer::get_error_message(err) << std::endl; return EXIT_FAILURE; break; default: // Error std::cerr << "Error: " << Parameterizer::get_error_message(err) << std::endl; return EXIT_FAILURE; break; }; //*************************************** // Output //*************************************** // Raw output: dump (u,v) pairs Polyhedron::Vertex_const_iterator pVertex; for (pVertex = mesh.vertices_begin(); pVertex != mesh.vertices_end(); pVertex++) { // (u,v) pair is stored in any halfedge double u = mesh_adaptor.info(pVertex->halfedge())->uv().x(); double v = mesh_adaptor.info(pVertex->halfedge())->uv().y(); std::cout << "(u,v) = (" << u << "," << v << ")" << std::endl; } return EXIT_SUCCESS; }
int main(int argc, char * argv[]) { std::cerr << "PARAMETERIZATION" << std::endl; std::cerr << " Floater parameterization" << std::endl; std::cerr << " Circle border" << std::endl; std::cerr << " Eigen solver" << std::endl; //*************************************** // decode parameters //*************************************** if (argc-1 != 1) { std::cerr << "Usage: " << argv[0] << " input_file.off" << std::endl; return(EXIT_FAILURE); } // File name is: const char* input_filename = argv[1]; //*************************************** // Read the mesh //*************************************** // Read the mesh std::ifstream stream(input_filename); Polyhedron mesh; stream >> mesh; if(!stream || !mesh.is_valid() || mesh.empty()) { std::cerr << "Error: cannot read OFF file " << input_filename << std::endl; return EXIT_FAILURE; } //*************************************** // Create Polyhedron adaptor // Note: no cutting => we support only // meshes that are topological disks //*************************************** typedef CGAL::Parameterization_polyhedron_adaptor_3<Polyhedron> Parameterization_polyhedron_adaptor; Timer t; t.start(); Parameterization_polyhedron_adaptor mesh_adaptor(mesh); //*************************************** // Floater Mean Value Coordinates parameterization // (circular border) with Eigen solver //*************************************** // Circular border parameterizer (the default) typedef CGAL::Circular_border_arc_length_parameterizer_3<Parameterization_polyhedron_adaptor> Border_parameterizer; // Eigen solver typedef CGAL::Eigen_solver_traits<Eigen::BiCGSTAB<CGAL::Eigen_sparse_matrix<double>::EigenType, Eigen::IncompleteLUT< double > > > Solver; // Floater Mean Value Coordinates parameterization // (circular border) with Eigen solver typedef CGAL::Mean_value_coordinates_parameterizer_3<Parameterization_polyhedron_adaptor, Border_parameterizer, Solver> Parameterizer; Parameterizer::Error_code err = CGAL::parameterize(mesh_adaptor, Parameterizer()); t.stop(); switch(err) { case Parameterizer::OK: // Success break; case Parameterizer::ERROR_EMPTY_MESH: // Input mesh not supported case Parameterizer::ERROR_NON_TRIANGULAR_MESH: case Parameterizer::ERROR_NO_TOPOLOGICAL_DISC: case Parameterizer::ERROR_BORDER_TOO_SHORT: std::cerr << "Input mesh not supported: " << Parameterizer::get_error_message(err) << std::endl; return EXIT_FAILURE; break; default: // Error std::cerr << "Error: " << Parameterizer::get_error_message(err) << std::endl; return EXIT_FAILURE; break; }; //*************************************** // Output //*************************************** // Raw output: dump (u,v) pairs Polyhedron::Vertex_const_iterator pVertex; for (pVertex = mesh.vertices_begin(); pVertex != mesh.vertices_end(); pVertex++) { // (u,v) pair is stored in any halfedge double u = mesh_adaptor.info(pVertex->halfedge())->uv().x(); double v = mesh_adaptor.info(pVertex->halfedge())->uv().y(); std::cout << "(u,v) = (" << u << "," << v << ")" << std::endl; } std::cerr << t.time() << "sec." << std::endl; return EXIT_SUCCESS; }
// a helper method for running different iterators void running_iterators( Polyhedron& P) { if ( P.size_of_facets() == 0) return; std::size_t nv = P.size_of_vertices(); std::cout << "The number of vertices in the Polyhedron: " << nv << std::endl; std::cout << "The number of facets in the Polyhedron: " << P.size_of_facets() << std::endl; std::cout << "The number of half edges in the Polyhedron: " << P.size_of_halfedges() << std::endl; std::cout << std:: endl; Polyhedron::Vertex_iterator last_v = P.vertices_end(); -- last_v; // the last of the old vertices Polyhedron::Edge_iterator last_e = P.edges_end(); -- last_e; // the last of the old edges Polyhedron::Facet_iterator last_f = P.facets_end(); -- last_f; // the last of the old facets int k = 0; Polyhedron::Facet_iterator f = P.facets_begin(); do { std::cout << "Printing a facet index: " << k++ << std::endl; f->halfedge(); } while ( f++ != last_f); std::cout << std::endl; // ------------------------------------------------- // traverse the vertices // ------------------------------------------------- std::cout << "Printing the vertex indices: " << std::endl; int n=0; for (Polyhedron::Vertex_iterator vi = P.vertices_begin(); vi != P.vertices_end(); ++vi) { Kernel::Point_3 p; p = vi->point(); std::cout << "Vertex index: " << n++ << std::endl; std::cout << "p.x() = " << p.x() << std::endl; std::cout << "p.y() = " << p.y() << std::endl; std::cout << "p.z() = " << p.z() << std::endl; } std::cout << std::endl; // ------------------------------------------------- // traverse the edges // ------------------------------------------------- std::cout << "Iterating over the edges.... " << std::endl; n=0; for (Polyhedron::Edge_iterator ei = P.edges_begin(); ei != P.edges_end(); ++ei) { ei->next(); Kernel::Point_3 p; p = ei->vertex()->point(); std::cout << "For edge index: " << n++ << std::endl; std::cout << "p.x() = " << p.x() << std::endl; std::cout << "p.y() = " << p.y() << std::endl; std::cout << "p.z() = " << p.z() << std::endl; } std::cout << std::endl; // ----------------------------------------------- // Do something else with the edge iterators // ----------------------------------------------- Polyhedron::Edge_iterator e = P.edges_begin(); ++ last_e; // make it the past-the-end position again while ( e != last_e) { Polyhedron::Halfedge_handle h = e; ++e; }; CGAL_postcondition( P.is_valid()); }
void Polyhedron_demo_jet_fitting_plugin::on_actionEstimateCurvature_triggered() { // get active polyhedron const Scene_interface::Item_id index = scene->mainSelectionIndex(); Scene_polyhedron_item* poly_item = qobject_cast<Scene_polyhedron_item*>(scene->item(index)); if(!poly_item) return; // wait cursor QApplication::setOverrideCursor(Qt::WaitCursor); Polyhedron* pMesh = poly_item->polyhedron(); // types typedef CGAL::Monge_via_jet_fitting<Kernel> Fitting; typedef Fitting::Monge_form Monge_form; typedef Kernel::Point_3 Point; Scene_polylines_item* max_curv = new Scene_polylines_item; max_curv->setColor(Qt::red); max_curv->setName(tr("%1 (max curvatures)").arg(poly_item->name())); Scene_polylines_item* min_curv = new Scene_polylines_item; min_curv->setColor(Qt::green); min_curv->setName(tr("%1 (min curvatures)").arg(poly_item->name())); Polyhedron::Vertex_iterator v; for(v = pMesh->vertices_begin(); v != pMesh->vertices_end(); v++) { std::vector<Point> points; // pick central point const Point& central_point = v->point(); points.push_back(central_point); // compute min edge len around central vertex // to scale the ribbons used to display the directions typedef Kernel::FT FT; FT min_edge_len = std::numeric_limits<FT>::infinity(); Polyhedron::Halfedge_around_vertex_circulator he = v->vertex_begin(); Polyhedron::Halfedge_around_vertex_circulator end = he; CGAL_For_all(he,end) { const Point& p = he->opposite()->vertex()->point(); points.push_back(p); FT edge_len = std::sqrt(CGAL::squared_distance(central_point,p)); min_edge_len = edge_len < min_edge_len ? edge_len : min_edge_len; // avoids #undef min } if(points.size() > 5) { // estimate curvature by fitting Fitting monge_fit; const int dim_monge = 2; const int dim_fitting = 2; Monge_form monge_form = monge_fit(points.begin(),points.end(),dim_fitting,dim_monge); // make monge form comply with vertex normal (to get correct // orientation) typedef Kernel::Vector_3 Vector; Vector n = CGAL::Polygon_mesh_processing::compute_vertex_normal(v, *pMesh); monge_form.comply_wrt_given_normal(n); Vector umin = min_edge_len * monge_form.minimal_principal_direction(); Vector umax = min_edge_len * monge_form.maximal_principal_direction(); Scene_polylines_item::Polyline max_segment(2), min_segment(2); const double du = 0.2; max_segment[0] = central_point + du * umax; max_segment[1] = central_point - du * umax; min_segment[0] = central_point + du * umin; min_segment[1] = central_point - du * umin; max_curv->polylines.push_back(max_segment); min_curv->polylines.push_back(min_segment); } } scene->addItem(max_curv); scene->addItem(min_curv); max_curv->changed(); min_curv->changed(); // default cursor QApplication::restoreOverrideCursor(); }