二维图形的矩阵变换(二)——WPF中的矩阵变换基础

简介: 原文:二维图形的矩阵变换(二)——WPF中的矩阵变换基础在前文二维图形的矩阵变换(一)——基本概念中已经介绍过二维图像矩阵变换的一些基础知识,本文中主要介绍一下如何在WPF中进行矩阵变换。   Matrix结构 在WPF中,用Matrix结构(struct类型)表示二维变换矩阵,它是一个3*3的数组,结构如下,      由于第三列是常量0,0,1,因此并不作为公开属性,可见的只有剩余六个属性。
原文: 二维图形的矩阵变换(二)——WPF中的矩阵变换基础

在前文二维图形的矩阵变换(一)——基本概念中已经介绍过二维图像矩阵变换的一些基础知识,本文中主要介绍一下如何在WPF中进行矩阵变换。

 

Matrix结构

在WPF中,用Matrix结构(struct类型)表示二维变换矩阵,它是一个3*3的数组,结构如下,

    

由于第三列是常量0,0,1,因此并不作为公开属性,可见的只有剩余六个属性。

 

构造变换

虽然Matrix类公开了这六个属性让我们设置,但是靠直接设置这六个属性来实现平移、旋转等变换对于我们来说实在太困难了,因此又增加了如下许多函数来帮助我们实现这一过程,常见了有:

  • Rotate
  • RotateAt
  • Scale
  • ScaleAt
  • Skew
  • Translate

这些函数的效果是叠加的,例如,我们要先平移(10,20),然后绕原点旋转30度,方式如下:

    Matrix matrix = Matrix.Identity;
    matrix.Translate(10, 20);
    matrix.Rotate(30);

其中Matrix.Identity矩阵的默认值,它是一个恒等矩阵(不进行任何变换,可以用于重置)。

 

反转矩阵

关于反转矩阵,Matrix类中提供了一个属性和函数:

  • HasInverse 属性    用于检查该矩阵是否可以反转。
  • Invert()    用于获取反转矩阵

反转矩阵可以非常方便我们进行矩阵的逆运算,十分有用。

 

应用变换

在WPF中可以接受矩阵运算的基础元素有Point和Vector,可以通过Transform函数进行矩阵变换:

    var transForm = Matrix.Identity;
    transForm.Scale(2, 3);

    var point = new Point(1, 1);
    var newPoint = transForm.Transform(point);

    Console.WriteLine(newPoint);            //
输出(2,3)

在C#中还重载了"*"运算符,这样更加直观了:

    var newPoint = point * transForm;

另外,Transform函数还有一个可以接收数组的的版本,这个版本中并不生成新的对象,因此具有更高的效率。

 

复合变换

前文已经介绍过,矩阵是可以通过乘运算实现变换的叠加的,Matrix类中提供了Multiply函数进行两个矩阵相乘,在C#中也可以使用"*"运算符来实现这一过程。

    Matrix scale = Matrix.Identity;
    scale.Scale(2, 2);

    Matrix transLate = Matrix.Identity;
    transLate.Translate(10, 20);

    var transForm = scale * transLate;

    Matrix transForm2 = Matrix.Identity;
    transForm2.Scale(2, 2);
    transForm2.Translate(10, 20);

    Contract.Assert(transForm == transForm2);

需要注意的是,矩阵并不满足交换律,如:

    Contract.Assert((transLate * scale) != (scale * transLate));

 

扩展函数

在日常的使用过程中,我们的变换矩阵往往是通过一系列操作叠加起来的。可能是为了效率,WPF的变换函数返回值都是Void,叠加起来并不方便。这里我写了几个扩展函数简化这一过程: 

    public class GeometryTransForm
    {
        Matrix _matrix;
        public Matrix Matrix
        {
            get { return _matrix; }
            private set { _matrix = value; }
        }

        /// <summary>
        ///  获取一个恒等变换
        /// </summary>
        public static GeometryTransForm Identity
        {
            get { return new GeometryTransForm(); }
        }

        /// <summary>
        /// 以指定点为中心旋转指定的角度。
        /// </summary>
        /// <param name="angle">要旋转的角度(单位为度)。</param>
        /// <param name="centerX">要围绕其旋转的点的 x 坐标。</param>
        /// <param name="centerY">要围绕其旋转的点的 y 坐标。</param>
        public GeometryTransForm Rotate(double angle, double centerX = 0, double centerY = 0)
        {
            _matrix.RotateAt(angle, centerX, centerY);
            return this;
        }


        /// <summary>
        /// 围绕指定的点按指定的量缩放
        /// </summary>
        /// <param name="scaleX">沿 x 轴的缩放量</param>
        /// <param name="scaleY">沿 y 轴的缩放量</param>
        /// <param name="centerX">缩放操作中心点的 x 坐标</param>
        /// <param name="centerY">缩放操作中心点的 y 坐标</param>
        public GeometryTransForm Scale(double scaleX, double scaleY, double centerX = 0, double centerY = 0)
        {
            _matrix.ScaleAt(scaleX, scaleY, centerX, centerY);

            return this;
        }

        /// <summary>
        /// 在 x 和 y 维中指定角度的扭曲。
        /// </summary>
        /// <param name="skewX">用于扭曲此的 x 维角度</param>
        /// <param name="skewY">用于扭曲此的 y 维角度</param>
        public GeometryTransForm Skew(double skewX, double skewY)
        {
            _matrix.Skew(skewX, skewY);
            return this;
        }


        /// <summary>
        /// 按指定偏移量的平移
        /// </summary>
        /// <param name="offsetX">沿 x 轴的偏移量</param>
        /// <param name="offsetY">沿 y 轴的偏移量</param>
        public GeometryTransForm Translate(double offsetX, double offsetY)
        {
            _matrix.Translate(offsetX, offsetY);
            return this;
        }


        public GeometryTransForm Transfrom(GeometryTransForm transform)
        {
            return Transfrom(transform.Matrix);
        }

        public GeometryTransForm Transfrom(Matrix transform)
        {
            _matrix = _matrix * transform;
            return this;
        }


        /// <summary>
        /// 反转变换
        /// </summary>
        public GeometryTransForm Invert()
        {
            _matrix.Invert();
            return this;
        }

        public static Point operator *(Point point, GeometryTransForm transform)
        {
            return point * transform.Matrix;
        }


        //如果是struct就用不着这个了,每一次 = 都是Clone
        public GeometryTransForm Clone()
        {
            return new GeometryTransForm() { Matrix = this.Matrix };
        }
    }
