Esempio n. 1
0
        // Result must be as large as Mesh.MaxVertexID
        public bool Solve(Vector3d[] Result)
        {
            if (WeightsM == null)
            {
                Initialize();       // force initialize...
            }
            UpdateForSolve();

            // use initial positions as initial solution.
            Array.Copy(Px, Sx, N);
            Array.Copy(Py, Sy, N);
            Array.Copy(Pz, Sz, N);

            Action <double[], double[]> CombinedMultiply = (X, B) => {
                // packed multiply is 3-4x faster...
                //M.Multiply(X, B);
                PackedM.Multiply(X, B);
                for (int i = 0; i < N; ++i)
                {
                    B[i] += WeightsM.D[i] * X[i];
                }
            };

            SparseSymmetricCG SolverX = new SparseSymmetricCG()
            {
                B                  = Bx, X = Sx,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };
            SparseSymmetricCG SolverY = new SparseSymmetricCG()
            {
                B                  = By, X = Sy,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };
            SparseSymmetricCG SolverZ = new SparseSymmetricCG()
            {
                B                  = Bz, X = Sz,
                MultiplyF          = CombinedMultiply, PreconditionMultiplyF = Preconditioner.Multiply,
                UseXAsInitialGuess = true
            };

            SparseSymmetricCG[] solvers = new SparseSymmetricCG[3] {
                SolverX, SolverY, SolverZ
            };
            bool[] ok      = new bool[3];
            int[]  indices = new int[3] {
                0, 1, 2
            };

            // preconditioned solve is slower =\
            //Action<int> SolveF = (i) => {  ok[i] = solvers[i].SolvePreconditioned(); };
            Action <int> SolveF = (i) => { ok[i] = solvers[i].Solve(); };

            gParallel.ForEach(indices, SolveF);

            if (ok[0] == false || ok[1] == false || ok[2] == false)
            {
                return(false);
            }

            for (int i = 0; i < N; ++i)
            {
                int vid = ToMeshV[i];
                Result[vid] = new Vector3d(Sx[i], Sy[i], Sz[i]);
            }

            // apply post-fixed constraints
            if (HavePostFixedConstraints)
            {
                foreach (var constraint in SoftConstraints)
                {
                    if (constraint.Value.PostFix)
                    {
                        int vid = constraint.Key;
                        Result[vid] = constraint.Value.Position;
                    }
                }
            }

            return(true);
        }
        public void Initialize()
        {
            ToMeshV = new int[Mesh.MaxVertexID];
            ToIndex = new int[Mesh.MaxVertexID];
            N       = 0;
            foreach (int vid in Mesh.VertexIndices())
            {
                ToMeshV[N]   = vid;
                ToIndex[vid] = N;
                N++;
            }

            Px         = new double[N];
            Py         = new double[N];
            Pz         = new double[N];
            nbr_counts = new int[N];
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            for (int i = 0; i < N; ++i)
            {
                int      vid = ToMeshV[i];
                Vector3d v   = Mesh.GetVertex(vid);
                Px[i]         = v.x; Py[i] = v.y; Pz[i] = v.z;
                nbr_counts[i] = Mesh.GetVtxEdgeCount(vid);
            }

            // construct laplacian matrix
            for (int i = 0; i < N; ++i)
            {
                int vid = ToMeshV[i];
                int n   = nbr_counts[i];

                double sum_w = 0;
                foreach (int nbrvid in Mesh.VtxVerticesItr(vid))
                {
                    int j  = ToIndex[nbrvid];
                    int n2 = nbr_counts[j];

                    // weight options
                    //double w = -1;
                    double w = -1.0 / Math.Sqrt(n + n2);
                    //double w = -1.0 / n;

                    M.Set(i, j, w);
                    sum_w += w;
                }
                sum_w = -sum_w;
                // TODO: Investigate: is this ia bug?
                // Source https://github.com/ZelimDamian/geometry3Sharp/commit/7a50d8de10faad762e726e60956acc4bdc5456b5
                // makes the following line M.Set(i, i, sum_w);
                M.Set(vid, vid, sum_w);
            }

            // transpose(L) * L, but matrix is symmetric...
            if (UseSoftConstraintNormalEquations)
            {
                //M = M.Multiply(M);
                // only works if M is symmetric!!
                PackedM = M.SquarePackedParallel();
            }
            else
            {
                PackedM = new PackedSparseMatrix(M);
            }

            // compute laplacian vectors of initial mesh positions
            MLx = new double[N];
            MLy = new double[N];
            MLz = new double[N];
            PackedM.Multiply(Px, MLx);
            PackedM.Multiply(Py, MLy);
            PackedM.Multiply(Pz, MLz);

            // allocate memory for internal buffers
            Preconditioner = new DiagonalMatrix(N);
            WeightsM       = new DiagonalMatrix(N);
            Cx             = new double[N]; Cy = new double[N]; Cz = new double[N];
            Bx             = new double[N]; By = new double[N]; Bz = new double[N];
            Sx             = new double[N]; Sy = new double[N]; Sz = new double[N];

            need_solve_update = true;
            UpdateForSolve();
        }
        public void Initialize()
        {
            ToMeshV = new int[Mesh.MaxVertexID];
            ToIndex = new int[Mesh.MaxVertexID];
            N       = 0;
            foreach (int vid in Mesh.VertexIndices())
            {
                ToMeshV[N]   = vid;
                ToIndex[vid] = N;
                N++;
            }

            Px         = new double[N];
            Py         = new double[N];
            Pz         = new double[N];
            nbr_counts = new int[N];
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            for (int i = 0; i < N; ++i)
            {
                int      vid = ToMeshV[i];
                Vector3d v   = Mesh.GetVertex(vid);
                Px[i]         = v.x; Py[i] = v.y; Pz[i] = v.z;
                nbr_counts[i] = Mesh.GetVtxEdgeCount(vid);
            }

            // construct laplacian matrix
            for (int i = 0; i < N; ++i)
            {
                int vid = ToMeshV[i];
                int n   = nbr_counts[i];

                double sum_w = 0;
                foreach (int nbrvid in Mesh.VtxVerticesItr(vid))
                {
                    int j  = ToIndex[nbrvid];
                    int n2 = nbr_counts[j];

                    // weight options
                    //double w = -1;
                    double w = -1.0 / Math.Sqrt(n + n2);
                    //double w = -1.0 / n;

                    M.Set(i, j, w);
                    sum_w += w;
                }
                sum_w = -sum_w;
                M.Set(vid, vid, sum_w);
            }

            // transpose(L) * L, but matrix is symmetric...
            if (UseSoftConstraintNormalEquations)
            {
                //M = M.Multiply(M);
                // only works if M is symmetric!!
                PackedM = M.SquarePackedParallel();
            }
            else
            {
                PackedM = new PackedSparseMatrix(M);
            }

            // compute laplacian vectors of initial mesh positions
            MLx = new double[N];
            MLy = new double[N];
            MLz = new double[N];
            PackedM.Multiply(Px, MLx);
            PackedM.Multiply(Py, MLy);
            PackedM.Multiply(Pz, MLz);

            // zero out...this is the smoothing bit!
            for (int i = 0; i < Px.Length; ++i)
            {
                MLx[i] = 0;
                MLy[i] = 0;
                MLz[i] = 0;
            }

            // allocate memory for internal buffers
            Preconditioner = new DiagonalMatrix(N);
            WeightsM       = new DiagonalMatrix(N);
            Cx             = new double[N]; Cy = new double[N]; Cz = new double[N];
            Bx             = new double[N]; By = new double[N]; Bz = new double[N];
            Sx             = new double[N]; Sy = new double[N]; Sz = new double[N];

            need_solve_update = true;
            UpdateForSolve();
        }
