Пример #1
0
                public static bool IsRotMatrix(MatrixByArr rot)
                {
                    // http://en.wikipedia.org/wiki/Rotation_matrix#Properties_of_a_rotation_matrix

                    if (rot.ColSize != 3)
                    {
                        return(false);
                    }
                    if (rot.RowSize != 3)
                    {
                        return(false);
                    }
                    // R^t = R^-1
                    // det R = 1
                    {   // (R-I)u = 0 where u is the null space of R-I
                        MatrixByArr RI = rot - LinAlg.Eye(3);
                        Vector[]    eigvec;
                        double[]    eigval;
                        NumericSolver.Eig(RI, out eigvec, out eigval);
                        double min_eigval = eigval.HAbs().Min();
                        if (min_eigval > 0.0000001)
                        {
                            return(false);
                        }
                    }
                    HDebug.ToDo("write selftest code");
                    return(true);
                }
Пример #2
0
                public static Vector GetRotAxis(MatrixByArr rot)
                {
                    HDebug.ToDo("write selftest code");
                    // http://en.wikipedia.org/wiki/Rotation_matrix#Determining_the_axis
                    //
                    // Determining the axis
                    //     Given a rotation matrix R, a vector u parallel to the rotation axis must satisfy
                    //         R u = u
                    //     since the rotation of u around the rotation axis must result in u. The equation
                    //     above may be solved for u which is unique up to a scalar factor.
                    //     Further, the equation may be rewritten
                    //         R u = I u  =>  (R-I) u = 0
                    //     which shows that u is the null space of R-I. Viewed another way, u is an eigenvector
                    //     of R corresponding to the eigenvalue λ=1(every rotation matrix must have this eigenvalue).
                    HDebug.Assert(IsRotMatrix(rot));
                    MatrixByArr RI = rot - LinAlg.Eye(3);

                    Vector[] eigvec;
                    double[] eigval;
                    NumericSolver.Eig(RI, out eigvec, out eigval);
                    int    idx  = eigval.HAbs().HIdxMin();
                    Vector axis = eigvec[idx];

                    return(axis);
                }
Пример #3
0
        public static Quaternion OptimalRotationWeighted(Vector[] p, Vector[] x, Vector up, Vector ux, double[] w)
        {
            MatrixByArr cov = CovarianceWeighted(p, x, up, ux, w);
            double      tr  = cov[0, 0] + cov[1, 1] + cov[2, 2];
            double      A23 = cov[1, 2] - cov[2, 1];
            double      A31 = cov[2, 0] - cov[0, 2];
            double      A12 = cov[0, 1] - cov[1, 0];

            MatrixByArr mat = new double[4, 4];

            mat[0, 0] = tr;
            mat[1, 0] = mat[0, 1] = A23;
            mat[2, 0] = mat[0, 2] = A31;
            mat[3, 0] = mat[0, 3] = A12;
            cov       = cov + cov.Tr();
            cov       = cov - LinAlg.Eye(3, tr);
            mat[1, 1] = cov[0, 0];
            mat[1, 2] = cov[1, 0];
            mat[1, 3] = cov[2, 0];
            mat[2, 1] = cov[0, 1];
            mat[2, 2] = cov[1, 1];
            mat[2, 3] = cov[2, 1];
            mat[3, 1] = cov[0, 2];
            mat[3, 2] = cov[1, 2];
            mat[3, 3] = cov[2, 2];

            LinAlg.Eigen eigen = new LinAlg.Eigen(mat);
            double[,] eigenD = eigen.getD();
            double[,] eigenV = eigen.getV();

            int index_max = 0;

            if (eigenD[1, 1] > eigenD[index_max, index_max])
            {
                index_max = 1;
            }
            if (eigenD[2, 2] > eigenD[index_max, index_max])
            {
                index_max = 2;
            }
            if (eigenD[3, 3] > eigenD[index_max, index_max])
            {
                index_max = 3;
            }

            Quaternion quater = new Quaternion(
                eigenV[0, index_max],
                eigenV[1, index_max],
                eigenV[2, index_max],
                eigenV[3, index_max]
                );

            return(quater);
        }
