// Compute cotan-weighted neighbour sum around a vertex. // These weights are numerically unstable if any of the triangles are degenerate. // We catch these problems and return input vertex as centroid // http://www.geometry.caltech.edu/pubs/DMSB_III.pdf public static Vector3d CotanCentroid(DMesh3 mesh, int v_i) { Vector3d vSum = Vector3d.Zero; double wSum = 0; Vector3d Vi = mesh.GetVertex(v_i); int v_j = DMesh3.InvalidID, opp_v1 = DMesh3.InvalidID, opp_v2 = DMesh3.InvalidID; int t1 = DMesh3.InvalidID, t2 = DMesh3.InvalidID; bool bAborted = false; foreach (int eid in mesh.VtxEdgesItr(v_i)) { opp_v2 = DMesh3.InvalidID; mesh.GetVtxNbrhood(eid, v_i, ref v_j, ref opp_v1, ref opp_v2, ref t1, ref t2); Vector3d Vj = mesh.GetVertex(v_j); Vector3d Vo1 = mesh.GetVertex(opp_v1); double cot_alpha_ij = MathUtil.VectorCot( (Vi - Vo1).Normalized, (Vj - Vo1).Normalized); if (cot_alpha_ij == 0) { bAborted = true; break; } double w_ij = cot_alpha_ij; if (opp_v2 != DMesh3.InvalidID) { Vector3d Vo2 = mesh.GetVertex(opp_v2); double cot_beta_ij = MathUtil.VectorCot( (Vi - Vo2).Normalized, (Vj - Vo2).Normalized); if (cot_beta_ij == 0) { bAborted = true; break; } w_ij += cot_beta_ij; } vSum += w_ij * Vj; wSum += w_ij; } if (bAborted || Math.Abs(wSum) < MathUtil.ZeroTolerance) { return(Vi); } return(vSum / wSum); }
// http://128.148.32.110/courses/cs224/papers/mean_value.pdf public static Vector3d MeanValueCentroid(DMesh3 mesh, int v_i) { Vector3d vSum = Vector3d.Zero; double wSum = 0; Vector3d Vi = mesh.GetVertex(v_i); int v_j = DMesh3.InvalidID, opp_v1 = DMesh3.InvalidID, opp_v2 = DMesh3.InvalidID; int t1 = DMesh3.InvalidID, t2 = DMesh3.InvalidID; foreach (int eid in mesh.VtxEdgesItr(v_i)) { opp_v2 = DMesh3.InvalidID; mesh.GetVtxNbrhood(eid, v_i, ref v_j, ref opp_v1, ref opp_v2, ref t1, ref t2); Vector3d Vj = mesh.GetVertex(v_j); Vector3d vVj = (Vj - Vi); double len_vVj = vVj.Normalize(); // [RMS] is this the right thing to do? if vertices are coincident, // weight of this vertex should be very high! if (len_vVj < MathUtil.ZeroTolerance) { continue; } Vector3d vVdelta = (mesh.GetVertex(opp_v1) - Vi).Normalized; double w_ij = VectorTanHalfAngle(vVj, vVdelta); if (opp_v2 != DMesh3.InvalidID) { Vector3d vVgamma = (mesh.GetVertex(opp_v2) - Vi).Normalized; w_ij += VectorTanHalfAngle(vVj, vVgamma); } w_ij /= len_vVj; vSum += w_ij * Vj; wSum += w_ij; } if (wSum < MathUtil.ZeroTolerance) { return(Vi); } return(vSum / wSum); }