Esempio n. 4
0
        public void Initialize()
        {
            int NV = Curve.VertexCount;

            ToCurveV = new int[NV];
            ToIndex  = new int[NV];

            N = 0;
            for (int k = 0; k < NV; k++)
            {
                int vid = k;
                ToCurveV[N]  = vid;
                ToIndex[vid] = N;
                N++;
            }

            Px         = new double[N];
            Py         = new double[N];
            Pz         = new double[N];
            nbr_counts = new int[N];
            SymmetricSparseMatrix M = new SymmetricSparseMatrix();

            for (int i = 0; i < N; ++i)
            {
                int      vid = ToCurveV[i];
                Vector3d v   = Curve.GetVertex(vid);
                Px[i]         = v.x; Py[i] = v.y; Pz[i] = v.z;
                nbr_counts[i] = (i == 0 || i == N - 1) ? 1 : 2;
            }

            // construct laplacian matrix
            for (int i = 0; i < N; ++i)
            {
                int vid = ToCurveV[i];
                int n   = nbr_counts[i];

                Index2i nbrs = Curve.Neighbours(vid);

                double sum_w = 0;
                for (int k = 0; k < 2; ++k)
                {
                    int nbrvid = nbrs[k];
                    if (nbrvid == -1)
                    {
                        continue;
                    }
                    int j  = ToIndex[nbrvid];
                    int n2 = nbr_counts[j];

                    // weight options
                    double w = -1;
                    //double w = -1.0 / Math.Sqrt(n + n2);
                    //double w = -1.0 / n;

                    M.Set(i, j, w);
                    sum_w += w;
                }
                sum_w = -sum_w;
                M.Set(vid, vid, sum_w);
            }

            // transpose(L) * L, but matrix is symmetric...
            if (UseSoftConstraintNormalEquations)
            {
                //M = M.Multiply(M);
                // only works if M is symmetric!!
                PackedM = M.SquarePackedParallel();
            }
            else
            {
                PackedM = new PackedSparseMatrix(M);
            }

            // compute laplacian vectors of initial mesh positions
            MLx = new double[N];
            MLy = new double[N];
            MLz = new double[N];
            PackedM.Multiply(Px, MLx);
            PackedM.Multiply(Py, MLy);
            PackedM.Multiply(Pz, MLz);

            // allocate memory for internal buffers
            Preconditioner = new DiagonalMatrix(N);
            WeightsM       = new DiagonalMatrix(N);
            Cx             = new double[N]; Cy = new double[N]; Cz = new double[N];
            Bx             = new double[N]; By = new double[N]; Bz = new double[N];
            Sx             = new double[N]; Sy = new double[N]; Sz = new double[N];

            need_solve_update = true;
            UpdateForSolve();
        }