WPF 画一个3D矩形并旋转
2021-03-07 04:29
标签:sla thread using val http pat public false iss
具体的代码还是线性代数。 主要是旋转和平移。 这个例子的中模型是在世界原点建立。所以旋转会以自身轴心旋转。 如果不在世界原点建立模型,还想以自身为旋转轴旋转。 则是需要以下步骤: 模型的中心点为V1(100,100,0)假设中心为轴(平行于Y轴),旋转A度,也就是说自身中心点的Y轴旋转。 步骤: (1)v1平移到世界原点后其他八个顶点的坐标。(中心点坐标的三个参数如果是大于0就是(每个)顶点减去相对应XYZ,如果中心点坐标的三个参数如果是小于0,则是(每个)顶点加上相对应XYZ,或者使用平移矩阵) (2)(每个)顶点先是平移到V1在原点时的所在的位置,再使用旋转矩阵经行旋转 (3) (每个)旋转后的顶点在平移回中心点原先所在位置。 ATP 附加属性类 xaml代码 //其中ModeData的三个参数为矩形的长高宽 //X,Y,Z为轴的旋转角度 矩阵类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;
}
}
}
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;
///
double>> m)
{
this.rows = m.Count;
this.cols = m[0].Count;
this.element = new double[Rows * Cols];
for (int i = 0; i )
{
for (int j = 0; j )
{
this[i, j] = m[i][j];
}
}
}
#region 矩阵数学运算
public static Matrix MAbs(Matrix a)
{
Matrix _thisCopy = a.DeepCopy();
for (int i = 0; i )
{
for (int j = 0; j )
{
_thisCopy[i, j] = Math.Abs(a[i, j]);
}
}
return _thisCopy;
}
///