Пример #1
0
        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);
        }
Пример #2
0
        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);
        }
Пример #3
0
        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);
        }
Пример #4
0
 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]);
     }
 }
Пример #5
0
        // 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);
        }
Пример #6
0
 // 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;
 }
Пример #7
0
 // 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;
 }
Пример #8
0
        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;
        }
Пример #9
0
        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);
        }
Пример #10
0
        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);
        }
Пример #11
0
        // 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;

        }
Пример #12
0
        // 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);
        }
Пример #13
0
        // 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);
        }
Пример #14
0
        // 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);
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
        }
Пример #17
0
        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);
        }
Пример #18
0
        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));
        }
Пример #19
0
        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);
        }
Пример #20
0
        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);
        }
Пример #21
0
        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;
        }
Пример #22
0
        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);
        }
Пример #23
0
        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;
        }
Пример #24
0
        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];
            }
        }
Пример #25
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);
        }
Пример #26
0
        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);
        }
Пример #27
0
        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);
        }
Пример #28
0
        // 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);
        }
Пример #29
0
        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);
        }
Пример #30
0
        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;
        }
Пример #31
0
        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];
            }
        }
Пример #32
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);
        }
Пример #33
0
        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);
        }
Пример #34
0
        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);
        }
Пример #35
0
        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);
        }
Пример #36
0
        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;
                }
            }
        }
Пример #37
0
        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;
        }
Пример #38
0
        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);
        }
Пример #39
0
        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;
        }
Пример #40
0
        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;
        }
Пример #41
0
        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]);
            }

        }
Пример #42
0
        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;
        }
Пример #43
0
        public void Write(ref DenseMatrixDouble A, string fileName)
        {

        }
Пример #44
0
        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;
        }
Пример #45
0
        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);

        }
Пример #46
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);
        }
Пример #47
0
        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;
        }
Пример #48
0
        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;
        }
Пример #49
0
        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;
        }
Пример #50
0
        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;
        }
Пример #51
0
        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;
        }
Пример #52
0
        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;
        }
Пример #53
0
 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;
 }
Пример #54
0
        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);
        }
Пример #55
0
        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;
        }
Пример #56
0
        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;
        }
Пример #57
0
        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;
        }
Пример #58
0
        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];
            }
        }
Пример #59
0
 public void Read(out DenseMatrixDouble A, string fileName)
 {
     A = new DenseMatrixDouble();
 }
Пример #60
0
        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;
        }