void operator() (const TriMesh *themesh, int v0, Vec<4> &d, float w, int v) const { Vec<4> ndcurv; proj_dcurv(themesh->pdir1[v], themesh->pdir2[v], themesh->dcurv[v], themesh->pdir1[v0], themesh->pdir2[v0], ndcurv); d += w * ndcurv; }
// 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]; } }