数学知识和计算机图形学方面的知识
12.12.1 基本数学知识
1、齐次坐标
二维空间中的点可使用(x, y)表示,但在计算机图形学中使用齐次坐标表示点更为方便,齐次坐标把点表示为三元组,即在(x,y)基础上增加一维表示为(x, y, w),其中w是一个非零值
每个点有很多个不同的齐次坐标表示(只要其中一个是另一个的倍数即可),比如(1, 2, 5),(2,4, 10),(4, 8, 20);都表示同一个点,通常会使用w去除齐次坐标,从而一个点被表示为(x/w, y/w, 1),这样,每一个二维坐标点都可以使用三维的齐次坐标来表示,同理,三维坐标点(x,y,z);可使用四维的齐次坐标表示为(x, y, z, 1);比如(2,5,9)的齐次坐标为(2,5,9,1);
使用齐次坐标后,所有的坐标变换公式都可以使用如下矩阵相乘的形式来表示,
2、坐标变换公式
以下各式中,dx和dy表示平移距离,Sx和Sy表示缩放系数,θ表示绕原点逆时针旋转的角度,P1(x1, y1)为坐标变换后的
点,P(x,y)为变换前的点。
3、坐标的复合变换
坐标的复合变换是指多个坐标变换序列的组合。
①、连续平移变换(其结果是平移相加)
把点P平移至点P1再平移至P2,则其平移公式的推导步骤为
由以上推导过程可见,对复合的坐标变换序列,只需计算其变换矩阵即可,以上规则同样适用于其他更复杂的复合变换,对于之后的变换,将只写出变换矩阵的计算。
下面为坐标平移复合变换后的计算过程。
5、总结
由以上讲解可知,只要给出变换矩阵,便可对其进行坐标变换,因此在计算机编程中,通常只需给出一个变换矩阵,然后给矩阵各元素赋予需要的值便可对其进行各种坐标变换。
6、其他
对于三维空间的坐标变换,其原理与二维类似,其坐标变换矩阵为
12.12.2 使用QPainter类中的基本变换函数进行坐标变换
默认情况下,QPainter是在自已所关联的绘制设备的坐标系(通常为像素)上运行的,绘制设备默认坐标系的原点位于左上角,X轴向右增长,Y轴向下增长。
2、QPainter类中的基本坐标变换函数如下
3、QPainter类中与绘制状态有关的函数如下
示例12.20:使用QPainter类中的基本坐标变换函数变换坐标
void paintEvent(QPaintEvent *e)
{
QPainter pr(this);
QBrush bs(QColor(1,111,1));
pr.setBrush(bs);
QRectF r(0,11,22,55);
pr.drawRect(r);
//变换1:平移(50,10)
pr.translate(50,10);
pr.drawRect(r);
pr.save(); //保存状态
//变换2:平移(50,50),缩放2倍(Y向),逆时针旋转60度
pr.translate(50,50);
pr.scale(1,2);
pr.rotate(-60);
pr.drawRect(r);
QTransform t=pr.transform(); //获取变换2的变换矩阵
qDebug()<
运行结果(见图12-55)
现以变换2计算其变换矩阵
注意:在使用QPainter类中的基本坐标变换函数进行复合坐标变换时,其变换矩阵应按相反的顺序进行计算。因此计算变换2的矩阵时应按旋转、缩放、平移的顺序进行计算,如下所示
12.12.3 使用变换矩阵(QTransform类)进行坐标变换
1、QPainter类中与QTransform类有关的函数如下
2、QTransform类
QTransform类主要用于创建一个3*3的变换矩阵,该矩阵用于坐标系的2D变换。该类取代了QMatrix类(此类已过时)。QTransform类通过操控变换矩阵来实现坐标变换。另外QTransform类还可对矩阵进行操作,比如可进行矩阵的加、乘等运算,还可对矩阵类型进行判断(比如是否是满秩矩阵等)。
QTransform类除了可通过操控其矩阵进行坐标变换外,还可使用QTransform类中内置的基本变换函数(比如QTransform::scale()、QTransform::scale()等)对坐标进行变换,这些函数的使用方法与QPainter类中的相应函数是相同的。简单的坐标变换完全可使用QPainter类中的基本坐标变换函数来完成,使用QTransform类可以把多个坐标变换组织在一起,然后在需要时使用。
QTransform类的变换矩阵如下
注:公式18~22其实就是使用的如下矩阵乘法计算出来的(读者可自行计算),在没有投影变换的情形下,w1直接取整数值1即可。因此在使用QTransform类进行坐标变换时,也可使用如下的矩阵形式计算变换后的坐标值。
把QTransform类的变换矩阵与坐标变换矩阵相对比,可得出如下规律m31和m32用于平移,m11和m22用于缩放,m21和m12用于错切(shear),m13和m23用于投影变换,m33是一个额外的投影因子,设置m11,m12,m21,m22可实现旋转变换。注:投影变换是一个比较复杂的变换,包括透视投影(图12-56为透视投影的一个简图)和平行投影,关于投影变换的内容请参阅《计算机图形学》课程。
12.12.4 QTransform类中的函数
1、构造函数
2、设置和获取变换矩阵的元素
3、QTransform内置的基本坐标变换函数
4、对变换矩阵的判断
5、构建变换矩阵
6、与线性代数有关的函数
7、使用变换矩阵转换图形坐标
以下函数用于转换坐标,比如QPoint p1=matrix.map(point);表示把点使用变换矩阵matrix进行转换,然后返回该点的副本。等效于p1= point*matrix;具体应用见示例12.22
8、下面为重新实现的操作符函数
示例12.21:使用QTransform类(变换矩阵)进行坐标变换(见图12-57)
//注意:变换矩阵应按设计的相反顺序计算,比如若设计为平移T、旋转R、缩放S,则矩阵计算应为S∙R∙T
void paintEvent(QPaintEvent *e)
{
QPainter pr(this);
QBrush bs(QColor(1,111,1));
pr.setBrush(bs);
QRectF r(0,55,22,55);
//变换1(平移、旋转)
QTransform t(1,0,0,1,20,0); //x方向平移20
t.rotate(-60); //使t再逆时针旋转60度。
pr.setTransform(t); //设置变换矩阵为t
qDebug()<
示例12.22:QTransform::map()函数的使用(见图12-58)
void paintEvent(QPaintEvent *e)
{
QPainter pr(this);
QBrush bs(QColor(1,111,1));
pr.setBrush(bs);
QRectF r(0,55,22,55);
QLineF n(50,0,50,555);
pr.drawLine(n);
pr.drawRect(r);
QTransform t;
t.translate(50,0); //x方向平移50
QRectF r1=t.mapRect(r); //使用t转换r的坐标。
QLineF n1=t.map(n); //使用t转换n的坐标
//n1也可使用如下等效语句创建,更简洁
//QLineF n1=n*t; //注意t*n是错误的
pr.drawRect(r1);
pr.drawLine(n1);//绘制转换后的图形
}
示例12.23:使用变换矩阵计算变换后的坐标值(见图12-59)
void paintEvent(QPaintEvent *e)
{
QPainter pr(this); QBrush bs(QColor(1,111,1)); pr.setBrush(bs);
QRect r(0,55,22,55);
pr.drawRect(r);
QTransform t; t.translate(50,0); t.rotate(-60);
QPolygon g1=t.mapToPolygon(r); pr.drawPolygon(g1);
qDebug()<