private void *Factorization(CCSMatrix C) { fixed(int *ri = C.RowIndex, ci = C.ColIndex) fixed(double *val = C.Values) return(CreaterCholeskySolver(C.ColumnSize, C.NumNonZero, ri, ci, val)); }
private CCSMatrix MultiplyATA(ColMatrix A) { int[] count = new int[A.RowSize]; for (int i = 0; i < count.Length; i++) { count[i] = 0; } foreach (int[] r in A.rowIndex) { foreach (int ri in r) { count[ri]++; } } int[][] colIndex = new int[A.RowSize][]; int[][] listIndex = new int[A.RowSize][]; for (int i = 0; i < A.RowSize; i++) { colIndex[i] = new int[count[i]]; listIndex[i] = new int[count[i]]; } for (int i = 0; i < count.Length; i++) { count[i] = 0; } for (int i = 0; i < A.values.Length; i++) { int[] row = A.rowIndex[i]; for (int j = 0; j < row.Length; j++) { int r = row[j]; int c = count[r]; colIndex[r][c] = i; listIndex[r][c] = j; count[r]++; } } count = null; CCSMatrix ATA = new CCSMatrix(A.ColumnSize, A.ColumnSize); Set <int> set = new Set <int>(); double[] tmp = new double[A.ColumnSize]; List <int> ATA_RowIndex = new List <int>(); List <double> ATA_Value = new List <double>(); for (int i = 0; i < A.ColumnSize; i++) { tmp[i] = 0; } for (int j = 0; j < A.ColumnSize; j++) { for (int ri = 0; ri < A.rowIndex[j].Length; ri++) { int k = A.rowIndex[j][ri]; double val = A.values[j][ri]; for (int k2 = 0; k2 < colIndex[k].Length; k2++) { int i = colIndex[k][k2]; if (i < j) { continue; } set.Add(i); tmp[i] += val * A.values[i][listIndex[k][k2]]; } } int[] s = set.ToArray(); Array.Sort(s); int cc = 0; foreach (int k in s) { if (tmp[k] == 0) { continue; } ATA_RowIndex.Add(k); ATA_Value.Add(tmp[k]); tmp[k] = 0; cc++; } ATA.ColIndex[j + 1] = ATA.ColIndex[j] + cc; set.Clear(); } ATA.RowIndex = ATA_RowIndex.ToArray(); ATA_RowIndex = null; ATA.Values = ATA_Value.ToArray(); ATA_Value = null; return(ATA); }
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); }
private CCSMatrix MultiplyATA(CCSMatrix A) { int[] last = new int[A.RowSize]; int[] next = new int[A.NumNonZero]; int[] colIndex = new int[A.NumNonZero]; for (int i = 0; i < last.Length; i++) { last[i] = -1; } for (int i = 0; i < next.Length; i++) { next[i] = -1; } for (int i = 0; i < A.ColumnSize; i++) { for (int j = A.ColIndex[i]; j < A.ColIndex[i + 1]; j++) { int k = A.RowIndex[j]; if (last[k] != -1) { next[last[k]] = j; } last[k] = j; colIndex[j] = i; } } last = null; CCSMatrix ATA = new CCSMatrix(A.ColumnSize, A.ColumnSize); Set <int> set = new Set <int>(); double[] tmp = new double[A.ColumnSize]; List <int> ATA_RowIndex = new List <int>(); List <double> ATA_Value = new List <double>(); for (int i = 0; i < A.ColumnSize; i++) { tmp[i] = 0; } for (int j = 0; j < A.ColumnSize; j++) { for (int col = A.ColIndex[j]; col < A.ColIndex[j + 1]; col++) { int k = A.RowIndex[col]; double val = A.Values[col]; int curr = col; while (true) { int i = colIndex[curr]; set.Add(i); tmp[i] += val * A.Values[curr]; if (next[curr] != -1) { curr = next[curr]; } else { break; } } } int[] s = set.ToArray(); Array.Sort(s); int count = 0; foreach (int k in s) { if (tmp[k] == 0) { continue; } ATA_RowIndex.Add(k); ATA_Value.Add(tmp[k]); tmp[k] = 0; count++; } ATA.ColIndex[j + 1] = ATA.ColIndex[j] + count; set.Clear(); } ATA.RowIndex = ATA_RowIndex.ToArray(); ATA_RowIndex = null; ATA.Values = ATA_Value.ToArray(); ATA_Value = null; return(ATA); }
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); }