public PrincipalCurvature ComputePrincipalCurvature(TriMesh.Vertex v) { Vector3D sum = Vector3D.Zero; Vector3D mid = v.Traits.Position; foreach (var hf in v.HalfEdges) { Vector3D buttom = hf.ToVertex.Traits.Position; Vector3D left = hf.Opposite.Next.ToVertex.Traits.Position; Vector3D right = hf.Next.ToVertex.Traits.Position; double cota = (mid - left).Dot(buttom - left) / (mid - left).Cross(buttom - left).Length(); double cotb = (mid - right).Dot(buttom - right) / (mid - right).Cross(buttom - right).Length(); sum += (cota + cotb) * (this.Normal[v.Index] - this.Normal[hf.ToVertex.Index]); } double mixedArea = TriMeshUtil.ComputeAreaMixed(v); Vector3D laplace = sum / mixedArea / 2d; double square = -laplace.Dot(this.Normal[v.Index]); double k = this.K[v.Index].Length(); double delta = -k * k + 2d * square; if (delta < 0d) { delta = 0d; } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = (k + Math.Pow(delta, 0.5)) / 2d; pc.min = (k - Math.Pow(delta, 0.5)) / 2d; return(pc); }
public static void SetUpCurvature(TriMesh mesh, PrincipalCurvature[] PrincipalCurv) { foreach (var v in mesh.Vertices) { PrincipalCurvature pc = PrincipalCurv[v.Index]; v.Traits.MaxCurvature = pc.max; v.Traits.MaxCurvatureDirection = pc.maxDir; v.Traits.MinCurvature = pc.min; v.Traits.MinCurvatureDirection = pc.minDir; v.Traits.MeanCurvature = (pc.max + pc.min) / 2d; v.Traits.GaussianCurvature = pc.max * pc.min; } }
public static void SetUpCurvature(TriMesh mesh, PrincipalCurvature[] PrincipalCurv) { foreach (var v in mesh.Vertices) { PrincipalCurvature pc = PrincipalCurv[v.Index]; v.Traits.MaxCurvature = pc.max; v.Traits.MaxCurvatureDirection = pc.maxDir; v.Traits.MinCurvature = pc.min; v.Traits.MinCurvatureDirection = pc.minDir; v.Traits.MeanCurvature = (pc.max + pc.min) / 2d; v.Traits.GaussianCurvature = pc.max * pc.min; } }
public static PrincipalCurvature[] ComputePricipalCurvature(TriMesh mesh) { double[] mean = ComputeMeanCurvature(mesh); double[] gauss = ComputeGaussianCurvatureIntegrated(mesh); int n = mesh.Vertices.Count; PrincipalCurvature[] pricipal = new PrincipalCurvature[n]; for (int i = 0; i < n; i++) { pricipal[i] = ComputePricipalCurvature(mean[i], gauss[i]); } return(pricipal); }
/// <summary> /// A class containing static methods for computing curvature on a mesh. /// </summary> public static PrincipalCurvature DiagonalizeCurvature(UV src, KUV srcK, Vector3D dstNormal) { UV rotated = Transform.RotateCoordinateSystem(src, dstNormal); double c = 1.0; double s = 0.0; double t = 0.0; // Jacobi rotation to diagonalize if (srcK.UV != 0.0f) { double h = 0.5f * (srcK.V - srcK.U) / srcK.UV; if (h < 0.0f) { t = 1.0f / (h - Math.Sqrt(1.0f + h * h)); } else { t = 1.0f / (h + Math.Sqrt(1.0f + h * h)); } c = 1.0f / Math.Sqrt(1.0f + t * t); s = t * c; } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = srcK.U - t * srcK.UV; pc.min = srcK.V + t * srcK.UV; if (Math.Abs(pc.max) >= Math.Abs(pc.min)) { pc.maxDir = c * rotated.U - s * rotated.V; } else { double temp = pc.min; pc.min = pc.max; pc.max = temp; pc.maxDir = s * rotated.U + c * rotated.V; } pc.minDir = dstNormal.Cross(pc.maxDir); return(pc); }
public static PrincipalCurvature[] ComputeCurvature() { PrincipalCurvature[] pc = new PrincipalCurvature[nv]; float[] buff = new float[nv * 8]; int n = GetCurv(buff); for (int i = 0; i < nv; i++) { pc[i] = new PrincipalCurvature { max = buff[i * 8], min = buff[i * 8 + 1], maxDir = new Vector3D(buff[i * 8 + 2], buff[i * 8 + 3], buff[i * 8 + 4]), minDir = new Vector3D(buff[i * 8 + 5], buff[i * 8 + 6], buff[i * 8 + 7]) }; } return(pc); }
public static PrincipalCurvature ComputePricipalCurvature(double mean, double gauss) { double rightTemp = mean * mean - gauss; double rightPart; if (rightTemp <= 0) { rightPart = 0; } else { rightPart = Math.Sqrt(rightTemp); } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = mean + rightPart; pc.min = mean - rightPart; return(pc); }
public static PrincipalCurvature[] ComputePricipalCurvature(TriMesh mesh) { double[] mean = ComputeMeanCurvature(mesh); double[] gauss = ComputeGaussianCurvatureIntegrated(mesh); int n = mesh.Vertices.Count; PrincipalCurvature[] pricipal = new PrincipalCurvature[n]; for (int i = 0; i < n; i++) { pricipal[i] = ComputePricipalCurvature(mean[i], gauss[i]); } return pricipal; }
public static PrincipalCurvature ComputePricipalCurvature(double mean, double gauss) { double rightTemp = mean * mean - gauss; double rightPart; if (rightTemp <= 0) { rightPart = 0; } else { rightPart = Math.Sqrt(rightTemp); } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = mean + rightPart; pc.min = mean - rightPart; return pc; }
public PrincipalCurvature ComputePrincipalCurvature(TriMesh.Vertex v) { Vector3D sum = Vector3D.Zero; Vector3D mid = v.Traits.Position; foreach (var hf in v.HalfEdges) { Vector3D buttom = hf.ToVertex.Traits.Position; Vector3D left = hf.Opposite.Next.ToVertex.Traits.Position; Vector3D right = hf.Next.ToVertex.Traits.Position; double cota = (mid - left).Dot(buttom - left) / (mid - left).Cross(buttom - left).Length(); double cotb = (mid - right).Dot(buttom - right) / (mid - right).Cross(buttom - right).Length(); sum += (cota + cotb) * (this.Normal[v.Index] - this.Normal[hf.ToVertex.Index]); } double mixedArea = TriMeshUtil.ComputeAreaMixed(v); Vector3D laplace = sum / mixedArea / 2d; double square = -laplace.Dot(this.Normal[v.Index]); double k = this.K[v.Index].Length(); double delta = -k * k + 2d * square; if (delta < 0d) { delta = 0d; } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = (k + Math.Pow(delta, 0.5)) / 2d; pc.min = (k - Math.Pow(delta, 0.5)) / 2d; return pc; }
public static PrincipalCurvature[] ComputeCurvature() { PrincipalCurvature[] pc = new PrincipalCurvature[nv]; float[] buff = new float[nv * 8]; int n = GetCurv(buff); for (int i = 0; i < nv; i++) { pc[i] = new PrincipalCurvature { max = buff[i * 8], min = buff[i * 8 + 1], maxDir = new Vector3D(buff[i * 8 + 2], buff[i * 8 + 3], buff[i * 8 + 4]), minDir = new Vector3D(buff[i * 8 + 5], buff[i * 8 + 6], buff[i * 8 + 7]) }; } return pc; }
public static PrincipalCurvature[] ComputePrincipleCurvatures(TriMesh mesh, double[] CornerArea, double[] PointArea) { Vector3D[] vertexNormal = TriMeshUtil.ComputeNormalVertex(mesh); // Add dynamic trait for principle curvature computation double[] curv = new double[mesh.Vertices.Count]; PrincipalCurvature[] pc = new PrincipalCurvature[mesh.Vertices.Count]; // Initialize a coordinate system for each vertex foreach (TriMesh.Vertex v in mesh.Vertices) { pc[v.Index] = new PrincipalCurvature(); // Vector that points from this vertex to an adjacent one pc[v.Index].maxDir = (v.HalfEdge.ToVertex.Traits.Position - v.Traits.Position).Cross(vertexNormal[v.Index]).Normalize(); // Get a vector orthogonal to this vector and the vertex normal pc[v.Index].minDir = vertexNormal[v.Index].Cross(pc[v.Index].maxDir); } TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3]; TriMesh.Vertex[] fv = new TriMesh.Vertex[3]; Vector3D[] e = new Vector3D[3]; Vector3D t, b, dn, faceNormal; // Compute curvature for each face foreach (TriMesh.Face f in mesh.Faces) { // Get halfedges for this face fh[0] = f.HalfEdge; fh[1] = fh[0].Next; fh[2] = fh[1].Next; // Get vertices for this face fv[0] = fh[0].ToVertex; fv[1] = fh[1].ToVertex; fv[2] = fh[2].ToVertex; // Edge vectors e[0] = fv[2].Traits.Position - fv[1].Traits.Position; e[1] = fv[0].Traits.Position - fv[2].Traits.Position; e[2] = fv[1].Traits.Position - fv[0].Traits.Position; t = e[0]; t.Normalize(); faceNormal = e[0].Cross(e[1]); faceNormal.Normalize(); b = faceNormal.Cross(t); b.Normalize(); // Estimate curvature by variation of normals along edges double[] m = new double[3]; double[,] w = new double[3, 3]; for (int i = 0; i < 3; ++i) { double u = e[i].Dot(t); double v = e[i].Dot(b); w[0, 0] += u * u; w[0, 1] += u * v; w[2, 2] += v * v; dn = vertexNormal[fv[(i + 2) % 3].Index] - vertexNormal[fv[(i + 1) % 3].Index]; double dnu = dn.Dot(t); double dnv = dn.Dot(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 = new double[3]; if (Transform.LdlTransposeDecomp(w, diag)) { Transform.LdlTransposeSolveInPlace(w, diag, m); // Adjust curvature for vertices of this face for (int i = 0; i < 3; ++i) { UV tb = new UV { U = t, V = b }; KUV mk = new KUV { U = m[0], UV = m[1], V = m[2] }; UV dst = new UV { U = pc[fv[i].Index].maxDir, V = pc[fv[i].Index].minDir }; KUV c = Transform.ProjectCurvature(tb, mk, dst); double weight = CornerArea[fh[i].Index] / PointArea[fv[i].Index]; pc[fv[i].Index].max += weight * c.U; curv[fv[i].Index] += weight * c.UV; pc[fv[i].Index].min += weight * c.V; } } } // Compute curvature for each vertex foreach (TriMesh.Vertex v in mesh.Vertices) { UV src = new UV { U = pc[v.Index].maxDir, V = pc[v.Index].minDir }; KUV srcK = new KUV { U = pc[v.Index].max, UV = curv[v.Index], V = pc[v.Index].min }; pc[v.Index] = Transform.DiagonalizeCurvature(src, srcK, vertexNormal[v.Index]); } return pc; }
/// <summary> /// A class containing static methods for computing curvature on a mesh. /// </summary> public static PrincipalCurvature DiagonalizeCurvature(UV src, KUV srcK, Vector3D dstNormal) { UV rotated = Transform.RotateCoordinateSystem(src, dstNormal); double c = 1.0; double s = 0.0; double t = 0.0; // Jacobi rotation to diagonalize if (srcK.UV != 0.0f) { double h = 0.5f * (srcK.V - srcK.U) / srcK.UV; if (h < 0.0f) { t = 1.0f / (h - Math.Sqrt(1.0f + h * h)); } else { t = 1.0f / (h + Math.Sqrt(1.0f + h * h)); } c = 1.0f / Math.Sqrt(1.0f + t * t); s = t * c; } PrincipalCurvature pc = new PrincipalCurvature(); pc.max = srcK.U - t * srcK.UV; pc.min = srcK.V + t * srcK.UV; if (Math.Abs(pc.max) >= Math.Abs(pc.min)) { pc.maxDir = c * rotated.U - s * rotated.V; } else { double temp = pc.min; pc.min = pc.max; pc.max = temp; pc.maxDir = s * rotated.U + c * rotated.V; } pc.minDir = dstNormal.Cross(pc.maxDir); return pc; }
public static PrincipalCurvature[] ComputePrincipleCurvatures(TriMesh mesh, double[] CornerArea, double[] PointArea) { Vector3D[] vertexNormal = TriMeshUtil.ComputeNormalVertex(mesh); // Add dynamic trait for principle curvature computation double[] curv = new double[mesh.Vertices.Count]; PrincipalCurvature[] pc = new PrincipalCurvature[mesh.Vertices.Count]; // Initialize a coordinate system for each vertex foreach (TriMesh.Vertex v in mesh.Vertices) { pc[v.Index] = new PrincipalCurvature(); // Vector that points from this vertex to an adjacent one pc[v.Index].maxDir = (v.HalfEdge.ToVertex.Traits.Position - v.Traits.Position).Cross(vertexNormal[v.Index]).Normalize(); // Get a vector orthogonal to this vector and the vertex normal pc[v.Index].minDir = vertexNormal[v.Index].Cross(pc[v.Index].maxDir); } TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3]; TriMesh.Vertex[] fv = new TriMesh.Vertex[3]; Vector3D[] e = new Vector3D[3]; Vector3D t, b, dn, faceNormal; // Compute curvature for each face foreach (TriMesh.Face f in mesh.Faces) { // Get halfedges for this face fh[0] = f.HalfEdge; fh[1] = fh[0].Next; fh[2] = fh[1].Next; // Get vertices for this face fv[0] = fh[0].ToVertex; fv[1] = fh[1].ToVertex; fv[2] = fh[2].ToVertex; // Edge vectors e[0] = fv[2].Traits.Position - fv[1].Traits.Position; e[1] = fv[0].Traits.Position - fv[2].Traits.Position; e[2] = fv[1].Traits.Position - fv[0].Traits.Position; t = e[0]; t.Normalize(); faceNormal = e[0].Cross(e[1]); faceNormal.Normalize(); b = faceNormal.Cross(t); b.Normalize(); // Estimate curvature by variation of normals along edges double[] m = new double[3]; double[,] w = new double[3, 3]; for (int i = 0; i < 3; ++i) { double u = e[i].Dot(t); double v = e[i].Dot(b); w[0, 0] += u * u; w[0, 1] += u * v; w[2, 2] += v * v; dn = vertexNormal[fv[(i + 2) % 3].Index] - vertexNormal[fv[(i + 1) % 3].Index]; double dnu = dn.Dot(t); double dnv = dn.Dot(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 = new double[3]; if (Transform.LdlTransposeDecomp(w, diag)) { Transform.LdlTransposeSolveInPlace(w, diag, m); // Adjust curvature for vertices of this face for (int i = 0; i < 3; ++i) { UV tb = new UV { U = t, V = b }; KUV mk = new KUV { U = m[0], UV = m[1], V = m[2] }; UV dst = new UV { U = pc[fv[i].Index].maxDir, V = pc[fv[i].Index].minDir }; KUV c = Transform.ProjectCurvature(tb, mk, dst); double weight = CornerArea[fh[i].Index] / PointArea[fv[i].Index]; pc[fv[i].Index].max += weight * c.U; curv[fv[i].Index] += weight * c.UV; pc[fv[i].Index].min += weight * c.V; } } } // Compute curvature for each vertex foreach (TriMesh.Vertex v in mesh.Vertices) { UV src = new UV { U = pc[v.Index].maxDir, V = pc[v.Index].minDir }; KUV srcK = new KUV { U = pc[v.Index].max, UV = curv[v.Index], V = pc[v.Index].min }; pc[v.Index] = Transform.DiagonalizeCurvature(src, srcK, vertexNormal[v.Index]); } return(pc); }
public static Vector4D[] ComputeDCruv(TriMesh mesh, double[] CornerArea, double[] PointArea) { PrincipalCurvature[] PrincipalCurv = ComputePrincipleCurvatures(mesh, CornerArea, PointArea); Vector4D[] dcurv = new Vector4D[mesh.Vertices.Count]; TriMesh.HalfEdge[] fh = new TriMesh.HalfEdge[3]; TriMesh.Vertex[] fv = new TriMesh.Vertex[3]; Vector3D[] e = new Vector3D[3]; Vector3D t, b, faceNormal; // Compute curvature for each face foreach (TriMesh.Face f in mesh.Faces) { // Get halfedges for this face fh[0] = f.HalfEdge; fh[1] = fh[0].Next; fh[2] = fh[1].Next; // Get vertices for this face fv[0] = fh[0].ToVertex; fv[1] = fh[1].ToVertex; fv[2] = fh[2].ToVertex; // Edge vectors e[0] = fv[2].Traits.Position - fv[1].Traits.Position; e[1] = fv[0].Traits.Position - fv[2].Traits.Position; e[2] = fv[1].Traits.Position - fv[0].Traits.Position; t = e[0]; t.Normalize(); faceNormal = e[0].Cross(e[1]); b = faceNormal.Cross(t); b.Normalize(); KUV[] fcurv = new KUV[3]; for (int i = 0; i < 3; i++) { PrincipalCurvature pc = PrincipalCurv[fv[i].Index]; UV src = new UV { U = pc.maxDir, V = pc.minDir }; KUV mk = new KUV { U = pc.max, UV = 0, V = pc.min }; UV tb = new UV { U = t, V = b }; fcurv[i] = Transform.ProjectCurvature(src, mk, tb); } double[] m = new double[4]; double[,] w = new double[4, 4]; for (int i = 0; i < 3; i++) { KUV prev = fcurv[(i + 2) % 3]; KUV next = fcurv[(i + 1) % 3]; KUV dfcurv = new KUV { U = prev.U - next.U, UV = prev.UV - next.UV, V = prev.V - next.V }; double u = e[i].Dot(t); double v = e[i].Dot(b); w[0, 0] += u * u; w[0, 1] += u * v; w[3, 3] += v * v; m[0] += u * dfcurv.U; m[1] += v * dfcurv.U + 2d * u * dfcurv.UV; m[2] += 2d * v * dfcurv.UV + u * dfcurv.V; m[3] += v * dfcurv.V; } w[1, 1] = 2d * w[0, 0] + w[3, 3]; w[1, 2] = 2d * w[0, 1]; w[2, 2] = w[0, 0] + 2d * w[3, 3]; w[2, 3] = w[0, 1]; double[] diag = new double[4]; if (Transform.LdlTransposeDecomp(w, diag)) { Transform.LdlTransposeSolveInPlace(w, diag, m); Vector4D d = new Vector4D(m); // Adjust curvature for vertices of this face for (int i = 0; i < 3; ++i) { UV tb = new UV { U = t, V = b }; PrincipalCurvature pc = PrincipalCurv[fv[i].Index]; UV dst = new UV { U = pc.maxDir, V = pc.minDir }; Vector4D c = Transform.ProjectDCurvature(tb, d, dst); double weight = CornerArea[fh[i].Index] / PointArea[fv[i].Index]; dcurv[fv[i].Index] += weight * d; } } } return(dcurv); }