View Code

通过这个扩展函数,前面的变换可以简化如下:

    var transForm = GeometryTransForm.Identity.Scale(2, 2).Translate(10, 20);

另外,这个类也支持直接和Point相乘,用起来还是蛮方便的。

 

UI的矩阵变换

由于篇幅所限,本文只介绍了WPF矩阵变换的基础操作,下一篇文章中再介绍如何将矩阵变换应用到UI界面上

目录
相关文章
|
C# Windows
WPF技术之图形系列Polygon控件
WPF Polygon是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制多边形形状。它可以通过设置多个点的坐标来定义多边形的形状,可以绘制任意复杂度的多边形。
897 0
|
C# 前端开发
WPF - 图形设计器(Diagram Designer)
原文:WPF - 图形设计器(Diagram Designer)   OpenExpressApp计划中包括建模工具,计划是采用MetaEdit+模型来作为元模型,使用codeproject的《WPF Diagram Designer》一系列文章来做为设计器实现参考,本篇介绍一下codeprojcet的这四个文章,推荐给对图形设计器感兴趣的人去看看,通过WPF的模板功能和其他功能可以很方便的设计出图形编辑器。
3574 0
|
3月前
|
C# Windows 开发者
当WPF遇见OpenGL:一场关于如何在Windows Presentation Foundation中融入高性能跨平台图形处理技术的精彩碰撞——详解集成步骤与实战代码示例
【8月更文挑战第31天】本文详细介绍了如何在Windows Presentation Foundation (WPF) 中集成OpenGL,以实现高性能的跨平台图形处理。通过具体示例代码,展示了使用SharpGL库在WPF应用中创建并渲染OpenGL图形的过程,包括开发环境搭建、OpenGL渲染窗口创建及控件集成等关键步骤,帮助开发者更好地理解和应用OpenGL技术。
246 0
|
3月前
|
开发者 C# 容器
【独家揭秘】当WPF邂逅DirectX:看这两个技术如何联手打造令人惊艳的高性能图形渲染体验,从环境搭建到代码实践,一步步教你成为图形编程高手
【8月更文挑战第31天】本文通过代码示例详细介绍了如何在WPF应用中集成DirectX以实现高性能图形渲染。首先创建WPF项目并使用SharpDX作为桥梁,然后在XAML中定义承载DirectX内容的容器。接着,通过C#代码初始化DirectX环境,设置渲染逻辑,并在WPF窗口中绘制图形。此方法适用于从简单2D到复杂3D场景的各种图形处理需求,为WPF开发者提供了高性能图形渲染的技术支持和实践指导。
214 0
|
3月前
|
API C# 开发者
WPF图形绘制大师指南:GDI+与Direct2D完美融合,带你玩转高性能图形处理秘籍!
【8月更文挑战第31天】GDI+与Direct2D的结合为WPF图形绘制提供了强大的工具集。通过合理地使用这两种技术,开发者可以创造出性能优异且视觉效果丰富的WPF应用程序。在实际应用中,开发者应根据项目需求和技术背景,权衡利弊,选择最合适的技术方案。
148 0
|
3月前
|
存储 搜索推荐 C#
WPF/C#:让绘制的图形可以被选中并将信息显示在ListBox中
WPF/C#:让绘制的图形可以被选中并将信息显示在ListBox中
43 0
|
3月前
|
前端开发 C# Windows
WPF基础:在Canvas上绘制图形
WPF基础:在Canvas上绘制图形
126 0
|
6月前
|
C#
WPF —— 动画缩放变换
`ScaleTransform`用于二维x-y坐标系中对象的缩放,可沿X或Y轴调整。在故事板中,通过RenderTransform.ScaleX和ScaleY属性控制缩放。示例代码展示了如何设置按钮的RenderTransformOrigin、Background等属性,并通过LayoutTransform应用ScaleTransform。当鼠标进入按钮时,EventTrigger启动DoubleAnimation实现X和Y轴的缩放动画。最后,展示了如何将动画集成到自定义按钮样式中。
173 0
|
C# 开发者 Windows
WPF技术之图形系列Path控件
WPF Path是Windows Presentation Foundation (WPF)框架中的一个标记元素,用于绘制复杂的几何路径形状。它可以通过设置一系列的路径命令以及相应的参数来定义形状,可以绘制任意复杂度的路径。
1068 0
|
前端开发 C# Windows
WPF技术之图形系列Rectangle控件
WPF Rectangle是Windows Presentation Foundation (WPF)中的一个图形控件,用于在界面上绘制矩形。它是一个非常常见的UI元素,可用于显示、布局和交互。
1175 0