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

主要是旋转和平移。

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

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

则是需要以下步骤:

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

步骤:

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

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

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

ATP 附加属性类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.Windows;
  7. using System.Windows.Controls;
  8. using System.Windows.Data;
  9. using System.Windows.Media;
  10. using System.Windows.Media.Media3D;
  11. using System.Windows.Shapes;
  12.  
  13. namespace ATP
  14. {
  15. public class ATP_Y
  16. {
  17. public static readonly DependencyProperty P_YProperty = DependencyProperty.RegisterAttached("P_Y", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_YChanged)));
  18.  
  19. private static void OnP_YChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  20. {
  21. PY = (double)e.NewValue;
  22. Draw(d, X, Y, Z);
  23. }
  24.  
  25. public static void SetP_Y(DependencyObject d, double v) => d.SetValue(P_YProperty, v);
  26.  
  27. public static double GetP_Y(DependencyObject d) => (double)d.GetValue(P_YProperty);
  28.  
  29. public static readonly DependencyProperty P_XProperty = DependencyProperty.RegisterAttached("P_X", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_XChanged)));
  30.  
  31. private static void OnP_XChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  32. {
  33. PX= (double)e.NewValue;
  34. Draw(d, X, Y, Z);
  35. }
  36.  
  37. public static void SetP_X(DependencyObject d, double v) => d.SetValue(P_XProperty, v);
  38.  
  39. public static double GetP_X(DependencyObject d) => (double)d.GetValue(P_XProperty);
  40.  
  41. public static readonly DependencyProperty P_ZProperty = DependencyProperty.RegisterAttached("P_Z", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(0.0, new PropertyChangedCallback(OnP_ZChanged)));
  42.  
  43. private static void OnP_ZChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  44. {
  45. PZ = (double)e.NewValue;
  46. Draw(d, X, Y, Z);
  47. }
  48.  
  49. public static void SetP_Z(DependencyObject d, double v) => d.SetValue(P_ZProperty, v);
  50.  
  51. public static double GetP_Z(DependencyObject d) => (double)d.GetValue(P_ZProperty);
  52.  
  53. public static readonly DependencyProperty ModeDataProperty = DependencyProperty.RegisterAttached("ModeData", typeof(Point3D), typeof(ATP_Y), new PropertyMetadata(new Point3D(, , ), new PropertyChangedCallback(OnModeDataChanged)));
  54.  
  55. public static void SetModeData(DependencyObject d, Point3D v) => d.SetValue(ModeDataProperty, v);
  56.  
  57. public static Point3D GetModeData(DependencyObject d) => (Point3D)d.GetValue(ModeDataProperty);
  58.  
  59. private static void OnModeDataChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  60. {
  61. var data = (Point3D)e.NewValue;
  62. ModeWidth = data.X;
  63. ModeHeight = data.Y;
  64. ModeZWidth = data.Z;
  65. Draw(d,X,Y,Z);
  66. }
  67.  
  68. public static readonly DependencyProperty YProperty = DependencyProperty.RegisterAttached("Y", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnYChanged)));
  69.  
  70. public static void SetY(DependencyObject d, double v) => d.SetValue(YProperty, v);
  71.  
  72. public static double GetY(DependencyObject d) => (double)d.GetValue(YProperty);
  73.  
  74. public static readonly DependencyProperty XProperty = DependencyProperty.RegisterAttached("X", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnXChanged)));
  75.  
  76. private static void OnXChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  77. {
  78. var deg = Math.PI / * (double)e.NewValue;
  79. X = deg;
  80. Draw(d, deg, Y, Z);
  81. }
  82.  
  83. public static void SetX(DependencyObject d, double v) => d.SetValue(XProperty, v);
  84.  
  85. public static double GetX(DependencyObject d) => (double)d.GetValue(XProperty);
  86.  
  87. public static readonly DependencyProperty ZProperty = DependencyProperty.RegisterAttached("Z", typeof(double), typeof(ATP.ATP_Y), new PropertyMetadata(-1.0, new PropertyChangedCallback(OnZChanged)));
  88.  
  89. private static void OnZChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  90. {
  91. var deg = Math.PI / * (double)e.NewValue;
  92. Z = deg;
  93. Draw(d, X, Y, deg);
  94. }
  95.  
  96. public static void SetZ(DependencyObject d, double v) => d.SetValue(ZProperty, v);
  97.  
  98. public static double GetZ(DependencyObject d) => (double)d.GetValue(ZProperty);
  99.  
  100. private static void OnYChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  101. {
  102. var deg = Math.PI / * (double)e.NewValue;
  103. Y = deg;
  104. Draw(d, X, deg, Z);
  105. }
  106.  
  107. private static double PX, PY, PZ;
  108. private static double X, Y, Z;
  109. private static double ModeHeight, ModeWidth, ModeZWidth;
  110. private static void Draw(DependencyObject d, double X, double Y, double Z)
  111. {
  112. var ui = d as Grid;
  113. ui.Children.Clear();
  114. var rect = new Rect(new Size(ModeWidth,ModeHeight));
  115. Group[] = new Point3D(rect.Width / , rect.Height / , -(ModeZWidth/));
  116. Group[] = new Point3D( - (rect.Width / ), rect.Height / , -(ModeZWidth / ));
  117. Group[] = new Point3D( - (rect.Width / ), - (rect.Height / ), -(ModeZWidth / ));
  118. Group[] = new Point3D((rect.Width / ), - (rect.Height / ), -(ModeZWidth / ));
  119. Group[] = new Point3D(rect.Width / , rect.Height / , (ModeZWidth / ));
  120. Group[] = new Point3D( - (rect.Width / ), rect.Height / , (ModeZWidth / ));
  121. Group[] = new Point3D( - (rect.Width / ), - (rect.Height / ), (ModeZWidth / ));
  122. Group[] = new Point3D((rect.Width / ), - (rect.Height / ), (ModeZWidth / ));
  123.  
  124. for (var i = ; i < ; i++)
  125. PP[i] = PSP(ReturnP3D(Y轴转置矩阵(X, Y, Z) * GetMatrixMP(Group[i])), new Rect(new Size(Math.Max(rect.Height, rect.Width),ModeZWidth)));
  126.  
  127. Set(, , ui,Colors.Black);
  128. Set(, , ui,Colors.Blue);
  129. Set(, , ui, Colors.Red);
  130. Set(, , ui, Colors.Fuchsia);
  131. Set(, , ui, Colors.DarkSlateBlue);
  132. Set(, , ui, Colors.Red);
  133. Set(, , ui, Colors.Red);
  134. Set(, , ui, Colors.Red);
  135. Set(, , ui, Colors.Red);
  136. Set(, , ui, Colors.Red);
  137. Set(, , ui, Colors.Red);
  138. Set(, , ui, Colors.Red);
  139. }
  140. private static void Set(int g1, int g2, Grid g,Color A)
  141. {
  142. var c1 = new Line();
  143. c1.Stroke = new SolidColorBrush(A);
  144. c1.X1 = PP[g1].X;
  145. c1.Y1 = PP[g1].Y;
  146. c1.X2 = PP[g2].X;
  147. c1.Y2 = PP[g2].Y;
  148. g.Children.Add(c1);
  149. }
  150. private static Matrix GetMatrixMP(Point3D MP)
  151. {
  152. var D = new double[, ];
  153. D[, ] = MP.X;
  154. D[, ] = MP.Y;
  155. D[, ] = MP.Z;
  156. D[, ] = ;
  157. return new Matrix(D);
  158. }
  159. private static Point3D ReturnP3D(Matrix MP) => new Point3D(MP[, ], MP[, ], MP[, ]);
  160.  
  161. private static Point PSP(Point3D ModePoint, Rect rect)
  162. {
  163. Point3D vp = new Point3D(PX, PY, Math.Max(rect.Height, rect.Width)+PZ);
  164. Point p;
  165. int x, y;
  166. x = (int)(vp.X + (ModePoint.X - vp.X) * vp.Z / (vp.Z - ModePoint.Z + 0.5));
  167. y = (int)(vp.Y + (ModePoint.Y - vp.Y) * vp.Z / (vp.Z - ModePoint.Z + 0.5));
  168. p = new Point(x, y);
  169. return p;
  170. }
  171. private static Point3D[] Group = new Point3D[];
  172. private static Point[] PP = new Point[];
  173. private static Matrix Y轴转置矩阵(double DegX, double DegY, double DegZ)
  174. {
  175. var A = new double[, ];
  176. A[, ] = ;
  177. A[, ] = ;
  178. A[, ] = ;
  179. A[, ] = ;
  180. A[, ] = Math.Cos(X);
  181. A[, ] = Math.Sin(X);
  182. A[, ] = ;
  183. A[, ] = - Math.Sin(X);
  184. A[, ] = Math.Cos(X);
  185. A[, ] = ;
  186. A[, ] = ;
  187. A[, ] = ;
  188. A[, ] = ;
  189. A[, ] = ;
  190. A[, ] = ;
  191. A[, ] = ;
  192. var B = new double[, ];
  193. B[, ] = Math.Cos(Y);
  194. B[, ] = ;
  195. B[, ] = -Math.Sin(Y);
  196. B[, ] = ;
  197. B[, ] = ;
  198. B[, ] = ;
  199. B[, ] = Math.Sin(Y);
  200. B[, ] = ;
  201. B[, ] = Math.Cos(Y);
  202. B[, ] = ;
  203. B[, ] = ;
  204. B[, ] = ;
  205. B[, ] = ;
  206. B[, ] = ;
  207. B[, ] = ;
  208. B[, ] = ;
  209. var C = new double[, ];
  210. C[, ] = Math.Cos(Z);
  211. C[, ] = Math.Sin(Z);
  212. C[, ] = ;
  213. C[, ] = - Math.Sin(Z);
  214. C[, ] = Math.Cos(Z);
  215. C[, ] = ;
  216. C[, ] = ;
  217. C[, ] = ;
  218. C[, ] = ;
  219. C[, ] = ;
  220. C[, ] = ;
  221. C[, ] = ;
  222. B[, ] = ;
  223. B[, ] = ;
  224. B[, ] = ;
  225. C[, ] = ;
  226. Matrix MT1 = new Matrix(A);
  227. Matrix MT2 = new Matrix(B);
  228. Matrix MT3 = new Matrix(C);
  229. var MT4 = MT1 * MT2;
  230. return MT4 * MT3;
  231. }
  232. }
  233. }

