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 void ComputeLocalTransformation() { Vector3d[][] newCenter = FindIsolineCenter(); double[][] tx = new double[3][]; for (int i = 0; i < 3; i++) { tx[i] = new double[hf.Length * (regionNum + 1) * 4]; } // for each handle int txIndex = 0; for (int i = 0; i < hf.Length; i++) { // for each isoline now for (int j = 0; j < isolineVertices[i].Length; j++) { Matrix3d UUT = new Matrix3d(); Matrix3d VUT = new Matrix3d(); int stepSize = 1; for (int k = j - stepSize; k <= j + stepSize; k++) { //int k = j; if (k < 0) { continue; } if (k >= isolineVertices[i].Length) { continue; } foreach (int index in isolineVertices[i][k]) { int c = index * 3; Vector3d u = new Vector3d(oldVertexPos, c) - isolineCenter[i][j]; Vector3d v = new Vector3d(mesh.VertexPos, c) - newCenter[i][j]; UUT += u.OuterCross(u); VUT += v.OuterCross(u); } } Matrix3d T = VUT * UUT.Inverse(); Matrix3d R = T.OrthogonalFactor(10e-6); Vector3d t = newCenter[i][j]; // -isolineCenter[i][j]; //R = R.Transpose(); tx[0][txIndex] = R[0, 0]; tx[0][txIndex + 1] = R[0, 1]; tx[0][txIndex + 2] = R[0, 2]; tx[0][txIndex + 3] = t[0]; tx[1][txIndex] = R[1, 0]; tx[1][txIndex + 1] = R[1, 1]; tx[1][txIndex + 2] = R[1, 2]; tx[1][txIndex + 3] = t[1]; tx[2][txIndex] = R[2, 0]; tx[2][txIndex + 1] = R[2, 1]; tx[2][txIndex + 2] = R[2, 2]; tx[2][txIndex + 3] = t[2]; txIndex += 4; } } double[][] x = new double[3][]; for (int i = 0; i < 3; i++) { x[i] = new double[colMT.ColumnSize]; colMT.PreMultiply(tx[i], x[i]); } for (int i = 0, j = 0; i < mesh.VertexCount; i++, j += 3) { if (mesh.Flag[i] != 0) { continue; } mesh.VertexPos[j] = x[0][i]; mesh.VertexPos[j + 1] = x[1][i]; mesh.VertexPos[j + 2] = x[2][i]; } }
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); }