Qt 坐标系统
数学基础
Qt坐标系统
视口
和OpenGL一样,视口确定了画面在窗口(QWidget)中显示的区域,Qt的绘图坐标会完全映射到视口(View port)上,就像图示一样。
默认情况下,窗口和视口是重合的,视口的大小覆盖了整个窗口。
和OpenGL一样,Qt的QPainter也有设置视口的接口:painter.setViewport(startX, startY, width, hight);
例如,对于一个400x400(resize(400,400)
)的窗口:
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
//在400x400的默认视口下画一个矩形区域,代表视口
painter.drawRect(100, 100, 200, 200);
//视口:限制窗口的绘图区域
painter.setViewport(100, 100, 200, 200);
painter.fillRect(100, 100, 200, 200, Qt::red);
}
上面的代码在400x400的逻辑画布中画了一个“正方形”,中心与画布中心重合,边界距离画布的边界为100。最后,Qt将画布线性地映射到视口中,结果如下:
平移变换
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
//平移
painter.translate(150, 150);
//在平移之后的坐标系中绘图
painter.fillRect(0, 0, 100, 100, Qt::red);
}
上面的代码在400x400的逻辑画布中,先将坐标系移动到点(150,150)
,然后在移动之后的坐标系中画一个100x100的矩形。结果如下:
缩放变换
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawRect(100, 100, 200, 200);
//平移
painter.translate(150, 150);
//缩放
painter.scale(2, 2);
painter.fillRect(0, 0, 50, 50, Qt::red);
}
上面的代码在400x400的逻辑画布中,先将坐标系移动到点(150,150)
,接着对移动之后的坐标系的x轴和y轴的基向量放大,得到新的坐标系,然后在这个坐标系中画一个50x50的矩形。结果和上图一样:
setWindow
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawRect(100, 100, 200, 200);
painter.setWindow(-75, -75, 200, 200);
painter.fillRect(0, 0, 50, 50, Qt::red);
}
上面的代码等价于上节中的变换:setWindow ↔ 平移+ 缩放。
也可以等价为先缩放,再在缩放之后的坐标系中平移:
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.drawRect(100, 100, 200, 200);
//缩放
painter.scale(2, 2);
//平移
painter.translate(75, 75);
painter.fillRect(0, 0, 50, 50, Qt::red);
}
setWindow ↔ 平移 + 缩放 ↔ 缩放 + 平移
所以,其实setWindow就是一个平移和缩放的组合操作,得到一个新的坐标系。
旋转
void paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.translate(200, 200);
// 顺时针旋转 30 度
painter.rotate(30);
painter.fillRect(0, 0, 100, 100, Qt::red);
}
总结
OpenGL 3D坐标系统图示:
2D坐标系统图示:
与3D相比,2D的z坐标为0。
图中转换