xaml代码

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

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

  1. <Window x:Class="ATP.MainWindow"
  2. xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3. xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4. xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  5. xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  6. xmlns:local="clr-namespace:ATP"
  7. mc:Ignorable="d"
  8. Title="MainWindow" Height="" Width="">
  9. <Grid> <Grid.RowDefinitions>
  10. <RowDefinition Height="*"/>
  11. <RowDefinition Height="auto"/>
  12. </Grid.RowDefinitions>
  13. <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}"/>
  14. <StackPanel Grid.Row="">
  15. <!--X轴旋转-->
  16. <Slider Minimum="" Maximum="" x:Name="s1"/>
  17. <!--Y轴旋转-->
  18. <Slider Minimum="" Maximum="" x:Name="s2"/>
  19. <!--Z轴旋转-->
  20. <Slider Minimum="" Maximum="" x:Name="s3"/>
  21. <!--视野远近-->
  22. <Slider Minimum="" Maximum="" x:Name="s4" />
  23. </StackPanel>
  24. </Grid>
  25. </Window>

矩阵类

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6.  
  7. namespace ATP
  8. {
  9. [Serializable]
  10. public class Matrix
  11. {
  12. public double[] element;
  13. private int rows = ;
  14. private int cols = ;
  15. /// <summary>
  16. /// 获取矩阵行数
  17. /// </summary>
  18. public int Rows
  19. {
  20. get
  21. {
  22. return rows;
  23. }
  24. }
  25. /// <summary>
  26. /// 获取矩阵列数
  27. /// </summary>
  28. public int Cols
  29. {
  30. get
  31. {
  32. return cols;
  33. }
  34. }
  35. /// <summary>
  36. /// 获取或设置第i行第j列的元素值
  37. /// </summary>
  38. /// <param name="i">第i行</param>
  39. /// <param name="j">第j列</param>
  40. /// <returns>返回第i行第j列的元素值</returns>
  41. public double this[int i, int j]
  42. {
  43. get
  44. {
  45. if (i < Rows && j < Cols)
  46. {
  47. return element[i * cols + j];
  48. }
  49. else
  50. {
  51. throw new Exception("索引越界");
  52. }
  53. }
  54. set
  55. {
  56. element[i * cols + j] = value;
  57. }
  58. }
  59. /// <summary>
  60. /// 用二维数组初始化Matrix
  61. /// </summary>
  62. /// <param name="m">二维数组</param>
  63. public Matrix(double[][] m)
  64. {
  65. this.rows = m.GetLength();
  66. this.cols = m.GetLength();
  67. int count = ;
  68. this.element = new double[Rows * Cols];
  69. for (int i = ; i < rows; i++)
  70. {
  71. for (int j = ; j < cols; j++)
  72. {
  73. element[count++] = m[i][j];
  74. }
  75. }
  76. }
  77. public Matrix(double[,] m)
  78. {
  79. this.rows = m.GetLength();
  80. this.cols = m.GetLength();
  81. this.element = new double[this.rows * this.cols];
  82. int count = ;
  83. for (int i = ; i < rows; i++)
  84. {
  85. for (int j = ; j < cols; j++)
  86. {
  87. element[count++] = m[i, j];
  88. }
  89. }
  90. }
  91. public Matrix(List<List<double>> m)
  92. {
  93. this.rows = m.Count;
  94. this.cols = m[].Count;
  95. this.element = new double[Rows * Cols];
  96. for (int i = ; i < rows; i++)
  97. {
  98. for (int j = ; j < cols; j++)
  99. {
  100. this[i, j] = m[i][j];
  101. }
  102. }
  103. }
  104. #region 矩阵数学运算
  105. public static Matrix MAbs(Matrix a)
  106. {
  107. Matrix _thisCopy = a.DeepCopy();
  108. for (int i = ; i < a.Rows; i++)
  109. {
  110. for (int j = ; j < a.Cols; j++)
  111. {
  112. _thisCopy[i, j] = Math.Abs(a[i, j]);
  113. }
  114. }
  115. return _thisCopy;
  116. }
  117. /// <summary>
  118. /// 矩阵相加
  119. /// </summary>
  120. /// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
  121. /// <param name="b">第二个矩阵</param>
  122. /// <returns>返回矩阵相加后的结果</returns>
  123. public static Matrix operator +(Matrix a, Matrix b)
  124. {
  125. if (a.cols == b.cols && a.rows == b.rows)
  126. {
  127. double[,] res = new double[a.rows, a.cols];
  128. for (int i = ; i < a.Rows; i++)
  129. {
  130. for (int j = ; j < a.Cols; j++)
  131. {
  132. res[i, j] = a[i, j] + b[i, j];
  133. }
  134. }
  135. return new Matrix(res);
  136. }
  137. else
  138. {
  139. throw new Exception("两个矩阵行列不相等");
  140. }
  141. }
  142. /// <summary>
  143. /// 矩阵相减
  144. /// </summary>
  145. /// <param name="a">第一个矩阵,和b矩阵必须同等大小</param>
  146. /// <param name="b">第二个矩阵</param>
  147. /// <returns>返回矩阵相减后的结果</returns>
  148. public static Matrix operator -(Matrix a, Matrix b)
  149. {
  150. if (a.cols == b.cols && a.rows == b.rows)
  151. {
  152. double[,] res = new double[a.rows, a.cols];
  153. for (int i = ; i < a.Rows; i++)
  154. {
  155. for (int j = ; j < a.Cols; j++)
  156. {
  157. res[i, j] = a[i, j] - b[i, j];
  158. }
  159. }
  160. return new Matrix(res);
  161. }
  162. else
  163. {
  164. throw new Exception("两个矩阵行列不相等");
  165. }
  166. }
  167. /// <summary>
  168. /// 对矩阵每个元素取相反数
  169. /// </summary>
  170. /// <param name="a">二维矩阵</param>
  171. /// <returns>得到矩阵的相反数</returns>
  172. public static Matrix operator -(Matrix a)
  173. {
  174. Matrix res = a;
  175. for (int i = ; i < a.rows; i++)
  176. {
  177. for (int j = ; j < a.cols; j++)
  178. {
  179. res.element[i * a.cols + j] = -res.element[i * a.cols + j];
  180. }
  181. }
  182. return res;
  183. }
  184. /// <summary>
  185. /// 矩阵相乘
  186. /// </summary>
  187. /// <param name="a">第一个矩阵</param>
  188. /// <param name="b">第二个矩阵,这个矩阵的行要与第一个矩阵的列相等</param>
  189. /// <returns>返回相乘后的一个新的矩阵</returns>
  190. public static Matrix operator *(Matrix a, Matrix b)
  191. {
  192. if (a.cols == b.rows)
  193. {
  194. double[,] res = new double[a.rows, b.cols];
  195. for (int i = ; i < a.rows; i++)
  196. {
  197. for (int j = ; j < b.cols; j++)
  198. {
  199. for (int k = ; k < a.cols; k++)
  200. {
  201. res[i, j] += a[i, k] * b[k, j];
  202. }
  203. }
  204. }
  205. return new Matrix(res);
  206. }
  207. else
  208. {
  209. throw new Exception("两个矩阵行和列不等");
  210. }
  211. }
  212. /// <summary>
  213. /// 矩阵与数相乘
  214. /// </summary>
  215. /// <param name="a">第一个矩阵</param>
  216. /// <param name="num">一个实数</param>
  217. /// <returns>返回相乘后的新的矩阵</returns>
  218. public static Matrix operator *(Matrix a, double num)
  219. {
  220. Matrix res = a;
  221. for (int i = ; i < a.rows; i++)
  222. {
  223. for (int j = ; j < a.cols; j++)
  224. {
  225. res.element[i * a.cols + j] *= num;
  226. }
  227. }
  228. return res;
  229. }
  230. /// <summary>
  231. /// 矩阵转置
  232. /// </summary>
  233. /// <returns>返回当前矩阵转置后的新矩阵</returns>
  234. public Matrix Transpose()
  235. {
  236. double[,] res = new double[cols, rows];
  237. {
  238. for (int i = ; i < cols; i++)
  239. {
  240. for (int j = ; j < rows; j++)
  241. {
  242. res[i, j] = this[j, i];
  243. }
  244. }
  245. }
  246. return new Matrix(res);
  247. }
  248. /// <summary>
  249. /// 矩阵求逆
  250. /// </summary>
  251. /// <returns>返回求逆后的新的矩阵</returns>
  252. public Matrix Inverse()
  253. {
  254. //最后原始矩阵并不变,所以需要深拷贝一份
  255. Matrix _thisCopy = this.DeepCopy();
  256. if (cols == rows && this.Determinant() != )
  257. {
  258. //初始化一个同等大小的单位阵
  259. Matrix res = _thisCopy.EMatrix();
  260. for (int i = ; i < rows; i++)
  261. {
  262. //首先找到第i列的绝对值最大的数,并将该行和第i行互换
  263. int rowMax = i;
  264. double max = Math.Abs(_thisCopy[i, i]);
  265. for (int j = i; j < rows; j++)
  266. {
  267. if (Math.Abs(_thisCopy[j, i]) > max)
  268. {
  269. rowMax = j;
  270. max = Math.Abs(_thisCopy[j, i]);
  271. }
  272. }
  273. //将第i行和找到最大数那一行rowMax交换
  274. if (rowMax != i)
  275. {
  276. _thisCopy.Exchange(i, rowMax);
  277. res.Exchange(i, rowMax);
  278.  
  279. }
  280. //将第i行做初等行变换,将第一个非0元素化为1
  281. double r = 1.0 / _thisCopy[i, i];
  282. _thisCopy.Exchange(i, -, r);
  283. res.Exchange(i, -, r);
  284. //消元
  285. for (int j = ; j < rows; j++)
  286. {
  287. //到本行后跳过
  288. if (j == i)
  289. continue;
  290. else
  291. {
  292. r = -_thisCopy[j, i];
  293. _thisCopy.Exchange(i, j, r);
  294. res.Exchange(i, j, r);
  295. }
  296. }
  297. }
  298. return res;
  299. }
  300. else
  301. {
  302. throw new Exception("矩阵不是方阵无法求逆");
  303. }
  304. }
  305. #region 重载比较运算符
  306. public static bool operator <(Matrix a, Matrix b)
  307. {
  308. bool issmall = true;
  309. for (int i = ; i < a.Rows; i++)
  310. {
  311. for (int j = ; j < a.Cols; j++)
  312. {
  313. if (a[i, j] >= b[i, j]) issmall = false;
  314. }
  315. }
  316. return issmall;
  317. }
  318. public static bool operator >(Matrix a, Matrix b)
  319. {
  320. bool issmall = true;
  321. for (int i = ; i < a.Rows; i++)
  322. {
  323. for (int j = ; j < a.Cols; j++)
  324. {
  325. if (a[i, j] <= b[i, j]) issmall = false;
  326. }
  327. }
  328. return issmall;
  329. }
  330. public static bool operator <=(Matrix a, Matrix b)
  331. {
  332. bool issmall = true;
  333. for (int i = ; i < a.Rows; i++)
  334. {
  335. for (int j = ; j < a.Cols; j++)
  336. {
  337. if (a[i, j] > b[i, j]) issmall = false;
  338. }
  339. }
  340. return issmall;
  341. }
  342. public static bool operator >=(Matrix a, Matrix b)
  343. {
  344. bool issmall = true;
  345. for (int i = ; i < a.Rows; i++)
  346. {
  347. for (int j = ; j < a.Cols; j++)
  348. {
  349. if (a[i, j] < b[i, j]) issmall = false;
  350. }
  351. }
  352. return issmall;
  353. }
  354. public static bool operator !=(Matrix a, Matrix b)
  355. {
  356. bool issmall = true;
  357. issmall = ReferenceEquals(a, b);
  358. if (issmall) return issmall;
  359. for (int i = ; i < a.Rows; i++)
  360. {
  361. for (int j = ; j < a.Cols; j++)
  362. {
  363. if (a[i, j] == b[i, j]) issmall = false;
  364. }
  365. }
  366. return issmall;
  367. }
  368. public static bool operator ==(Matrix a, Matrix b)
  369. {
  370. bool issmall = true;
  371. issmall = ReferenceEquals(a, b);
  372. if (issmall) return issmall;
  373. for (int i = ; i < a.Rows; i++)
  374. {
  375. for (int j = ; j < a.Cols; j++)
  376. {
  377. if (a[i, j] != b[i, j]) issmall = false;
  378. }
  379. }
  380. return issmall;
  381. }
  382. public override bool Equals(object obj)
  383. {
  384. Matrix b = obj as Matrix;
  385. return this == b;
  386. }
  387. public override int GetHashCode()
  388. {
  389. return base.GetHashCode();
  390. }
  391. #endregion
  392. public double Determinant()
  393. {
  394. if (cols == rows)
  395. {
  396. Matrix _thisCopy = this.DeepCopy();
  397. //行列式每次交换行,都需要乘以-1
  398. double res = ;
  399. for (int i = ; i < rows; i++)
  400. {
  401. //首先找到第i列的绝对值最大的数
  402. int rowMax = i;
  403. double max = Math.Abs(_thisCopy[i, i]);
  404. for (int j = i; j < rows; j++)
  405. {
  406. if (Math.Abs(_thisCopy[j, i]) > max)
  407. {
  408. rowMax = j;
  409. max = Math.Abs(_thisCopy[j, i]);
  410. }
  411. }
  412. //将第i行和找到最大数那一行rowMax交换,同时将单位阵做相同初等变换
  413. if (rowMax != i)
  414. {
  415. _thisCopy.Exchange(i, rowMax);
  416. res *= -;
  417. }
  418. //消元
  419. for (int j = i + ; j < rows; j++)
  420. {
  421. double r = -_thisCopy[j, i] / _thisCopy[i, i];
  422. _thisCopy.Exchange(i, j, r);
  423. }
  424. }
  425. //计算对角线乘积
  426. for (int i = ; i < rows; i++)
  427. {
  428. res *= _thisCopy[i, i];
  429. }
  430. return res;
  431. }
  432. else
  433. {
  434. throw new Exception("不是行列式");
  435. }
  436. }
  437. #endregion
  438. #region 初等变换
  439. /// <summary>
  440. /// 初等变换:交换第r1和第r2行
  441. /// </summary>
  442. /// <param name="r1">第r1行</param>
  443. /// <param name="r2">第r2行</param>
  444. /// <returns>返回交换两行后的新的矩阵</returns>
  445. public Matrix Exchange(int r1, int r2)
  446. {
  447. if (Math.Min(r2, r1) >= && Math.Max(r1, r2) < rows)
  448. {
  449. for (int j = ; j < cols; j++)
  450. {
  451. double temp = this[r1, j];
  452. this[r1, j] = this[r2, j];
  453. this[r2, j] = temp;
  454. }
  455. return this;
  456. }
  457. else
  458. {
  459. throw new Exception("超出索引");
  460. }
  461. }
  462. /// <summary>
  463. /// 初等变换:将r1行乘以某个数加到r2行
  464. /// </summary>
  465. /// <param name="r1">第r1行乘以num</param>
  466. /// <param name="r2">加到第r2行,若第r2行为负,则直接将r1乘以num并返回</param>
  467. /// <param name="num">某行放大的倍数</param>
  468. /// <returns></returns>
  469. public Matrix Exchange(int r1, int r2, double num)
  470. {
  471. if (Math.Min(r2, r1) >= && Math.Max(r1, r2) < rows)
  472. {
  473. for (int j = ; j < cols; j++)
  474. {
  475. this[r2, j] += this[r1, j] * num;
  476. }
  477. return this;
  478. }
  479. else if (r2 < )
  480. {
  481. for (int j = ; j < cols; j++)
  482. {
  483. this[r1, j] *= num;
  484. }
  485. return this;
  486. }
  487. else
  488. {
  489. throw new Exception("超出索引");
  490. }
  491. }
  492. /// <summary>
  493. /// 得到一个同等大小的单位矩阵
  494. /// </summary>
  495. /// <returns>返回一个同等大小的单位矩阵</returns>
  496. public Matrix EMatrix()
  497. {
  498. if (rows == cols)
  499. {
  500. double[,] res = new double[rows, cols];
  501. for (int i = ; i < rows; i++)
  502. {
  503. for (int j = ; j < cols; j++)
  504. {
  505. if (i == j)
  506. res[i, j] = ;
  507. else
  508. res[i, j] = ;
  509. }
  510. }
  511. return new Matrix(res);
  512. }
  513. else
  514. throw new Exception("不是方阵,无法得到单位矩阵");
  515. }
  516. #endregion
  517. /// <summary>
  518. /// 深拷贝,仅仅将值拷贝给一个新的对象
  519. /// </summary>
  520. /// <returns>返回深拷贝后的新对象</returns>
  521. public Matrix DeepCopy()
  522. {
  523. double[,] ele = new double[rows, cols];
  524. for (int i = ; i < rows; i++)
  525. {
  526. for (int j = ; j < cols; j++)
  527. {
  528. ele[i, j] = this[i, j];
  529. }
  530. }
  531. return new Matrix(ele);
  532. }
  533.  
  534. public override string ToString()
  535. {
  536. string str = "";
  537. for (int i = ; i < Rows; i++)
  538. {
  539. for (int j = ; j < Cols; j++)
  540. {
  541. str += this[i, j].ToString();
  542. if (j != Cols - )
  543. str += " ";
  544. else if (i != Rows - )
  545. str += Environment.NewLine;
  546. }
  547. }
  548. return str;
  549. }
  550. }
  551. }

