28

WPF 画一个3D矩形并旋转

 4 years ago
source link: http://www.cnblogs.com/T-ARF/p/12045857.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

具体的代码还是线性代数。

主要是旋转和平移。

这个例子的中模型是在世界原点建立。所以旋转会以自身轴心旋转。

如果不在世界原点建立模型,还想以自身为旋转轴旋转。

则是需要以下步骤:

模型的中心点为V1(100,100,0)假设中心为轴(平行于Y轴),旋转A度,也就是说自身中心点的Y轴旋转。

步骤:

(1)v1平移到世界原点后其他八个顶点的坐标。(中心点坐标的三个参数如果是大于0就是(每个)顶点减去相对应XYZ,如果中心点坐标的三个参数如果是小于0,则是(每个)顶点加上相对应XYZ,或者使用平移矩阵)

(2)(每个)顶点先是平移到V1在原点时的所在的位置,再使用旋转矩阵经行旋转

(3) (每个)旋转后的顶点在平移回中心点原先所在位置。

ATP 附加属性类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Media3D;
using System.Windows.Shapes;

namespace ATP
{
    public class ATP_Y
    {
        public static readonly DependencyProperty P_YProperty = DependencyProperty.RegisterAttached("P_Y", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_YChanged)));

        private static void OnP_YChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PY = (double)e.NewValue;
            Draw(d, X, Y, Z);
        }

        public static void SetP_Y(DependencyObject d, double v) => d.SetValue(P_YProperty, v);

        public static double GetP_Y(DependencyObject d) => (double)d.GetValue(P_YProperty);

        public static readonly DependencyProperty P_XProperty = DependencyProperty.RegisterAttached("P_X", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_XChanged)));

        private static void OnP_XChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PX= (double)e.NewValue;
            Draw(d, X, Y, Z);
        }

     

        public static void SetP_X(DependencyObject d, double v) => d.SetValue(P_XProperty, v);

        public static double GetP_X(DependencyObject d) => (double)d.GetValue(P_XProperty);

        public static readonly DependencyProperty P_ZProperty = DependencyProperty.RegisterAttached("P_Z", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_ZChanged)));

        private static void OnP_ZChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            PZ = (double)e.NewValue;
            Draw(d, X, Y, Z);
        }


        public static void SetP_Z(DependencyObject d, double v) => d.SetValue(P_ZProperty, v);

        public static double GetP_Z(DependencyObject d) => (double)d.GetValue(P_ZProperty);

       
        public static readonly DependencyProperty ModeDataProperty = DependencyProperty.RegisterAttached("ModeData", typeof(Point3D), typeof(ATP_Y), new PropertyMetadata(new Point3D(10, 10, 10), new PropertyChangedCallback(OnModeDataChanged)));

        public static void SetModeData(DependencyObject d, Point3D v) => d.SetValue(ModeDataProperty, v);

        public static Point3D GetModeData(DependencyObject d) => (Point3D)d.GetValue(ModeDataProperty);

        private static void OnModeDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var data = (Point3D)e.NewValue;
            ModeWidth = data.X;
            ModeHeight = data.Y;
            ModeZWidth = data.Z;
            Draw(d,X,Y,Z);
        }

        public static readonly DependencyProperty YProperty = DependencyProperty.RegisterAttached("Y", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnYChanged)));

        public static void SetY(DependencyObject d, double v) => d.SetValue(YProperty, v);

        public static double GetY(DependencyObject d) => (double)d.GetValue(YProperty);

        public static readonly DependencyProperty XProperty = DependencyProperty.RegisterAttached("X", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnXChanged)));

        private static void OnXChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var deg = Math.PI / 180 * (double)e.NewValue;
            X = deg;
            Draw(d, deg, Y, Z);
        }

        public static void SetX(DependencyObject d, double v) => d.SetValue(XProperty, v);

        public static double GetX(DependencyObject d) => (double)d.GetValue(XProperty);

        public static readonly DependencyProperty ZProperty = DependencyProperty.RegisterAttached("Z", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnZChanged)));

        private static void OnZChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var deg = Math.PI / 180 * (double)e.NewValue;
            Z = deg;
            Draw(d, X, Y, deg);
        }

        public static void SetZ(DependencyObject d, double v) => d.SetValue(ZProperty, v);

        public static double GetZ(DependencyObject d) => (double)d.GetValue(ZProperty);

        private static void OnYChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var deg = Math.PI / 180 * (double)e.NewValue;
            Y = deg;
            Draw(d, X, deg, Z);
        }

        private static double PX, PY, PZ;
        private static double X, Y, Z;
        private static double ModeHeight, ModeWidth, ModeZWidth;
        private static void Draw(DependencyObject d, double X, double Y, double Z)
        {
            var ui = d as Grid;
            ui.Children.Clear();
            var rect = new Rect(new Size(ModeWidth,ModeHeight));
            Group[0] = new Point3D(rect.Width / 2, rect.Height / 2, -(ModeZWidth/2));
            Group[1] = new Point3D(0 - (rect.Width / 2), rect.Height / 2, -(ModeZWidth / 2));
            Group[2] = new Point3D(0 - (rect.Width / 2), 0 - (rect.Height / 2), -(ModeZWidth / 2));
            Group[3] = new Point3D((rect.Width / 2), 0 - (rect.Height / 2), -(ModeZWidth / 2));
            Group[4] = new Point3D(rect.Width / 2, rect.Height / 2, (ModeZWidth / 2));
            Group[5] = new Point3D(0 - (rect.Width / 2), rect.Height / 2, (ModeZWidth / 2));
            Group[6] = new Point3D(0 - (rect.Width / 2), 0 - (rect.Height / 2), (ModeZWidth / 2));
            Group[7] = new Point3D((rect.Width / 2), 0 - (rect.Height / 2), (ModeZWidth / 2));

            for (var i = 0; i < 8; i++)
                PP[i] = PSP(ReturnP3D(Y轴转置矩阵(X, Y, Z) * GetMatrixMP(Group[i])), new Rect(new Size(Math.Max(rect.Height, rect.Width),ModeZWidth)));


            Set(0, 1, ui,Colors.Black);
            Set(1, 2, ui,Colors.Blue);
            Set(2, 3, ui, Colors.Red);
            Set(3, 0, ui, Colors.Fuchsia);
            Set(4, 5, ui, Colors.DarkSlateBlue);
            Set(5, 6, ui, Colors.Red);
            Set(6, 7, ui, Colors.Red);
            Set(7, 4, ui, Colors.Red);
            Set(0, 4, ui, Colors.Red);
            Set(1, 5, ui, Colors.Red);
            Set(2, 6, ui, Colors.Red);
            Set(3, 7, ui, Colors.Red);
        }
        private static void Set(int g1, int g2, Grid g,Color A)
        {
            var c1 = new Line();
            c1.Stroke = new SolidColorBrush(A);
            c1.X1 = PP[g1].X;
            c1.Y1 = PP[g1].Y;
            c1.X2 = PP[g2].X;
            c1.Y2 = PP[g2].Y;
            g.Children.Add(c1);
        }
        private static Matrix GetMatrixMP(Point3D MP)
        {
            var D = new double[4, 1];
            D[0, 0] = MP.X;
            D[1, 0] = MP.Y;
            D[2, 0] = MP.Z;
            D[3, 0] = 1;
            return new Matrix(D);
        }
        private static Point3D ReturnP3D(Matrix MP) => new Point3D(MP[0, 0], MP[1, 0], MP[2, 0]);

        private static Point PSP(Point3D ModePoint, Rect rect)
        {
            Point3D vp = new Point3D(PX, PY, Math.Max(rect.Height, rect.Width)+PZ);
            Point p;
            int x, y;
            x = (int)(vp.X + (ModePoint.X - vp.X) * vp.Z / (vp.Z - ModePoint.Z + 0.5));
            y = (int)(vp.Y + (ModePoint.Y - vp.Y) * vp.Z / (vp.Z - ModePoint.Z + 0.5));
            p = new Point(x, y);
            return p;
        }
        private static Point3D[] Group = new Point3D[8];
        private static Point[] PP = new Point[8];
        private static Matrix Y轴转置矩阵(double DegX, double DegY, double DegZ)
        {
            var A = new double[4, 4];
            A[0, 0] = 1;
            A[0, 1] = 0;
            A[0, 2] = 0;
            A[1, 0] = 0;
            A[1, 1] = Math.Cos(X);
            A[1, 2] = Math.Sin(X);
            A[2, 0] = 0;
            A[2, 1] = 0 - Math.Sin(X);
            A[2, 2] = Math.Cos(X);
            A[0, 3] = 0;
            A[1, 3] = 0;
            A[2, 3] = 0;
            A[3, 0] = 1;
            A[3, 1] = 1;
            A[3, 2] = 1;
            A[3, 3] = 1;
            var B = new double[4, 4];
            B[0, 0] = Math.Cos(Y);
            B[0, 1] = 0;
            B[0, 2] = -Math.Sin(Y);
            B[1, 0] = 0;
            B[1, 1] = 1;
            B[1, 2] = 0;
            B[2, 0] = Math.Sin(Y);
            B[2, 1] = 0;
            B[2, 2] = Math.Cos(Y);
            B[0, 3] = 1;
            B[1, 3] = 1;
            B[2, 3] = 1;
            B[3, 0] = 1;
            B[3, 1] = 1;
            B[3, 2] = 1;
            B[3, 3] = 1;
            var C = new double[4, 4];
            C[0, 0] = Math.Cos(Z);
            C[0, 1] = Math.Sin(Z);
            C[0, 2] = 0;
            C[1, 0] = 0 - Math.Sin(Z);
            C[1, 1] = Math.Cos(Z);
            C[1, 2] = 0;
            C[2, 0] = 0;
            C[2, 1] = 0;
            C[2, 2] = 1;
            C[0, 3] = 1;
            C[1, 3] = 1;
            C[2, 3] = 1;
            B[3, 0] = 1;
            B[3, 1] = 1;
            B[3, 2] = 1;
            C[3, 3] = 1;
            Matrix MT1 = new Matrix(A);
            Matrix MT2 = new Matrix(B);
            Matrix MT3 = new Matrix(C);
            var MT4 = MT1 * MT2;
            return MT4 * MT3;
        }
    }
}

