Field<T,VertexHandle> gaussian_curvatures(const TriMesh& mesh) { // Compute mixed areas Field<T,VertexHandle> area(mesh.n_vertices()); // Actually 8*area for (const auto f : mesh.face_handles()) { const auto v = mesh.vertex_handles(f); const TV x0 = mesh.point(v.x), x1 = mesh.point(v.y), x2 = mesh.point(v.z), x01 = x1-x0, x12 = x2-x1, x20 = x0-x2; const T cot0 = cot(x01,x20), cot1 = cot(x01,x12), cot2 = cot(x12,x20); // Compute A_mixed as in Meyer et al. if (cot0<=0 && cot1<=0 && cot2<=0) { // Voronoi case const T area0 = cot0*sqr_magnitude(x12), area1 = cot1*sqr_magnitude(x20), area2 = cot2*sqr_magnitude(x01); area[v.x] -= (area1+area2); area[v.y] -= (area2+area0); area[v.z] -= (area0+area1); } else { // One of the triangles is obtuse const T a = 2*mesh.area(f); area[v.x] += (1+(cot0>0))*a; area[v.y] += (1+(cot1>0))*a; area[v.z] += (1+(cot2>0))*a; } } // Compute curvatures Field<T,VertexHandle> K(mesh.n_vertices(),uninit); for (const auto v : mesh.vertex_handles()) { const TV x = mesh.point(v); T sum = 0; for (auto e=mesh.cvoh_iter(v);e;++e) if (!mesh.is_boundary(e)) { const auto v0 = mesh.to_vertex_handle(e), v1 = mesh.from_vertex_handle(mesh.prev_halfedge_handle(e)); sum += angle_between(mesh.point(v0)-x,mesh.point(v1)-x); } K[v] = 8*((1+!mesh.is_boundary(v))*pi-sum)/area(v); } return K; }
void MeshDenoisingViaL0Minimization::calculateAreaBasedEdgeOperator(TriMesh &mesh, std::vector<TriMesh::Point> &area_based_edge_operator, std::vector< std::vector<TriMesh::VertexHandle> > &edge_vertex_handle, std::vector< std::vector<double> > &coef) { std::vector<double> face_area; getFaceArea(mesh, face_area); area_based_edge_operator.resize((int)mesh.n_edges(), TriMesh::Point(0.0, 0.0, 0.0)); std::vector<double> temp_coef(4, 0.0); coef.resize(mesh.n_edges(), temp_coef); std::vector<TriMesh::VertexHandle> vertex_handle(4); edge_vertex_handle.resize(mesh.n_edges(), vertex_handle); for(TriMesh::EdgeIter e_it = mesh.edges_begin(); e_it != mesh.edges_end(); e_it++) { if(!mesh.is_boundary(*e_it)) { int index = e_it->idx(); double edge_length = mesh.calc_edge_length(*e_it); // get four vertices correspond to edge *e_it TriMesh::HalfedgeHandle he = mesh.halfedge_handle(*e_it, 0); TriMesh::VertexHandle v1 = mesh.from_vertex_handle(he); TriMesh::VertexHandle v3 = mesh.to_vertex_handle(he); TriMesh::HalfedgeHandle he_next = mesh.next_halfedge_handle(he); TriMesh::VertexHandle v4 = mesh.to_vertex_handle(he_next); TriMesh::HalfedgeHandle he_oppo = mesh.opposite_halfedge_handle(he); TriMesh::HalfedgeHandle he_oppo_next = mesh.next_halfedge_handle(he_oppo); TriMesh::VertexHandle v2 = mesh.to_vertex_handle(he_oppo_next); // two faces TriMesh::FaceHandle f1 = mesh.face_handle(he); TriMesh::FaceHandle f2 = mesh.face_handle(he_oppo); // the area of two faces correspond to edge *e_it double area134 = face_area[f1.idx()]; double area123 = face_area[f2.idx()]; double totalArea = area123 + area134; TriMesh::Point p1 = mesh.point(v1); TriMesh::Point p2 = mesh.point(v2); TriMesh::Point p3 = mesh.point(v3); TriMesh::Point p4 = mesh.point(v4); TriMesh::Point p12 = p1 - p2; TriMesh::Point p13 = p1 - p3; TriMesh::Point p14 = p1 - p4; TriMesh::Point p23 = p2 - p3; TriMesh::Point p34 = p3 - p4; // calc coefficient temp_coef[0] = (area123 * (p34 | p13) - area134 * (p13 | p23)) / (edge_length * edge_length * totalArea); temp_coef[1] = area134 / totalArea; temp_coef[2] = (-area123 * (p13 | p14) - area134 * (p12 | p13)) / (edge_length * edge_length * totalArea); temp_coef[3] = area123 / totalArea; coef[index] = temp_coef; vertex_handle[0] = v1; vertex_handle[1] = v2; vertex_handle[2] = v3; vertex_handle[3] = v4; edge_vertex_handle[index] = vertex_handle; // calc area-based edge operator TriMesh::Point pt = p1 * temp_coef[0] + p2 * temp_coef[1] + p3 * temp_coef[2] + p4 * temp_coef[3]; area_based_edge_operator[index] = pt; } } }