void operator() (const TriMesh *themesh, int v0, vec &c, float w, int v) const { vec ncurv; proj_curv(themesh->pdir1[v], themesh->pdir2[v], themesh->curv1[v], 0, themesh->curv2[v], themesh->pdir1[v0], themesh->pdir2[v0], ncurv[0], ncurv[1], ncurv[2]); c += w * ncurv; }
void Curvature::computePrincipalCurvatures( Surface_mesh * src_mesh ) { computePointAreas(src_mesh); uint nv = src_mesh->n_vertices(), nf = src_mesh->n_faces(); curv1.resize(nv); curv2.resize(nv); pdir1.resize(nv); pdir2.resize(nv); std::vector<double> curv12(nv); Surface_mesh::Vertex_property<Point> points = src_mesh->vertex_property<Point>("v:point"); Surface_mesh::Vertex_property<Normal> normals = src_mesh->vertex_property<Normal>("v:normal"); Surface_mesh::Face_iterator fit, fend = src_mesh->faces_end(); Surface_mesh::Vertex_around_face_circulator fvit, fvend; Surface_mesh::Vertex_iterator vit, vend = src_mesh->vertices_end(); //#pragma omp parallel for for (fit = src_mesh->faces_begin(); fit != fend; ++fit) { fvit = src_mesh->vertices(fit); uint vi0 = ((Vertex)fvit).idx(); Point v0 = points[fvit]; ++fvit; uint vi1 = ((Vertex)fvit).idx(); Point v1 = points[fvit]; ++fvit; uint vi2 = ((Vertex)fvit).idx(); Point v2 = points[fvit]; pdir1[vi0] = v1 - v0; pdir1[vi1] = v2 - v1; pdir1[vi2] = v0 - v2; } //#pragma omp parallel for for (vit = src_mesh->vertices_begin(); vit != vend; ++vit) { uint vi = ((Vertex)vit).idx(); pdir1[vi] = cross(pdir1[vi], normals[vit]); pdir1[vi].normalize(); pdir2[vi] = cross(normals[vit], pdir1[vi]); } // Compute curvature per-face //#pragma omp parallel for for (fit = src_mesh->faces_begin(); fit != fend; ++fit) { uint i = ((Surface_mesh::Face)fit).idx(); // face index uint vi[3]; Normal vn[3]; fvit = src_mesh->vertices(fit); vi[0] = ((Vertex)fvit).idx(); Point v0 = points[fvit]; vn[0] = normals[fvit]; ++fvit; vi[1] = ((Vertex)fvit).idx(); Point v1 = points[fvit]; vn[1] = normals[fvit]; ++fvit; vi[2] = ((Vertex)fvit).idx(); Point v2 = points[fvit]; vn[2] = normals[fvit]; ++fvit; // Edges Point e[3] = {v2 - v1, v0 - v2, v1 - v0}; // N-T-B coordinate system per face Point t = e[0]; t.normalize(); Point n = cross(e[0], e[1]); Point b = cross(n, t); b.normalize(); // Estimate curvature based on variation of normals // along edges double m[3] = { 0, 0, 0 }; double w[3][3] = { {0,0,0}, {0,0,0}, {0,0,0} }; for (int j = 0; j < 3; j++) { double u = dot(e[j], t); double v = dot(e[j], b); w[0][0] += u*u; w[0][1] += u*v; //w[1][1] += v*v + u*u; //w[1][2] += u*v; w[2][2] += v*v; Point dn = vn[PREV_Index(j)] - vn[NEXT_Index(j)]; double dnu = dot(dn, t); double dnv = dot(dn, b); m[0] += dnu*u; m[1] += dnu*v + dnv*u; m[2] += dnv*v; } w[1][1] = w[0][0] + w[2][2]; w[1][2] = w[0][1]; // Least squares solution double diag[3]; if (!ldltdc<double,3>(w, diag)) { //printf("ldltdc failed!\n"); continue; } ldltsl<double,3>(w, diag, m, m); // Push it back out to the vertices for (uint j = 0; j < 3; j++) { int vj = vi[j]; double c1, c12, c2; proj_curv(t, b, m[0], m[1], m[2], pdir1[vj], pdir2[vj], c1, c12, c2); double wt = cornerareas[i][j] / pointareas[vj]; //#pragma omp atomic curv1[vj] += wt * c1; //#pragma omp atomic curv12[vj] += wt * c12; //#pragma omp atomic curv2[vj] += wt * c2; } } // Store results into Surface_mesh object Surface_mesh::Vertex_property<double> my_curv1 = src_mesh->vertex_property<double>("v:curv1"); Surface_mesh::Vertex_property<double> my_curv2 = src_mesh->vertex_property<double>("v:vurv2"); Surface_mesh::Vertex_property<Vec3d> my_pdir1 = src_mesh->vertex_property<Vec3d>("v:pdir1"); Surface_mesh::Vertex_property<Vec3d> my_pdir2 = src_mesh->vertex_property<Vec3d>("v:pdir2"); // Compute principal directions and curvatures at each vertex //#pragma omp parallel for for (vit = src_mesh->vertices_begin(); vit != vend; ++vit) { uint i = ((Surface_mesh::Vertex)vit).idx(); diagonalize_curv(pdir1[i], pdir2[i],curv1[i], curv12[i], curv2[i], normals[vit], pdir1[i], pdir2[i],curv1[i], curv2[i]); my_curv1[vit] = curv1[i]; my_curv2[vit] = curv2[i]; my_pdir1[vit] = pdir1[i]; my_pdir2[vit] = pdir2[i]; } }
// Compute derivatives of curvature void Curvature::computeDerivativesCurvatures(Surface_mesh * src_mesh) { // Compute principal curvatures and directions computePrincipalCurvatures(src_mesh); Surface_mesh::Vertex_property<Point> points = src_mesh->vertex_property<Point>("v:point"); Surface_mesh::Vertex_property<Normal> normals = src_mesh->vertex_property<Normal>("v:normal"); Surface_mesh::Face_iterator fit, fend = src_mesh->faces_end(); Surface_mesh::Vertex_around_face_circulator fvit, fvend; // Resize the arrays we'll be using uint nv = src_mesh->n_vertices(), nf = src_mesh->n_faces(); dcurv.resize(nv); // Compute derivatives of curvature per-face //#pragma omp parallel for for (fit = src_mesh->faces_begin(); fit != fend; ++fit) { uint i = ((Surface_mesh::Face)fit).idx(); // face index uint vi[3]; Normal vn[3]; fvit = src_mesh->vertices(fit); vi[0] = ((Vertex)fvit).idx(); Point v0 = points[fvit]; vn[0] = normals[fvit]; ++fvit; vi[1] = ((Vertex)fvit).idx(); Point v1 = points[fvit]; vn[1] = normals[fvit]; ++fvit; vi[2] = ((Vertex)fvit).idx(); Point v2 = points[fvit]; vn[2] = normals[fvit]; ++fvit; // Edges Point e[3] = {v2 - v1, v0 - v2, v1 - v0}; // N-T-B coordinate system per face Point t = e[0]; t.normalize(); Point n = cross(e[0], e[1]); Point b = cross(n, t); b.normalize(); // Project curvature tensor from each vertex into this // face's coordinate system Point fcurv[3]; for (int j = 0; j < 3; j++) { int vj = vi[j]; proj_curv(pdir1[vj], pdir2[vj], curv1[vj], 0, curv2[vj],t, b, fcurv[j][0], fcurv[j][1], fcurv[j][2]); } // Estimate derivatives of curvature based on variation of curvature along edges double m[4] = {0,0,0,0}; double w[4][4] = { {0,0,0,0}, {0,0,0,0}, {0,0,0,0}, {0,0,0,0} }; for (int j = 0; j < 3; j++) { // Variation of curvature along each edge Point dfcurv = fcurv[PREV_Index(j)] - fcurv[NEXT_Index(j)]; double u = dot(e[j], t); double v = dot(e[j], b); double u2 = u*u, v2 = v*v, uv = u*v; w[0][0] += u2; w[0][1] += uv; //w[1][1] += 2.0f*u2 + v2; //w[1][2] += 2.0f*uv; //w[2][2] += u2 + 2.0f*v2; //w[2][3] += uv; w[3][3] += v2; m[0] += u*dfcurv[0]; m[1] += v*dfcurv[0] + 2.0f*u*dfcurv[1]; m[2] += 2.0f*v*dfcurv[1] + u*dfcurv[2]; m[3] += v*dfcurv[2]; } w[1][1] = 2.0f * w[0][0] + w[3][3]; w[1][2] = 2.0f * w[0][1]; w[2][2] = w[0][0] + 2.0f * w[3][3]; w[2][3] = w[0][1]; // Least squares solution double d[4]; if (!ldltdc<double,4>(w, d)) { //printf("ldltdc failed!\n"); continue; } ldltsl<double,4>(w, d, m, m); Vec4d face_dcurv(m[0], m[1], m[2], m[3]); // Push it back out to each vertex for (int j = 0; j < 3; j++) { int vj = vi[j]; Vec4d this_vert_dcurv; proj_dcurv(t, b, face_dcurv, pdir1[vj], pdir2[vj], this_vert_dcurv); double wt = cornerareas[i][j] / pointareas[vj]; dcurv[vj] += wt * this_vert_dcurv; } } Surface_mesh::Vertex_property<Vec4d> my_dcurv = src_mesh->vertex_property<Vec4d>("v:dcurv"); Surface_mesh::Vertex_iterator vit, vend = src_mesh->vertices_end(); for (vit = src_mesh->vertices_begin(); vit != vend; ++vit){ uint i = ((Vertex) vit).idx(); my_dcurv[vit] = dcurv[i]; } }