截图

WPF 画一个3D矩形并旋转的更多相关文章

  1. vb代码之------画一个半透明矩形

    入吾QQ群183435019 (学习 交流+唠嗑). 废话不说,咱们来看代码吧 程序结果运行如下 需要如下API 1:GdipCreateFromHDC 功能:创建设备场景相对应的绘图区域(相当于给设 ...

  2. Qt 怎么画一个圆角矩形对话框,或者圆角控件

    1. 2. 在自定义控件的 构造函数中加入如下一段断码 this->setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); //隐藏对话框标题 ...

  3. Directx11学习笔记【十二】 画一个旋转的彩色立方体

    上一次我们学习了如何画一个2D三角形,现在让我们进一步学习如何画一个旋转的彩色立方体吧. 具体流程同画三角形类似,因此不再给出完整代码了,不同的部分会再说明. 由于我们要画彩色的立方体,所以顶点结构体 ...

  4. CSS3D动画制作一个3d旋转的筛子

    希望这个demo能让大家理解CSS3的3d空间动画(其实是个假3D) 首先给一个3d的解剖图,x/y/z轴线轴线已经标出 下面附上添加特效的动画旋转 可以根据demo并参考上面解剖图进行理解 < ...

  5. 使用纯CSS3实现一个3D旋转的书本

    有一些前沿的电商站点已经開始使用3D模型来展示商品并支持在线定制,而当中图书的展示是最为简单的一种, 无需复杂的建模过程,使用图片和CSS3的一些变换就可以实现更好的展示效果,简洁而有用. 书本的3D ...

  6. WPF中的3D特性和常见的几个类

    原文:WPF中的3D特性和常见的几个类 WPF 3D 常用的几个类及其关系 1.  Visual 类      所有二维可视化元素的基类,为 WPF 中的呈现提供支持,其中包括命中测试.坐标转换和边界 ...

  7. 在WPF中添加3D特性

    原文:在WPF中添加3D特性 35.4  在WPF中添加3D特性 本节介绍WPF中的3D特性,其中包含了开始使用该特性的信息. 提示: WPF中的3D特性在System.Windows.Media.M ...

  8. 一个3D ar打飞机的游戏iOS源码

    这是国内目前第一款集合了AR实景,3D游戏和人脸识别的射击游戏,通过旋转和改变手机的角度与位置,所有的射击操作都靠手势来完成,目前所有的源码全部都在这里.appStore地址:https://itun ...

  9. wpf做的3d滑动gallery

    原文:wpf做的3d滑动gallery wpf做的3d滑动gallery 随着iphone\ipad的流行及热捧,现在做移动产品不管是什么平台的,领导总想做成像ios系统的样子.自从微软发布了wind ...

