// from http://www.geometry.caltech.edu/pubs/DMSB_III.pdf public static double VoronoiArea(DMesh3 mesh, int v_i) { double areaSum = 0; Vector3d Vi = mesh.GetVertex(v_i); foreach (int tid in mesh.VtxTrianglesItr(v_i)) { Index3i t = mesh.GetTriangle(tid); int ti = (t[0] == v_i) ? 0 : ((t[1] == v_i) ? 1 : 2); Vector3d Vj = mesh.GetVertex(t[(ti + 1) % 3]); Vector3d Vk = mesh.GetVertex(t[(ti + 2) % 3]); if (MathUtil.IsObtuse(Vi, Vj, Vk)) { Vector3d Vij = Vj - Vi; Vector3d Vik = Vk - Vi; Vij.Normalize(); Vik.Normalize(); double areaT = 0.5 * Vij.Cross(Vik).Length; if (Vector3d.AngleR(Vij, Vik) > MathUtil.HalfPI) { areaSum += (areaT * 0.5); // obtuse at v_i } else { areaSum += (areaT * 0.25); // not obtuse } } else { // voronoi area Vector3d Vji = Vi - Vj; double dist_ji = Vji.Normalize(); Vector3d Vki = Vi - Vk; double dist_ki = Vki.Normalize(); Vector3d Vkj = (Vj - Vk).Normalized; double cot_alpha_ij = MathUtil.VectorCot(Vki, Vkj); double cot_alpha_ik = MathUtil.VectorCot(Vji, -Vkj); areaSum += dist_ji * dist_ji * cot_alpha_ij * 0.125; areaSum += dist_ki * dist_ki * cot_alpha_ik * 0.125; } } return(areaSum); }