13

使用下面的代码片段,我创建了一个包含 100.000 个矩形的场景。
表现不错;视图响应没有延迟。

QGraphicsScene * scene = new QGraphicsScene;
for (int y = -50000; y < 50000; y++) {
   scene->addRect(0, y * 25, 40, 20);
}
...
view->setScene(scene);

现在第二个片段很烂

for (int y = 0; y < 100000; y++) {
   scene->addRect(0, y * 25, 40, 20);
}

对于第一半场景元素,视图延迟响应鼠标和按键事件,而另一半似乎没问题?!?

前一个场景有sceneRect (x, y, w, h) = (0, -1250000, 40, 2499995)。
后一个场景有sceneRect (x, y, w, h) = (0, 0, 40, 2499995)。

我不知道为什么 sceneRect 会影响性能,因为 BSP 索引是基于相对项目坐标的。

我错过了什么吗?我在文档上没有找到任何信息,加上 Qt demo 40000 Chips也将元素分布在 (0, 0) 周围,没有解释选择的原因。

 // Populate scene
 int xx = 0;
 int nitems = 0;
 for (int i = -11000; i < 11000; i += 110) {
     ++xx;
     int yy = 0;
     for (int j = -7000; j < 7000; j += 70) {
         ++yy;
         qreal x = (i + 11000) / 22000.0;
         qreal y = (j + 7000) / 14000.0;
         ...
4

3 回答 3

6

我有一个解决方案给你,但保证不要问我为什么这有效,因为我真的不知道 :-)

QGraphicsScene * scene = new QGraphicsScene;
// Define a fake symetrical scene-rectangle
scene->setSceneRect(0, -(25*100000+20), 40, 2 * (25*100000+20) );

for (int y = 0; y < 100000; y++) {
    scene->addRect(0, y * 25, 40, 20);
}
view->setScene(scene);
// Tell the view to display only the actual scene-objects area
view->setSceneRect(0, 0, 40, 25*100000+20);
于 2011-06-01T03:47:38.677 回答
0

这可能是由于float. 32 位浮点数具有 23 位尾数(或有效位)、1 位符号和 8 位指数。这就像科学记数法。您有 23 个“有效数字”(实际上是 24,因为隐含的前导 1)和 2^exp 的指数,其中指数的范围可以从 -126 到 127(其他的用来给你和 之类的东西NaNInf。所以你可以表示非常大的数字,比如 2^24*2^127 ,但下一个最接近这种浮点数的浮点数是 (2^24-1)*2^127 或 1700 亿十亿。如果您尝试将较小的数量(如 1000)添加到这样的数字,它不会改变。它没有办法代表它。

这在计算机图形学中变得很重要,因为您需要留下一些有效数字来制作小数部分。当您的场景范围高达 1250000.0 时,您可以将 0.1 添加到该范围并获得 1250000.1。如果你取 2500000.0 + 0.1,你会得到 2500000.0。发生的任何缩放或旋转都会放大问题。如果您真的飞到这些坐标并查看您的场景,这可能会导致明显的视觉问题。

为什么以 0 为中心有帮助?因为浮点表示中有一个单独的符号位。在浮点数中,(-x,+x) 之间的数字比 (0,2x) 之间的数字多。如果我是对的,如果您只是将整个场景缩小 1/2,它也会起作用。这会将最重要的位向下移动,使其在另一端保持精确。

为什么这会导致性能不佳?我只能在不阅读 Qt 源代码的情况下进行推测,但考虑一种按位置存储对象的数据结构。如果两个对象由于精度损失而接触(或重叠),而当它们不重叠时您不必这样做,您可能需要做些什么不同的事情?

于 2011-06-05T22:48:37.277 回答
0

对于常见情况,默认索引方法 BspTreeIndex 可以正常工作。如果您的场景使用了许多动画并且您遇到了缓慢的问题,您可以通过调用 setItemIndexMethod(NoIndex) 来禁用索引。Qt文档

您需要setItemIndexMethod(QGraphicsScene::NoIndex)在插入前致电:

scene->setItemIndexMethod(QGraphicsScene::NoIndex);

for (int y = 0; y < 100000; y++) {
   scene->addRect(0, y * 25, 40, 20);
}
//...
于 2011-06-01T05:53:04.627 回答