Пример #4
0
        public static void SelfTest()
        {
            if (_SelfTest == false)
            {
                return;
            }
            _SelfTest = false;
            MatrixBySparseMatrix mat = new MatrixBySparseMatrix(4, 4, 2);

            HDebug.AssertToleranceMatrix(0, mat - MatrixByArr.Zeros(4, 4));

            mat[0, 0] = mat[1, 1] = mat[2, 2] = mat[3, 3] = 1;
            HDebug.AssertToleranceMatrix(0, mat - LinAlg.Eye(4, 1));

            mat[0, 0] = mat[1, 1] = mat[2, 2] = mat[3, 3] = 0;
            HDebug.AssertToleranceMatrix(0, mat - MatrixByArr.Zeros(4, 4));
        }
Пример #5
0
        public static MatrixByArr InvSymm(MatrixByArr A)
        {
            if (HDebug.Selftest())
            {
                MatrixByArr tA = new double[, ] {
                    { 1, 2, 3 },
                    { 2, 9, 5 },
                    { 3, 5, 6 }
                };
                MatrixByArr tB0 = new double[, ] {
                    { -1.8125, -0.1875, 1.0625 },
                    { -0.1875, 0.1875, -0.0625 },
                    { 1.0625, -0.0625, -0.3125 }
                };
                MatrixByArr tI = LinAlg.Eye(3);

                MatrixByArr tB1 = InvSymm(tA);

                HDebug.AssertTolerance(0.0001, tB0 - tB1);
                HDebug.AssertTolerance(0.0001, tI - tA * tB1);
                HDebug.AssertTolerance(0.0001, tI - tB1 * tA);
            }

            HDebug.Assert(A.ColSize == A.RowSize);
            //double[] eigval;
            //double[,] eigvec;

            bool success = false;//alglib.smatrixevd(A, A.ColSize, 1, false, out eigval, out eigvec);

            if (success == false)
            {
                HDebug.Assert(false);
                return(null);
            }
            HDebug.Assert(false);
            return(null);
        }
Пример #6
0
        static public MatrixByArr Inv3x3(MatrixByArr _this)
        {
            if (HDebug.Selftest())
            {
                MatrixByArr tA = new double[, ] {
                    { 1, 2, 3 },
                    { 2, 9, 5 },
                    { 3, 5, 6 }
                };
                MatrixByArr tB0 = new double[, ] {
                    { -1.8125, -0.1875, 1.0625 },
                    { -0.1875, 0.1875, -0.0625 },
                    { 1.0625, -0.0625, -0.3125 }
                };
                MatrixByArr tI = LinAlg.Eye(3);

                MatrixByArr tB1 = Inv3x3(tA);

                HDebug.AssertTolerance(0.0001, tB0 - tB1);
                HDebug.AssertTolerance(0.0001, tI - tA * tB1);
                HDebug.AssertTolerance(0.0001, tI - tB1 * tA);
            }

            // http://www.cvl.iis.u-tokyo.ac.jp/~miyazaki/tech/teche23.html
            if (_this.RowSize != 3 || _this.ColSize != 3)
            {
                return(null);
            }

            double a11  = _this[0, 0];
            double a12  = _this[0, 1];
            double a13  = _this[0, 2];
            double a21  = _this[1, 0];
            double a22  = _this[1, 1];
            double a23  = _this[1, 2];
            double a31  = _this[2, 0];
            double a32  = _this[2, 1];
            double a33  = _this[2, 2];
            double detA = a11 * a22 * a33 + a21 * a32 * a13 + a31 * a12 * a23
                          - a11 * a32 * a23 - a31 * a22 * a13 - a21 * a12 * a33;

            MatrixByArr inv = new MatrixByArr(3, 3);

            inv[0, 0] = a22 * a33 - a23 * a32;
            inv[0, 1] = a13 * a32 - a12 * a33;
            inv[0, 2] = a12 * a23 - a13 * a22;
            inv[1, 0] = a23 * a31 - a21 * a33;
            inv[1, 1] = a11 * a33 - a13 * a31;
            inv[1, 2] = a13 * a21 - a11 * a23;
            inv[2, 0] = a21 * a32 - a22 * a31;
            inv[2, 1] = a12 * a31 - a11 * a32;
            inv[2, 2] = a11 * a22 - a12 * a21;
            inv      /= detA;

            if (HDebug.IsDebuggerAttached)
            {
                MatrixByArr I33 = _this * inv;
                for (int r = 0; r < 3; r++)
                {
                    for (int c = 0; c < 3; c++)
                    {
                        if (r == c)
                        {
                            Debug.Assert(Math.Abs(I33[r, c] - 1) < 0.00001);
                        }
                        else
                        {
                            Debug.Assert(Math.Abs(I33[r, c] - 0) < 0.00001);
                        }
                    }
                }
                I33 = inv * _this;
                for (int r = 0; r < 3; r++)
                {
                    for (int c = 0; c < 3; c++)
                    {
                        if (r == c)
                        {
                            Debug.Assert(Math.Abs(I33[r, c] - 1) < 0.00001);
                        }
                        else
                        {
                            Debug.Assert(Math.Abs(I33[r, c] - 0) < 0.00001);
                        }
                    }
                }
            }
            return(inv);
        }
