WPF实现平面三角形3D运动效果

作者:RunnerDNA 时间:2021-10-25 02:35:02 

本文实例为大家分享了WPF实现平面三角形3D运动效果的具体代码,供大家参考,具体内容如下

实现效果如下:

WPF实现平面三角形3D运动效果

思路:封装三角形三个顶点和路径的三角形类,图形渲染时同步更新公共顶点三角形的顶点位置。

步骤:

1、三角形类Triangle.cs


public Point A, B, C;//初始三个顶点
public Point VA, VB, VC;//运动的三个顶点
public Path trianglePath;//三角形路径
public Color triangleColor;//填充
public double ColorIndex;//颜色深度

public Triangle(Point a, Point b, Point c, Color co, double z)
 {
  A = VA = a;
  B = VB = b;
  C = VC = c;
  triangleColor = co;
  ColorIndex = z;
  trianglePath = new Path();
  Draw();
 }

/// <summary>
 /// 绘制三角形
 /// </summary>
 public void Draw()
 {
  var g = new StreamGeometry();
  using (StreamGeometryContext context = g.Open())
  {
   context.BeginFigure(VA, true, true);
   context.LineTo(VB, true, false);
   context.LineTo(VC, true, false);
  }
  trianglePath.Data = g;
  trianglePath.Fill = new SolidColorBrush(triangleColor);
 }

2、 三角形系统类TriangleSystem.cs


public class TriangleSystem
{
 /// <summary>
 /// 三角形列表
 /// </summary>
 private List<Triangle> triangles;

/// <summary>
 /// 点和与其对应三角形字典
 /// </summary>
 public Dictionary<Point, PointClass> pointTriangles;

/// <summary>
 /// 容器
 /// </summary>
 private Canvas containerCanvas;

/// <summary>
 /// 三角形宽
 /// </summary>
 private int triangleWidth = 100;

/// <summary>
 /// 三角形高
 /// </summary>
 private int triangleHeight = 100;

/// <summary>
 /// 三角形横向数量
 /// </summary>
 private int horizontalCount = 10;

/// <summary>
 /// 三角形纵向数量
 /// </summary>
 private int verticalCount = 5;

/// <summary>
 /// X坐标运动范围
 /// </summary>
 private int XRange = 100;

/// <summary>
 /// Y坐标运动范围
 /// </summary>
 private int YRange = 10;

/// <summary>
 /// 坐标运动速度
 /// </summary>
 private int speed = 10;

/// <summary>
 /// 三角形颜色深度
 /// </summary>
 private double zIndex = 10.0;

/// <summary>
 /// 随机数
 /// </summary>
 private Random random;

public TriangleSystem(Canvas ca)
 {
  containerCanvas = ca;
  random = new Random();
  triangles = new List<Triangle>();
  pointTriangles = new Dictionary<Point, PointClass>();

SpawnTriangle();
 }

/// <summary>
 /// 三角形初始化
 /// </summary>
 private void SpawnTriangle()
 {
  //清空队列
  triangles.Clear();

for (int i = 0; i < horizontalCount; i++)
  {
   for (int j = 0; j < verticalCount; j++)
   {
    Point A = new Point(i * triangleWidth, j * triangleHeight);
    Point B = new Point(i * triangleWidth, (j + 1) * triangleHeight);
    Point C = new Point((i + 1) * triangleWidth, (j + 1) * triangleHeight);
    Point D = new Point((i + 1) * triangleWidth, j * triangleHeight);

double index = (i * horizontalCount / zIndex + j * verticalCount / zIndex ) / zIndex;
    index = index > 1 ? 1 : index < 0.1 ? 0.1 : index;
    Triangle t1 = new Triangle(A, B, C, GetTriangleColor(index), index);
    Triangle t2 = new Triangle(A, D, C, GetTriangleColor(index - 0.1), index - 0.1);

//公共点和三角形集合键值对
    AddPointTriangles(A, t1, t2);
    AddPointTriangles(B, t1, t2);
    AddPointTriangles(C, t1, t2);
    AddPointTriangles(D, t1, t2);

//添加三角形
    this.containerCanvas.Children.Add(t1.trianglePath);
    this.containerCanvas.Children.Add(t2.trianglePath);
    this.triangles.Add(t1);
    this.triangles.Add(t2);
   }
  }
 }

/// <summary>
 /// 添加公共点和三角形集合键值对
 /// </summary>
 private void AddPointTriangles(Point p, Triangle t1, Triangle t2)
 {
  if (!this.pointTriangles.Keys.Contains(p))
  {
   List<Triangle> ts = new List<Triangle>();
   ts.Add(t1);
   ts.Add(t2);
   PointClass pc = new PointClass
   {
    triangles = ts,
    vector = new Vector(random.Next(-speed, speed) * 0.05, random.Next(-speed, speed) * 0.05),
   };
   this.pointTriangles.Add(p, pc);
  }
  else
  {
   if (!this.pointTriangles[p].triangles.Contains(t1))
    this.pointTriangles[p].triangles.Add(t1);
   if (!this.pointTriangles[p].triangles.Contains(t2))
    this.pointTriangles[p].triangles.Add(t2);
  }
 }

/// <summary>
 /// 获取三角形颜色
 /// </summary>
 private Color GetTriangleColor(double index)
 {
  return Color.FromArgb((byte)(255 * index), 230, 18, 65);
 }

/// <summary>
 /// 更新三角形
 /// </summary>
 public void Update()
 {
  foreach (var pt in pointTriangles)
  {
   foreach (var t in pt.Value.triangles)
   {
    if (t.A == pt.Key)
     t.VA = GetPointValue(t.VA, t.A, ref pt.Value.vector, ref t.triangleColor, ref t.ColorIndex);
    if (t.B == pt.Key)
     t.VB = GetPointValue(t.VB, t.B, ref pt.Value.vector, ref t.triangleColor, ref t.ColorIndex);
    if (t.C == pt.Key)
     t.VC = GetPointValue(t.VC, t.C, ref pt.Value.vector, ref t.triangleColor, ref t.ColorIndex);
    t.Draw();
   }
  }
 }

/// <summary>
 /// 计算顶点值
 /// </summary>
 private Point GetPointValue(Point p1, Point p2, ref Vector v, ref Color c, ref double index)
 {
  Point getPoint = new Point();
  if (p1.X + v.X < p2.X + XRange && p1.X + v.X > p2.X - XRange)
   getPoint.X = p1.X + v.X;
  else
  {
   v.X = -v.X;
   index = index > 1 ? index - 0.01 : index < 0.01 ? index + 0.01 : index - 0.01;
   c = GetTriangleColor(index);
   getPoint.X = p1.X + v.X;
  }

if (p1.Y + v.Y < p2.Y + YRange && p1.Y + v.Y > p2.Y - YRange)
   getPoint.Y = p1.Y + v.Y;
  else
  {
   v.Y = -v.Y;
   getPoint.Y = p1.Y + v.Y;
  }
  return getPoint;
 }
}

