float Acos(OpenMesh::Vec3f vec1, OpenMesh::Vec3f vec2, OpenMesh::Vec3f vec3) { float c = vec3.norm(); float b = vec2.norm(); float a = vec1.norm(); float costheta = (a*a + b*b - c*c) / (2 * a * b); return acos(costheta); }
Mesh MeshManipulation::smoothLength(Mesh &mesh, int iterations) { std::vector<Mesh::Point> cogs; std::vector<Mesh::Point>::iterator cog_it; cogs.reserve(mesh.n_vertices()); Mesh::VertexIter vIt, vEnd(mesh.vertices_end()); Mesh::VertexVertexIter vvIt; OpenMesh::Vec3f newP; float sum; for(int i = 0; i < iterations; i++) { cogs.clear(); for( vIt = mesh.vertices_begin(); vIt != vEnd; ++vIt ) { newP[0] = newP[1] = newP[2] = sum = 0.0f; for(vvIt = mesh.vv_iter(*vIt); vvIt.is_valid(); ++vvIt) { OpenMesh::Vec3f vec = mesh.point(*vvIt) - mesh.point(*vIt); sum += (1.0f / vec.length()); newP += (vec / vec.length()); } OpenMesh::Vec3f l = sum * newP; cogs.push_back(l); } float lambda = 0.2f; Mesh::VertexIter v_it, v_end(mesh.vertices_end()); for (v_it=mesh.vertices_begin(), cog_it=cogs.begin(); v_it!=v_end; ++v_it, ++cog_it){ if ( !mesh.is_boundary( *v_it ) ) { OpenMesh::Vec3f oldP = mesh.point(*v_it); OpenMesh::Vec3f L = *cog_it; OpenMesh::Vec3f P = oldP + lambda * L; mesh.set_point( *v_it, P ); } } } return mesh; }
// https://msdn.microsoft.com/en-us/library/ms182372.aspx -< Profiler int main(int argc, char **argv) { //ann_test(); glutInit(&argc, argv); ValenceViewer window("Wireframe", 512, 512); // window.open_mesh("bunny.off"); window.open_mesh("torus(10,3,50).off"); glutMainLoop(); /* cgal<myPoint> cg; pointSet<myPoint> ps("pentagram.pts"); cg = ps; cg.polyStats(); cout<<cg.inside(Point(15,0))<<endl; // yes cout<<cg.inside(Point(15,0.5))<<endl; // yes cout<<cg.inside(Point(1,1))<<endl; // yes cout<<cg.inside(Point(100,100))<<endl; // no return; */ // testMyPolyTriangulation(); /* LightVector<double> angles(7); angles.fill(0); // double lens[7] = {3, 6, 8, 10, 4, 9, 2}; double lens[7] = {10, 3, 8, 10, 4, 9, 7}; LightVector<double> edgeLengths(7, lens); mp.init(angles, edgeLengths); mp.list(); mp.breakDown(1.618, true); // use the golden ratio, go clockwise mp.list(); mp.breakDown(1.618, false); // use the golden ratio, go counter-clockwise mp.list(); mp.head->clear(); mp.head = NULL; return; */ //tutorial1(); //tutorial2("tetrahedron.off", "tetrahedron2.off",5); //tutorial1Hu(); // Mat3 m(1,2,3,4,4,6,7,8,9); // Mat3 m2 = m.inverse(); // cout<<m.determinant()<<endl; // cout<<m2; TriMesh mesh2 = createTorus(10, 3, 50); ring ri(mesh2); LightVector<TriMesh::VertexHandle> vhv = ri.getRing(TriMesh::VertexHandle(0), 2); for (unsigned int i= 0; i<vhv.size(); ++i) { cout<< vhv[i]<<" "; } OpenMesh::IO::write_mesh(mesh2, "torus.off"); mesh2.request_face_normals(); mesh2.request_vertex_normals(); mesh2.update_normals(); TriMesh::VertexHandle vh = TriMesh::VertexHandle(5); TriMesh::VertexFaceIter vfi = mesh2.vf_iter(vh); int cc=0; OpenMesh::Vec3f norm (0, 0, 0), normv; while (vfi) { cout<<"+"<<vfi.handle()<<endl; norm += mesh2.normal(*vfi); ++cc; ++vfi; } double len = norm.length(); if (len != 0) { norm *= 1/len; } normv = mesh2.normal(vh); meshVolume(mesh2); return 0; TriMesh mesh; //mesh = createSphere(2.0f,4); OpenMesh::IO::write_mesh(mesh, "tetraSphere.off"); //mesh = createTetra(2); OpenMesh::IO::write_mesh(mesh, "tetra.off"); readmesh(mesh, "tetra.off"); // readmesh(mesh, "sphereholes.off"); readmesh(mesh, "lyukas.off"); // suboptimal, add normals to all faces while we need it only for the 1-ring around the hole if ( ! mesh.has_face_normals()) mesh.request_face_normals(); // mesh.update_normals(); holeFiller hf(mesh); hf.findHoles(); hf.displayHoles(); // hf.fill(0); // Az emberkeben, i.e. readmesh(mesh, "lyukas.off"); // hf.fill(0); // hat // hf.fill(1); // has hf.fill(2); // fej // printOff(mesh, holes[2]); mesh.release_face_normals(); // always release after request // closeHole(mesh, holes[1]); // closeHole(mesh, holes[0]); // closeHole(mesh, holes[2]); /* mesh.request_face_normals(); if (mesh.has_vertex_normals() ) mesh.update_vertex_normals(); for (; v_it!=v_end; ++v_it) this->set_normal(v_it.handle(), calc_vertex_normal(v_it.handle())); */ /* readmesh(mesh, "icosahedron.off"); OpenMesh::Vec3f P(-2,0.2,2); OpenMesh::FaceHandle fh = faceClosestToPoint(mesh,P); cout<<fh.idx(); extendMesh(mesh, fh, P, true); OpenMesh::IO::write_mesh(mesh, "ico--.off"); */ //cout<<"Volume = "<<meshVolume(mesh)<<endl; // OpenMesh::IO::write_mesh(mesh, "spherevolt.off"); OpenMesh::IO::write_mesh(mesh, "lyukasvolt.off"); } // void main()
//----------------------------------------------------------------------- //read mesh from file //----------------------------------------------------------------------- void OMmodel::OpenMeshReadFile(const char * filename) { // request vertex normals, so the mesh reader can use normal information // if available mesh.request_vertex_normals(); // request face normals, mesh.request_face_normals(); //request vertex color mesh.request_vertex_colors(); // assure we have vertex normals if (!mesh.has_vertex_normals()) { std::cerr << "ERROR: Standard vertex property 'Normals' not available!\n"; } OpenMesh::IO::Options opt; // read mesh from file if (!OpenMesh::IO::read_mesh(mesh, filename, opt)) { std::cerr << "Error: Cannot read mesh from " << filename << std::endl; } // If the file did not provide vertex normals, then calculate them if (!opt.check(OpenMesh::IO::Options::VertexNormal)) { // let the mesh update the normals mesh.update_normals(); } // this vertex property stores the computed mean curvature OpenMesh::VPropHandleT<double> HCurvature; mesh.add_property(HCurvature); //store valence OpenMesh::VPropHandleT<int> valence; mesh.add_property(valence); //store gaussian curvature OpenMesh::VPropHandleT<double> GCurvature; mesh.add_property(GCurvature); //caculate curvature and valence vector<MyMesh::Point> oneRing; float maxCur = 0; float minCur = 0; float maxGCur = 0; float minGCur = 0; int val = 0; for (MyMesh::VertexIter v_it = mesh.vertices_begin(); v_it != mesh.vertices_end(); ++v_it) { oneRing.clear(); for (MyMesh::VertexVertexIter vv_it = mesh.vv_iter(*v_it); vv_it.is_valid(); ++vv_it) { ++val; oneRing.push_back(mesh.point(*vv_it)); } OpenMesh::Vec3f H = OpenMesh::Vec3f(0.0f, 0.0f, 0.0f); float A = 0; float Gcurvature = 0; float Hcurvature = 0; float theta = 0; float alpha = 0; float beta = 0; float arccosAlpha = 0; float arccosBeta = 0; float arccosTheta = 0; float cotAlpha = 0; float cotBeta = 0; for (int i = 0; i < val; ++i) { OpenMesh::Vec3f Vvtovi, Vvtovi1, Vvi_1tovi, Vvi_1tov, Vvi1tovi, Vvi1tov, Vvitovi1; MyMesh::Point PositionV = mesh.point(*v_it); Vvtovi = oneRing[i] - PositionV; OpenMesh::Vec3f nVvtovi = Vvtovi.normalized(); if (i == 0) { Vvi_1tovi = oneRing[0] - oneRing[val - 1]; Vvi_1tov = PositionV - oneRing[val - 1]; Vvi_1tovi.normalize(); Vvi_1tov.normalize(); } else { Vvi_1tovi = oneRing[i] - oneRing[i - 1]; Vvi_1tov = PositionV - oneRing[i - 1]; Vvi_1tovi.normalize(); Vvi_1tov.normalize(); } if (i == val - 1) { Vvtovi1 = oneRing[0] - PositionV; Vvi1tovi = oneRing[i] - oneRing[0]; Vvi1tov = PositionV - oneRing[0]; Vvtovi1.normalize(); Vvi1tovi.normalize(); Vvi1tov.normalize(); } else { Vvtovi1 = oneRing[i + 1] - PositionV; Vvi1tovi = oneRing[i] - oneRing[i + 1]; Vvi1tov = PositionV - oneRing[i + 1]; Vvtovi1.normalize(); Vvi1tovi.normalize(); Vvi1tov.normalize(); } alpha = dot(Vvi_1tovi, Vvi_1tov); beta = dot(Vvi1tov, Vvi1tovi); arccosAlpha = acos(alpha); arccosBeta = acos(beta); cotAlpha = cot(arccosAlpha); cotBeta = cot(arccosBeta); A += ((cotAlpha + cotBeta) * Vvtovi.sqrnorm()); H += ((cotAlpha + cotBeta) * Vvtovi); //theta += Acos(Vvtovi, Vvtovi1, Vvi1tovi); theta = dot(nVvtovi, Vvtovi1); //debug2 << nVvtovi.sqrnorm()<<" "<<acos(theta) << endl; arccosTheta += acos(theta); } //debug << arccosTheta << " " << H << " " << A << endl;; A = A / 8.0f; H = 2.0f * (H / A); Hcurvature = 0.5f * H.norm(); Gcurvature = ((2.0f * M_PI) - arccosTheta)/ A; maxCur = max(Hcurvature, maxCur); minCur = min(Hcurvature, minCur); if (Gcurvature < 1000000) maxGCur = max(Gcurvature, maxGCur); minGCur = min(Gcurvature, minGCur); mesh.property(valence, *v_it) = val; mesh.property(HCurvature, *v_it) = Hcurvature; mesh.property(GCurvature, *v_it) = Gcurvature; //debug << val << " " << Hcurvature << " " << Gcurvature << endl; val = 0; } //std::cout << 2.0f * M_PI << endl; //std::cout << maxCur << " " << minCur <<endl; //std::cout << maxGCur << " " << minGCur << endl; for (MyMesh::FaceIter f_it = mesh.faces_begin(); f_it != mesh.faces_end(); ++f_it) { for (MyMesh::FaceVertexIter fv_it = mesh.fv_iter(*f_it); fv_it.is_valid(); ++fv_it) { int value = mesh.property(valence, *fv_it); if (value <= 4) { meshVertexColorBuffer.push_back(OpenMesh::Vec3f(0.0f, 0.0f, 1.0f)); } if (value >= 5 && value <= 7) { meshVertexColorBuffer.push_back(OpenMesh::Vec3f(0.0f, 1.0f, 0.0f)); } if (value >= 8) { meshVertexColorBuffer.push_back(OpenMesh::Vec3f(1.0f, 0.0f, 0.0f)); } //cout << mesh.property(curvature, *fv_it) << endl; meshCurColorBuffer.push_back(interporlationColor(maxCur, minCur, mesh.property(HCurvature, *fv_it), 1)); meshGCurColorBuffer.push_back(interporlationColor(maxGCur, minGCur, mesh.property(GCurvature, *fv_it), 10)); meshVertexBuffer.push_back(mesh.point(*fv_it)); meshVertexNormalBuffer.push_back(mesh.normal(*fv_it)); meshFaceNormalBuffer.push_back(mesh.normal(*f_it)); } } // don't need the normals anymore? Remove them! mesh.release_vertex_normals(); // dispose the face normals, as we don't need them anymore mesh.release_face_normals(); //release color mesh.release_vertex_colors(); mesh.request_vertex_status(); meshVetexNum = mesh.n_vertices(); mesh.request_face_status(); meshFaceNum = mesh.n_faces(); mesh.request_halfedge_status(); meshHalfEdgeNum = mesh.n_halfedges(); // iterate over all halfedges for (MyMesh::HalfedgeIter h_it = mesh.halfedges_begin(); h_it != mesh.halfedges_end(); ++h_it) { if (!mesh.face_handle(*h_it).is_valid()) { ++meshBoundryEdgeNum; } } mesh.release_face_status(); mesh.release_vertex_status(); mesh.release_halfedge_status(); }