诸如图像、模型等的基本变换,实际上都是点坐标的变换,通过矩阵,可以非常方便的达到这个目的。在下文仅介绍二维坐标变换原理。
首先,定义点类如下:
//定义点类,亦可表示向量
class vec2
{
public:
float v[2];//v[0]为横坐标,v[1]为纵坐标
vec2(){}
~vec2(){}
//构造函数,例vec2 p(0,0);表示构造p点坐标为(0,0)
vec2(const float &x, const float &y){v[0] = x; v[1] = y;}
//重载[],如vec2 p ;p[0]即表示x坐标值,p[1]表示y坐标值
float &operator[] (int i) { return v[i]; }
const float &operator[] (int i) const { return v[i]; }
};
注意,为了形式统一,变换矩阵应统一为3*3阶,同理,对于三维坐标变换矩阵应是4*4阶。关于矩阵的表示,实际上便是一个二维数组,其相关运算可以直接利用Eigen库,具体如何配置就不在此赘述。矩阵如何定义可参考如下,注意矩阵的初始化不应该是全部元素为0,而是对角元素为1,其余为0,即单位矩阵E.
class Matrix2D
{
public:
double A[3][3];
} ;
对于一点表示为1*3的矩阵,则一个点集S = {}表示为一个n*3的矩阵:
我们将这个矩阵称为原始矩阵,而后续的变换表示为这个矩阵乘以一个或多个矩阵,实则为两个二维数组的乘法与加法。
一、平移
对于平移我们需要知道一个平移的方向和平移的距离,因此可以通过一个向量表示这2个量,即
,平移矩阵表示为:
平移后的坐标即为*。
二、旋转
对于旋转我们需要的是一个弧度θ,则旋转矩阵表示为:
若只是乘上,表示的是坐标绕原点旋转,如果输入旋转中心,应当将旋转中心平移至原点,待求坐标跟随移动,在原点完成旋转后再平移回来,变换矩阵应为**,即:
旋转后的坐标即为 * **。
三、缩放
对于缩放我们需要的是一个缩放系数t,则缩放矩阵表示为:
若输入缩放中心,同旋转,应先平移至原点缩放完再平移回来。变换矩阵应为,即:
缩放后的坐标即为 *。
四、镜像
对于镜像,我们需要输入对称轴,即输入2个点p,q,但实际上计算需要的是对称轴的法向量,通过p-q获得对称轴方向向量,再求其垂直向量即可。镜像矩阵表示为:
另外就是需要一个表示对称轴位置的点,在输入的对称轴2点中随便取一点即可,表示为 ,变换矩阵为,即:
镜像后的坐标即为*。
五、阵列
阵列可以分为环形阵列和方向阵列。
1.环形阵列
和旋转变换类似,输入阵列中心,阵列数量,通过不断旋转获得阵列对象,变换矩阵表示为:
环形阵列的每个对象坐标为*。
2.方向阵列
和平移变换类似,输入2个点,表示阵列的方向,实际上我们需要的是单位方向向量、阵列对象之间的间距和阵列数量,其单位方向向量由输入的2个点相减后除以模长获得,变换矩阵表示为:
方向阵列的每个对象坐标为*。
六、实现效果
在MFC中实现的效果如下图所示: