// In perspective mode, the warping functions are: // x' = (a0 + a1 x + a2 y) / (c0 x + c1 y + 1) // y' = (b0 + b1 x + b2 y) / (c0 x + c1 y + 1) // // The following calculates the factors a#, b# and c#. // We do this by creating a set of eight equations with a#, b# and c# as unknowns. // The equations are derived by: // 1. substituting the srcPoints for (x, y); // 2. substituting the corresponding destPoints for (x', y'); // 3. solving the resulting set of equations, with the factors as unknowns. // // The equations are like these: // a0 x a1 y a2 0 0 0 -xx'c0 -yx'c1 = x' // 0 0 0 b0 x b1 y b2 -xy'c0 -yy'c1 = y' // The known factors of left hand side ar put in the 8x8 matrix mxLeft for // all four point pairs, and the right hand side in the one column matrix mxRight. // After solving, m_mxWarpFactors contains a0, a1, a2, b0, b1, b2, c0, c1. private void PreCalc(PointD[] destPoints, PointD[] srcPoints) { var mxLeft = new GeneralMatrix(8, 8); //mxLeft.Null(); var mxRight = new GeneralMatrix(8, 1); var row = 0; for (int i = 0; i < 4; i++) { mxLeft.Array[row][0] = 1.0; mxLeft.Array[row][1] = srcPoints[i].X; mxLeft.Array[row][2] = srcPoints[i].Y; mxLeft.Array[row][6] = -srcPoints[i].X * destPoints[i].X; mxLeft.Array[row][7] = -srcPoints[i].Y * destPoints[i].X; mxRight.Array[row][0] = destPoints[i].X; row++; mxLeft.Array[row][3] = 1.0f; mxLeft.Array[row][4] = srcPoints[i].X; mxLeft.Array[row][5] = srcPoints[i].Y; mxLeft.Array[row][6] = -srcPoints[i].X * destPoints[i].Y; mxLeft.Array[row][7] = -srcPoints[i].Y * destPoints[i].Y; mxRight.Array[row][0] = destPoints[i].Y; row++; } _mxWarpFactors = mxLeft.Solve(mxRight); }
public void SolveLinear() { double[][] subavals = { new double[] { 5.0, 8.0, 11.0 }, new double[] { 6.0, 9.0, 12.0 } }; double[][] sqSolution = { new double[] { 13.0 }, new double[] { 15.0 } }; GeneralMatrix sub = new GeneralMatrix(subavals); GeneralMatrix o = new GeneralMatrix(sub.RowDimension, 1, 1.0); GeneralMatrix sol = new GeneralMatrix(sqSolution); GeneralMatrix sq = sub.GetMatrix(0, sub.RowDimension - 1, 0, sub.RowDimension - 1); Assert.IsTrue(GeneralTests.Check(sq.Solve(sol), o)); }
// In bilinear mode, the warping functions are: // x' = a0 + a1 x y + a2 x + a3 y // y' = b0 + b1 x y + b2 x + b3 y // // Here, we have two sets of four equations. In the first set, the a# factors // are the unknowns, in the second set the b# factors. // The equations are of the form: // a0 + xy a1 + x a2 + y a3 = x' // The left hand side is identical for both sets. The right hand side differs. // Therefore, we can solve them in one operation. // The left hand side factors are put in the 4x4 matrix mxLeft, the right side // factors are put in the 4x2 matrix mxRight. // After solving, the first column of m_mxWarpFactors contains a0, a1, a2, a3; the // second columne contains b0, b1, b2, b3. private void PreCalc(PointD[] destPoints, PointD[] srcPoints) { var mxLeft = new GeneralMatrix(4, 4); var mxRight = new GeneralMatrix(4, 2); for (int row = 0; row < 4; row++) { mxLeft.Array[row][0] = 1.0; mxLeft.Array[row][1] = srcPoints[row].X * srcPoints[row].Y; mxLeft.Array[row][2] = srcPoints[row].X; mxLeft.Array[row][3] = srcPoints[row].Y; mxRight.Array[row][0] = destPoints[row].X; mxRight.Array[row][1] = destPoints[row].Y; } _mxWarpFactors = mxLeft.Solve(mxRight); }
public void TestSolve() { GeneralMatrix _ls = new GeneralMatrix(2, 2); _ls.SetElement(0, 0, 1); _ls.SetElement(0, 1, 2); _ls.SetElement(1, 0, 3); _ls.SetElement(1, 1, 4); GeneralMatrix _rs = new GeneralMatrix(2, 1); _rs.SetElement(0, 0, -3); _rs.SetElement(1, 0, -5); GeneralMatrix _solution = _ls.Solve(_rs); Assert.AreEqual(_solution.GetElement(0, 0), 1); Assert.AreEqual(_solution.GetElement(1, 0), -2); }
private void computeaccCalButton_Click(object sender, EventArgs e) { int i, j; calStatusText.Text = "Computing Calibration..."; // Construct D matrix // D = [x.^2, y.^2, z.^2, x.*y, x.*z, y.*z, x, y, z, ones(N,1)]; for (i = 0; i < SAMPLES; i++) { // x^2 term D.SetElement(i, 0, loggedData[i, 0] * loggedData[i, 0]); // y^2 term D.SetElement(i, 1, loggedData[i, 1] * loggedData[i, 1]); // z^2 term D.SetElement(i, 2, loggedData[i, 2] * loggedData[i, 2]); // x*y term D.SetElement(i, 3, loggedData[i, 0] * loggedData[i, 1]); // x*z term D.SetElement(i, 4, loggedData[i, 0] * loggedData[i, 2]); // y*z term D.SetElement(i, 5, loggedData[i, 1] * loggedData[i, 2]); // x term D.SetElement(i, 6, loggedData[i, 0]); // y term D.SetElement(i, 7, loggedData[i, 1]); // z term D.SetElement(i, 8, loggedData[i, 2]); // Constant term D.SetElement(i, 9, 1); } // QR=triu(qr(D)) QRDecomposition QR = new QRDecomposition(D); // [U,S,V] = svd(D) SingularValueDecomposition SVD = new SingularValueDecomposition(QR.R); GeneralMatrix V = SVD.GetV(); GeneralMatrix A = new GeneralMatrix(3, 3); double[] p = new double[V.RowDimension]; for (i = 0; i < V.RowDimension; i++) { p[i] = V.GetElement(i, V.ColumnDimension - 1); } /* * A = [p(1) p(4)/2 p(5)/2; * p(4)/2 p(2) p(6)/2; * p(5)/2 p(6)/2 p(3)]; */ if (p[0] < 0) { for (i = 0; i < V.RowDimension; i++) { p[i] = -p[i]; } } A.SetElement(0, 0, p[0]); A.SetElement(0, 1, p[3] / 2); A.SetElement(1, 2, p[4] / 2); A.SetElement(1, 0, p[3] / 2); A.SetElement(1, 1, p[1]); A.SetElement(1, 2, p[5] / 2); A.SetElement(2, 0, p[4] / 2); A.SetElement(2, 1, p[5] / 2); A.SetElement(2, 2, p[2]); CholeskyDecomposition Chol = new CholeskyDecomposition(A); GeneralMatrix Ut = Chol.GetL(); GeneralMatrix U = Ut.Transpose(); double[] bvect = { p[6] / 2, p[7] / 2, p[8] / 2 }; double d = p[9]; GeneralMatrix b = new GeneralMatrix(bvect, 3); GeneralMatrix v = Ut.Solve(b); double vnorm_sqrd = v.GetElement(0, 0) * v.GetElement(0, 0) + v.GetElement(1, 0) * v.GetElement(1, 0) + v.GetElement(2, 0) * v.GetElement(2, 0); double s = 1 / Math.Sqrt(vnorm_sqrd - d); GeneralMatrix c = U.Solve(v); for (i = 0; i < 3; i++) { c.SetElement(i, 0, -c.GetElement(i, 0)); } U = U.Multiply(s); for (i = 0; i < 3; i++) { for (j = 0; j < 3; j++) { calMat[i, j] = U.GetElement(i, j); } } for (i = 0; i < 3; i++) { bias[i] = c.GetElement(i, 0); } accAlignment00.Text = calMat[0, 0].ToString(); accAlignment01.Text = calMat[0, 1].ToString(); accAlignment02.Text = calMat[0, 2].ToString(); accAlignment10.Text = calMat[1, 0].ToString(); accAlignment11.Text = calMat[1, 1].ToString(); accAlignment12.Text = calMat[1, 2].ToString(); accAlignment20.Text = calMat[2, 0].ToString(); accAlignment21.Text = calMat[2, 1].ToString(); accAlignment22.Text = calMat[2, 2].ToString(); biasX.Text = bias[0].ToString(); biasY.Text = bias[1].ToString(); biasZ.Text = bias[2].ToString(); calStatusText.Text = "Done"; flashCommitButton.Enabled = true; accAlignmentCommitButton.Enabled = true; }
internal void FillInFendu(SaveFileDialog saveFileDialog1) { bool docopen = false; Input askdlg = new Input(); decimal t_start; decimal t_end; Dictionary <Decimal, Decimal> points = new Dictionary <Decimal, Decimal>(); /*points[-55] = 78.2953M; * points[-40] = 84.2496M; * points[-20] = 92.1416M; * points[0] = 99.9841M; * points[50] = 119.4089M; * points[100] = 138.5204M; * points[125] = 147.9672M; */ #region input askdlg.Message = "请输入铂电阻的出厂编号"; if (askdlg.ShowDialog() != DialogResult.OK) { return; } string ccbh = askdlg.result; string ibcid = ""; string pageid = ""; //search the corresponding page id and ibc ids for (int ibc = 0; ibc < 12; ibc++) { pageid = "abcdef"[ibc / 4].ToString(); if (!IsValueAvailable(new string[] { "m_" + (ibc + 1).ToString() + "_ccbh" })) { continue; } if (StrValue("m_" + (ibc + 1).ToString() + "_ccbh") == ccbh) { ibcid = (ibc + 1).ToString(); for (int iwd = 1; iwd <= 3; iwd++) { if (!IsValueAvailable(new string[] { "m_" + pageid + "_" + iwd.ToString() + "jddwd", "c_" + (ibc + 1).ToString() + "_" + iwd.ToString() + "bc" })) { continue; } string wdd = StrValue("m_" + pageid + "_" + iwd.ToString() + "jddwd").Trim(); if (wdd == "") { continue; } string sjz = FormatValue(data_record.Property("c_" + (ibc + 1).ToString() + "_" + iwd.ToString() + "sjzbc"), false); points[Decimal.Parse(wdd)] = Decimal.Parse(sjz); } } } if (points.Count <= 0) { MessageBox.Show("未找到出厂编号为" + ccbh + "的铂电阻,请检查后再试"); return; } #endregion double r0 = 999; if (points.ContainsKey(0)) { r0 = Convert.ToDouble(points[0]); } else { MessageBox.Show("未发现0℃温度点实际值,无法计算分度表"); return; } double[][] mn = new double[3][]; double[] yn = new double[3]; decimal ptn1, ptn2, ptn3; ptn1 = 1000; ptn2 = 0; ptn3 = -1000; mn[0] = new double[3]; mn[1] = new double[3]; mn[2] = new double[3]; decimal ptp1, ptp2; ptp1 = 1000; ptp2 = -1000; double[][] mp = new double[2][]; mp[0] = new double[2]; mp[1] = new double[2]; double[] yp = new double[2]; //count points for range int np = 0; int nn = 0; foreach (Decimal d in points.Keys) { double dv; if ((d < 0) && (d >= -200)) { if (d < ptn1) { ptn2 = ptn1; ptn1 = d; } if (d > ptn3) { ptn2 = ptn3; ptn3 = d; } if (points.ContainsKey(ptn1)) { dv = Convert.ToDouble(ptn1); mn[0][0] = dv; mn[0][1] = dv * dv; mn[0][2] = (dv - 100) * dv * dv * dv; yn[0] = Convert.ToDouble(points[ptn1]) / r0 - 1; } if (points.ContainsKey(ptn2)) { dv = Convert.ToDouble(ptn2); mn[1][0] = dv; mn[1][1] = dv * dv; mn[1][2] = (dv - 100) * dv * dv * dv; yn[1] = Convert.ToDouble(points[ptn2]) / r0 - 1; } if (points.ContainsKey(ptn3)) { dv = Convert.ToDouble(ptn3); mn[2][0] = dv; mn[2][1] = dv * dv; mn[2][2] = (dv - 100) * dv * dv * dv; yn[2] = Convert.ToDouble(points[ptn3]) / r0 - 1; } nn++; } if ((d > 0) && (d <= 850)) { if (d < ptp1) { ptp1 = d; dv = Convert.ToDouble(ptp1); mp[0][0] = dv; mp[0][1] = dv * dv; yp[0] = Convert.ToDouble(points[ptp1]) / r0 - 1; } if (d > ptp2) { ptp2 = d; dv = Convert.ToDouble(ptp2); mp[1][0] = dv; mp[1][1] = dv * dv; yp[1] = Convert.ToDouble(points[ptp2]) / r0 - 1; } np++; } } if (ptn1 > 0) { ptn1 = 0; } if (ptp2 < 0) { ptp2 = 0; } askdlg.Message = "请输入分度表起始温度"; if (askdlg.ShowDialog() != DialogResult.OK) { return; } if (!Decimal.TryParse(askdlg.result, out t_start) || (t_start < ptn1)) { MessageBox.Show("无效的起始温度,分度表不能外插"); return; } askdlg.Message = "请输入分度表结束温度"; if (askdlg.ShowDialog() != DialogResult.OK) { return; } if (!Decimal.TryParse(askdlg.result, out t_end) || (t_end > ptp2)) { MessageBox.Show("无效的结束温度,分度表不能外插"); return; } Decimal s = t_start; Decimal e = t_end; if ((s < 0) && (nn < 3)) { MessageBox.Show("检定点不足。-200℃ ~ 0 ℃的分度表计算至少有需要3个检定点."); return; } if ((e > 0) && (np < 2)) { MessageBox.Show("检定点不足。0℃ ~ 850 ℃的分度表计算至少有需要2个检定点."); return; } double[] xn = new double[3]; //A,B,C double[] xp = new double[2]; //A,B GeneralMatrix gxn; GeneralMatrix gxp; if (nn >= 3) { GeneralMatrix gm = new GeneralMatrix(mn); gxn = gm.Solve(new GeneralMatrix(yn, yn.Length)); xn[0] = gxn.GetElement(0, 0); xn[1] = gxn.GetElement(1, 0); xn[2] = gxn.GetElement(2, 0); } if (np >= 2) { GeneralMatrix gm = new GeneralMatrix(mp); gxp = gm.Solve(new GeneralMatrix(yp, yp.Length)); xp[0] = gxp.GetElement(0, 0); xp[1] = gxp.GetElement(1, 0); } List <string> rows = new List <string>(); while (s <= e) { double sv = Convert.ToDouble(s); if (s < 0) { rows.Add(String.Format("{0}\t{1:F4}", s.ToString(), r0 * (1 + xn[0] * sv + xn[1] * sv * sv + xn[2] * (sv - 100) * sv * sv * sv))); } else { rows.Add(String.Format("{0}\t{1:F4}", s.ToString(), r0 * (1 + xp[0] * sv + xp[1] * sv * sv))); } s = s + 1; } saveFileDialog1.DefaultExt = ".doc"; saveFileDialog1.Filter = "DOC File(*.doc)|*.doc|All Files(*.*)|*.*"; saveFileDialog1.FileName = DateTime.Now.ToString("yyyy-MM-dd") + "分度表证书.doc"; if (saveFileDialog1.ShowDialog() != DialogResult.OK) { return; } string tofile = saveFileDialog1.FileName; try { string tmpl = "分度表"; string src = Path.Combine(Util.basedir, "报告模板\\" + tmpl + ".doc"); File.Copy(src, tofile, true); doctool.PrepareWord(tofile); docopen = true; doctool.FillInTableByBookMarks("ITEMS", rows); doctool.FillInHeader(tofile, data_record.Properties(), ibcid, Microsoft.Office.Interop.Word.WdSeekView.wdSeekCurrentPageHeader); doctool.FillInHeader(tofile, data_record.Properties(), ibcid, Microsoft.Office.Interop.Word.WdSeekView.wdSeekPrimaryHeader); doctool.SaveWord(tofile); MessageBox.Show("导出" + tmpl + "成功"); docopen = false; return; } catch (Exception ex) { MessageBox.Show("导出报告失败: " + ex.Message); if (docopen) { doctool.SaveWord(tofile); } docopen = false; } }