gpt4 book ai didi

c++ - Qt - drawPolyline 和 drawLine 之间的区别

转载 作者:行者123 更新时间:2023-11-30 01:36:15 25 4
gpt4 key购买 nike

在我的示例中,我按以下方式转换了 qt painter 的坐标系:

 QTransform xform;
xform.rotate(90);
xform.scale(1, 1000000000000000);
xform.translate(0, -std::abs(max));
if (limit != 0)
xform.scale(1, std::abs(max)/std::abs(limit));
painter->setTransform(xform)

之所以有这么大的规模,是因为我的例子中的数据非常少。然后我为我的数据画图 - 它的值大约是 1e-14 并且一切都正确绘制。然后,除了由两点指定的图之外,我还想画几条线。

我应用 drawPolyLine 函数:

QPointF* line = new QPointF[2];
line[0].setX(0);
line[0].setY(0);
line[1].setX(0);
line[1].setY(std::abs(seismMax));
painter.drawPolyline(line, 2);

其中 seismMax 的数量级为 1e-14(作为我在图中的所有点)。然后画线。然后我应用 drawLine(因为我只有两点):

painter.drawLine(QPointF(0, 0), QPointF(0, std::abs(seismMax)));

并且在这种情况下没有画线。我怀疑这两个函数处理坐标的方式可能不同。当我用 drawLine 以原始比例绘制线时(例如像这样):

 painter.drawLine(QPointF(0, 0), QPointF(0, 1000));

线条绘制正确。

最佳答案

我做了一个 MCVE接触问题。

因此,我使用了更小的缩放比例,无法重现该问题。然后,我使用了 OP 所述的缩放比例 1.0E14。突然,线条画消失了。降低缩放比例,我弄清楚了(在我的例子中)直到 1E12 它工作得很好但是随着更高的缩放比例线开始消失。在玩弄这个时,一位同事离开并暗示这可能只是 float 问题。我们很快讨论了这个并得出结论:

  • 将非常大的数字与非常小的数字相乘根本不是问题。它由(整数)尾数相乘和指数相加组成。
  • 大数与非常小的数的加法/减法是一个问题,因为两个数必须具有相同的指数(通过移位尾数)以加减尾数。

因此,后者可能会发生,将非 0 值删除为 0。

1014 是二进制的 47 位数字。这接近具有 53 位尾数的 double 的精度。 但是:QPainter 使用的渲染引擎可能是基于 OpenGL 的,其中 float 是很多东西的默认值。 float 只提供 23 位的尾数!

因此,在稍微考虑一下之后,我找到了不使用 1014 比例因子绘画的充分理由。

为了演示这一点,我制作了一个小示例 testQPainterDrawLine.cc:

#include <QtWidgets>

class Widget: public QWidget {
public:
const double scale;
public:
Widget(double scale, QWidget *pQParent = nullptr):
QWidget(pQParent),
scale(scale)
{ }
virtual ~Widget() = default;
Widget(const Widget&) = delete;
Widget& operator=(const Widget&) = delete;
protected:
virtual void paintEvent(QPaintEvent *pQEvent) override;
};

void Widget::paintEvent(QPaintEvent*)
{
const double value = height() / scale;
QPainter qPainter(this);
qPainter.fillRect(0, 0, width(), height(), QColor(Qt::white));
qPainter.drawRect(0, 0, width() - 1, height() - 1);
QTransform xform;
xform.scale(1, scale);
qPainter.setTransform(xform);
qPainter.setPen(QPen(QColor(Qt::red), 3.0));
const double xL = 0.333 * width();
qPainter.drawLine(QPointF(xL, 0.0), QPointF(xL, value));
qPainter.setPen(QPen(QColor(Qt::blue), 3.0));
const double xPL = 0.667 * width();
QPointF qPts[] = { QPointF(xPL, 0.0), QPointF(xPL, value) };
const int nPts = sizeof qPts / sizeof *qPts;
qPainter.drawPolyline(qPts, nPts);
}

int main(int argc, char **argv)
{
qDebug() << "Qt Version:" << QT_VERSION_STR;
QApplication app(argc, argv);
QWidget qWin;
QGridLayout qGrid;
qGrid.setRowStretch(0, 0); qGrid.setRowStretch(1, 1);
double scale = 1.0E11;
for (int i = 0; i < 4; ++i, scale *= 10.0) {
qGrid.addWidget(
new QLabel(QString("Scale: %1").arg(scale)),
0, i);
qGrid.addWidget(new Widget(scale), 1, i);
}
qWin.setLayout(&qGrid);
qWin.resize(1024, 256);
qWin.show();
return app.exec();
}

testQPainterDrawLine.pro:

SOURCES = testQPainterDrawLine.cc

QT = widgets

cygwin64 中编译和测试:

$ qmake-qt5 testQPainterDrawLine.pro

$ make

$ ./testQPainterDrawLine
Qt Version: 5.9.4

snapshot of testQPainterDrawLine

所以,最后,我相信,它与 QPainter::drawLine()QPainter::drawPolyline() 没有任何关系。这只是缩放太高并导致浮点问题。这就是线条可能会意外(消失)的原因。

解决方案很简单:在使用 QPainter 绘制值之前必须对其进行缩放,以便 QPainter 中的内部转换发生在更接近 0 和 1 的幅度上。

关于c++ - Qt - drawPolyline 和 drawLine 之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52512387/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com