Пример #1
0
        public void EigenValueDecomposition2()
        {
            double[][]              evals = { new double[] { 0.0, 1.0, 0.0, 0.0 }, new double[] { 1.0, 0.0, 2e-7, 0.0 }, new double[] { 0.0, -2e-7, 0.0, 1.0 }, new double[] { 0.0, 0.0, 1.0, 0.0 } };
            GeneralMatrix           A     = new GeneralMatrix(evals);
            EigenvalueDecomposition Eig   = A.Eigen();
            GeneralMatrix           D     = Eig.D;
            GeneralMatrix           V     = Eig.GetV();

            Assert.IsTrue(GeneralTests.Check(A.Multiply(V), V.Multiply(D)));
        }
Пример #2
0
        private static void CalculatePCA(List <Point3D> _points, out Point3D pivotO,
                                         out Vector3D vecX, out Vector3D vecY, out Vector3D vecZ)
        {
            pivotO = new Point3D(0, 0, 0);
            vecX   = new Vector3D(0, 0, 0);
            vecY   = new Vector3D(0, 0, 0);
            vecZ   = new Vector3D(0, 0, 0);
            if (_points == null || _points.Count < 1)
            {
                return;
            }

            Point3D pivot = GeometricTransforms.GetPivot(_points);

            pivotO = new Point3D(pivot.X, pivot.Y, pivot.Z);
            List <Vector3D> point_deviations = _points.Select(x => x - pivot).ToList();
            int             nrP = _points.Count;

            #region COVARIANCE:Old
            //// compute the covariance matrix
            //double[] m = new double[3*nrP];
            //for(int i = 0; i < nrP; i++)
            //{
            //    m[i*3] = point_deviations[i].X;
            //    m[i*3 + 1] = point_deviations[i].Y;
            //    m[i*3 + 2] = point_deviations[i].Z;
            //}
            //MatrixNxN M = new MatrixNxN(nrP, 3, m);
            //MatrixNxN MtxM = MatrixNxN.Squared(M);
            //MtxM.Scale(1.0 / nrP);
            #endregion

            // compute the covariance matrix ...
            // using 3rd party library DotNetMatrix
            double[][] pd_as_array = new double[nrP][];
            for (int i = 0; i < nrP; i++)
            {
                pd_as_array[i] = new double[] { point_deviations[i].X, point_deviations[i].Y, point_deviations[i].Z };
            }
            GeneralMatrix gm_M    = new GeneralMatrix(pd_as_array);
            GeneralMatrix gm_Mt   = gm_M.Transpose();
            GeneralMatrix gm_Msq  = gm_Mt.Multiply(gm_M);
            GeneralMatrix gm_Msqn = gm_Msq.Multiply(1.0 / nrP);

            // extract the sorted Eigenvalues of the matrix...
            // using 3rd party library DotNetMatrix
            EigenvalueDecomposition decomp  = gm_Msqn.Eigen();
            GeneralMatrix           gm_EVec = decomp.GetV();
            double[] gm_EVal = decomp.RealEigenvalues;

            // from smallest to largest eigenvalue
            vecX = new Vector3D(gm_EVec.GetElement(0, 0), gm_EVec.GetElement(1, 0), gm_EVec.GetElement(2, 0));
            vecY = new Vector3D(gm_EVec.GetElement(0, 1), gm_EVec.GetElement(1, 1), gm_EVec.GetElement(2, 1));
            vecZ = new Vector3D(gm_EVec.GetElement(0, 2), gm_EVec.GetElement(1, 2), gm_EVec.GetElement(2, 2));
        }
