public static Matrix4d FindTransformationMatrix(List <Vector3d> pointsTarget, List <Vector3d> pointsSource, ICP_VersionUsed icpVersionUsed)
        {
            //shift points to the center of mass (centroid)
            Vector3d        centroidReference = TransformPointsUtils.CalculateCentroid(pointsTarget);
            List <Vector3d> pointsTargetShift = TransformPointsUtils.CalculatePointsShiftedByCentroid(pointsTarget, centroidReference);

            Vector3d        centroidToBeMatched = TransformPointsUtils.CalculateCentroid(pointsSource);
            List <Vector3d> pointsSourceShift   = TransformPointsUtils.CalculatePointsShiftedByCentroid(pointsSource, centroidToBeMatched);


            //calculate correlation matrix
            Matrix3d H = TransformPointsUtils.CalculateCorrelationMatrix(pointsTargetShift, pointsSourceShift);

            //Matrix3d S;
            double[] eigenvalues = new double[3];

            Matrix3d R = CalculateRotationBySingularValueDecomposition(H, pointsSourceShift, icpVersionUsed);

            double c;

            if (icpVersionUsed == ICP_VersionUsed.Scaling_Zinsser)
            {
                c = CalculateScale_Zinsser(pointsSourceShift, pointsTargetShift, ref R);
            }
            if (icpVersionUsed == ICP_VersionUsed.Scaling_Du)
            {
                Matrix3d C = CalculateScale_Du(pointsSourceShift, pointsTargetShift, R);
                R = Matrix3d.Mult(R, C);
            }

            Vector3d T = SVD.CalculateTranslation(centroidReference, centroidToBeMatched, R);



            Matrix4d myMatrix = SVD.PutTheMatrix4together(T, R);

            //double d = myMatrix.Determinant;

            return(myMatrix);
        }
        //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);
        }