public double[][] SolveSystem(double[] lapWeight, double[] posWeight)
        {
            int vn = mesh.VertexCount;
            int fn = mesh.FaceCount;

            double[][] pos = new double[3][];
            pos[0] = new double[vn];
            pos[1] = new double[vn];
            pos[2] = new double[vn];
//          for (int i = 0; i < simplifiedMeshes[0].Count; i++)
//          {
//              int j = simplifiedMeshes[0][i].index;
//              pos[0][j] = mesh.VertexPos[j * 3];
//              pos[1][j] = mesh.VertexPos[j * 3 + 1];
//              pos[2][j] = mesh.VertexPos[j * 3 + 2];
//          }
            for (int i = 0; i < vn; i++)
            {
                int j = i;
                pos[0][j] = mesh.VertexPos[j * 3];
                pos[1][j] = mesh.VertexPos[j * 3 + 1];
                pos[2][j] = mesh.VertexPos[j * 3 + 2];
            }

            this.originalArea = new double[vn];
            for (int i = 0; i < vn; i++)
            {
                originalArea[i] = 0;
            }
            for (int i = 0, j = 0; i < fn; i++, j += 3)
            {
                int    c1   = mesh.FaceIndex[j];
                int    c2   = mesh.FaceIndex[j + 1];
                int    c3   = mesh.FaceIndex[j + 2];
                double area = mesh.ComputeFaceArea(i);
                originalArea[c1] += area;
                originalArea[c2] += area;
                originalArea[c3] += area;
            }

            double weightAdjustment = Math.Pow((simplificationRatio), simplifiedMeshes.Count - 1);

            weightAdjustment = 1.0;
            for (int level = 0; level < simplifiedMeshes.Count; level++)
            {
                ColMatrix colA   = BuildMatrixA(simplifiedMeshes[level], faceRecords[level], lapWeight, posWeight, weightAdjustment);
                CCSMatrix ccsATA = MultiplyATA(colA);
                //CCSMatrix ccsA = new CCSMatrix(A);
                //RowBasedMatrix rbA = new RowBasedMatrix(A); A = null;
                List <VertexRecord> records = simplifiedMeshes[level];
                int      n      = records.Count;
                double[] x      = new double[n];
                double[] b      = new double[n * 2];
                double[] ATb    = new double[n];
                double[] inv    = null;
                void *   solver = null;
                string   s      = "";
                s += weightAdjustment.ToString();
                //weightAdjustment /= (simplificationRatio);

                if (level == 0)
                {
                    solver = Factorization(ccsATA);
                    if (solver == null)
                    {
                        throw new Exception();
                    }
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        b[j] = 0;
                        int k = records[j].index;
                        b[j + n] = mesh.VertexPos[k * 3 + i] * posWeight[k] * (currentArea[j] / originalArea[k]);
                        //b[j + n] = mesh.VertexPos[k * 3 + i] * posWeight[k];
                        //x[j] = mesh.VertexPos[k * 3 + i];
                        x[j] = pos[i][k];
                    }
                    colA.PreMultiply(b, ATb);

                    if (level == 0)
                    {
                        fixed(double *_x = x, _ATb = ATb)
                        Solve(solver, _x, _ATb);
                    }
                    else
                    {
                        int iter = colA.ATACG(x, ATb, convergeRatio, n);
                        s += " " + iter;
                    }

                    //if (level == 0)
                    for (int j = 0; j < n; j++)
                    {
                        int k = records[j].index;
                        pos[i][k] = x[j];
                        //Program.PrintText(x[j].ToString());
                    }
                }

                if (solver != null)
                {
                    FreeSolver(solver);
                    solver = null;
                }

                if (level < simplifiedMeshes.Count - 1)
                {
                    //Program.PrintText(collapsedRecords[level].Count.ToString());
                    foreach (EdgeRecord rec in collapsedRecords[level])
                    {
                        Vector3d p = new Vector3d();
                        foreach (int j in rec.adjV)
                        {
                            p.x += pos[0][j];
                            p.y += pos[1][j];
                            p.z += pos[2][j];
                        }
                        pos[0][rec.vIndex] = p.x /= rec.adjV.Count;
                        pos[1][rec.vIndex] = p.y /= rec.adjV.Count;
                        pos[2][rec.vIndex] = p.z /= rec.adjV.Count;
                    }
                }
                Program.PrintText(s);
            }
            return(pos);
        }
        public double[][] SolveSystem(double[] lapWeight, double[] posWeight)
        {
            #region Init Variables
            int        vn  = mesh.VertexCount;
            int        fn  = mesh.FaceCount;
            double[][] pos = new double[3][];
            pos[0] = new double[vn];
            pos[1] = new double[vn];
            pos[2] = new double[vn];
            for (int i = 0, j = 0; i < vn; i++, j += 3)
            {
                pos[0][i] = mesh.VertexPos[j];
                pos[1][i] = mesh.VertexPos[j + 1];
                pos[2][i] = mesh.VertexPos[j + 2];
            }
            #endregion

            for (int level = 0; level < resolutions.Count; level++)
            {
                Resolution r = resolutions[level];

                // build matrix
                ColMatrix colA   = BuildMatrixA(r, lapWeight, posWeight);
                CCSMatrix ccsATA = MultiplyATA(colA);
                string    s      = "#: " + r.vertexList.Length + " iter: ";

                // solve system
                int      n      = r.vertexList.Length;
                double[] x      = new double[n];
                double[] b      = new double[n * 2];
                double[] ATb    = new double[n];
                void *   solver = null;
                if (level == 0)
                {
                    solver = Factorization(ccsATA);
                }

                for (int i = 0; i < 3; i++)
                {
                    for (int j = 0; j < n; j++)
                    {
                        b[j] = 0;
                        int k = r.vertexList[j];
                        //b[j + n] = mesh.VertexPos[k * 3 + i] * posWeight[k] * (currentArea[j] / originalArea[k]);
                        b[j + n] = mesh.VertexPos[k * 3 + i] * posWeight[k];
                        //x[j] = mesh.VertexPos[k * 3 + i];
                        x[j] = pos[i][k];
                    }
                    colA.PreMultiply(b, ATb);

                    if (level == 0)
                        fixed(double *_x = x, _ATb = ATb)
                        Solve(solver, _x, _ATb);
                    else
                    {
                        int iter = colA.ATACG(x, ATb, convergeRatio, n);
                        s += " " + iter;
                    }

                    //if (level == resolutions.Count-1)
                    for (int j = 0; j < n; j++)
                    {
                        pos[i][r.vertexList[j]] = x[j];
                    }
                }
                Program.PrintText(s);

                // interpolation solution
                if (level < resolutions.Count - 1)
                {
                    for (int i = 0; i < r.collapsedIndex.Length; i++)
                    {
                        int      index     = r.collapsedIndex[i];
                        Vector3d p         = new Vector3d();
                        double   totWeight = 0;
                        foreach (int adj in r.weight[i].Keys)
                        {
                            double w = r.weight[i][adj];
                            p.x       += pos[0][adj] * w;
                            p.y       += pos[1][adj] * w;
                            p.z       += pos[2][adj] * w;
                            totWeight += w;
                        }
                        pos[0][index] = p.x /= totWeight;
                        pos[1][index] = p.y /= totWeight;
                        pos[2][index] = p.z /= totWeight;
                    }
                }
            }

            return(pos);
        }