private Line2 ApproximateFromTop()
    {
        //guess axis with top face(s)

        Line2 main_axis = null;

        face_center = new List <Vector2>();
        List <Vector2> normal = new List <Vector2>();

        List <double> minoraxislength = new List <double>();

        foreach (Image <Gray, byte> fimg in face_img)
        {
            Vector2        mean   = new Vector2();
            List <Vector2> points = IExtension.GetMaskPoints(fimg);
            foreach (Vector2 p in points)
            {
                mean += p;
            }
            mean /= points.Count;
            face_center.Add(mean);
            float W = points.Count;

            float[,] C = new float[2, 2];
            foreach (Vector2 point in points)
            {
                C[0, 0] += (point.x - mean.x) * (point.x - mean.x);
                C[0, 1] += (point.x - mean.x) * (point.y - mean.y);

                C[1, 0] += (point.y - mean.y) * (point.x - mean.x);
                C[1, 1] += (point.y - mean.y) * (point.y - mean.y);
            }

            C[0, 0] /= W;
            C[0, 1] /= W;
            C[1, 0] /= W;
            C[1, 1] /= W;

            Matrix2d             CM  = new Matrix2d(C);
            NumericalRecipes.SVD svd = new NumericalRecipes.SVD(C);
            //svd.w - eigenvalue, start from 1
            //svd.u - eigenvector, start from 1

            int max = 1, min = 2;
            if (svd.w[max] < svd.w[min])
            {
                int temp = max;
                max = min;
                min = temp;
            }

            float   major     = 2 * Mathf.Sqrt(svd.w[max]);
            Vector2 majoraxis = new Vector2(svd.u[1, max], svd.u[2, max]);
            majoraxis.Normalize();
            float   minor     = 2 * Mathf.Sqrt(svd.w[min]);
            Vector2 minoraxis = new Vector2(svd.u[1, min], svd.u[2, min]);
            minoraxis.Normalize();

            Vector2 majorendp   = mean + majoraxis * major;
            Vector2 majorstartp = mean - majoraxis * major;
            Vector2 minorendp   = mean + minoraxis * minor;
            Vector2 minorstartp = mean - minoraxis * minor;


            //minoraxislength.Add(Vector2.Distance(minorendp, minorstartp));
            minoraxislength.Add((double)minor * 2);
            normal.Add(Utility.PerpendicularRight(majoraxis));
            //normal.Add(majoraxis);
        }


        if (face_center.Count > 1)
        {
            //Vector2 mean_normal = normal.First();
            Line2  best_top_normal_line = new Line2(face_center.First(), normal.First(), true);
            double maxdis         = 0;
            int    farthesttopidx = 0;
            for (int i = 1; i < face_center.Count; i++)
            {
                double tofirstcenterdis = Vector2.Distance(face_center[0], face_center[i]);
                if (tofirstcenterdis > maxdis)
                {
                    maxdis         = tofirstcenterdis;
                    farthesttopidx = i;
                }
                double dis = best_top_normal_line.DistanceToLine(face_center[i]);
                if (dis > 10)
                {
                    main_axis = null;
                }
            }
            main_axis = new Line2(face_center.First(), face_center[farthesttopidx]);
        }
        else
        {
            Line2   top_normal_line = new Line2(face_center.First(), normal.First(), true);
            Vector2 online_point    = top_normal_line.GetPointwithT((float)minoraxislength[0]);
            if (online_point.x >= 0 && online_point.y >= 0 && online_point.x < body_img.Width && online_point.y < body_img.Height)
            {
                if (!this.body_img[(int)online_point.y, (int)online_point.x].Equals(new Gray(255)))
                {
                    top_normal_line.Flip();
                }
            }
            else
            {
                top_normal_line.Flip();
            }
            main_axis = top_normal_line;
        }

        return(main_axis);
    }
 public double[] SVDSingularMatW()
 {
     SVD svd = new SVD(e, row_size, row_size);
     if (svd.State == false) throw new ArithmeticException();
     return svd.w;
 }
 public Matrix4d Inverse()
 {
     SVD svd = new SVD(e, row_size, row_size);
     if (svd.State == false) throw new ArithmeticException();
     return new Matrix4d(svd.Inverse);
 }
 public double[] SVDSingularMat()
 {
     SVD svd = new SVD(e, 3, 3);
     return svd.w;
 }
 public Matrix3d OrthogonalFactorSVD()
 {
     SVD svd = new SVD(e, 3, 3);
     lastSVDIsFullRank = svd.FullRank;
     return new Matrix3d(svd.OrthogonalFactor);
 }
 public Matrix3d InverseSVD()
 {
     SVD svd = new SVD(e, 3, 3);
     Matrix3d inv = new Matrix3d(svd.Inverse);
     lastSVDIsFullRank = svd.FullRank;
     return inv;
 }