随机推荐

  1. Typescript I: 遍历Array的方法:for, forEach, every等

    Typescript的官方文档 Iterators and Geneators (https://www.typescriptlang.org/docs/handbook/iterators-and- ...

  2. 启动Spring Tool Suite 4时出现 could not find tools.jar spring boot live hovers....弹窗

    第一步:检查一下STS启动时的加载环境 Help  —› About Spring Tool Suite 4 —› Installation Details —› Configuration 本人已经 ...

  3. Jquery 处理返回的 Json 数组

    Jquery 处理返回的 Json 数组 <script> for (var i = 0; i < photos.length; ++ i) { console.log(photos ...

  4. WordPress 去掉功能中的 wordpress.org

    WordPress 去掉功能中的 wordpress.org  

  5. nyoj 163 Phone List(动态字典树<trie>) poj Phone List (静态字典树<trie>)

    Phone List 时间限制:1000 ms  |  内存限制:65535 KB 难度:4   描述 Given a list of phone numbers, determine if it i ...

  6. 如何在当前文件夹打开cmd(基于win10)

    如何在当前文件夹打开cmd(基于win10) 方法一: 1.先打开你要进入的文件夹 2.在标记的位置输入cmd,就可以进入当前文件的cmd 方法二: 1.打开你要进入的文件夹 2.通过shift + ...

  7. DAL

    using System;using System.Collections.Generic;using System.Linq;using System.Web;using System.Data;u ...

  8. 领扣(LeetCode)字母大小写全排列 个人题解

    给定一个字符串S,通过将字符串S中的每个字母转变大小写,我们可以获得一个新的字符串.返回所有可能得到的字符串集合. 示例: 输入: S = "a1b2" 输出: ["a1 ...

  9. 自制反汇编逆向分析工具 与hopper逆向输出对比

    经过一个阶段5次迭代之后,本逆向分析工具功能基本成形.工具的基本功能介绍请参看前面的posts. 现在就和hopper的逆向函数伪代码的功能对比一下效果.在这里并非定胜劣,因为差异可以拿来对比参照,通 ...

  10. RxJS入门

    一.RxJS是什么? 官方文档使用了一句话总结RxJS: Think of RxJS as Lodash for events.那么Lodash主要解决了什么问题?Lodash主要集成了一系列关于数组 ...