private static Matrix4d PutTheMatrix4together(Vector3d T, Matrix3d Rotation)
        {
            //put the 4d matrix together
            Matrix3d r3D      = MatrixUtilsOpenTK.Matrix3dfromMatrix3d(Rotation);
            Matrix4d myMatrix = new Matrix4d(r3D);

            myMatrix[0, 3] = T.X;
            myMatrix[1, 3] = T.Y;
            myMatrix[2, 3] = T.Z;
            myMatrix[3, 3] = 1D;
            //myMatrix[0, 3] = T.X;
            //myMatrix[3, 1] = T.Y;
            //myMatrix[3, 2] = T.Z;
            //myMatrix[3, 3] = 1D;
            return(myMatrix);
        }
        private static double CalculateScale_Zinsser(List <Vector3d> pointsSourceShift, List <Vector3d> pointsTargetShift, ref Matrix3d R)
        {
            double   sum1   = 0;
            double   sum2   = 0;
            Matrix3d RT     = Matrix3d.Transpose(R);
            Matrix3d checkT = Matrix3d.Mult(RT, R);

            Matrix4d R4D = PutTheMatrix4together(Vector3d.Zero, R);

            //Matrix4d R4DT = Matrix4d.Transpose(R4D);


            //double check = 0;

            //Matrix4d checkIdentity = Matrix4d.Mult(R4DT, R4D);

            //checkIdentity = Matrix4d.Mult(R4DT, R4D);
            for (int i = 0; i < pointsSourceShift.Count; i++)
            {
                //Vector3d v = Vector3d.TransformNormalInverse(pointsSourceShift[i], R4D);


                Vector3d v = Vector3d.TransformNormalInverse(pointsSourceShift[i], R4D);
                //v = Matrix3d.Tr Vector3d.TransformNormal(pointsSourceShift[i], R4D);
                v = R.TransformVector(pointsSourceShift[i]);

                //v = Vector3d.TransformVector(pointsSourceShift[i], R4D);
                //v = Vector3d.TransformNormalInverse(pointsSourceShift[i], R4D);



                sum1 += Vector3d.Dot(v, pointsTargetShift[i]);
                sum2 += Vector3d.Dot(pointsSourceShift[i], pointsSourceShift[i]);
            }

            double c = sum1 / sum2;

            R = MatrixUtilsOpenTK.MultiplyScalar3D(R, c);
            return(c);
        }
Exemple #3
0
        public void GetOrientationWXYZ(double[] wxyz)
        {
            int i;

            Matrix3d ortho = new Matrix3d();

            for (i = 0; i < 3; i++)
            {
                ortho[0, i] = Matrix[0, i];
                ortho[1, i] = Matrix[1, i];
                ortho[2, i] = Matrix[2, i];
            }
            if (ortho.Determinant < 0)
            {
                ortho[0, i] = -ortho[0, i];
                ortho[1, i] = -ortho[1, i];
                ortho[2, i] = -ortho[2, i];
            }
            double[,] orthoArray = MatrixUtilsOpenTK.MatrixToDoubleArray(ortho);
            MathUtils.Matrix3x3ToQuaternion(orthoArray, wxyz);

            // calc the return value wxyz
            double mag = Math.Sqrt(wxyz[1] * wxyz[1] + wxyz[2] * wxyz[2] + wxyz[3] * wxyz[3]);

            if ((int)mag != 0)
            {
                wxyz[0]  = 2.0 * Math.Acos(wxyz[0]) / MathBase.DegreesToRadians;
                wxyz[1] /= mag;
                wxyz[2] /= mag;
                wxyz[3] /= mag;
            }
            else
            {
                wxyz[0] = 0.0;
                wxyz[1] = 0.0;
                wxyz[2] = 0.0;
                wxyz[3] = 1.0;
            }
        }
        private static double CalculateScale_Umeyama(List <Vector3d> pointsSourceShift, double[] eigenvalues, Matrix3d K2)
        {
            double sigmaSquared = 0f;

            for (int i = 0; i < pointsSourceShift.Count; i++)
            {
                sigmaSquared += MatrixUtilsOpenTK.Norm(pointsSourceShift[i]);
            }

            sigmaSquared /= pointsSourceShift.Count;

            double c = 0.0F;

            for (int i = 0; i < 3; i++)
            {
                c += eigenvalues[i];
            }
            if (K2[2, 2] < 0)
            {
                c -= 2 * eigenvalues[2];
            }
            c = c / sigmaSquared;
            return(c);
        }
        //other methods for SVD, for possible later usage
        //MathUtils.SingularValueDecomposition3x3(Harray, Uarray, warray, VTarray);
        //MathNet.Numerics.Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider svd = new MathNet.Numerics.Providers.LinearAlgebra.Mkl.MklLinearAlgebraProvider();
        //double[] a = MatrixUtilsNumerics.doubleFromArrayDouble(Harray);
        //double[] u = MatrixUtilsNumerics.doubleFromArrayDouble(Uarray);
        //double[] vt = MatrixUtilsNumerics.doubleFromArrayDouble(Uarray);
        //double[] s = new double[3];
        //svd.SingularValueDecomposition(true, a, 3, 3, s, u, vt);
        private static Matrix3d CalculateRotationBySingularValueDecomposition(Matrix3d H, List <Vector3d> pointsSourceShift, ICP_VersionUsed icpVersionUsed)
        {
            double[,] Harray  = TransformPointsUtils.DoubleArrayFromMatrix(H);
            double[,] Uarray  = new double[3, 3];
            double[,] VTarray = new double[3, 3];
            double[] eigenvalues = new double[3];


            //trial 3:
            alglib.svd.rmatrixsvd(Harray, 3, 3, 2, 2, 2, ref eigenvalues, ref Uarray, ref VTarray);


            Matrix3d U  = MatrixUtilsOpenTK.DoubleArrayToMatrix3d(Uarray);
            Matrix3d VT = MatrixUtilsOpenTK.DoubleArrayToMatrix3d(VTarray);
            Matrix3d R  = Matrix3d.Mult(U, VT);

            Matrix3d UT    = Matrix3d.Transpose(U);
            Matrix3d V     = Matrix3d.Transpose(VT);
            Matrix3d Rtest = Matrix3d.Mult(UT, V);
            //R = Rtest;

            Matrix3d checkShouldGiveI = Matrix3d.Mult(UT, U);

            checkShouldGiveI = Matrix3d.Mult(VT, V);
            Matrix3d RT = Matrix3d.Transpose(R);

            checkShouldGiveI = Matrix3d.Mult(RT, R);
            //see article by Umeyama

            //if (H.Determinant < 0)
            //{
            //    R[2, 2] = -R[2, 2];
            //    //S[2, 2] = -1;
            //}

            //calculate the sign matrix for using the scale factor
            Matrix3d K2    = Matrix3d.Identity;
            double   check = U.Determinant * VT.Determinant;

            //if (check < 0 && Math.Abs(check) > 1E-3)
            //{
            //    K2[2, 2] = -1;
            //}

            RT = Matrix3d.Transpose(R);
            checkShouldGiveI = Matrix3d.Mult(RT, R);

            double scale = CalculateScale_Umeyama(pointsSourceShift, eigenvalues, K2);

            R = Matrix3d.Mult(R, K2);
            if (icpVersionUsed == ICP_VersionUsed.Scaling_Umeyama)
            {
                //R = Matrix3d.Mult(R, K2);
                R = MatrixUtilsOpenTK.MultiplyScalar3D(R, scale);
            }
            ////check eigenvectors
            //Matrix3d Snew = Matrix3d.Mult(U, MatrixUtilsOpenTK.Matrix3FromMatrix3d(H));
            //Snew = Matrix3d.Mult(Snew, VT);

            //Matrix3d si = S.Inverted();
            //Matrix3d Rnew = Matrix3d.Mult(VT, si);
            //Rnew = Matrix3d.Mult(Rnew, U);

            //Rnew = Matrix3d.Mult(VT, S);
            //Rnew = Matrix3d.Mult(Rnew, U);

            return(R);
        }
