public SparseMatrix BuildLaplaceGraphNomalized(TriMesh mesh) { SparseMatrix m = new SparseMatrix(mesh.Vertices.Count, mesh.Vertices.Count); foreach (TriMesh.Vertex vertex in mesh.Vertices) { foreach (TriMesh.Vertex neigh in vertex.Vertices) { double result = -1d / Math.Sqrt(vertex.VertexCount * neigh.VertexCount); m.AddValueTo(vertex.Index, neigh.Index, result); } m.AddValueTo(vertex.Index, vertex.Index, 1); } m.SortElement(); return m; }
public SparseMatrix BuildLaplaceTutte(TriMesh mesh) { SparseMatrix m = new SparseMatrix(mesh.Vertices.Count, mesh.Vertices.Count); foreach (TriMesh.Vertex vertex in mesh.Vertices) { foreach (TriMesh.Vertex neigh in vertex.Vertices) { double result = -1d / vertex.VertexCount; m.AddElementIfNotExist(vertex.Index, neigh.Index, result); } m.AddValueTo(vertex.Index, vertex.Index, 1); } m.SortElement(); return m; }
public static SparseMatrix BuildMatrixDualL(ref NonManifoldMesh mesh) { // build dual Laplacian weight matrix L int vn = mesh.VertexCount; int fn = mesh.FaceCount; SparseMatrix L = new SparseMatrix(fn, vn, 6); for (int i = 0; i < fn; i++) { int f1 = mesh.AdjFF[i][0]; int f2 = mesh.AdjFF[i][1]; int f3 = mesh.AdjFF[i][2]; Vector3D dv = mesh.GetDualPosition(i); Vector3D dv1 = mesh.GetDualPosition(f1); Vector3D dv2 = mesh.GetDualPosition(f2); Vector3D dv3 = mesh.GetDualPosition(f3); Vector3D u = dv - dv3; Vector3D v1 = dv1 - dv3; Vector3D v2 = dv2 - dv3; Vector3D normal = (v1.Cross(v2)).Normalize(); Matrix3D M = new Matrix3D(v1, v2, normal); Vector3D coord = M.Inverse() * u; double alpha; alpha = 1.0 / 3.0; for (int j = 0, k = i * 3; j < 3; j++) L.AddValueTo(i, mesh.FaceIndex[k++], alpha); alpha = coord[0] / 3.0; for (int j = 0, k = f1 * 3; j < 3; j++) L.AddValueTo(i, mesh.FaceIndex[k++], -alpha); alpha = coord[1] / 3.0; for (int j = 0, k = f2 * 3; j < 3; j++) L.AddValueTo(i, mesh.FaceIndex[k++], -alpha); alpha = (1.0 - coord[0] - coord[1]) / 3.0; for (int j = 0, k = f3 * 3; j < 3; j++) L.AddValueTo(i, mesh.FaceIndex[k++], -alpha); } L.SortElement(); return L; }
public static SparseMatrix BuildCurvatureMatrixL(ref NonManifoldMesh mesh) { if (mesh == null) throw new Exception("mesh is null"); int n = mesh.VertexCount; SparseMatrix L = new SparseMatrix(n, n); for (int i = 0, j = 0; i < mesh.FaceCount; i++, j += 3) { int c1 = mesh.FaceIndex[j]; int c2 = mesh.FaceIndex[j + 1]; int c3 = mesh.FaceIndex[j + 2]; Vector3D v1 = new Vector3D(mesh.VertexPos, c1 * 3); Vector3D v2 = new Vector3D(mesh.VertexPos, c2 * 3); Vector3D v3 = new Vector3D(mesh.VertexPos, c3 * 3); double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); L.AddValueTo(c1, c2, -cot3); L.AddValueTo(c2, c1, -cot3); L.AddValueTo(c2, c3, -cot1); L.AddValueTo(c3, c2, -cot1); L.AddValueTo(c3, c1, -cot2); L.AddValueTo(c1, c3, -cot2); } double[] voronoiArea=ComputeVoronoiArea(ref mesh); for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element e in L.Rows[i]) { e.value = e.value / (voronoiArea[e.i]*2); } foreach (SparseMatrix.Element e in L.Rows[i]) { sum += e.value; } L.AddValueTo(i, i, -sum); } L.SortElement(); return L; }
private ColMatrix BuildMatrixA(List <VertexRecord> records, int[] faceIndex, double[] lapWeight, double[] posWeight, double weightAdjustment) { // build backward map int[] map = new int[mesh.VertexCount]; for (int i = 0; i < records.Count; i++) { map[records[i].index] = i; } int n = records.Count; int fn = faceIndex.Length / 3; SparseMatrix A = new SparseMatrix(2 * n, n); this.currentArea = new double[n]; for (int i = 0; i < n; i++) { currentArea[i] = 0; } for (int i = 0, j = 0; i < fn; i++, j += 3) { int c1 = faceIndex[j]; int c2 = faceIndex[j + 1]; int c3 = faceIndex[j + 2]; Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3); Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3); Vector3d v3 = new Vector3d(mesh.VertexPos, c3 * 3); double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); //cot1 = cot2 = cot3 = 1.0; if (double.IsNaN(cot1)) { throw new Exception(); } if (double.IsNaN(cot2)) { throw new Exception(); } if (double.IsNaN(cot3)) { throw new Exception(); } c1 = map[c1]; c2 = map[c2]; c3 = map[c3]; A.AddValueTo(c2, c2, -cot1); A.AddValueTo(c2, c3, cot1); A.AddValueTo(c3, c3, -cot1); A.AddValueTo(c3, c2, cot1); A.AddValueTo(c3, c3, -cot2); A.AddValueTo(c3, c1, cot2); A.AddValueTo(c1, c1, -cot2); A.AddValueTo(c1, c3, cot2); A.AddValueTo(c1, c1, -cot3); A.AddValueTo(c1, c2, cot3); A.AddValueTo(c2, c2, -cot3); A.AddValueTo(c2, c1, cot3); double area = ((v2 - v1).Cross(v3 - v1)).Length() / 2.0; currentArea[c1] += area; currentArea[c2] += area; currentArea[c3] += area; } for (int i = 0; i < n; i++) { double tot = 0; foreach (SparseMatrix.Element e in A.Rows[i]) { if (e.i != e.j) { tot += e.value; } } if (tot > 10000) { foreach (SparseMatrix.Element e in A.Rows[i]) { e.value /= (tot / 10000); } } foreach (SparseMatrix.Element e in A.Rows[i]) { e.value *= lapWeight[records[i].index] * weightAdjustment; } } // positional constraints for (int i = 0; i < n; i++) { int j = records[i].index; double weight = posWeight[j] * (currentArea[i] / originalArea[j]); if (weight <= 0) { weight = posWeight[i]; } A.AddValueTo(i + n, i, weight); } A.SortElement(); ColMatrixCreator cmA = new ColMatrixCreator(2 * n, n); foreach (List <SparseMatrix.Element> r in A.Rows) { foreach (SparseMatrix.Element e in r) { cmA.AddValueTo(e.i, e.j, e.value); } } return(cmA); }
private SparseMatrix BuildMatrixA_old(List <VertexRecord> records, int[] faceIndex, double[] lapWeight, double[] posWeight) { // build backward map int[] map = new int[mesh.VertexCount]; for (int i = 0; i < records.Count; i++) { map[records[i].index] = i; } int n = records.Count; int fn = faceIndex.Length / 3; SparseMatrix A = new SparseMatrix(2 * n, n); for (int i = 0, j = 0; i < fn; i++, j += 3) { int c1 = faceIndex[j]; int c2 = faceIndex[j + 1]; int c3 = faceIndex[j + 2]; Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3); Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3); Vector3d v3 = new Vector3d(mesh.VertexPos, c3 * 3); double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); //cot1 = cot2 = cot3 = 1.0; if (double.IsNaN(cot1)) { throw new Exception(); } if (double.IsNaN(cot2)) { throw new Exception(); } if (double.IsNaN(cot3)) { throw new Exception(); } c1 = map[c1]; c2 = map[c2]; c3 = map[c3]; A.AddValueTo(c2, c2, -cot1); A.AddValueTo(c2, c3, cot1); A.AddValueTo(c3, c3, -cot1); A.AddValueTo(c3, c2, cot1); A.AddValueTo(c3, c3, -cot2); A.AddValueTo(c3, c1, cot2); A.AddValueTo(c1, c1, -cot2); A.AddValueTo(c1, c3, cot2); A.AddValueTo(c1, c1, -cot3); A.AddValueTo(c1, c2, cot3); A.AddValueTo(c2, c2, -cot3); A.AddValueTo(c2, c1, cot3); } for (int i = 0; i < n; i++) { double tot = 0; foreach (SparseMatrix.Element e in A.Rows[i]) { if (e.i != e.j) { tot += e.value; } } if (tot > 10000) { foreach (SparseMatrix.Element e in A.Rows[i]) { e.value /= (tot / 10000); } } foreach (SparseMatrix.Element e in A.Rows[i]) { e.value *= lapWeight[records[i].index]; } } // positional constraints for (int i = 0; i < n; i++) { A.AddElement(i + n, i, posWeight[records[i].index]); } A.SortElement(); return(A); }
public SparseMatrix BuildMatrix2N(SparseMatrix L) { int n = L.ColumnSize; SparseMatrix Ld = new SparseMatrix(2 * n, 2 * n); foreach (List<SparseMatrix.Element> row in L.Rows) { foreach (SparseMatrix.Element rowItem in row) { int i = rowItem.i; int j = rowItem.j; double value = rowItem.value; Ld.AddValueTo(2 * i, 2 * j, value); Ld.AddValueTo(2 * i + 1, 2 * j + 1, value); } } return Ld; }
//public SparseMatrix BuildMatrixArea(TriMesh mesh) //{ // List<List<TriMesh.Vertex>> bounds = TriMeshUtil.RetrieveBoundaryAllVertex(mesh); // int n = mesh.Vertices.Count; // SparseMatrix A = new SparseMatrix(2 * n + 4, 2 * n); // foreach (List<TriMesh.Vertex> oneBoundary in bounds) // { // TriMesh.HalfEdge boundaryStartHF = oneBoundary[0].FindHalfedgeTo(oneBoundary[1]); // TriMesh.HalfEdge currentHF = boundaryStartHF; // do // { // TriMesh.Vertex Vi = currentHF.FromVertex; // TriMesh.Vertex Vj = currentHF.ToVertex; // //Mark UiVj // A[2 * Vi.Index, 2 * Vj.Index + 1] += 0.5; // A[2 * Vj.Index + 1, 2 * Vi.Index] += 0.5; // //Mark VjUi // A[2 * Vj.Index, 2 * Vi.Index + 1] += -0.5; // A[2 * Vi.Index + 1, 2 * Vj.Index] += -0.5; // currentHF = currentHF.Next; // } while (currentHF != boundaryStartHF); // } // return A; //} public SparseMatrix BuildMatrix2N(TriMesh mesh) { SparseMatrix L = LaplaceManager.Instance.BuildMatrixRigid(mesh); int n = mesh.Vertices.Count; SparseMatrix Ld = new SparseMatrix(2 * n, 2 * n); foreach (List<SparseMatrix.Element> row in L.Rows) { foreach (SparseMatrix.Element rowItem in row) { int i = rowItem.i; int j = rowItem.j; double value = rowItem.value; Ld.AddValueTo(2 * i, 2 * j, value); Ld.AddValueTo(2 * i + 1, 2 * j + 1, value); } } return Ld; }
public SparseMatrix BuildLaplaceMatrixCotBasic(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = new SparseMatrix(n, n); for (int i = 0; i < mesh.Faces.Count; i++) { int c1 = mesh.Faces[i].GetVertex(0).Index; int c2 = mesh.Faces[i].GetVertex(1).Index; int c3 = mesh.Faces[i].GetVertex(2).Index; Vector3D v1 = mesh.Faces[i].GetVertex(0).Traits.Position; Vector3D v2 = mesh.Faces[i].GetVertex(1).Traits.Position; Vector3D v3 = mesh.Faces[i].GetVertex(2).Traits.Position; double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); L.AddValueTo(c1, c2, cot3); L.AddValueTo(c2, c1, cot3); L.AddValueTo(c2, c3, cot1); L.AddValueTo(c3, c2, cot1); L.AddValueTo(c3, c1, cot2); L.AddValueTo(c1, c3, cot2); } return L; }
public SparseMatrix BuildMatrixDual(TriMesh mesh) { int vn = mesh.Vertices.Count; int fn = mesh.Faces.Count; SparseMatrix L = new SparseMatrix(fn, vn, 6); for (int i = 0; i < fn; i++) { int f1 = mesh.Faces[i].GetFace(0).Index; int f2 = mesh.Faces[i].GetFace(1).Index; int f3 = mesh.Faces[i].GetFace(2).Index; Vector3D dv = mesh.DualGetVertexPosition(i); Vector3D dv1 = mesh.DualGetVertexPosition(f1); Vector3D dv2 = mesh.DualGetVertexPosition(f2); Vector3D dv3 = mesh.DualGetVertexPosition(f3); Vector3D u = dv - dv3; Vector3D v1 = dv1 - dv3; Vector3D v2 = dv2 - dv3; Vector3D normal = (v1.Cross(v2)).Normalize(); Matrix3D M = new Matrix3D(v1, v2, normal); Vector3D coord = M.Inverse() * u; double alpha; alpha = 1.0 / 3.0; L.AddValueTo(i, mesh.Faces[i].GetVertex(0).Index, alpha); L.AddValueTo(i, mesh.Faces[i].GetVertex(1).Index, alpha); L.AddValueTo(i, mesh.Faces[i].GetVertex(2).Index, alpha); alpha = coord[0] / 3.0; L.AddValueTo(i, mesh.Faces[f1].GetVertex(0).Index, -alpha); L.AddValueTo(i, mesh.Faces[f1].GetVertex(1).Index, -alpha); L.AddValueTo(i, mesh.Faces[f1].GetVertex(2).Index, -alpha); alpha = coord[1] / 3.0; L.AddValueTo(i, mesh.Faces[f2].GetVertex(0).Index, -alpha); L.AddValueTo(i, mesh.Faces[f2].GetVertex(1).Index, -alpha); L.AddValueTo(i, mesh.Faces[f2].GetVertex(2).Index, -alpha); alpha = (1.0 - coord[0] - coord[1]) / 3.0; L.AddValueTo(i, mesh.Faces[f3].GetVertex(0).Index, -alpha); L.AddValueTo(i, mesh.Faces[f3].GetVertex(1).Index, -alpha); L.AddValueTo(i, mesh.Faces[f3].GetVertex(2).Index, -alpha); } L.SortElement(); return L; }
public SparseMatrix BuildMatrixMass(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = new SparseMatrix(n, n); for (int i = 0; i < mesh.Edges.Count; i++) { double face0area = 0; double face1area = 0; if (mesh.Edges[i].Face0 != null) { face0area = TriMeshUtil.ComputeAreaFace(mesh.Edges[i].Face0); } if (mesh.Edges[i].Face1 != null) { face1area =TriMeshUtil.ComputeAreaFace(mesh.Edges[i].Face1); } L.AddValueTo(mesh.Edges[i].Vertex0.Index, mesh.Edges[i].Vertex1.Index, (face0area + face1area) / 12); L.AddValueTo(mesh.Edges[i].Vertex1.Index, mesh.Edges[i].Vertex0.Index, (face0area + face1area) / 12); } for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element e in L.Rows[i]) { sum += e.value; } L.AddValueTo(i, i, sum); } L.SortElement(); return L; }
public SparseMatrix BuildMatrixMeanValue(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = BuildAdjacentMatrixVV(mesh); SparseMatrix D = new SparseMatrix(n, n); foreach (TriMesh.HalfEdge halfedge in mesh.HalfEdges) { TriMesh.Vertex fromJ = halfedge.FromVertex; TriMesh.Vertex toI = halfedge.ToVertex; Vector3D jtoI = (toI.Traits.Position - fromJ.Traits.Position).Normalize(); Vector3D alphaToI = (halfedge.Next.ToVertex.Traits.Position - toI.Traits.Position).Normalize(); Vector3D betaToI = (halfedge.Opposite.Previous.FromVertex.Traits.Position - toI.Traits.Position).Normalize(); double cosGamaIJ = jtoI.Dot(alphaToI) / (jtoI.Length() * alphaToI.Length()); double cosThetaIJ = jtoI.Dot(betaToI) / (jtoI.Length() * betaToI.Length()); double angelGama = Math.Acos(cosGamaIJ); double angelTheta = Math.Acos(cosThetaIJ); double wij = (Math.Tan(angelGama / 2) + Math.Tan(angelTheta / 2)) / (toI.Traits.Position - fromJ.Traits.Position).Length(); int indexI = toI.Index; int indexJ = fromJ.Index; D.AddValueTo(indexI, indexJ, wij); } for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element item in D.Rows[i]) { sum += item.value; } D.AddValueTo(i, i, -sum); } return D; }
public SparseMatrix BuildMatrixCombinatorialGraph(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix W = BuildAdjacentMatrixVV(mesh); SparseMatrix D = new SparseMatrix(n, n); for (int i = 0; i < n; i++) { double sum = W.Rows[i].Count; D.AddValueTo(i, i, sum); } SparseMatrix K = W.Minus(D); return K; }
public SparseMatrix BuildMatrixRigidPositive(TriMesh mesh) { int n = mesh.Vertices.Count; SparseMatrix L = new SparseMatrix(n, n); for (int i = 0; i < mesh.Faces.Count; i++) { int c1 = mesh.Faces[i].GetVertex(0).Index; int c2 = mesh.Faces[i].GetVertex(1).Index; int c3 = mesh.Faces[i].GetVertex(2).Index; Vector3D v1 = mesh.Faces[i].GetVertex(0).Traits.Position; Vector3D v2 = mesh.Faces[i].GetVertex(1).Traits.Position; Vector3D v3 = mesh.Faces[i].GetVertex(2).Traits.Position; double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); L.AddValueTo(c1, c2, cot3 / 2); L.AddValueTo(c2, c1, cot3 / 2); L.AddValueTo(c2, c3, cot1 / 2); L.AddValueTo(c3, c2, cot1 / 2); L.AddValueTo(c3, c1, cot2 / 2); L.AddValueTo(c1, c3, cot2 / 2); } for (int i = 0; i < n; i++) { double sum = 0; foreach (SparseMatrix.Element e in L.Rows[i]) { sum += e.value; } L.AddValueTo(i, i, -sum); } L.SortElement(); return L; }
private ColMatrix BuildMatrixA(Resolution r, double[] lapWeight, double[] posWeight) { // build backward map int[] map = new int[mesh.VertexCount]; for (int i = 0; i < r.vertexList.Length; i++) { map[r.vertexList[i]] = i; } int n = r.vertexList.Length; int fn = r.faceList.Length / 3; SparseMatrix A = new SparseMatrix(2 * n, n); for (int i = 0, j = 0; i < fn; i++, j += 3) { int c1 = r.faceList[j]; int c2 = r.faceList[j + 1]; int c3 = r.faceList[j + 2]; Vector3d v1 = new Vector3d(mesh.VertexPos, c1 * 3); Vector3d v2 = new Vector3d(mesh.VertexPos, c2 * 3); Vector3d v3 = new Vector3d(mesh.VertexPos, c3 * 3); double cot1 = (v2 - v1).Dot(v3 - v1) / (v2 - v1).Cross(v3 - v1).Length(); double cot2 = (v3 - v2).Dot(v1 - v2) / (v3 - v2).Cross(v1 - v2).Length(); double cot3 = (v1 - v3).Dot(v2 - v3) / (v1 - v3).Cross(v2 - v3).Length(); //cot1 = cot2 = cot3 = 1.0; if (double.IsNaN(cot1)) { throw new Exception(); } if (double.IsNaN(cot2)) { throw new Exception(); } if (double.IsNaN(cot3)) { throw new Exception(); } c1 = map[c1]; c2 = map[c2]; c3 = map[c3]; A.AddValueTo(c2, c2, -cot1); A.AddValueTo(c2, c3, cot1); A.AddValueTo(c3, c3, -cot1); A.AddValueTo(c3, c2, cot1); A.AddValueTo(c3, c3, -cot2); A.AddValueTo(c3, c1, cot2); A.AddValueTo(c1, c1, -cot2); A.AddValueTo(c1, c3, cot2); A.AddValueTo(c1, c1, -cot3); A.AddValueTo(c1, c2, cot3); A.AddValueTo(c2, c2, -cot3); A.AddValueTo(c2, c1, cot3); } for (int i = 0; i < n; i++) { double tot = 0; foreach (SparseMatrix.Element e in A.Rows[i]) { if (e.i != e.j) { tot += e.value; } } if (tot > 10000) { foreach (SparseMatrix.Element e in A.Rows[i]) { e.value /= (tot / 10000); } } foreach (SparseMatrix.Element e in A.Rows[i]) { e.value *= lapWeight[r.vertexList[i]]; } } // positional constraints for (int i = 0; i < n; i++) { A.AddElement(i + n, i, posWeight[r.vertexList[i]]); } A.SortElement(); ColMatrixCreator cmA = new ColMatrixCreator(2 * n, n); foreach (List <SparseMatrix.Element> row in A.Rows) { foreach (SparseMatrix.Element e in row) { cmA.AddValueTo(e.i, e.j, e.value); } } return(cmA); }