3、PointClass.cs


public class PointClass
{
 public List<Triangle> triangles;
 public Vector vector;
}

4、主窗体交互逻辑


private TriangleSystem ts;

public MainWindow()
 {
  InitializeComponent();
  ts = new TriangleSystem(this.mainCanvas);
  CompositionTarget.Rendering += CompositionTarget_Rendering;
 }

/// <summary>
 /// 帧渲染事件
 /// </summary>
 private void CompositionTarget_Rendering(object sender, EventArgs e)
 {
  ts.Update();
 }

不足:其中颜色渲染方式不够完善,无法完全模仿3D起伏的效果,有兴趣的可以一起探讨优化。

来源:https://blog.csdn.net/dnazhd/article/details/108368026

标签:WPF,三角形,3D运动
0
投稿

猜你喜欢

  • SpringBoot中的PUT和Delete请求使用

    2022-01-22 19:33:32
  • 解决异常FileNotFoundException:class path resource找不到资源文件的问题

    2021-12-26 18:24:14
  • Android内存优化杂谈

    2023-06-18 15:46:41
  • C#编写发送邮件组件

    2022-08-26 19:28:57
  • Kotlin协程开发之Flow的融合与Channel容量及溢出策略介绍

    2023-07-02 23:52:01
  • Java实现插入公式到PPT的示例代码

    2023-11-12 03:04:41
  • 基于android中的各种颜色在drawable.xml中的值详解

    2022-03-30 01:56:18
  • Avalonia封装实现指定组件允许拖动的工具类

    2023-01-01 19:03:03
  • 根据灰度值填充字符-单文件单线程版

    2023-10-12 00:50:24
  • 关于Java8 parallelStream并发安全的深入讲解

    2023-11-15 06:37:35
  • Java简单工厂模式定义与用法实例分析

    2023-10-12 10:58:38
  • C#使用虚拟方法实现多态

    2023-01-01 05:21:08
  • Android开发时尽管已root但是ddms还是没有data路径怎么办

    2023-01-28 03:19:36
  • Java获取彩色图像中的主色彩的实例代码

    2021-10-16 01:09:39
  • Java8中的 Lambda表达式教程

    2023-10-13 01:32:29
  • C#.net实现在Winform中从internet下载文件的方法

    2023-09-13 18:04:15
  • springboot2.x 接入阿里云市场短信发送的实现

    2023-09-20 23:03:57
  • 浅谈java 执行jar包中的main方法

    2022-06-28 07:58:27
  • C#中的位操作小结

    2023-08-07 07:01:29
  • SpringCloud HystrixDashboard服务监控详解

    2021-12-16 03:35:47
  • asp之家 软件编程 m.aspxhome.com