Exemple #6
0
        public void GetOrientation(double[] orientation, Matrix4 amatrix)
        {
            int i;

            // convenient access to matrix
            //double[] matrixElement = amatrix;
            //float[,] ortho = new float[3, 3];
            Matrix3d ortho = new Matrix3d();

            for (i = 0; i < 3; i++)
            {
                ortho[0, i] = amatrix[0, i];
                ortho[1, i] = amatrix[1, i];
                ortho[2, i] = amatrix[2, i];
            }

            if (ortho.Determinant < 0)
            {
                ortho[0, 2] = -ortho[0, 2];
                ortho[1, 2] = -ortho[1, 2];
                ortho[2, 2] = -ortho[2, 2];
            }
            double[,] orthoArray = MatrixUtilsOpenTK.MatrixToDoubleArray(ortho);
            MathUtils.Orthogonalize3x3(orthoArray, orthoArray);

            // first rotate about y axis
            double x2 = ortho[2, 0];
            double y2 = ortho[2, 1];
            double z2 = ortho[2, 2];

            double x3 = ortho[1, 0];
            double y3 = ortho[1, 1];
            double z3 = ortho[1, 2];

            double d1 = Math.Sqrt(x2 * x2 + z2 * z2);

            double cosTheta;
            double sinTheta;

            if (d1 < AXIS_EPSILON)
            {
                cosTheta = 1.0;
                sinTheta = 0.0;
            }
            else
            {
                cosTheta = z2 / d1;
                sinTheta = x2 / d1;
            }

            double theta = Math.Atan2(sinTheta, cosTheta);

            orientation[1] = -theta / MathBase.DegreesToRadians;

            // now rotate about x axis
            double d = Math.Sqrt(x2 * x2 + y2 * y2 + z2 * z2);

            double sinPhi;
            double cosPhi;

            if (d < AXIS_EPSILON)
            {
                sinPhi = 0.0;
                cosPhi = 1.0;
            }
            else if (d1 < AXIS_EPSILON)
            {
                sinPhi = y2 / d;
                cosPhi = z2 / d;
            }
            else
            {
                sinPhi = y2 / d;
                cosPhi = (x2 * x2 + z2 * z2) / (d1 * d);
            }

            double phi = Math.Atan2(sinPhi, cosPhi);

            orientation[0] = phi / MathBase.DegreesToRadians;

            // finally, rotate about z
            double x3p = x3 * cosTheta - z3 * sinTheta;
            double y3p = -sinPhi * sinTheta * x3 + cosPhi * y3 - sinPhi * cosTheta * z3;
            double d2  = Math.Sqrt(x3p * x3p + y3p * y3p);

            double cosAlpha;
            double sinAlpha;

            if (d2 < AXIS_EPSILON)
            {
                cosAlpha = 1.0;
                sinAlpha = 0.0;
            }
            else
            {
                cosAlpha = y3p / d2;
                sinAlpha = x3p / d2;
            }

            double alpha = Math.Atan2(sinAlpha, cosAlpha);

            orientation[2] = alpha / MathBase.DegreesToRadians;
        }