Qt坐标系转换(绘制逻辑坐标系)

  • O8_908569
    了解作者
  • 7.3KB
    文件大小
  • zip
    文件格式
  • 0
    收藏次数
  • VIP专享
    资源类型
  • 0
    下载次数
  • 2022-06-10 11:04
    上传日期
本资源为Qt绘图基础,世界坐标系转换为逻辑坐标系。世界坐标系原点在视图左上角,本例子通过世界坐标转换,将坐标原点定位在视图中央,Y轴向上,X轴向右,并绘制坐标轴,基于逻辑坐标系下的绘图,可将转换关系函数取消生效,对比世界坐标系下的绘图。 重写PainterEvent函数: void QtPixPainter::paintEvent(QPaintEvent* event) { QPainter painter(this); // 反走样 painter.setRenderHint(QPainter::Antialiasing, true); //物理坐标系与逻辑坐标系的转换,如果不转换,下面的绘图都是在世界坐标系下 setWorldTransform(painter); // 其他一些绘制矩形,多边形的例子,经过上面转换,都是在逻辑坐标系下 drawRectScale(painter); //draw_shearRect(painter); //利用rotate()函数进行比例变换,实现缩放效果 //draw_rotate_act(painter); //draw_by_save_restore(painter); //transform_draw_SinX(painter); transform_draw(painter); local_drawConvexPolygon(painter); } // 将世界坐标(原点左上角)转换为逻辑坐标(原点在屏幕中间) QPointF QtPixPainter::mapToScene(const QPointF& point) { QTransform transMatrix = _transform.inverted(); //翻转矩阵? return transMatrix.map(point); //将点piont映射到transMatrix定义的坐标系中来 } // 将鼠标的逻辑位置返回并以标签形式展示 void QtPixPainter::mouseMoveEvent(QMouseEvent* event) { QString msg; QPointF mouse_po = mapToScene(event->pos()); //总是返回屏幕物理坐标系 double x = mouse_po.x(); // 总是返回屏幕物理坐标系 double y = mouse_po.y(); QString str = "(" + QString::number(x) + "," + QString::number(y) + ")"; //qDebug()<<"world x = "<<event->pos().x()<<",world y = "<<event->pos().y(); m_mouse_lable->setText(str); }
QtPixPainter.zip
  • QtPixPainter
  • qtpixpainter.h
    1.2KB
  • QtPixPainter.pro.user
    22.2KB
  • main.cpp
    187B
  • qtpixpainter.cpp
    8.1KB
  • QtPixPainter.pro
    992B
内容介绍
#include "qtpixpainter.h" #include <QPainter> #include <QtMath> #include <QtDebug> #include <QStatusBar> #include <QEvent> #include <QMouseEvent> QtPixPainter::QtPixPainter(QWidget *parent) : QMainWindow(parent) { this->setMouseTracking(true); resize(1600,900); m_mouse_lable = new QLabel; m_mouse_lable->resize(100, 30); QStatusBar *statusBar = new QStatusBar(this); statusBar->addPermanentWidget(m_mouse_lable); this->setStatusBar(statusBar); } QtPixPainter::~QtPixPainter() { } void QtPixPainter::SetLocalTransFrom(QPainter &painter) { /* * 绘图设备的坐标原点(0,0)在左上角,水平向右增长,垂直向下增长。 * 首先先平移坐标原点,让原点在绘图设备的中心 */ } void drawRectScale(QPainter &painter) { painter.save(); painter.setBrush(Qt::yellow); painter.scale(2,2); //放大两倍 放大倍数对后面的所有动作生效 painter.drawRect(0,0,50,50); painter.translate(100,100); //将点(100,100)设为原点 painter.setBrush(Qt::red); // painter.scale(2,2); //放大两倍 painter.drawRect(0,0,50,50); painter.translate(-100,-100);// 如果前面设置放大两倍 那么这里就是 -200,-200 下面的直线就显示不出来 // painter.scale(2,2); //放大两倍 painter.drawLine(0,0,20,20); painter.restore(); } void draw_shearRect(QPainter &painter)// 扭曲 { painter.setBrush(Qt::yellow); painter.drawRect(0,0,50,50); painter.shear(0,1); //纵向扭曲变形 painter.setBrush(Qt::red); painter.drawRect(50,0,50,50); } void draw_rotate_act(QPainter &painter)// 旋转 { painter.drawLine(0,0,100,100); painter.rotate(30); //以原点为中心,顺时针旋转30度 painter.drawLine(0,0,100,0);// 不旋转条件下,直线与世界坐标的x轴重合 painter.translate(100,100); painter.rotate(30); // 到这里再次旋转 已经旋转了60度 如果想要恢复 旋转-30 painter.drawLine(0,0,100,0); painter.rotate(-60); painter.drawLine(0,0,100,0); } void draw_by_save_restore(QPainter &painter) { painter.save(); //保存坐标系状态 painter.translate(100,100); painter.drawLine(0,0,120,100); painter.restore(); //恢复以前的坐标系状态 painter.drawLine(0,0,50,50); } void QtPixPainter::transform_draw(QPainter &painter) { // 将坐标平移到当前窗口中心 // double orig_x = width() / 2; // double orig_y = height() / 2; // painter.translate(orig_x, orig_y); // 将坐标原点平移到中心 //在中心画直线交叉 double x_begin = - width() / 2; double y_begin = 0; double x_end = width()/2; double y_end = 0; QPointF point_begin_x = QPointF(x_begin,y_begin); QPointF point_end_x = QPointF(x_end,y_end); double xz_begin = 0; double yz_begin = - height() / 2; double xz_end = 0; double yz_end = height()/2; QPointF point_begin_y = QPointF(xz_begin,yz_begin); QPointF point_end_y = QPointF(xz_end,yz_end); qDebug()<<"try to drawline..."; painter.drawLine(point_begin_x, point_end_x); painter.drawLine(point_begin_y, point_end_y); } void QtPixPainter::setWorldTransform(QPainter &painter) { // 获取窗口的宽和高 计算中心点 double center_x = width() / 2.0; double center_y = height() / 2.0; origXY.setX(center_x); origXY.setY(center_y); _transform.reset(); //重置为单位矩阵 _transform.scale(1, 1); // 缩放 不能设置为0,0,一般需要符合坐标系大小 设置为1,1为原始坐标系 如果设置为其他值 需要重新计算原点的坐标系 _transform.translate(origXY.x(), origXY.y()); //平移 将坐标平移至视图中心并以此为0,0点 _transform.rotate(180, Qt::XAxis); // 旋转 将物理坐标旋转为逻辑坐标系 将坐标系沿X轴旋转180度 X轴不变 二位坐标系一般就是y从向下顺时针旋转180度至向上 painter.setTransform(_transform); //painter.combinedTransform().inverted(); 获取变换关系 } void QtPixPainter::transform_draw_SinX(QPainter &painter) { QPen pen; pen.setColor(Qt::green); pen.setStyle(Qt::SolidLine); pen.setWidthF(0.01); painter.setPen(pen); painter.setViewport(50, 50, width()-100, height()-100);//视图 // 如果这里不是宽和高 那么窗口时固定大小 不会自适应伸缩 painter.setWindow(-10, 2, 20, -4); //窗口 // 窗口会自适应大小 painter.fillRect(-10, 2, 20, -4, Qt::black); painter.drawLine(QPointF(-10, 0), QPointF(10, 0)); // x painter.drawLine(QPointF(0, 2), QPointF(0, -2)); // y for(float x=-10; x<10; x+=0.01) { float y = qSin(x); painter.drawPoint(QPointF(x, y)); } } bool QtPixPainter::PointCmp(const QPointF &a,const QPointF &b,const QPointF &center) { int oax = a.x() - center.x(); int oay = a.y() - center.y(); int obx = b.x() - center.x(); int oby = b.y() - center.y(); auto atan2a = std::atan2(oay, oax); auto atan2b = std::atan2(oby, obx); if (atan2a < 0) atan2a = atan2a + 3.1415926 * 2; if (atan2b < 0) atan2b = atan2b + 3.1415926 * 2; // 小于0的角度需要变换下,使得它可以进行总体的角度排序; return atan2a > atan2b; } void QtPixPainter::ClockwiseSortPoints(QPolygonF &qpl) { //计算重心 QPointF center; double x = 0,y = 0; for (int i = 0;i < qpl.size();i++) { x += qpl[i].x() ; y += qpl[i].y(); } center.rx() = (int)x/qpl.size(); center.ry() = (int)y/qpl.size(); //冒泡排序 for(int i = 0;i < qpl.size() - 1;i++) { for (int j = 0;j < qpl.size() - i - 1;j++) { if (PointCmp(qpl[j],qpl[j+1],center)) { QPointF tmp = qpl[j]; qpl[j] = qpl[j + 1]; qpl[j + 1] = tmp; } } } } void QtPixPainter::local_drawConvexPolygon(QPainter &painter) { painter.save(); //painter.setBrush(Qt::red); QPen pen(Qt::SolidLine); //实线 //pen.setWidthF(pen.widthF() / _zoomScale); pen.setWidth(4); pen.setColor(QColor(135, 206, 255)); painter.setPen(pen); QPolygonF qpl;// 设置点集合 QVector<QPointF> qpl.append(QPointF(60,-104)); qpl.append(QPointF(-140,123.6)); qpl.append(QPointF(2.5,4.3)); qpl.append(QPointF(0,0)); qpl.append(QPointF(48.6,123.6)); qpl.append(QPointF(-140,-24.6)); qpl.append(QPointF(2.0,4.6)); // 对点排序 ClockwiseSortPoints(qpl); for (int i = 0; i < qpl.size(); i++) { qDebug()<<"qpl["<<i<<"] = "<<qpl[i]; } // 绘制图形 painter.drawConvexPolygon(qpl); painter.restore(); } void QtPixPainter::paintEvent(QPaintEvent* event) { QPainter painter(this); // 反走样 painter.setRenderHint(QPainter::Antialiasing, true); //物理坐标系与逻辑坐标系的转换 setWorldTransform(painter); drawRectScale(painter); //draw_shearRect(painter); //利用rotate()函数进行比例变换,实现缩放效果 //draw_rotate_act(painter); //draw_by_save_restore(painter); //transform_draw_SinX(painter); transform_draw(painter); local_drawConvexPolygon(painter); } QPointF QtPixPainter::mapToScene(const QPointF& point) { QTransform transMatrix = _transform.inverted(); //翻转矩阵? return transMatrix.map(point); //将点piont映射到transMatrix定义的坐标系中来 } void QtPixPainter::mouseMoveEvent(QMouseEvent* event) { QString msg; QPointF mouse_po = mapToScene(event->pos()); //总是返回屏幕物理坐标系
评论
    相关推荐
    • 矩阵按钮控件源码
      矩阵按钮控件,可以设置行列数,和按钮的HEIGHT和WIDTH属性, 按钮可以显示图片,可以设置按钮的FLAT风格。 可以增加,删除按钮,也可以修改按钮标题。 主要属性 property Enabled;; property Visible;; ...
    • 矩阵运算库 包含逆矩阵算法等
      矩阵运算库 包含转置、逆矩阵算法、矩阵相乘、矩阵加减法等
    • j2me BUG
      NULL 博文链接:https://buerkai.iteye.com/blog/1119025
    • led矩阵字模仿真器
      这次发布的PCtoLCD2002完美版与前一版本相比没有增加太多的功能,因为我觉得现有的这些功能已经足够用于生成各种字模的需要了,所以完美版的主要工作是反复测试,精心去除各种BUG,以及调节一些细微之处,目的当然...
    • spammpack:稀疏近似矩阵-矩阵乘积
      SpAMM,稀疏近似矩阵乘。 制作说明 该库使用CMake。 只需运行 cmake . make 建造它。 为了提供更多的便利,我们提供了一个shell脚本,用于在名为build的目录中进行源代码外配置和构建spammpack。 ./build.sh 将...
    • Russion-tw.rar
      本人写的一个关于俄罗斯套娃的源程序,其目的是抛砖引玉,欢迎大家分享优质、高效的代码。 经过本人强力测试,可以处理重量为0的娃娃。...如果在测试用过程中您发现什么BUG,请及时和我联系。 灰常感谢~~~~
    • 计算机区域填充有BUG
      计算机图形学实验,区域填充算法,使用OPENGL语言
    • 标准C++矩阵运算类包SMatrix
      由于作业需要,自己花了整天改成的一个矩阵类;支持矩阵的切割,求逆等相互间的运算,目前没发现bug,分享一下~~
    • WEBGL里lib目录,里面封装了相机和物理矩阵
      WEBGL里lib目录,里面封装了相机和物理矩阵等,还有WEBGL运行中的BUG处理
    • GaussDB_100_1.0.1-DATABASE-REDHAT-64bit.tar.gz
      guassdb100在redhat上安装包,单机部署的包,安装步骤请看我的文中介绍,经过大量实验搭建总结出来的文档