xaml代码

//其中ModeData的三个参数为矩形的长高宽

//X,Y,Z为轴的旋转角度

<Window x:Class="ATP.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:ATP"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid> <Grid.RowDefinitions>
            <RowDefinition Height="*"/>
            <RowDefinition Height="auto"/>
        </Grid.RowDefinitions>
        <Grid x:Name="G"  local:ATP_Y.P_Z="{Binding ElementName=s4,Path=Value}"  local:ATP_Y.ModeData="100,100,100"  HorizontalAlignment="Center" VerticalAlignment="Center" local:ATP_Y.Y="{Binding ElementName=s2,Path=Value}"  local:ATP_Y.X="{Binding ElementName=s1,Path=Value}" local:ATP_Y.Z="{Binding ElementName=s3,Path=Value}"/>
        <StackPanel Grid.Row="1">
            <!--X轴旋转-->
            <Slider Minimum="0"  Maximum="360" x:Name="s1"/>
            <!--Y轴旋转-->
            <Slider Minimum="0"  Maximum="360" x:Name="s2"/>
            <!--Z轴旋转-->
            <Slider Minimum="0"  Maximum="360" x:Name="s3"/>
            <!--视野远近-->
            <Slider Minimum="0"  Maximum="360" x:Name="s4" />
        </StackPanel>
    </Grid>