Пример #7
0
        static public MatrixByArr Inv4x4(MatrixByArr _this)
        {
            if (HDebug.Selftest())
            {
                /// >> A=[ 1,2,3,4 ; 5,7,9,10 ; 13,24,52,14 ; 12,43,73,28 ]
                /// >> invA = inv(A)
                ///    -0.5599    0.2942    0.0557   -0.0529
                ///    -0.8416    0.2638   -0.1128    0.0824
                ///     0.3886   -0.1754    0.0576   -0.0216
                ///     0.5193   -0.0739   -0.0007   -0.0117
                /// >> A*invA
                ///     1.0000    0.0000         0   -0.0000
                ///    -0.0000    1.0000   -0.0000    0.0000
                ///          0    0.0000    1.0000    0.0000
                ///          0    0.0000    0.0000    1.0000
                MatrixByArr _A = new double[4, 4] {
                    { 1, 2, 3, 4 }, { 5, 7, 9, 10 }, { 13, 24, 52, 14 }, { 12, 43, 73, 28 }
                };
                MatrixByArr _invA_sol = new double[4, 4]
                {
                    { -0.5599, 0.2942, 0.0557, -0.0529 }
                    , { -0.8416, 0.2638, -0.1128, 0.0824 }
                    , { 0.3886, -0.1754, 0.0576, -0.0216 }
                    , { 0.5193, -0.0739, -0.0007, -0.0117 }
                };
                MatrixByArr _invA = Inv4x4(_A);

                double err1 = (_invA - _invA_sol).HAbsMax();
                HDebug.Assert(err1 < 0.0001);

                MatrixByArr _I     = LinAlg.Eye(4);
                MatrixByArr _AinvA = _A * _invA;
                double      err2   = (_I - _AinvA).HAbsMax();
                HDebug.Assert(err2 < 0.000000001);

                MatrixByArr _invAA = _invA * _A;
                double      err3   = (_I - _invAA).HAbsMax();
                HDebug.Assert(err3 < 0.000000001);
            }

            //////////////////////////////////////////////////////////////////////////
            // http://www.koders.com/cpp/fidFB7C4F93FDDB86E33EB66D177335BA81D86E58B5.aspx
            // Matrix.cpp
            // bool idMat4::InverseFastSelf( void )
            //////////////////////////////////////////////////////////////////////////
            //  //	6*8+2*6 = 60 multiplications
            //  //		2*1 =  2 divisions
            //  idMat2 r0, r1, r2, r3;
            //  float a, det, invDet;
            //  float *mat = reinterpret_cast<float *>(this);
            //
            //  // r0 = m0.Inverse();
            //  det = mat[0*4+0] * mat[1*4+1] - mat[0*4+1] * mat[1*4+0];
            //
            //  if ( idMath::Fabs( det ) < MATRIX_INVERSE_EPSILON ) {
            //      return false;
            //  }
            //
            //  invDet = 1.0f / det;
            //
            //  r0[0][0] =   mat[1*4+1] * invDet;
            //  r0[0][1] = - mat[0*4+1] * invDet;
            //  r0[1][0] = - mat[1*4+0] * invDet;
            //  r0[1][1] =   mat[0*4+0] * invDet;
            //
            //  // r1 = r0 * m1;
            //  r1[0][0] = r0[0][0] * mat[0*4+2] + r0[0][1] * mat[1*4+2];
            //  r1[0][1] = r0[0][0] * mat[0*4+3] + r0[0][1] * mat[1*4+3];
            //  r1[1][0] = r0[1][0] * mat[0*4+2] + r0[1][1] * mat[1*4+2];
            //  r1[1][1] = r0[1][0] * mat[0*4+3] + r0[1][1] * mat[1*4+3];
            //
            //  // r2 = m2 * r1;
            //  r2[0][0] = mat[2*4+0] * r1[0][0] + mat[2*4+1] * r1[1][0];
            //  r2[0][1] = mat[2*4+0] * r1[0][1] + mat[2*4+1] * r1[1][1];
            //  r2[1][0] = mat[3*4+0] * r1[0][0] + mat[3*4+1] * r1[1][0];
            //  r2[1][1] = mat[3*4+0] * r1[0][1] + mat[3*4+1] * r1[1][1];
            //
            //  // r3 = r2 - m3;
            //  r3[0][0] = r2[0][0] - mat[2*4+2];
            //  r3[0][1] = r2[0][1] - mat[2*4+3];
            //  r3[1][0] = r2[1][0] - mat[3*4+2];
            //  r3[1][1] = r2[1][1] - mat[3*4+3];
            //
            //  // r3.InverseSelf();
            //  det = r3[0][0] * r3[1][1] - r3[0][1] * r3[1][0];
            //
            //  if ( idMath::Fabs( det ) < MATRIX_INVERSE_EPSILON ) {
            //      return false;
            //  }
            //
            //  invDet = 1.0f / det;
            //
            //  a = r3[0][0];
            //  r3[0][0] =   r3[1][1] * invDet;
            //  r3[0][1] = - r3[0][1] * invDet;
            //  r3[1][0] = - r3[1][0] * invDet;
            //  r3[1][1] =   a * invDet;
            //
            //  // r2 = m2 * r0;
            //  r2[0][0] = mat[2*4+0] * r0[0][0] + mat[2*4+1] * r0[1][0];
            //  r2[0][1] = mat[2*4+0] * r0[0][1] + mat[2*4+1] * r0[1][1];
            //  r2[1][0] = mat[3*4+0] * r0[0][0] + mat[3*4+1] * r0[1][0];
            //  r2[1][1] = mat[3*4+0] * r0[0][1] + mat[3*4+1] * r0[1][1];
            //
            //  // m2 = r3 * r2;
            //  mat[2*4+0] = r3[0][0] * r2[0][0] + r3[0][1] * r2[1][0];
            //  mat[2*4+1] = r3[0][0] * r2[0][1] + r3[0][1] * r2[1][1];
            //  mat[3*4+0] = r3[1][0] * r2[0][0] + r3[1][1] * r2[1][0];
            //  mat[3*4+1] = r3[1][0] * r2[0][1] + r3[1][1] * r2[1][1];
            //
            //  // m0 = r0 - r1 * m2;
            //  mat[0*4+0] = r0[0][0] - r1[0][0] * mat[2*4+0] - r1[0][1] * mat[3*4+0];
            //  mat[0*4+1] = r0[0][1] - r1[0][0] * mat[2*4+1] - r1[0][1] * mat[3*4+1];
            //  mat[1*4+0] = r0[1][0] - r1[1][0] * mat[2*4+0] - r1[1][1] * mat[3*4+0];
            //  mat[1*4+1] = r0[1][1] - r1[1][0] * mat[2*4+1] - r1[1][1] * mat[3*4+1];
            //
            //  // m1 = r1 * r3;
            //  mat[0*4+2] = r1[0][0] * r3[0][0] + r1[0][1] * r3[1][0];
            //  mat[0*4+3] = r1[0][0] * r3[0][1] + r1[0][1] * r3[1][1];
            //  mat[1*4+2] = r1[1][0] * r3[0][0] + r1[1][1] * r3[1][0];
            //  mat[1*4+3] = r1[1][0] * r3[0][1] + r1[1][1] * r3[1][1];
            //
            //  // m3 = -r3;
            //  mat[2*4+2] = -r3[0][0];
            //  mat[2*4+3] = -r3[0][1];
            //  mat[3*4+2] = -r3[1][0];
            //  mat[3*4+3] = -r3[1][1];
            //
            //  return true;

            if (_this.RowSize != 4 || _this.ColSize != 4)
            {
                return(null);
            }

            MatrixByArr  mat = new MatrixByArr(_this);
            const double MATRIX_INVERSE_EPSILON = 0.000000001;

            //	6*8+2*6 = 60 multiplications
            //		2*1 =  2 divisions
            double det, invDet;

            // r0 = m0.Inverse();
            det = mat[0, 0] * mat[1, 1] - mat[0, 1] * mat[1, 0];

            if (Math.Abs(det) < MATRIX_INVERSE_EPSILON)
            {
                Debug.Assert(false);
                return(null);
            }

            invDet = 1.0f / det;

            double r0_00 = mat[1, 1] * invDet;
            double r0_01 = -mat[0, 1] * invDet;
            double r0_10 = -mat[1, 0] * invDet;
            double r0_11 = mat[0, 0] * invDet;

            // r1 = r0 * m1;
            double r1_00 = r0_00 * mat[0, 2] + r0_01 * mat[1, 2];
            double r1_01 = r0_00 * mat[0, 3] + r0_01 * mat[1, 3];
            double r1_10 = r0_10 * mat[0, 2] + r0_11 * mat[1, 2];
            double r1_11 = r0_10 * mat[0, 3] + r0_11 * mat[1, 3];

            // r2 = m2 * r1;
            double r2_00 = mat[2, 0] * r1_00 + mat[2, 1] * r1_10;
            double r2_01 = mat[2, 0] * r1_01 + mat[2, 1] * r1_11;
            double r2_10 = mat[3, 0] * r1_00 + mat[3, 1] * r1_10;
            double r2_11 = mat[3, 0] * r1_01 + mat[3, 1] * r1_11;

            // r3 = r2 - m3;
            double r3_00 = r2_00 - mat[2, 2];
            double r3_01 = r2_01 - mat[2, 3];
            double r3_10 = r2_10 - mat[3, 2];
            double r3_11 = r2_11 - mat[3, 3];

            // r3.InverseSelf();
            det = r3_00 * r3_11 - r3_01 * r3_10;

            if (Math.Abs(det) < MATRIX_INVERSE_EPSILON)
            {
                Debug.Assert(false);
                return(null);
            }

            invDet = 1.0f / det;

            double r3_00_prv = r3_00;

            r3_00 = r3_11 * invDet;
            r3_01 = -r3_01 * invDet;
            r3_10 = -r3_10 * invDet;
            r3_11 = r3_00_prv * invDet;

            // r2 = m2 * r0;
            r2_00 = mat[2, 0] * r0_00 + mat[2, 1] * r0_10;
            r2_01 = mat[2, 0] * r0_01 + mat[2, 1] * r0_11;
            r2_10 = mat[3, 0] * r0_00 + mat[3, 1] * r0_10;
            r2_11 = mat[3, 0] * r0_01 + mat[3, 1] * r0_11;

            // m2 = r3 * r2;
            mat[2, 0] = r3_00 * r2_00 + r3_01 * r2_10;
            mat[2, 1] = r3_00 * r2_01 + r3_01 * r2_11;
            mat[3, 0] = r3_10 * r2_00 + r3_11 * r2_10;
            mat[3, 1] = r3_10 * r2_01 + r3_11 * r2_11;

            // m0 = r0 - r1 * m2;
            mat[0, 0] = r0_00 - r1_00 * mat[2, 0] - r1_01 * mat[3, 0];
            mat[0, 1] = r0_01 - r1_00 * mat[2, 1] - r1_01 * mat[3, 1];
            mat[1, 0] = r0_10 - r1_10 * mat[2, 0] - r1_11 * mat[3, 0];
            mat[1, 1] = r0_11 - r1_10 * mat[2, 1] - r1_11 * mat[3, 1];

            // m1 = r1 * r3;
            mat[0, 2] = r1_00 * r3_00 + r1_01 * r3_10;
            mat[0, 3] = r1_00 * r3_01 + r1_01 * r3_11;
            mat[1, 2] = r1_10 * r3_00 + r1_11 * r3_10;
            mat[1, 3] = r1_10 * r3_01 + r1_11 * r3_11;

            // m3 = -r3;
            mat[2, 2] = -r3_00;
            mat[2, 3] = -r3_01;
            mat[3, 2] = -r3_10;
            mat[3, 3] = -r3_11;

            return(mat);
        }