2011-05-28 31 views
13

Con el siguiente fragmento de código creo una escena con 100.000 rectángulos.
El rendimiento es bueno; la vista responde sin retrasos.QGraphicsScene, las coordenadas de los artículos afectan el rendimiento?

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

Y ahora el segundo fragmento chupa

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

Para la primera mitad de elementos de la escena la vista demoras para responder en ratón y la tecla eventos, y para la otra mitad parece estar bien?! ?

La escena anterior tiene sceneRect (x, y, w, h) = (0, -1250000, 40, 2499995).
La última escena tiene sceneRect (x, y, w, h) = (0, 0, 40, 2499995).

No sé por qué el sceneRect afecta el rendimiento, ya que el índice BSP se basa en las coordenadas del artículo relativo.

¿Echo de menos algo? No encontré ninguna información sobre la documentación, más la demostración de Qt 40000 Chips, también distribuye los elementos alrededor (0, 0), sin explicar el motivo de esa elección.

// 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; 
     ... 
+1

Mi primera suposición es el recálculo de la escena rect. ¿Qué sucede si configura sceneRect antes de agregar los elementos? –

+0

@Stephen, el resultado es el mismo. La vista tarda en responder aunque la escena esté lista y estática. –

+1

Guau, muy sorprendente. Ejecuté algunas pruebas, y parece que el widget se vuelve lento solo cuando miras las cajas de 1 a 50.000. Después, es decir, 50.001-100.000, todo está sin problemas. Aún más preocupante, si rango 'for (int y = -70000; y <30000; y ++)', entonces el desplazamiento es suave para -70.000/-20.000, es lento para -20.000/0, luego suave de nuevo para 0/30.000 ! – Fezvez

Respuesta

6

tengo una solución para usted, pero prometen no me pregunte por qué es este trabajo, porque realmente no sé :-)

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); 
+0

hola Fivo. Sí, funciona, buen truco;) –

+0

por supuesto, realmente quiero saber el motivo de ese comportamiento. Un error en el Qt, ¿o es algo más? –

+0

la recompensa es tuya Fivo, pero el caso todavía está abierto :) –

0

Para el caso común, el índice predeterminado método BspTreeIndex funciona bien. Si su escena utiliza muchas animaciones y que está experimentando lentitud, puede desactivar la indexación llamando setItemIndexMethod (NOINDEX). Qt-doc

Tendrá que llamar setItemIndexMethod(QGraphicsScene::NoIndex) antes de la inserción:

scene->setItemIndexMethod(QGraphicsScene::NoIndex); 

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

esto no es lo que estoy buscando, Red Hue. Deshabilitar el índice no es una buena idea si la escena contiene cientos de miles de elementos, o millones. Lo que quiero es rastrear la raíz de este extraño comportamiento. Además, ya sabía una solución alternativa para acelerar el código, y Fivos Vilanakis publicó otra. –

+0

@Nick Dandoulakis ¿Has hecho un informe de error? – Arlen

+0

pero ¿es un error? Podría ser por diseño. De todos modos, hacer un informe es una buena idea. –

0

Podría ser debido a la pérdida de precisión con float. Un flotador de 32 bits tiene una mantisa de 23 bits (o significando), signo de 1 bit y exponente de 8 bits. Esto es como notación científica. Tienes 23 "dígitos significativos" (realmente 24 debido a una ventaja implícita 1) y un exponente de 2^exp donde el exponente puede ir de -126 a 127 (otros se usan para darte cosas como NaN y Inf). De modo que puede representar números realmente grandes como 2^24 * 2^127 pero el siguiente número de punto flotante más cercano a dicho flotante es (2^24-1) * 2^127 o 170 billones de billones de billones de distancia. Si intenta agregar una cantidad menor (como 1000) a dicho número, no cambiará. No tiene forma de representar eso.

Esto se vuelve significativo en gráficos de computadora porque necesita algunos de sus dígitos significativos para hacer una parte fraccionaria. Cuando su escena se extiende hasta 1250000.0 puede agregar 0.1 a eso y obtener 1250000.1. Si toma 2500000.0 + 0.1, obtiene 2500000.0. El problema se magnifica por cualquier escala o rotación que ocurra. Esto puede ocasionar problemas visuales obvios si realmente vuela hacia esas coordenadas y observa su escena.

¿Por qué centrar alrededor de 0 ayuda? Porque hay un bit de signo separado en la representación de coma flotante.En punto flotante hay "más números" entre (-x, + x) que los que hay desde (0,2x). Si estoy en lo cierto, también funcionaría si simplemente redujese la escena completa a la mitad. Esto mueve el bit más significativo hacia abajo dejándolo libre para precisión en el otro extremo.

¿Por qué esto llevaría a un rendimiento pobre? Solo puedo especular sin leer la fuente de Qt, pero considero una estructura de datos para almacenar objetos por ubicación. ¿Qué podría tener que hacer de otra manera si dos objetos tocan (o se superponen) debido a la pérdida de precisión que no tenía que hacer cuando no se solapaban?

+0

Hola Ben. Acabo de probar tu suposición reduciendo la escala de 2.500.000 a 1.000.000 e incluso a 500.000, pero no hay ninguna mejora. Supongo que el problema (¿o el error?) No está relacionado con la precisión, sino que tiene que ver principalmente con la forma en que Qt QGraphicsView utiliza el índice BSP de QGraphicsScene para recortar los objetos de escena cuando se actualiza/refresca la ventana QGraphicsView. –

+0

hi @Ben y @Fivo. Revisé la implementación del BSP, y la precisión del flotador no parece ser el caso. ¡El BSP de Qt solo segmenta la escena/área en N * N sectores sin tener en cuenta las posiciones de los artículos! Quizás es de hecho un error en 'QGraphicsView'. –

Cuestiones relacionadas