坐标系
先看官方解释的图
在Qt中,对于绘图而言,有三个坐标系
- 世界坐标系(World Coordinates)
- 窗口坐标系(“Window” Coordinates)
- 设备坐标系(Device Coordinates)
世界坐标系:即逻辑坐标系,也就是笛卡尔坐标系。左下角为原点。此为Qt绘图的坐标系,左上角为原点。
窗口坐标系:这个坐标系是QPainter设置setWindow以后的一个坐标系。(注意,这个“窗口”不是平常的程序/控件窗口概念)
设备坐标系:即绘图设备的物理坐标系,默认的原点为应用程序的左上角。QPainter相关的draw函数是物理坐标系下的点。
这三个坐标系的映射(投射)关系,如下图所示。
平时我们的三个坐标系都是相同的,都是水平方向是X轴,垂直方向是Y轴,坐标原点是左上角(0, 0)。X轴从左到右增加,Y轴从上到下增加。
转换矩阵
2D绘图中,窗口坐标系和设备坐标系是一致的,仅通过对逻辑坐标系变换就可实现的平移、缩放、旋转效果。
在最开始那张图中,从世界坐标系变换到窗口坐标系,写着transformation matrix。
没错,通过转换矩阵实现一系列变换!
该篇文章Direct2D教程VI——转换(Transform)详细讲解了转换的公式。可结合视频无所不能的矩阵 - 三维图形变换帮助理解。(注:需要懂矩阵相关知识)
代码实现
.h文件实现代码
#ifndef MATRIX_H
#define MATRIX_H
struct Point {
double x;
double y;
};
class Matrix {
public:
Matrix();
Matrix(double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33);
~Matrix();
//水平平移dx个单位,垂直平移dy个单位
void translate(double dx, double dy);
//横向缩放sx比例,纵向缩放sy比例。大于1是放大,小于1是缩小。1,-1值可以改变坐标轴正方向。
void scale(double sx, double sy);
//顺时针旋转,单位度
void rotate(double angle);
//坐标变换
Point map(Point before) const;
private:
double m_11;
double m_12;
double m_13;
double m_21;
double m_22;
double m_23;
double m_31;
double m_32;
double m_33;
};
#endif // MATRIX_H
cpp文件实现代码
#include "matrix.h"
#include <QtMath>
Matrix::Matrix()
{
}
Matrix::Matrix(double m11, double m12, double m13, double m21, double m22, double m23, double m31, double m32, double m33)
: m_11(m11)
, m_12(m12)
, m_13(m13)
, m_21(m21)
, m_22(m22)
, m_23(m23)
, m_31(m31)
, m_32(m32)
, m_33(m33)
{
}
Matrix::~Matrix()
{
}
//设置平移矩阵
void Matrix::translate(double dx, double dy)
{
m_11 = 1;
m_12 = 0;
m_13 = 0;
m_21 = 0;
m_22 = 1;
m_23 = 0;
m_31 = dx;
m_32 = dy;
m_33 = 1;
}
//设置缩放矩阵
void Matrix::scale(double sx, double sy)
{
m_11 = sx;
m_12 = 0;
m_13 = 0;
m_21 = 0;
m_22 = sy;
m_23 = 0;
m_31 = 0;
m_32 = 0;
m_33 = 1;
}
//设置旋转矩阵
void Matrix::rotate(double angle)
{
m_11 = cos(angle);
m_12 = sin(angle);
m_13 = 0;
m_21 = -sin(angle);
m_22 = cos(angle);
m_23 = 0;
m_31 = 0;
m_32 = 0;
m_33 = 1;
}
//坐标变换
Point Matrix::map(Point before) const
{
Point after;
after.x = before.x * m_11 + before.y * m_21 + m_31;
after.y = before.x * m_12 + before.y * m_22 + m_32;
return after;
}
Qt中的实现函数
QPainter绘图之坐标转换函数
函数原型 | 作用 |
---|---|
void translate(qreal dx,qreal dy) | 平移 |
void rotate(qreal angle) | 旋转 |
void scale(qreal sx,qreal sy) | 缩放 |
void shear(qreal sh,qreal sv) | 扭转 |
坐标系统的2D变换由QTransform
类实现,QPainter
也可以实现,而QTransform
可以存储多个变换操作,对数据量大且复合变换有优势。
窗口—视口转换
视口一般设定与屏幕的DPI一致,通常不用变
更多的坐标系概念
窗口,视口,场景坐标系,对象坐标系,世界坐标系,逻辑坐标,物理坐标。
Graphics View Framework图形视图框架,相关的概念。
绘制坐标系
可平移缩放刻度自适应的坐标系
(放图)
我学习过程的疑惑
1.为什么有这么多不同的坐标系
三维降二维,世界不同,视角不同。
2.我以为逻辑坐标转成物理坐标,只是一个公式变换
原一开始,我以为,设定原点,对直接输入的逻辑坐标,经过公式转换,转成物理坐标,然后画在设备窗口上就行。没想到,大有学问啊。
3.如何画上去
变换坐标系,通过translate偏移,scale翻转轴方向。然后draw(x1,y1,x2,y2)
变点,通过公式或通过矩阵变换,计算逻辑坐标点落在物理坐标的点。然后draw(map(x1,y1),map(x2,y2))