Пример #3
0
        public void CalculateEigenvalueDecomposition()
        {
            double[] i = new double[3];
            double[] j = new double[3];
            double[] k = new double[3];
            double[] u = new double[3];

            double[] t_vol = new double[3];
            double[] vol   = new double[3];
            vol[0] = 0;
            vol[1] = 0;
            vol[2] = 0;

            double[] func_sum = new double[3];
            func_sum[0] = 0;
            func_sum[1] = 0;
            func_sum[2] = 0;

            double[] func_sum_inertia = new double[3];
            func_sum_inertia[0] = 0;
            func_sum_inertia[1] = 0;
            func_sum_inertia[2] = 0;

            double func_sum_xy = 0;
            double func_sum_xz = 0;
            double func_sum_yz = 0;

            double surfaceArea = 0;

            //loop through all the triangles
            for (int count = 0; count < _connections.Length; count++)
            {
                //get the 3 points of the triangle
                double[] p1 = new double[3];
                double[] p2 = new double[3];
                double[] p3 = new double[3];

                //Fix so its relative to the centroid center of mass
                p1[0] = (double)_pts[_connections[count][0]][0] - _centroid[0]; //fix x's first
                p2[0] = (double)_pts[_connections[count][1]][0] - _centroid[0];
                p3[0] = (double)_pts[_connections[count][2]][0] - _centroid[0];

                p1[1] = (double)_pts[_connections[count][0]][1] - _centroid[1]; //fix y's
                p2[1] = (double)_pts[_connections[count][1]][1] - _centroid[1];
                p3[1] = (double)_pts[_connections[count][2]][1] - _centroid[1];

                p1[2] = (double)_pts[_connections[count][0]][2] - _centroid[2]; //fix z's
                p2[2] = (double)_pts[_connections[count][1]][2] - _centroid[2];
                p3[2] = (double)_pts[_connections[count][2]][2] - _centroid[2];

                //calculate the i, j, k vectors
                i[0] = p2[0] - p1[0]; j[0] = p2[1] - p1[1]; k[0] = p2[2] - p1[2];
                i[1] = p3[0] - p1[0]; j[1] = p3[1] - p1[1]; k[1] = p3[2] - p1[2];
                i[2] = p3[0] - p2[0]; j[2] = p3[1] - p2[1]; k[2] = p3[2] - p2[2];

                //cross product between two vectors, to determine normal vector
                u[0] = j[0] * k[1] - k[0] * j[1];
                u[1] = k[0] * i[1] - i[0] * k[1];
                u[2] = i[0] * j[1] - j[0] * i[1];

                //Normalize vector to 1
                double norm = Math.Sqrt(u[0] * u[0] + u[1] * u[1] + u[2] * u[2]);
                if (norm != 0.0)
                {
                    u[0] = u[0] / norm;
                    u[1] = u[1] / norm;
                    u[2] = u[2] / norm;
                }
                else
                {
                    u[0] = 0.0;
                    u[1] = 0.0;
                    u[2] = 0.0;
                }

                //This is reduced to ...

                //area of a triangle...
                double a    = Math.Sqrt(i[1] * i[1] + j[1] * j[1] + k[1] * k[1]);
                double b    = Math.Sqrt(i[0] * i[0] + j[0] * j[0] + k[0] * k[0]);
                double c    = Math.Sqrt(i[2] * i[2] + j[2] * j[2] + k[2] * k[2]);
                double s    = 0.5 * (a + b + c);
                double area = Math.Sqrt(Math.Abs(s * (s - a) * (s - b) * (s - c)));
                //patches(count,1) = area
                //
                surfaceArea += area;

                //volume elements ...
                double zavg = (p1[2] + p2[2] + p3[2]) / 3.0;
                double yavg = (p1[1] + p2[1] + p3[1]) / 3.0;
                double xavg = (p1[0] + p2[0] + p3[0]) / 3.0;

                //sum of function for centroid calculation
                func_sum[0] += t_vol[0] * xavg;
                func_sum[1] += t_vol[1] * yavg;
                func_sum[2] += t_vol[2] * zavg;

                //sum of function for inertia calculation
                func_sum_inertia[0] += area * u[0] * xavg * xavg * xavg;
                func_sum_inertia[1] += area * u[1] * yavg * yavg * yavg;
                func_sum_inertia[2] += area * u[2] * zavg * zavg * zavg;

                //sum of function for products of inertia calculation
                func_sum_xz += area * u[0] * xavg * xavg * zavg;
                func_sum_xy += area * u[1] * yavg * yavg * xavg;
                func_sum_yz += area * u[2] * zavg * zavg * yavg;
            }

            func_sum_inertia[0] /= 3;
            func_sum_inertia[1] /= 3;
            func_sum_inertia[2] /= 3;

            double Ixy = -1 * func_sum_xy / 2;
            double Ixz = -1 * func_sum_xz / 2;
            double Iyz = -1 * func_sum_yz / 2;
            double Iyx = Ixy;
            double Izx = Ixz;
            double Izy = Iyz;

            double Ixx = func_sum_inertia[1] + func_sum_inertia[2];
            double Iyy = func_sum_inertia[0] + func_sum_inertia[2];
            double Izz = func_sum_inertia[0] + func_sum_inertia[1];

            GeneralMatrix i_CoM = new GeneralMatrix(3, 3);

            i_CoM.Array[0][0] = Ixx;
            i_CoM.Array[0][1] = Ixy;
            i_CoM.Array[0][2] = Ixz;

            i_CoM.Array[1][0] = Iyx;
            i_CoM.Array[1][1] = Iyy;
            i_CoM.Array[1][2] = Iyz;

            i_CoM.Array[2][0] = Izx;
            i_CoM.Array[2][1] = Izy;
            i_CoM.Array[2][2] = Izz;

            EigenvalueDecomposition eig = i_CoM.Eigen();

            _eigenvalues  = eig.D;
            _eigenvectors = eig.GetV();
            //make sure this is a right handed matrix
            if (_eigenvectors.Determinant() < 0)
            {
                _eigenvectors = _eigenvectors.Multiply(-1);
            }
        }