zoukankan      html  css  js  c++  java
  • C# 矩阵运算和一些基本的几何运算

    以前工作中写的,这里备个份,有可能用到

    基本的矩阵运算类,测试20阶以内应该没啥问题,超过20阶不好使。。。

     /// <summary>
        /// 矩阵   异常 512索引 1024无解 2046矩阵行列 
        /// </summary>
        public class Matrix
        {
            private int m_row;//
            private int m_col;//
            private double[,] m_data;//数据
            /// <summary>元素
            /// </summary>
            /// <param name="ro"></param>
            /// <param name="co"></param>
            /// <returns></returns>
            public double this[int ro, int co]
            {
                get
                {
                    if (ro >= m_row || co >= m_col || ro < 0 || co < 0) throw new Exception("512");
                    return m_data[ro, co];
                }
                set
                {
                    if (ro >= m_row || co >= m_col || ro < 0 || co < 0) throw new Exception("512");
                    m_data[ro, co] = value;
                }
            }
            /// <summary>行数
            /// </summary>
            public int Row
            { get { return m_row; } }
            /// <summary>列数
            /// </summary>
            public int Column
            { get { return m_col; } }
            public Matrix()
            { m_row = 0; m_col = 0; m_data = new double[0, 0]; }
            public Matrix(double[,] matrix)
            {
                m_row = matrix.GetLength(0);
                m_col = matrix.GetLength(1);
                m_data = matrix;
            }
            public Matrix(int ro, int co)
            {
                if (ro < 0 || co < 0) throw new Exception("512");
                m_row = ro;
                m_col = co;
                m_data = new double[ro, co];
            }
            public static Matrix operator *(Matrix left, Matrix right)
            {
                if (left.Column != right.Row) throw new Exception("2046");
                Matrix re = new Matrix(left.Row, right.Column);
                for (int i = 0; i < left.Row; i++)
                {
                    for (int j = 0; j < right.Column; j++)
                    {
                        for (int k = 0; k < left.Column; k++)
                        {
                            re[i, j] += left[i, k] * right[k, j];
                        }
                    }
                }
                return re;
    
            }
            public static Matrix operator +(Matrix left, Matrix right)
            {
                if (left.Row != right.Row || left.Column != right.Column)
                    throw new Exception("2046");
                Matrix re = new Matrix(left.Row, left.Column);
                for (int i = 0; i < left.Row; i++)
                {
                    for (int j = 0; j < left.Column; j++)
                    {
                        re[i, j] = left[i, j] + right[i, j];
                    }
                }
                return re;
            }
            public static Matrix operator -(Matrix left, Matrix right)
            {
                if (left.Row != right.Row || left.Column != right.Column)
                    throw new Exception("2046");
                Matrix re = new Matrix(left.Row, left.Column);
                for (int i = 0; i < left.Row; i++)
                {
                    for (int j = 0; j < left.Column; j++)
                    {
                        re[i, j] = left[i, j] - right[i, j];
                    }
                }
                return re;
            }
            public static Matrix operator *(double factor, Matrix right)
            {
                Matrix re = new Matrix(right.Row, right.Column);
                for (int i = 0; i < right.Row; i++)
                {
                    for (int j = 0; j < right.Column; j++)
                    {
                        re[i, j] = right[i, j] * factor;
                    }
                }
                return re;
            }
            public static Matrix operator *(Matrix left, double factor)
            {
                return factor * left;
            }
            /// <summary>转置
            /// </summary>
            /// <returns></returns>
            public Matrix Matrixtran()
            {
                Matrix re = new Matrix(this.m_col, this.m_row);
                for (int i = 0; i < this.m_row; i++)
                {
                    for (int j = 0; j < this.m_col; j++)
                    {
                        re[j, i] = this[i, j];
                    }
                }
                return re;
            }
            /// <summary>行列式        //加边法
            /// </summary>
            /// <param name="Matrix"></param>
            /// <returns></returns>
            public double Matrixvalue()
            {
                if (this.m_row != this.m_col)
                { throw new Exception("2046"); }
                int n = this.m_row;
                if (n == 2) return this[0, 0] * this[1, 1] - this[0, 1] * this[1, 0];
                double dsum = 0, dSign = 1;
                for (int i = 0; i < n; i++)
                {
                    Matrix tempa = new Matrix(n - 1, n - 1);
                    for (int j = 0; j < n - 1; j++)
                    {
                        for (int k = 0; k < n - 1; k++)
                        {
                            tempa[j, k] = this[j + 1, k >= i ? k + 1 : k];
                        }
                    }
                    dsum += this[0, i] * dSign * tempa.Matrixvalue();
                    dSign = dSign * -1;
                }
                return dsum;
            }
            /// <summary>求逆
            /// </summary>
            /// <param name="Matrix"></param>
            /// <returns></returns>
            public Matrix InverseMatrix()
            {
                int row = this.m_row; int col = this.m_col;
                if (row != col) throw new Exception("2046");
                Matrix re = new Matrix(row, col);
                double val = this.Matrixvalue();
                if (Math.Abs(val) <= 1E-6) { throw new Exception("1024"); }
                re = this.AdjointMatrix();
                for (int i = 0; i < row; i++)
                {
                    for (int j = 0; j < row; j++)
                    {
                        re[i, j] = re[i, j] / val;
                    }
                }
                return re;
    
            }
            /// <summary>求伴随矩阵
            /// </summary>
            /// <param name="Matrix"></param>
            /// <returns></returns>
            public Matrix AdjointMatrix()
            {
                int row = this.m_row;
                Matrix re = new Matrix(row, row);
                for (int i = 0; i < row; i++)
                {
                    for (int j = 0; j < row; j++)
                    {
                        Matrix temp = new Matrix(row - 1, row - 1);
                        for (int x = 0; x < row - 1; x++)
                        {
                            for (int y = 0; y < row - 1; y++)
                            {
                                temp[x, y] = this[x < i ? x : x + 1, y < j ? y : y + 1];
                            }
                        }
                        re[j, i] = ((i + j) % 2 == 0 ? 1 : -1) * temp.Matrixvalue();
                    }
                }
                return re;
            }
        }

    一些基本的几何运算

     public class CalcCls
        {
    
            /// <summary>
            /// 根据两点计算距离两点连线为R的两点,默认垂足为A
            /// </summary>
            /// <param name="pointa">A 已知点</param>
            /// <param name="pointb">B 已知点</param>
            /// <param name="R">距离</param>
            /// <param name="pointc">C 待求点</param>
            /// <param name="pointd">D 待求点</param>
            /// <returns>AB两点重合返回false 正常为true</returns>
            protected bool Vertical(PointXY pointa, PointXY pointb, double R,
                ref PointXY pointc, ref PointXY pointd)
            {
                try
                {
                    //(X-xa)^2+(Y-ya)^2=R*R    距离公式
                    //(X-xa)*(xb-xa)+(Y-ya)*(yb-ya)=0   垂直
                    //解方程得两点即为所求点
                    pointc.X = pointa.X - (pointb.Y - pointa.Y) * R / Distance(pointa, pointb);
                    pointc.Y = pointa.Y + (pointb.X - pointa.X) * R / Distance(pointa, pointb);
    
                    pointd.X = pointa.X + (pointb.Y - pointa.Y) * R / Distance(pointa, pointb);
                    pointd.Y = pointa.Y - (pointb.X - pointa.X) * R / Distance(pointa, pointb);
    
                    return true;
                }
                catch
                {
                    //如果A,B两点重合会报错,那样就返回false
                    return false;
                }
            }
            /// <summary> 判断pt在pa到pb的左侧</summary>
            /// <returns></returns>
            protected bool IsLeft(PointXY pa, PointXY pb, PointXY pt)
            {
                //ax+by+c=0
                double a = pb.Y - pa.Y;
                double b = pa.X - pb.X;
                double c = pb.X * pa.Y - pa.X * pb.Y;
                double d = a * pt.X + b * pt.Y + c;
                if (d < 0)
                {
                    return false;
                }
                else
                {
                    return true;
                }
            }
    
            /// <summary> 计算P1P2和P3P4两条线段所在直线的交点
            /// 如果两条线段在同一直线,返回较短的线段的端点,p2或P3</summary>
            /// <param name="pt">输出交点</param>
            /// <returns>有交点返回true 否则返回false</returns>
            protected void calcIntersectionPoint(PointXY pt1, PointXY pt2, PointXY pt3, PointXY pt4, ref PointXY pt)
            {   //ax+by=c
                double a1, b1, c1, a2, b2, c2;
                a1 = pt1.Y - pt2.Y;
                b1 = pt2.X - pt1.X;
                c1 = pt1.Y * pt2.X - pt2.Y * pt1.X;
    
                a2 = pt3.Y - pt4.Y;
                b2 = pt4.X - pt3.X;
                c2 = pt3.Y * pt4.X - pt4.Y * pt3.X;
                double db = a1 * b2 - a2 * b1;
                if (db == 0)//平行或共线
                {
                    if (a1 * pt3.X + b1 * pt3.Y == c1)//共线
                    {
                        pt = (Distance(pt1, pt2) > Distance(pt3, pt4)) ? pt3 : pt2;
                    }
                }
                else
                {
                    pt.X = (b2 * c1 - b1 * c2) / db;
                    pt.Y = (a1 * c2 - a2 * c1) / db;
                }
            }
            /// <summary>判断P1P2和P3P4线段是否相交</summary>
            protected bool IsIntersect(PointXY pt1, PointXY pt2, PointXY pt3, PointXY pt4)
            {
                //return ((max(u.s.x, u.e.x) >= min(v.s.x, v.e.x)) && //排斥实验 
                //(max(v.s.x, v.e.x) >= min(u.s.x, u.e.x)) &&
                //(max(u.s.y, u.e.y) >= min(v.s.y, v.e.y)) &&
                //(max(v.s.y, v.e.y) >= min(u.s.y, u.e.y)) &&
                //(multiply(v.s, u.e, u.s) * multiply(u.e, v.e, u.s) >= 0) && //跨立实验 
                //(multiply(u.s, v.e, v.s) * multiply(v.e, u.e, v.s) >= 0)); 
                //判断矩形是否相交
                if (Math.Max(pt1.X, pt2.X) >= Math.Min(pt3.X, pt4.X) &&
                    Math.Max(pt3.X, pt4.X) >= Math.Min(pt3.X, pt4.X) &&
                    Math.Max(pt1.Y, pt2.Y) >= Math.Min(pt3.Y, pt4.Y) &&
                    Math.Max(pt3.Y, pt4.Y) >= Math.Min(pt1.Y, pt2.Y))
                {
                    //线段跨立
                    if (multiply(pt3, pt2, pt1) * multiply(pt2, pt4, pt1) >= 0 &&
                        multiply(pt1, pt4, pt3) * multiply(pt4, pt2, pt3) >= 0)
                    {
                        return true;
                    }
    
                }
                return false;
            }
            /****************************************************************************** 
            r=multiply(sp,ep,op),得到(sp-op)*(ep-op)的叉积 
            r>0:ep在矢量opsp的逆时针方向; 
            r=0:opspep三点共线; 
            r<0:ep在矢量opsp的顺时针方向 
            *******************************************************************************/
            /// <summary> 计算p1p0和p2p0叉积 </summary>
            /// <returns></returns>
            protected double multiply(PointXY pt1, PointXY pt2, PointXY p0)
            {
                //return ((sp.x - op.x) * (ep.y - op.y) - (ep.x - op.x) * (sp.y - op.y)); 
                double mult = (pt1.X - p0.X) * (pt2.Y - p0.Y) - (pt2.X - p0.X) * (pt1.Y - p0.Y);
                return mult;
    
            }
            /// <summary>按照距离将交点排序 </summary>
            /// <param name="temline"></param>
            /// <param name="ps">起点</param>
            /// <returns></returns>
            protected PointXY[] sortPoint(PointXY[] temline, PointXY ps)
            {
                List<PointXY> lp = new List<PointXY>();
                List<PointXY> sortlp = new List<PointXY>();
                lp.AddRange(temline);
                if (temline.Length < 1) return sortlp.ToArray();
                for (; lp.Count > 1; )
                {
                    PointXY pd = lp[0];
                    for (int i = 0; i < lp.Count - 1; i++)
                    {
                        if (Distance(ps, pd) > Distance(ps, lp[i + 1]))
                        {
                            pd = lp[i + 1];
                        }
                    }
                    lp.Remove(pd);
                    sortlp.Add(pd);
                }
                sortlp.Add(lp[0]);
                return sortlp.ToArray();
            }
    
            /// <summary>
            /// 根据两点计算两点连线上距离A点L的点 输出C点为距离B近的点上的点 D为距离B远的点
            /// </summary>
            /// <param name="pointa">A点 默认为计算距离A点L的点</param>
            /// <param name="pointb">B点</param>
            /// <param name="L">距离</param>
            /// <param name="pointc">返回点C</param>
            /// <param name="pointd">返回点D 有时候没用</param>
            /// <returns></returns>
            protected bool GapP(PointXY pointa, PointXY pointb, double L, ref PointXY pointc, ref PointXY pointd)
            {
                try
                {
                    PointXY pc = new PointXY();
                    PointXY pd = new PointXY();
                    //(north-xa)^2+(east-ya)^2=L    两点距离公式
                    //(north-xa)*(ya-yb)-(east-ya)(xa-xb)=0   直线平行条件,注意,是CA和AB平行(实际是C点在AB上)
                    pc.X = pointa.X +
                        (pointa.X - pointb.X) * L / Distance(pointa, pointb);
                    pc.Y = pointa.Y +
                        (pointa.Y - pointb.Y) * L / Distance(pointa, pointb);
    
                    pd.X = pointa.X -
                        (pointa.X - pointb.X) * L / Distance(pointa, pointb);
                    pd.Y = pointa.Y -
                        (pointa.Y - pointb.Y) * L / Distance(pointa, pointb);
    
                    pointc = Distance(pc, pointb) > Distance(pd, pointb) ? pd : pc; //取距离B近的点
                    pointd = Distance(pc, pointb) > Distance(pd, pointb) ? pc : pd;//取距离B远的点
    
                    return true;
                }
                catch
                {
                    //如果A,B两点重合会报错,那样就返回false
                    return false;
                }
            }
    
            /// <summary> 返回两点的距离 </summary>
            /// <param name="pa"></param>
            /// <param name="pb"></param>
            /// <returns></returns>
            public double Distance(double xa, double ya, double xb, double yb)
            {
                double L;
                L = Math.Sqrt(Math.Pow(xa - xb, 2) + Math.Pow(ya - yb, 2));
                return L;
            }
            public double Distance(PointXY pa, PointXY pb)
            {
                return Distance(pa.X, pa.Y, pb.X, pb.Y);
            }
    
            /// <summary> 用VS自带算法判断点是否在区域内 </summary>
            /// <param name="pt"></param>
            /// <param name="pointsArray"></param>
            /// <returns></returns>
            public bool PtInPolygon(PointXY pd, PointXY[] pdsArray)
            {
                PointF pt = new PointF();
                pt.X = (float)pd.X;
                pt.Y = (float)pd.Y;
                List<Point> pl = new List<Point>();
                for (int i = 0; i < pdsArray.Length; i++)
                {
                    Point p = new Point();
                    p.X = (int)pdsArray[i].X;
                    p.Y = (int)pdsArray[i].Y;
                    pl.Add(p);
                }
                if (pl.Count < 3) return false;
                using (System.Drawing.Drawing2D.GraphicsPath gp = new System.Drawing.Drawing2D.GraphicsPath())
                {
                    gp.AddPolygon(pl.ToArray());
                    return gp.IsVisible(pt);
                }
            }
    
            /// <summary>
            /// 求线段的方位角0-360
            /// </summary>
            /// <param name="pa">线段起点</param>
            /// <param name="pb">线段终点</param>
            /// <returns>从0度顺时针偏转到该线段所划过的角度</returns>
            protected double Angle(PointXY pa, PointXY pb)
            {
                double Ang = 0;
                double a;
                try
                {
                    a = Math.Acos((pb.X - pa.X) / Distance(pa, pb));
    
                    if (pb.Y - pa.Y < 0)
                    {
                        a = 2 * Math.PI - a;
                    }
                    Ang = a * 180d / Math.PI;
                    return Ang;
                }
                catch
                {
                    Ang = 0;
                    return Ang;
                }
            }
    
            /// <summary>角度到弧度</summary>
            /// <param name="value"></param>
            /// <returns></returns>
            private double AngleToRadian(double value)
            {
                return value * Math.PI / 180d;
            }
    
            /// <summary> 弧度到角度</summary>
            /// <param name="value"></param>
            /// <returns></returns>
            private double RadianToAngle(double value)
            {
                return value * 180d / Math.PI;
            }
    
        }
    
        public struct PointXY
        {
            public double Y;
            public double X;
     
        }
  • 相关阅读:
    Linux c++ time different
    数据库初始化以及制作为Windows服务
    数据库无法注册服务
    JS中String转int
    数据库服务注册(使用命令注册):解决my.ini配置文件不存在的问题
    数据库启动丢失MSVCP120.dll
    jQuery
    BOM和DOM
    用yield实现python协程
    深入理解python中的yield关键字
  • 原文地址:https://www.cnblogs.com/onegarden/p/5622166.html
Copyright © 2011-2022 走看看