</Window>

矩阵类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ATP
{
   [Serializable]
        public class Matrix
        {
            public double[] element;
            private int rows = 0;
            private int cols = 0;
            /// <summary>
            /// 获取矩阵行数
            /// </summary>
            public int Rows
            {
                get
                {
                    return rows;
                }
            }
            /// <summary>
            /// 获取矩阵列数
            /// </summary>
            public int Cols
            {
                get
                {
                    return cols;
                }
            }
            /// <summary>
            /// 获取或设置第i行第j列的元素值
            /// </summary>
            /// <param name="i">第i行</param>
            /// <param name="j">第j列</param>
            /// <returns>返回第i行第j列的元素值</returns>
            public double this[int i, int j]
            {
                get
                {
                    if (i < Rows && j < Cols)
                    {
                        return element[i * cols + j];
                    }
                    else
                    {
                        throw new Exception("索引越界");
                    }
                }
                set
                {
                    element[i * cols + j] = value;
                }
            }
            /// <summary>
            /// 用二维数组初始化Matrix
            /// </summary>
            /// <param name="m">二维数组</param>
            public Matrix(double[][] m)
            {
                this.rows = m.GetLength(0);
                this.cols = m.GetLength(1);
                int count = 0;
                this.element = new double[Rows * Cols];
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        element[count++] = m[i][j];
                    }
                }
            }
            public Matrix(double[,] m)
            {
                this.rows = m.GetLength(0);
                this.cols = m.GetLength(1);
                this.element = new double[this.rows * this.cols];
                int count = 0;
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        element[count++] = m[i, j];
                    }
                }
            }
            public Matrix(List<List<double>> m)
            {
                this.rows = m.Count;
                this.cols = m[0].Count;
                this.element = new double[Rows * Cols];
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        this[i, j] = m[i][j];
                    }
                }
            }
            #region 矩阵数学运算
            public static Matrix MAbs(Matrix a)
            {
                Matrix _thisCopy = a.DeepCopy();
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        _thisCopy[i, j] = Math.Abs(a[i, j]);
                    }
                }
                return _thisCopy;
            }
            /// <summary>
            /// 矩阵相加
            /// </summary>
            /// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
            /// <param name="b">第二个矩阵</param>
            /// <returns>返回矩阵相加后的结果</returns>
            public static Matrix operator +(Matrix a, Matrix b)
            {
                if (a.cols == b.cols && a.rows == b.rows)
                {
                    double[,] res = new double[a.rows, a.cols];
                    for (int i = 0; i < a.Rows; i++)
                    {
                        for (int j = 0; j < a.Cols; j++)
                        {
                            res[i, j] = a[i, j] + b[i, j];
                        }
                    }
                    return new Matrix(res);
                }
                else
                {
                    throw new Exception("两个矩阵行列不相等");
                }
            }
            /// <summary>
            /// 矩阵相减
            /// </summary>
            /// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
            /// <param name="b">第二个矩阵</param>
            /// <returns>返回矩阵相减后的结果</returns>
            public static Matrix operator -(Matrix a, Matrix b)
            {
                if (a.cols == b.cols && a.rows == b.rows)
                {
                    double[,] res = new double[a.rows, a.cols];
                    for (int i = 0; i < a.Rows; i++)
                    {
                        for (int j = 0; j < a.Cols; j++)
                        {
                            res[i, j] = a[i, j] - b[i, j];
                        }
                    }
                    return new Matrix(res);
                }
                else
                {
                    throw new Exception("两个矩阵行列不相等");
                }
            }
            /// <summary>
            /// 对矩阵每个元素取相反数
            /// </summary>
            /// <param name="a">二维矩阵</param>
            /// <returns>得到矩阵的相反数</returns>
            public static Matrix operator -(Matrix a)
            {
                Matrix res = a;
                for (int i = 0; i < a.rows; i++)
                {
                    for (int j = 0; j < a.cols; j++)
                    {
                        res.element[i * a.cols + j] = -res.element[i * a.cols + j];
                    }
                }
                return res;
            }
            /// <summary>
            /// 矩阵相乘
            /// </summary>
            /// <param name="a">第一个矩阵</param>
            /// <param name="b">第二个矩阵,这个矩阵的行要与第一个矩阵的列相等</param>
            /// <returns>返回相乘后的一个新的矩阵</returns>
            public static Matrix operator *(Matrix a, Matrix b)
            {
                if (a.cols == b.rows)
                {
                    double[,] res = new double[a.rows, b.cols];
                    for (int i = 0; i < a.rows; i++)
                    {
                        for (int j = 0; j < b.cols; j++)
                        {
                            for (int k = 0; k < a.cols; k++)
                            {
                                res[i, j] += a[i, k] * b[k, j];
                            }
                        }
                    }
                    return new Matrix(res);
                }
                else
                {
                    throw new Exception("两个矩阵行和列不等");
                }
            }
            /// <summary>
            /// 矩阵与数相乘
            /// </summary>
            /// <param name="a">第一个矩阵</param>
            /// <param name="num">一个实数</param>
            /// <returns>返回相乘后的新的矩阵</returns>
            public static Matrix operator *(Matrix a, double num)
            {
                Matrix res = a;
                for (int i = 0; i < a.rows; i++)
                {
                    for (int j = 0; j < a.cols; j++)
                    {
                        res.element[i * a.cols + j] *= num;
                    }
                }
                return res;
            }
            /// <summary>
            /// 矩阵转置
            /// </summary>
            /// <returns>返回当前矩阵转置后的新矩阵</returns>
            public Matrix Transpose()
            {
                double[,] res = new double[cols, rows];
                {
                    for (int i = 0; i < cols; i++)
                    {
                        for (int j = 0; j < rows; j++)
                        {
                            res[i, j] = this[j, i];
                        }
                    }
                }
                return new Matrix(res);
            }
            /// <summary>
            /// 矩阵求逆
            /// </summary>
            /// <returns>返回求逆后的新的矩阵</returns>
            public Matrix Inverse()
            {
                //最后原始矩阵并不变,所以需要深拷贝一份
                Matrix _thisCopy = this.DeepCopy();
                if (cols == rows && this.Determinant() != 0)
                {
                    //初始化一个同等大小的单位阵
                    Matrix res = _thisCopy.EMatrix();
                    for (int i = 0; i < rows; i++)
                    {
                        //首先找到第i列的绝对值最大的数,并将该行和第i行互换
                        int rowMax = i;
                        double max = Math.Abs(_thisCopy[i, i]);
                        for (int j = i; j < rows; j++)
                        {
                            if (Math.Abs(_thisCopy[j, i]) > max)
                            {
                                rowMax = j;
                                max = Math.Abs(_thisCopy[j, i]);
                            }
                        }
                        //将第i行和找到最大数那一行rowMax交换
                        if (rowMax != i)
                        {
                            _thisCopy.Exchange(i, rowMax);
                            res.Exchange(i, rowMax);

                        }
                        //将第i行做初等行变换,将第一个非0元素化为1
                        double r = 1.0 / _thisCopy[i, i];
                        _thisCopy.Exchange(i, -1, r);
                        res.Exchange(i, -1, r);
                        //消元
                        for (int j = 0; j < rows; j++)
                        {
                            //到本行后跳过
                            if (j == i)
                                continue;
                            else
                            {
                                r = -_thisCopy[j, i];
                                _thisCopy.Exchange(i, j, r);
                                res.Exchange(i, j, r);
                            }
                        }
                    }
                    return res;
                }
                else
                {
                    throw new Exception("矩阵不是方阵无法求逆");
                }
            }
            #region 重载比较运算符
            public static bool operator <(Matrix a, Matrix b)
            {
                bool issmall = true;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] >= b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public static bool operator >(Matrix a, Matrix b)
            {
                bool issmall = true;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] <= b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public static bool operator <=(Matrix a, Matrix b)
            {
                bool issmall = true;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] > b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public static bool operator >=(Matrix a, Matrix b)
            {
                bool issmall = true;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] < b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public static bool operator !=(Matrix a, Matrix b)
            {
                bool issmall = true;
                issmall = ReferenceEquals(a, b);
                if (issmall) return issmall;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] == b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public static bool operator ==(Matrix a, Matrix b)
            {
                bool issmall = true;
                issmall = ReferenceEquals(a, b);
                if (issmall) return issmall;
                for (int i = 0; i < a.Rows; i++)
                {
                    for (int j = 0; j < a.Cols; j++)
                    {
                        if (a[i, j] != b[i, j]) issmall = false;
                    }
                }
                return issmall;
            }
            public override bool Equals(object obj)
            {
                Matrix b = obj as Matrix;
                return this == b;
            }
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
            #endregion
            public double Determinant()
            {
                if (cols == rows)
                {
                    Matrix _thisCopy = this.DeepCopy();
                    //行列式每次交换行,都需要乘以-1
                    double res = 1;
                    for (int i = 0; i < rows; i++)
                    {
                        //首先找到第i列的绝对值最大的数
                        int rowMax = i;
                        double max = Math.Abs(_thisCopy[i, i]);
                        for (int j = i; j < rows; j++)
                        {
                            if (Math.Abs(_thisCopy[j, i]) > max)
                            {
                                rowMax = j;
                                max = Math.Abs(_thisCopy[j, i]);
                            }
                        }
                        //将第i行和找到最大数那一行rowMax交换,同时将单位阵做相同初等变换
                        if (rowMax != i)
                        {
                            _thisCopy.Exchange(i, rowMax);
                            res *= -1;
                        }
                        //消元
                        for (int j = i + 1; j < rows; j++)
                        {
                            double r = -_thisCopy[j, i] / _thisCopy[i, i];
                            _thisCopy.Exchange(i, j, r);
                        }
                    }
                    //计算对角线乘积
                    for (int i = 0; i < rows; i++)
                    {
                        res *= _thisCopy[i, i];
                    }
                    return res;
                }
                else
                {
                    throw new Exception("不是行列式");
                }
            }
            #endregion
            #region 初等变换
            /// <summary>
            /// 初等变换:交换第r1和第r2行
            /// </summary>
            /// <param name="r1">第r1行</param>
            /// <param name="r2">第r2行</param>
            /// <returns>返回交换两行后的新的矩阵</returns>
            public Matrix Exchange(int r1, int r2)
            {
                if (Math.Min(r2, r1) >= 0 && Math.Max(r1, r2) < rows)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        double temp = this[r1, j];
                        this[r1, j] = this[r2, j];
                        this[r2, j] = temp;
                    }
                    return this;
                }
                else
                {
                    throw new Exception("超出索引");
                }
            }
            /// <summary>
            /// 初等变换:将r1行乘以某个数加到r2行
            /// </summary>
            /// <param name="r1">第r1行乘以num</param>
            /// <param name="r2">加到第r2行,若第r2行为负,则直接将r1乘以num并返回</param>
            /// <param name="num">某行放大的倍数</param>
            /// <returns></returns>
            public Matrix Exchange(int r1, int r2, double num)
            {
                if (Math.Min(r2, r1) >= 0 && Math.Max(r1, r2) < rows)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        this[r2, j] += this[r1, j] * num;
                    }
                    return this;
                }
                else if (r2 < 0)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        this[r1, j] *= num;
                    }
                    return this;
                }
                else
                {
                    throw new Exception("超出索引");
                }
            }
            /// <summary>
            /// 得到一个同等大小的单位矩阵
            /// </summary>
            /// <returns>返回一个同等大小的单位矩阵</returns>
            public Matrix EMatrix()
            {
                if (rows == cols)
                {
                    double[,] res = new double[rows, cols];
                    for (int i = 0; i < rows; i++)
                    {
                        for (int j = 0; j < cols; j++)
                        {
                            if (i == j)
                                res[i, j] = 1;
                            else
                                res[i, j] = 0;
                        }
                    }
                    return new Matrix(res);
                }
                else
                    throw new Exception("不是方阵,无法得到单位矩阵");
            }
            #endregion
            /// <summary>
            /// 深拷贝,仅仅将值拷贝给一个新的对象
            /// </summary>
            /// <returns>返回深拷贝后的新对象</returns>
            public Matrix DeepCopy()
            {
                double[,] ele = new double[rows, cols];
                for (int i = 0; i < rows; i++)
                {
                    for (int j = 0; j < cols; j++)
                    {
                        ele[i, j] = this[i, j];
                    }
                }
                return new Matrix(ele);
            }

            public override string ToString()
            {
                string str = "";
                for (int i = 0; i < Rows; i++)
                {
                    for (int j = 0; j < Cols; j++)
                    {
                        str += this[i, j].ToString();
                        if (j != Cols - 1)
                            str += " ";
                        else if (i != Rows - 1)
                            str += Environment.NewLine;
                    }
                }
                return str;
            }
        }
}

截图

6VFj6fi.gif


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK