public DenseMatrixDouble SolveLinearSystemByLU(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { if (A.RowCount != b.RowCount) { throw new Exception("The dimension of A and b must be agree"); } CholmodInfo cholmodb = CholmodConverter.ConvertDouble(ref b); CholmodInfo cholmodA = CholmodConverter.ConverterDouble(ref A, CholmodInfo.CholmodMatrixStorage.CCS); double[] x = new double[A.ColumnCount]; fixed(int *Index = cholmodA.rowIndex, Pt = cholmodA.colIndex) fixed(double *val = cholmodA.values, bp = cholmodb.values, xx = x) { SolveRealByLU_CCS(cholmodA.RowCount, cholmodA.ColumnCount, cholmodA.nnz, Index, //Row Index Pt, //Column Pointer val, xx, bp); } DenseMatrixDouble unknown = CholmodConverter.dConvertArrayToDenseMatrix(ref x, x.Length, 1); cholmodA = null; cholmodb = null; GC.Collect(); return(unknown); }
protected DenseMatrixDouble ComputeDivergence(TriMesh mesh, Vector3D[] vectorFields) { DenseMatrixDouble div = new DenseMatrixDouble(mesh.Vertices.Count, 1); foreach (TriMesh.Vertex v in mesh.Vertices) { double sum = 0; foreach (TriMesh.HalfEdge hf in v.HalfEdges) { if (hf.OnBoundary) { continue; } Vector3D n = RotatedEdge(hf.Next); Vector3D vf = vectorFields[hf.Face.Index]; sum += n.Dot(vf); } div[v.Index, 0] = sum; } return(div); }
public static DenseMatrixDouble operator *(SparseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.ColumnCount != right.RowCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble resultMatrix = new DenseMatrixDouble(left.RowCount, right.columnCount); double[,] result = resultMatrix.datas; for (int i = 0; i < right.columnCount; i++) { foreach (KeyValuePair <Pair, double> item in left.Datas) { Pair pair = item.Key; double value = item.Value; int m = pair.Key; int n = pair.Value; //M: mutiply index N: vector store index result[m, i] += right[n, i] * value; } } return(resultMatrix); }
void ApplyCotanWeights(TriMesh mesh, ref DenseMatrixDouble x) { foreach (TriMesh.Edge edge in mesh.Edges) { x[edge.Index, 0] = x[edge.Index, 0] * Math.Sqrt(EdgeHodgeStar1[edge.Index]); } }
// solves A x = lambda x for the smallest nonzero eigenvalue lambda // A must be positive (semi-)definite; x is used as an initial guess public DenseMatrixDouble smallestEigPositiveDefinite(ref SparseMatrixDouble A, bool ignoreConstantVector) { ignoreConstantVector = true; DenseMatrixDouble x = new DenseMatrixDouble(); return(x); }
// solves the positive definite sparse linear system Ax = b using sparse Cholesky factorization public DenseMatrixDouble solvePositiveDefinite(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { LinearSystemGenericByLib linearSolver = new LinearSystemGenericByLib(); linearSolver.FactorizationCholesky(ref A); DenseMatrixDouble x = null; linearSolver.FreeSolver(); return x; }
// solves the positive definite sparse linear system Ax = b using sparse QR factorization public DenseMatrixDouble solveLeastNormal(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { LinearSystemGenericByLib linearSolver = new LinearSystemGenericByLib(); linearSolver.FactorizationQR(ref A); DenseMatrixDouble x = null; linearSolver.FreeSolver(); return x; }
public static CholmodInfo ConvertDouble(ref DenseMatrixDouble b) { CholmodInfo info = new CholmodInfo(); info.MatrixType = CholmodInfo.CholmodMatrixType.Dense; b.ToArray(out info.RowCount, out info.ColumnCount, out info.values); return info; }
public static DenseMatrixDouble Copy(ref DenseMatrixDouble B) { DenseMatrixDouble newMatrix = new DenseMatrixDouble(); newMatrix.rowCount = B.rowCount; newMatrix.columnCount = B.columnCount; Array.Copy(B.datas, newMatrix.datas, B.datas.Length); return(newMatrix); }
public Vector3D[] ComputeVectorField(DenseMatrixDouble x, double initAngle) { Vector3D[] vectorFields = new Vector3D[mesh.Faces.Count]; bool[] visitedFlags = new bool[mesh.Faces.Count]; for (int i = 0; i < visitedFlags.Length; i++) { visitedFlags[i] = false; } //Find a initial root to expend TriMesh.Face rootFace = mesh.Faces[0]; var v1 = rootFace.GetVertex(0); var v3 = rootFace.GetVertex(2); var v2 = rootFace.GetVertex(1); Vector3D w0 = (rootFace.GetVertex(2).Traits.Position - rootFace.GetVertex(0).Traits.Position).Normalize(); //Init transpot Vector3D av = v1.Traits.Position; Vector3D bv = v2.Traits.Position; Vector3D cv = v3.Traits.Position; Matrix3D Ei = Orthogonalize(bv - av, cv - av); Vector3D w0i = (Ei * Matrix3D.Rotate(initAngle) * Ei.Inverse() * w0); vectorFields[rootFace.Index] = w0i; visitedFlags[rootFace.Index] = true; //Recurse all faces Queue <TriMesh.Face> queue = new Queue <HalfEdgeMesh.Face>(); queue.Enqueue(rootFace); int ii = 0; while (queue.Count > 0) { TriMesh.Face currentFace = queue.Dequeue(); Vector3D wI = vectorFields[currentFace.Index]; foreach (TriMesh.Face neighbor in currentFace.Faces) { if (visitedFlags[neighbor.Index] == false) { Vector3D wj = Transport(wI, currentFace, neighbor, x); vectorFields[neighbor.Index] = wj; queue.Enqueue(neighbor); visitedFlags[neighbor.Index] = true; } } ii++; } return(vectorFields); }
// solves the positive definite sparse linear system Ax = b using sparse Cholesky factorization public DenseMatrixDouble solveBackPositiveDefiniteIterate(ref DenseMatrixDouble b) { DenseMatrixDouble x = null; if (linearSolver != null) { // x= linearSolver.SolveLinerSystem(ref b); } return x; }
// solves the positive definite sparse linear system Ax = b using sparse QR factorization public DenseMatrixDouble solveLeastNormal(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { LinearSystemGenericByLib linearSolver = new LinearSystemGenericByLib(); linearSolver.FactorizationQR(ref A); DenseMatrixDouble x = null; linearSolver.FreeSolver(); return(x); }
// solves the positive definite sparse linear system Ax = b using sparse Cholesky factorization public DenseMatrixDouble solvePositiveDefinite(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { LinearSystemGenericByLib linearSolver = new LinearSystemGenericByLib(); linearSolver.FactorizationCholesky(ref A); DenseMatrixDouble x = null; linearSolver.FreeSolver(); return(x); }
// solves the positive definite sparse linear system Ax = b using sparse Cholesky factorization public DenseMatrixDouble solveBackPositiveDefiniteIterate(ref DenseMatrixDouble b) { DenseMatrixDouble x = null; if (linearSolver != null) { // x= linearSolver.SolveLinerSystem(ref b); } return(x); }
public static CholmodInfo ConvertDouble(ref DenseMatrixDouble b) { CholmodInfo info = new CholmodInfo(); info.MatrixType = CholmodInfo.CholmodMatrixType.Dense; b.ToArray(out info.RowCount, out info.ColumnCount, out info.values); return(info); }
public static DenseMatrixDouble Identity(int N) { DenseMatrixDouble identity = new DenseMatrixDouble(N, N); for (int i = 0; i < N; i++) { identity.datas[i, i] = 1; } return(identity); }
protected double[] AssignDistance(DenseMatrixDouble phi) { double[] vertexDistance = new double[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { vertexDistance[i] = phi[i, 0]; mesh.Vertices[i].Traits.Distance = phi[i, 0]; } return(vertexDistance); }
public double F_Norm() { DenseMatrixDouble tr = this.Transpose() * this; double sum = 0; for (int i = 0; i < tr.RowCount; i++) { sum += tr[i, i]; } return(Math.Sqrt(sum)); }
public static DenseMatrixDouble operator *(double left, DenseMatrixDouble right) { DenseMatrixDouble result = new DenseMatrixDouble(right.rowCount, right.columnCount); for (int i = 0; i < right.rowCount; i++) { for (int j = 0; j < right.columnCount; j++) { result.datas[i, j] = right.datas[i, j] * left; } } return(result); }
public DenseMatrixDouble Transpose() { DenseMatrixDouble tr = new DenseMatrixDouble(this.columnCount, this.rowCount); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { tr.datas[j, i] = datas[i, j]; } } return(tr); }
public DenseMatrixDouble Transpose() { DenseMatrixDouble tr = new DenseMatrixDouble(this.columnCount, this.rowCount); for (int i = 0; i < rowCount; i++) { for (int j = 0; j < columnCount; j++) { tr.datas[j, i] = datas[i, j]; } } return tr; }
public void FaceFrame(TriMesh.HalfEdge hf, out Vector3D a, out Vector3D b) { a = Vector3D.Zero; b = Vector3D.Zero; if (hf.OnBoundary) { return; } TriMesh.Vertex v0 = hf.FromVertex; TriMesh.Vertex v1 = hf.ToVertex; a = (v0.Traits.Position - v1.Traits.Position).Normalize(); b = hf.Face.Traits.Normal.Cross(a); }
public static DenseMatrixDouble dConvertArrayToDenseMatrix(ref double[] x, int m, int n) { DenseMatrixDouble unknown = new DenseMatrixDouble(m, n); int count = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { unknown[i, j] = x[count]; count++; } } return unknown; }
public void Build(TriMesh mesh) { int nBasisCycles = basisCycles.Count; //Build Matrix A A = BuildCycleMatrix(mesh, basisCycles); ApplyCotanWeights(ref A); //Factorize LinearSystemGenericByLib.Instance.FactorizationQR(ref A); K = new DenseMatrixDouble(basisCycles.Count, 1); b = new DenseMatrixDouble(basisCycles.Count, 1); //Add constraint of angle defect for (int i = 0; i < nContractibleCycles; i++) { K[i, 0] = -ComputeGeneratorDefect(basisCycles[i]); } //Add constraint of Generator int nGenerators = dualCycles.Count; for (int i = nContractibleCycles; i < nGenerators + nContractibleCycles; i++) { List <TriMesh.HalfEdge> generatorCycle = basisCycles[i]; //Boundary condition if (treeCotree.IsBoundaryGenerator(generatorCycle)) { K[i, 0] = -BoundaryLoopCurvature(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = true; } //None-Boundary condition else { K[i, 0] = -ComputeGeneratorDefect(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = false; } } //Copy to b for (int i = 0; i < nBasisCycles; i++) { b[i, 0] = K[i, 0]; } }
public void InitProcess() { SparseMatrixDouble d0 = DECDouble.Instance.BuildExteriorDerivative0Form(mesh); SparseMatrixDouble d1 = DECDouble.Instance.BuildExteriorDerivative1Form(mesh); //SparseMatrixDouble d1 = SparseMatrixDouble.ReadFromFile("d1.mat"); double[] guassianCurvatures = TriMeshUtil.ComputeGaussianCurvatureIntegrated(mesh); //Seize all singularities if (Singularities.Count == 0) { Singularities.Add(new KeyValuePair <TriMesh.Vertex, double>(mesh.Vertices[0], 2.0f)); } x = ComputeTrivaialConnection(d0, d1, guassianCurvatures); }
protected int BuildImpulseSingal(TriMesh mesh, out DenseMatrixDouble x) { int nb = 0; x = new DenseMatrixDouble(mesh.Vertices.Count, 1); foreach (TriMesh.Vertex v in mesh.Vertices) { if (v.Traits.selectedFlag > 0) { x[v.Index, 0] = 1; nb++; } } return(nb); }
public static DenseMatrixDouble dConvertArrayToDenseMatrix(ref double[] x, int m, int n) { DenseMatrixDouble unknown = new DenseMatrixDouble(m, n); int count = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < n; j++) { unknown[i, j] = x[count]; count++; } } return(unknown); }
// solves A x = lambda x for the smallest nonzero eigenvalue lambda // A must be symmetric; x is used as an initial guess public DenseMatrixDouble smallestEig(ref SparseMatrixDouble A, bool ignoreConstantVector) { ignoreConstantVector = true; DenseMatrixDouble x = new DenseMatrixDouble(); for (int iter = 0; iter < maxEigIter; iter++) { x = solveLU(ref A, ref x); if (ignoreConstantVector) { // x.removeMean(); } //x.normalize(); } return(x); }
public DenseMatrixDouble BuildClosedPrimalOneForm(TriMesh mesh, List <TriMesh.HalfEdge> cycle) { DenseMatrixDouble w = new DenseMatrixDouble(mesh.Edges.Count, 1); foreach (TriMesh.HalfEdge hf in cycle) { double value = 1.0f; if (hf.Edge.HalfEdge0 != hf) { value = -value; } w[hf.Edge.Index, 0] = value; } return(w); }
public DenseMatrixDouble BuildClosedPrimalOneForm(TriMesh mesh, List<TriMesh.HalfEdge> cycle) { DenseMatrixDouble w = new DenseMatrixDouble(mesh.Edges.Count, 1); foreach (TriMesh.HalfEdge hf in cycle) { double value = 1.0f; if (hf.Edge.HalfEdge0 != hf) { value = -value; } w[hf.Edge.Index, 0] = value; } return w; }
public void Update() { SetupRHS(Mesh); DenseMatrixDouble x = LinearSystemGenericByLib.Instance.SolveByFractorizedQRLeastNorm(ref b); ApplyCotanWeights(Mesh, ref x); foreach (TriMesh.Edge edge in Mesh.Edges) { EdgeTheta[edge.Index] = x[edge.Index, 0]; } //Reset for (int i = 0; i < b.RowCount; i++) { b[i, 0] = K[i, 0]; } }
public DenseMatrixDouble SolveByFactorizedLU(ref DenseMatrixDouble b) { CholmodInfo cholmodb = CholmodConverter.ConvertDouble(ref b); DenseMatrixDouble result = new DenseMatrixDouble(n, 1); double[] x = new double[n]; SolveLU(ref cholmodb.values, ref x); for (int i = 0; i < n; i++) { result[i, 0] = x[i]; } x = null; GC.Collect(); return(result); }
public static DenseMatrixDouble operator +(DenseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.columnCount != right.columnCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble matrix = new DenseMatrixDouble(left.RowCount, left.ColumnCount); for (int i = 0; i < left.RowCount; i++) { for (int j = 0; j < left.columnCount; j++) { matrix.datas[i, j] = left.datas[i, j] + right.datas[i, j]; } } return(matrix); }
protected DenseMatrixDouble ComputeTrivaialConnection(SparseMatrixDouble d0, SparseMatrixDouble d1, double[] Guassian) { DenseMatrixDouble b = CholmodConverter.dConvertArrayToDenseMatrix(ref Guassian, Guassian.Length, 1); double[] singularValues = new double[Singularities.Count]; //Init with avg of 2 double avgValue = 2.0f / (double)Singularities.Count; int j = 0; foreach (KeyValuePair <TriMesh.Vertex, double> vItem in Singularities) { int index = vItem.Key.Index; double value = vItem.Value; b[index, 0] = Guassian[index] - 2 * Math.PI * value; j++; } for (int i = 0; i < Guassian.Length; i++) { b[i, 0] = -b[i, 0]; } SparseMatrixDouble A = d0.Transpose(); DenseMatrixDouble x = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref b); SparseMatrixDouble d1T = d1.Transpose(); SparseMatrixDouble Laplace = d1 * d1T; DenseMatrixDouble rhs = d1 * x; DenseMatrixDouble y = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref Laplace, ref rhs); x = x - d1T * y; return(x); }
public static DenseMatrixDouble operator *(DenseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.columnCount != right.rowCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble result = new DenseMatrixDouble(left.rowCount, right.columnCount); for (int i = 0; i < left.rowCount; i++) { for (int j = 0; j < right.columnCount; j++) { for (int z = 0; z < left.columnCount; z++) { result.datas[i, j] += left.datas[i, z] * right.datas[z, j]; } } } return(result); }
protected void SetMinToZero(DenseMatrixDouble phi) { double min = double.MaxValue; for (int i = 0; i < phi.RowCount; i++) { for (int j = 0; j < phi.ColumnCount; j++) { if (min > phi[i, j]) { min = phi[i, j]; } } } for (int i = 0; i < phi.RowCount; i++) { for (int j = 0; j < phi.ColumnCount; j++) { phi[i, j] -= min; } } }
protected double ComputeConnectionOneForm(TriMesh.HalfEdge hf, List<double>[] HarmonicBasis, double[] HarmonicCoeffition, DenseMatrixDouble u) { double angle = 0.0f; double star1 = 0.5 * (ComputeTan(hf) + ComputeTan(hf.Opposite)); double u0 = u[hf.Opposite.FromVertex.Index, 0]; double u1 = u[hf.FromVertex.Index, 0]; angle += star1 * (u1 - u0); List<double> harmonis = HarmonicBasis[hf.Index]; if (harmonis != null) { for (int k = 0; k < harmonis.Count; k++) { angle += HarmonicCoeffition[k] * harmonis[k]; } } //double star0 = 0.5 * (Comput) return angle; }
public DenseMatrixDouble InitWithTrivalHolonmy(SparseMatrixDouble Laplace, TriMesh mesh) { DenseMatrixDouble b = new DenseMatrixDouble(mesh.Vertices.Count, 1); double[] tempSingularities = new double[mesh.Vertices.Count]; for (int i = 0; i < tempSingularities.Length; i++) { tempSingularities[i] = 0; } foreach (KeyValuePair <TriMesh.Vertex, double> pair in Singularities) { int index = pair.Key.Index; double value = pair.Value; tempSingularities[index] = value; } double[] GuassianCurvs = TriMeshUtil.ComputeGaussianCurvatureIntegrated(mesh); foreach (TriMesh.Vertex v in mesh.Vertices) { double value = 0; if (!v.OnBoundary) { value -= GuassianCurvs[v.Index]; value += 2 * Math.PI * tempSingularities[v.Index]; } b[v.Index, 0] = value; } DenseMatrixDouble u = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref Laplace, ref b); return(u); }
public static DenseMatrixDouble operator *(SparseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.ColumnCount != right.RowCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble resultMatrix = new DenseMatrixDouble(left.RowCount, right.columnCount); double[,] result = resultMatrix.datas; for (int i = 0; i < right.columnCount; i++) { foreach (KeyValuePair<Pair, double> item in left.Datas) { Pair pair = item.Key; double value = item.Value; int m = pair.Key; int n = pair.Value; //M: mutiply index N: vector store index result[m, i] += right[n, i] * value; } } return resultMatrix; }
protected double[] AssignDistance(DenseMatrixDouble phi) { double[] vertexDistance = new double[mesh.Vertices.Count]; for (int i = 0; i < mesh.Vertices.Count; i++) { vertexDistance[i] = phi[i, 0]; mesh.Vertices[i].Traits.Distance = phi[i, 0]; } return vertexDistance; }
public static DenseMatrixDouble operator +(DenseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.columnCount != right.columnCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble matrix = new DenseMatrixDouble(left.RowCount, left.ColumnCount); for (int i = 0; i < left.RowCount; i++) { for (int j = 0; j < left.columnCount; j++) { matrix.datas[i, j] = left.datas[i, j] + right.datas[i, j]; } } return matrix; }
public void Write(ref DenseMatrixDouble A, string fileName) { }
protected Vector3D[] ComputeVectorField(DenseMatrixDouble u, TriMesh mesh) { Vector3D[] vectors = new Vector3D[mesh.Faces.Count]; foreach (TriMesh.Face f in mesh.Faces) { if (f.OnBoundary) { continue; } TriMesh.HalfEdge hij = f.HalfEdge; TriMesh.HalfEdge hjk = hij.Next; TriMesh.HalfEdge hki = hjk.Next; TriMesh.Vertex vi = hij.FromVertex; TriMesh.Vertex vj = hjk.FromVertex; TriMesh.Vertex vk = hki.FromVertex; double ui = u[vi.Index, 0]; double uj = u[vj.Index, 0]; double uk = u[vk.Index, 0]; Vector3D eijL = RotatedEdge(hij); Vector3D ejkL = RotatedEdge(hjk); Vector3D ekiL = RotatedEdge(hki); double area = TriMeshUtil.ComputeAreaFaceTwo(f); Vector3D x = 0.5 * (ui * ejkL + uj * ekiL + uk * eijL) / area; vectors[f.Index] = -x.Normalize(); } return vectors; }
public void Run() { Stopwatch clock = new Stopwatch(); clock.Start(); double step = 0.01; DECMeshDouble decMesh = new DECMeshDouble(mesh); SparseMatrixDouble laplace = decMesh.Laplace; SparseMatrixDouble star0 = decMesh.HodgeStar0Form; SparseMatrixDouble star1 = decMesh.HodgeStar1Form; SparseMatrixDouble d0 = decMesh.ExteriorDerivative0Form; SparseMatrixDouble L = d0.Transpose() * star1 * d0; SparseMatrixDouble A = star0 + step * L; A.WriteToFile("A.ma"); double[] xs = new double[mesh.Vertices.Count]; double[] ys = new double[mesh.Vertices.Count]; double[] zs = new double[mesh.Vertices.Count]; foreach (TriMesh.Vertex v in mesh.Vertices) { xs[v.Index] = v.Traits.Position.x; ys[v.Index] = v.Traits.Position.y; zs[v.Index] = v.Traits.Position.z; } double[] rhs1 = star0 * xs; double[] rhs2 = star0 * ys; double[] rhs3 = star0 * zs; //SparseMatrix.WriteVectorToFile("xs.ve", rhs1); //SparseMatrix.WriteVectorToFile("ys.ve", rhs2); //SparseMatrix.WriteVectorToFile("zs.ve", rhs3); DenseMatrixDouble rhsx = new DenseMatrixDouble(mesh.Vertices.Count, 1); DenseMatrixDouble rhsy = new DenseMatrixDouble(mesh.Vertices.Count, 1); DenseMatrixDouble rhsz = new DenseMatrixDouble(mesh.Vertices.Count, 1); for (int i = 0; i < mesh.Vertices.Count; i++) { rhsx[i, 0] = rhs1[i]; rhsy[i, 0] = rhs2[i]; rhsz[i, 0] = rhs3[i]; } DenseMatrixDouble newX = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsx); DenseMatrixDouble newY = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsy); DenseMatrixDouble newZ = LinearSystemGenericByLib.Instance.SolveLinerSystem(ref A, ref rhsz); foreach (TriMesh.Vertex v in mesh.Vertices) { v.Traits.Position.x = newX[v.Index, 0]; v.Traits.Position.y = newY[v.Index, 0]; v.Traits.Position.z = newZ[v.Index, 0]; } TriMeshUtil.ScaleToUnit(mesh,1.0f); TriMeshUtil.MoveToCenter(mesh); clock.Stop(); decimal micro = clock.Elapsed.Ticks / 10m; Console.WriteLine("Total time cost:{0}", micro); }
public void InitProcess() { SparseMatrixDouble d0 = DECDouble.Instance.BuildExteriorDerivative0Form(mesh); SparseMatrixDouble d1 = DECDouble.Instance.BuildExteriorDerivative1Form(mesh); //SparseMatrixDouble d1 = SparseMatrixDouble.ReadFromFile("d1.mat"); double[] guassianCurvatures = TriMeshUtil.ComputeGaussianCurvatureIntegrated(mesh); //Seize all singularities if (Singularities.Count == 0) { Singularities.Add(new KeyValuePair<TriMesh.Vertex, double>(mesh.Vertices[0], 2.0f)); } x = ComputeTrivaialConnection(d0, d1, guassianCurvatures); }
public double BoundaryLoopCurvature(List<TriMesh.HalfEdge> cycle) { double totalK = 0; //Get the virtual face Boundary. TriMesh.Vertex v0 = cycle[0].Opposite.Next.FromVertex; if (!v0.OnBoundary) { v0 = cycle[0].Next.FromVertex; } TriMesh.HalfEdge he0 = v0.HalfEdge; do { he0 = he0.Opposite.Next; if (he0.OnBoundary) { int a = 0; } } while (!he0.OnBoundary); Vector3D c = new Vector3D(0, 0, 0); TriMesh.HalfEdge he = he0; int boundaryLength = 0; do { c += he.FromVertex.Traits.Position; boundaryLength++; he = he.Next; } while (he != he0); c /= (double)boundaryLength; double K = 2 * Math.PI; he = he0; do { Vector3D a = he.FromVertex.Traits.Position; Vector3D b = he.Next.FromVertex.Traits.Position; K -= TipAngle(c, a, b); he = he.Next; } while (he != he0); totalK += K; // add the curvature around each of the boundary vertices, using // the following labels: // c - virtual center vertex of boundary loop (computed above) // d - current boundary vertex (we walk around the 1-ring of this vertex) // a,b - consecutive interior vertices in 1-ring of d // e,f - boundary vertices adjacent to d he = he0; do { TriMesh.Vertex v = he.FromVertex; Vector3D d = v.Traits.Position; K = 2 * Math.PI; TriMesh.HalfEdge he2 = v.HalfEdge; do { if (he2.OnBoundary) { Vector3D f = he2.Next.FromVertex.Traits.Position; K -= TipAngle(d, f, c); } else { Vector3D a = he2.Next.FromVertex.Traits.Position; Vector3D b = he2.Next.Next.FromVertex.Traits.Position; K -= TipAngle(d, a, b); if (he2.Opposite.OnBoundary) { Vector3D e = he2.Opposite.FromVertex.Traits.Position; K -= TipAngle(d, c, e); } } he2 = he2.Opposite.Next; } while (he2 != v.HalfEdge); totalK += K; he = he.Next; } while (he != he0); return totalK; }
public DenseMatrixDouble SolveLinearSystemByLU(ref SparseMatrixDouble A, ref DenseMatrixDouble b) { if (A.RowCount != b.RowCount) { throw new Exception("The dimension of A and b must be agree"); } CholmodInfo cholmodb = CholmodConverter.ConvertDouble(ref b); CholmodInfo cholmodA = CholmodConverter.ConverterDouble(ref A, CholmodInfo.CholmodMatrixStorage.CCS); double[] x = new double[A.ColumnCount]; fixed (int* Index = cholmodA.rowIndex, Pt = cholmodA.colIndex) fixed (double* val = cholmodA.values, bp = cholmodb.values, xx = x) { SolveRealByLU_CCS(cholmodA.RowCount, cholmodA.ColumnCount, cholmodA.nnz, Index, //Row Index Pt, //Column Pointer val, xx, bp); } DenseMatrixDouble unknown = CholmodConverter.dConvertArrayToDenseMatrix(ref x, x.Length, 1); cholmodA = null; cholmodb = null; GC.Collect(); return unknown; }
public static DenseMatrixDouble operator *(double left, DenseMatrixDouble right) { DenseMatrixDouble result = new DenseMatrixDouble(right.rowCount, right.columnCount); for (int i = 0; i < right.rowCount; i++) { for (int j = 0; j < right.columnCount; j++) { result.datas[i, j] = right.datas[i, j] * left; } } return result; }
public DenseMatrixDouble SolveByFractorizedQRLeastSqure(ref DenseMatrixDouble b) { CholmodInfo cholmodb = CholmodConverter.ConvertDouble(ref b); DenseMatrixDouble result = new DenseMatrixDouble(n, 1); double[] x = new double[n]; SolveLeastSqureByFractorizedQR(ref cholmodb.values, ref x); for (int i = 0; i < n; i++) { result[i, 0] = x[i]; } x = null; GC.Collect(); return result; }
public static DenseMatrixDouble operator *(DenseMatrixDouble left, DenseMatrixDouble right) { //Make sure matrix dimensions are equal if (left.columnCount != right.rowCount) { throw new Exception("The dimension of two matrix must be equal"); } DenseMatrixDouble result = new DenseMatrixDouble(left.rowCount, right.columnCount); for (int i = 0; i < left.rowCount; i++) { for (int j = 0; j < right.columnCount; j++) { for (int z = 0; z < left.columnCount; z++) { result.datas[i, j] += left.datas[i, z] * right.datas[z, j]; } } } return result; }
public Vector3D[] ComputeVectorField(DenseMatrixDouble x,double initAngle) { Vector3D[] vectorFields = new Vector3D[mesh.Faces.Count]; bool[] visitedFlags = new bool[mesh.Faces.Count]; for (int i = 0; i < visitedFlags.Length; i++) { visitedFlags[i] = false; } //Find a initial root to expend TriMesh.Face rootFace = mesh.Faces[0]; var v1 = rootFace.GetVertex(0); var v3 = rootFace.GetVertex(2); var v2 = rootFace.GetVertex(1); Vector3D w0 = (rootFace.GetVertex(2).Traits.Position - rootFace.GetVertex(0).Traits.Position).Normalize(); //Init transpot Vector3D av = v1.Traits.Position; Vector3D bv = v2.Traits.Position; Vector3D cv = v3.Traits.Position; Matrix3D Ei = Orthogonalize(bv - av, cv - av); Vector3D w0i = (Ei * Matrix3D.Rotate(initAngle) * Ei.Inverse() * w0); vectorFields[rootFace.Index] = w0i; visitedFlags[rootFace.Index] = true; //Recurse all faces Queue<TriMesh.Face> queue = new Queue<HalfEdgeMesh.Face>(); queue.Enqueue(rootFace); int ii = 0; while (queue.Count > 0) { TriMesh.Face currentFace = queue.Dequeue(); Vector3D wI = vectorFields[currentFace.Index]; foreach (TriMesh.Face neighbor in currentFace.Faces) { if (visitedFlags[neighbor.Index] == false) { Vector3D wj = Transport(wI, currentFace, neighbor, x); vectorFields[neighbor.Index] = wj; queue.Enqueue(neighbor); visitedFlags[neighbor.Index] = true; } } ii++; } return vectorFields; }
public static DenseMatrixDouble Copy(ref DenseMatrixDouble B) { DenseMatrixDouble newMatrix = new DenseMatrixDouble(); newMatrix.rowCount = B.rowCount; newMatrix.columnCount = B.columnCount; Array.Copy(B.datas, newMatrix.datas, B.datas.Length); return newMatrix; }
public static DenseMatrixDouble Identity(int N) { DenseMatrixDouble identity = new DenseMatrixDouble(N, N); for (int i = 0; i < N; i++) { identity.datas[i, i] = 1; } return identity; }
protected Vector3D Transport(Vector3D wI, TriMesh.Face faceI, TriMesh.Face faceJ, DenseMatrixDouble x) { /* * triangles i and j according to the following labels: b /|\ / | \ / | \ / | \ c i | j d \ | / \ | / \ | / \|/ a */ //Find Shared edge IJ TriMesh.HalfEdge sharedEdgeI = null; TriMesh.HalfEdge sharedEdgeJ = null; TriMesh.Edge sharedEdge = null; foreach (TriMesh.HalfEdge edgeI in faceI.Halfedges) { foreach (TriMesh.HalfEdge edgeJ in faceJ.Halfedges) { if (edgeI.Opposite == edgeJ) { sharedEdge = edgeI.Edge; sharedEdgeI = edgeI; sharedEdgeJ = edgeJ; break; } } } if (sharedEdge == null) throw new Exception("Error"); //Find vertex correspondent to figure above Vector3D av = sharedEdgeI.FromVertex.Traits.Position; Vector3D bv = sharedEdgeJ.FromVertex.Traits.Position; Vector3D cv = sharedEdgeI.Next.ToVertex.Traits.Position; Vector3D dv = sharedEdgeJ.Next.ToVertex.Traits.Position; double angle = x[sharedEdge.Index, 0]; if (sharedEdge.HalfEdge0 == sharedEdgeI) { angle = -angle; } //Compute the basis Matrix3D Ei = Orthogonalize(bv - av, cv - av); Matrix3D Ej = Orthogonalize(bv - av, bv - dv); //Build Rotate Matrix between two Faces Matrix3D rotateMatrix = Matrix3D.Rotate(angle); Vector3D wj = (Ej * rotateMatrix * Ei.Inverse() * wI); return wj; }
protected DenseMatrixDouble ComputeDivergence(TriMesh mesh, Vector3D[] vectorFields) { DenseMatrixDouble div = new DenseMatrixDouble(mesh.Vertices.Count, 1); foreach (TriMesh.Vertex v in mesh.Vertices) { double sum = 0; foreach (TriMesh.HalfEdge hf in v.HalfEdges) { if (hf.OnBoundary) { continue; } Vector3D n = RotatedEdge(hf.Next); Vector3D vf = vectorFields[hf.Face.Index]; sum += n.Dot(vf); } div[v.Index, 0] = sum; } return div; }
public void Build(TriMesh mesh) { int nBasisCycles = basisCycles.Count; //Build Matrix A A = BuildCycleMatrix(mesh, basisCycles); ApplyCotanWeights(ref A); //Factorize LinearSystemGenericByLib.Instance.FactorizationQR(ref A); K = new DenseMatrixDouble(basisCycles.Count, 1); b = new DenseMatrixDouble(basisCycles.Count, 1); //Add constraint of angle defect for (int i = 0; i < nContractibleCycles; i++) { K[i, 0] = -ComputeGeneratorDefect(basisCycles[i]); } //Add constraint of Generator int nGenerators = dualCycles.Count; for (int i = nContractibleCycles; i < nGenerators + nContractibleCycles; i++) { List<TriMesh.HalfEdge> generatorCycle = basisCycles[i]; //Boundary condition if (treeCotree.IsBoundaryGenerator(generatorCycle)) { K[i, 0] = -BoundaryLoopCurvature(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = true; } //None-Boundary condition else { K[i, 0] = -ComputeGeneratorDefect(generatorCycle); GeneratorOnBoundary[i - nContractibleCycles] = false; } } //Copy to b for (int i = 0; i < nBasisCycles; i++) { b[i, 0] = K[i, 0]; } }
public void Read(out DenseMatrixDouble A, string fileName) { A = new DenseMatrixDouble(); }
protected int BuildImpulseSingal(TriMesh mesh, out DenseMatrixDouble x) { int nb = 0; x = new DenseMatrixDouble(mesh.Vertices.Count, 1); foreach (TriMesh.Vertex v in mesh.Vertices) { if (v.Traits.selectedFlag > 0) { x[v.Index, 0] = 1; nb++; } } return nb; }