PDA

View Full Version : QGraphicsScene/QGraphicsView performance problems



bnilsson
4th January 2008, 11:58
Hi!

I am trying to write a microchip CAD datafile display program using the QGraphics View framework. It is the first time i use this, and it seems to be very convenient, very little (of my own) code is needed to do what I want to do.
However, my data files may range from small to quite large, anything between a few 100kb and up to a few 100Mb. At about 20Mb, my application begins to choke, i think mainly due to memory consumption. A Linux amd64 dual core system gets completely stuck when loading a 40Mb file, I had to terminate to avoid a complete system crash.
My MacOSX ppc G5 dual core behaves just the same.
I have not tried Windows yet.

I use Qt4.3.3 and recently Qt4.4.0 snapshot, same results on each.

I have a feeling there is a lot of stuff in the QGraphics View that is not needed for my app, I just need to draw, scroll and zoom, no select, move or transform.

Is the QGraphics View framework the right thing to use for me?
If so, can I turn off some of the bells and whistles to gain performance?
Or should I use some different methods?

Any suggestions are appreciated.

wysota
4th January 2008, 15:10
If it chokes while loading the data, there is a chance the slowdown is not related to graphics view at all but instead to the loading routine. Use a profiler to find the bottleneck of the application. Also if you have multiple cores, try to design your application in such a way that all cores are used (especially when loading the data).

bnilsson
4th January 2008, 16:38
Just realized how not to use itemized data, so I am drawing in myQGraphicsView::drawBackground() instead. Now it doesn't use much memory, so I can load large files.
Now the problem is back to performance speed again, and I need to check in my own code wether the shapes are in the visible view or not, and find a way to sift through the data real fast. Also, the scrolling is directly depending on how fast I can draw.
I found that it was impossible to draw a mouse rubberband if GraphicsView was not cashed.
Is there a way to cache the background drawing?

wysota
4th January 2008, 16:42
Just realized how not to use itemized data, so I am drawing in myQGraphicsView::drawBackground() instead.
But now you are not using the graphics view architecture at all. You could as well use a plain QWidget instead.

bnilsson
4th January 2008, 17:00
Yes, I realize that. Yet the way of using methods of zooming in/out and the scrollers are the same. which is convenient for me right now. I am only a Qt beginner, so I would need to study how to do the same with more "standard" methods. Will I gain much performance if I change to QWidget? I suspect I would never get it working for a 150Mb data file if I use QGraphicsItems with QGraphicsScene/QGraphicsView.

BTW, I am using QDataStream to repeatedly read my data, even for updates. I guess this is not terribly efficient. Can you recommend another way?

wysota
4th January 2008, 18:48
Will I gain much performance if I change to QWidget?
You'll lose the overhead caused by everything that QGraphicsView has and QWidget has not.


I suspect I would never get it working for a 150Mb data file if I use QGraphicsItems with QGraphicsScene/QGraphicsView.
I'm not so sure. One graphics item takes about 50 bytes of memory on average. How many items would you have in a 150MB file? 1M? That's less than 100MB of RAM used for the items.


BTW, I am using QDataStream to repeatedly read my data, even for updates. I guess this is not terribly efficient. Can you recommend another way?

Hard to say without knowing what your data represents. But if you do that constantly then that is surely inefficient.

pherthyl
5th January 2008, 00:22
Is there a way to cache the background drawing?


view.setCacheMode(QGraphicsView::CacheBackground);

But really you need to provide some more information. How many items, how complex are these items? Drawing them manually in drawbackground is not really the best way to go about it.

bnilsson
5th January 2008, 10:35
Typically, I might want to display a few thousand up to 10-20 million trapezoidal shapes, either as filled or empty, with different colours.

When I have used itemized drawing, I do

if(fill) scene->addPolygon(Trapezoid,AreaShotPen,AreaShotBrush);
else scene->addPolygon(Trapezoid,AreaShotPen);
or
if(fill) scene->addRect(outRect,AreaShotPen, AreaShotBrush);
else scene->addRect(outRect,AreaShotPen);


This should be simple, but about 1 million shapes seems to be the limit right now, both for memory consumption and the patience of the user.

I am using QRectF and QPolygonF and true microns as internal numbers, would it improve performance if I use integer QRect and QPolygon instead?

wysota
5th January 2008, 11:37
I wouldn't use polygons here. You have a pretty simple shape, you can create your own item class which will be much faster.

bnilsson
5th January 2008, 11:39
Quote:
I suspect I would never get it working for a 150Mb data file if I use QGraphicsItems with QGraphicsScene/QGraphicsView.
I'm not so sure. One graphics item takes about 50 bytes of memory on average. How many items would you have in a 150MB file? 1M? That's less than 100MB of RAM used for the items.

I have a hard time believing that. A file of 600,000 shapes costs me about 500Mb of additional RAM, which indicates almost 1kb per item. I must be doing something seriously wrong....


I wouldn't use polygons here. You have a pretty simple shape, you can create your own item class which will be much faster.
Sorry, I am too new to Qt to implement such a thing. Could you direct me to some example?
Also, polygons are mostly only about 10-20% of the total population, the rest are rectangles. Still worthwile to make a new class?

wysota
5th January 2008, 12:45
I have a hard time believing that. A file of 600,000 shapes costs me about 500Mb of additional RAM, which indicates almost 1kb per item. I must be doing something seriously wrong....

Because you are using QGraphicsPolygonItem. You can probably use something simpler instead.


Sorry, I am too new to Qt to implement such a thing. Could you direct me to some example?
See examples bundled with Qt.

Also, polygons are mostly only about 10-20% of the total population, the rest are rectangles. Still worthwile to make a new class?

Yes, because they are the most heavy of your items so they probably occupy about 50% of the memory used by items. A simple esitmate of the memory can be calculated as follows:
total_per_item = sizeof(QGraphicsItem) + sizeof(data_stored_within_item) where the latter is:

in case of a rect item: sizeof(QRectF) + sizeof(QPen) + sizeof(QBrush) = sizeof(QPointF)+sizeof(QSizeF) + sizeof(QPen)+sizeof(QBrush) = 2*sizeof(double) + 2*sizeof(double) + ...

in case of a polygon item: sizeof(QPolygonF) + sizeof(QPen) + sizeof(QBrush) = sizeof(QVector<QPointF>) + ... = n * sizeof(QPointF) + ... = n*2*double + ... = at least twice as much as for QRectF with n>=4.

So a rect item data occupies probably about 70-80 bytes and a polygon item probably around 100. Add all the additional stuff kept by all the classes to that and multiply by the number of items.

BTW. Also consider using fewer more complex items instead of more simpler ones. Maybe you can "connect" your trapezoids into more complex shapes?

bnilsson
5th January 2008, 14:32
Thanks for your engagement, but I don't seen go get anywhere.
I managed to implement a subclass of QGraphicsItem, but it does not draw, I have no idea why. Could you help me?

#ifndef SHAPEITEM_H
#define SHAPEITEM_H

#include <QtGui>
#include <QGraphicsItem>
#include <QObject>

class ShapeItem : public QGraphicsItem
{

public:
ShapeItem(void);
ShapeItem(const QRect *rect);
ShapeItem(const QPolygon *poly);

QRectF boundingRect() const;
QPainterPath shape(void) const;

virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget);
private:

int x0,y0,x1,y1,x2,y2,x3,y3;
int xmin,ymin,xmax,ymax;
};

#endif


#include "shapeitem.h"

ShapeItem::ShapeItem(const QRect *rect)
: QGraphicsItem()
{
x0 = rect->x();
y0 = rect->y();

x1 = rect->x() + rect->width();
y1 = y0;

x2 = x1;
y2 = y0 + rect->height();

x3 = x0;
y3 = y2;

xmin = x0;
xmax = x1;
ymin = y0;
ymax = y2;

}

ShapeItem::ShapeItem(const QPolygon *poly)
: QGraphicsItem()
{
poly->point(0,&x0,&y0);
poly->point(1,&x1,&y1);
poly->point(2,&x2,&y2);
poly->point(3,&x3,&y3);

xmin = xmax = x0;
ymin = ymax = y0;

if(x1<xmin) xmin = x1;
if(x2<xmin) xmin = x2;
if(x3<xmin) xmin = x3;

if(y1<ymin) ymin = y1;
if(y2<ymin) ymin = y2;
if(y3<ymin) ymin = y3;

if(x1>xmax) xmax = x1;
if(x2>xmax) xmax = x2;
if(x3>xmax) xmax = x3;

if(y1>ymax) ymax = y1;
if(y2>ymax) ymax = y2;
if(y3>ymax) ymax = y3;

}


QRectF
ShapeItem::boundingRect() const
{
qreal penWidth = 1;
return QRectF(xmin - penWidth / 2, ymin - penWidth / 2,
xmax + penWidth / 2, ymax + penWidth / 2);
}

QPainterPath
ShapeItem::shape() const
{
QPainterPath path;
path.addRect(boundingRect());
return path;
}


void
ShapeItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
QWidget *widget)
{
painter->drawLine ( x0,y0,x1,y1 );
painter->drawLine ( x1,y1,x2,y2 );
painter->drawLine ( x2,y2,x3,y3 );
painter->drawLine ( x3,y3,x0,y0 );
}


Not at all optimized, as soon as it draws me anything in the scene, I will test different variants. At this stage, numItems=0 in myQGraphicsItems::drawIntems, so I'm stuck.

I am using it lile this:

ShapeItem item(&outRect);
scene->addItem(&item);
//scene->addRect(outRect,solidBlue);


The commented-out line draws as it should, while the active lines does not.

wysota
5th January 2008, 15:41
Create the item on heap.


ShapeItem *item = new ShapeItem(...);
scene->addItem(item);

bnilsson
5th January 2008, 15:56
Thanks, now it is working.
Unfortunately, now the app started gobbling up all memory even for a smaller file, so it got worse. I will have to figure out why...

jacek
5th January 2008, 16:00
Unfortunately, now the app started gobbling up all memory even for a smaller file, so it got worse. I will have to figure out why...
Use valgrind. The Massif tool might be especially helpful.

bnilsson
5th January 2008, 16:36
Use valgrind. The Massif tool might be especially helpful.
For the moment I'm on MacOSX, so this is not applicable.

bnilsson
5th January 2008, 16:39
The behaviour was a bit better using Qt4.4.0 than Qt4.3.3, so maybe it's not in my code entirely. But still in the 1Gb range for a 40Mb file.
The behaviour was very strange indeed (excessive cpu and memory load when zooming IN) on my amd46 Debian using Qt4.3.3, and this particular problem was fixed by the Qt4.4.0 snapshot.

Anyway, standard usage of QGraphicsView/QGraphiscScene was not dramatically improved using Qt4.4.0.

wysota
5th January 2008, 18:30
Could you provide a minimal compilable example reproducing the problem so that we might try it ourselves?

bnilsson
5th January 2008, 18:54
Sure, the project is not very big, I will try to prepare something.
I am new to this forum, what are the provisions for uploading?

wysota
5th January 2008, 19:06
Use the attachments feature ("Manage attachments" button below the advanced editor).

bnilsson
5th January 2008, 23:08
What would be your primary platform?

I will have to arrange some way for you to pick up the datafiles, they will be too large for an attachment. I think I have some space at my ISP's web hotel, I will do this tomorrow.
What will be your primary project platform?

Here is the project. It is currently tested only for Mac, I have not built this particular project for Linux yet.

wysota
6th January 2008, 00:05
What would be your primary platform?
Mine is Linux/x86.


I will have to arrange some way for you to pick up the datafiles, they will be too large for an attachment.
Can't you just provide some small application that would generate such example datafile? They don't have to make sense and they don't have to be larger than a megabyte. It's just a test app.


Here is the project.

It'd be best if you provided something small. It's easier to debug then.

BTW. I just had a quick look at the code you provided and I have some comments:
- I'm not sure if manipulating the update mode the way you do is a good idea, you should set the update mode once and never touch it again
- I'm not sure if beginning by reimplementing the main drawing routine is a good idea. I'd start with the base class implementation first, it's probably trying to be smarter than your implementation
- why do you use the data stream if you only read raw data and seek through the file? Operate on the file directly instead
- try not to fall of the scale with your dimensions, 10nm = 10E-8, pretty close to 32bit precision.

bnilsson
6th January 2008, 11:55
Mine is Linux/x86.

Were you able to build the application?


Can't you just provide some small application that would generate such example datafile? They don't have to make sense and they don't have to be larger than a megabyte. It's just a test app.

The example datafile supplided, "testexp_c.j51" should enable you to thest the function, but maybe not show the problem. I don't have a J51 generator ready, but I can try to make one. It would not take long, I hope.


It'd be best if you provided something small. It's easier to debug then.

I can strip it down further if you want. Should I?



BTW. I just had a quick look at the code you provided and I have some comments:
- I'm not sure if manipulating the update mode the way you do is a good idea, you should set the update mode once and never touch it again

If I turn off update permantly it doesn't scroll. If I turn it on a large file will be drawn twice or more, taking maybe 10-30s extra before the user can zoom in to any region of interest.
Do you have any suggestion on how to handle this?


- I'm not sure if beginning by reimplementing the main drawing routine is a good idea. I'd start with the base class implementation first, it's probably trying to be smarter than your implementation

I dont' quite uderstand. Please expalin.
This is my very forst Qt application, I took the outline from a basic example (a text editor) described in the documentation. My plan was to clean it up later, and evenually make a multidocument application. But I got stuck before I got to that point.


- why do you use the data stream if you only read raw data and seek through the file? Operate on the file directly instead

Sure. In one of my later versions I make a linked list from the data analyzed.


- try not to fall of the scale with your dimensions, 10nm = 10E-8, pretty close to 32bit precision.
10-8 compared to 1 meter, yes. In the drawing unity means 1 micrometer, so the precision is no problem here.

wysota
6th January 2008, 12:39
Were you able to build the application?
I had no data so I didn't even try.


I can strip it down further if you want. Should I?
You could get rid of the loading routines and just generate polygons and rectangles in the application.


Do you have any suggestion on how to handle this?
Yes, find out why it draws twice.


I dont' quite uderstand. Please expalin.
Don't reimplement anything from the scene or the view. Just you the classes provided only changing their properties and adding items to the scene.

Edit:
The application works just fine with the provided data. It uses about 15MB of RAM which I assume is quite fine.

bnilsson
6th January 2008, 16:49
Here is a stripped down version with no loader and a limited set of redundant functions. I did not want to change the UI part so there are some empty action handling methods, please ignore them.

It draws an area set by "chipsize", divided into fields of size "fieldsize", whuch are in turn divided into subfields of size "subfieldsize", and in each subfield there is one rectangle and one polygon. Chip, field and subfield boundaries are drawn in blue color, while the rectangles and polygons are drawn in black.

Chipsize can range from 50,000 microns up to 125,000 microns, the field size is 800 microns, and subfield size is 100 microns. I kept this sceme to be able to relate to my real needs.

Here, 125,000 micron chipsize is beyond the capacity of any of my machines (1 Mac G5 1GB RAM, and 1 amd64 1GB RAM) while 50,000 micron chipsize can be managed with some patience.
Note that Qt4.3.3 has real problems when zooming in on the amd64, the Qt4.4.0 snapshot is much better. They really must have done something there.

Some logs:
Chipsize 50000.000 um, 3844 fields, 246016 subfields, 246016 rects, 246016 polys
Chipsize 100000.000 um, 15625 fields, 1000000 subfields, 1000000 rects, 1000000 polys
Chipsize 125000.000 um, 24336 fields, 1557504 subfields, 1557504 rects, 1557504 polys

bnilsson
6th January 2008, 21:10
Don't reimplement anything from the scene or the view. Just you the classes provided only changing their properties and adding items to the scene.


Please define "reimplement".
I need to tell you I never took the course in C++ :) so sometimes I have problems with the programming lingo. I just look at examples and try to do the same, and then fill in my own stuff.

It would be great if you could explain with "more words".

wysota
6th January 2008, 21:16
Please define "reimplement".
"Subclass and rewrite a method which is defined in the base class and has the same signature (return value, name and arguments)".

Use QGraphicsView and QGraphicsScene instead of MyQGraphics... classes.

bnilsson
7th January 2008, 08:03
Ok, I think I understand.
But this removes the possibility to add new methods for the class, right?
Now I have a myQGraphicsView member pointing at the coordinate display in the main window, and I give it a value by the method setCoordDisplay(QLineEdit *in);
Please suggest how I should transfer the result form QGraphicsView::mouseMoveEvent to the coordinate display field in the main window using some alternate method.

If new methods can be added, please advice me on how the header should be written.

wysota
7th January 2008, 08:16
But this removes the possibility to add new methods for the class, right?
You can add new methods, just don't reimplement the ones that already exist and do something - namely drawItems().

bnilsson
7th January 2008, 09:33
So you mean that the problem was NOT the new class myQGraphicsView, but the fact that drawItems was re-implemented?
If so, what about mouse*Event methods?

wysota
7th January 2008, 09:51
I didn't say anything like that. I said you shouldn't start programming by reimplementing methods that do something useful. The base class implementation is probably sufficient for you.

bnilsson
7th January 2008, 10:28
I am sorry, but I am getting confused. Let's take this very slowly.

Use QGraphicsView and QGraphicsScene instead of MyQGraphics... classes.
You suggest that I should not create a derived class, but instead override the existing methods when needed, such as mouseMoveEvent, mousePressEvent and mouseReleaseEvent, and not override drawItems.

Did I understand this correctly?

I appreciate your patience.

bnilsson
7th January 2008, 12:14
Let's close the discussion about "reimplementation", after reading all of your comments again I now understand your point. Thanks for your patience.

wysota
7th January 2008, 12:37
If you want to override anything, then you need to subclass. The rest is correct.

pherthyl
8th January 2008, 19:13
This may be useful to you.

http://labs.trolltech.com/blogs/2008/01/08/accurate-update-regions-for-thin-qgraphicsitems/

wysota
8th January 2008, 23:40
Ok, I finally managed to take a look at the app. The example you gave us occupies about 200MB of memory, which is not that bad for 0.5M items ( ~400B per item). The application is horribly slow, but I see some ways to speed it up. I don't know if this will improve the speed significantly, but it's worth to try. I'm going to get rid of your polygon items first.

Edit: Ok, I'm not going to do that, because it'd be quite hard for me as I don't know your code. But I already know the difference should be huge. From what I understand you make each item very big - it's pos() is set to (0,0) and it's rect is defined by the polygon. As you have only four points, there is no point in creating a path from them - you should draw them manualy and return a very tiny bounding rectangle. Furthermore you should make use of the levelOfDetail while painting items - from a big distance you could paint polygons as rects or even just points. It should make a huge difference. And it's not a matter of memory, it's consumption is fine.

Gopala Krishna
9th January 2008, 01:51
Ok, I finally managed to take a look at the app. The example you gave us occupies about 200MB of memory, which is not that bad for 0.5M items ( ~400B per item). The application is horribly slow, but I see some ways to speed it up. I don't know if this will improve the speed significantly, but it's worth to try. I'm going to get rid of your polygon items first.

Edit: Ok, I'm not going to do that, because it'd be quite hard for me as I don't know your code. But I already know the difference should be huge. From what I understand you make each item very big - it's pos() is set to (0,0) and it's rect is defined by the polygon. As you have only four points, there is no point in creating a path from them - you should draw them manualy and return a very tiny bounding rectangle. Furthermore you should make use of the levelOfDetail while painting items - from a big distance you could paint polygons as rects or even just points. It should make a huge difference. And it's not a matter of memory, it's consumption is fine.

Very true.. Level of detail really makes lot of difference.. The chip demo which qt provides is really a nice demo on how graphicsview applications can be optimized atleast to some extent.

Actually your app didn't run on my system(1Gb ram, 3GHz, pentium 4 HT) until i changed chip size to 5k.
But to be frank enough, I personally feel gv framework is overkill. Infact your app didn't run(50k) even when i turned of all possible bells and whistles. Also you don't need those unnecessary memory strain as well.
If you are sure that you don't need to select or move items here and there, definitely implementing a widget is best option. Remember you always don't have to draw everything as drawing everything at < .25 scale is hardly visible.

bnilsson
9th January 2008, 07:31
First, I want to thank you for your engagement in this. This is my VERY first Qt project, and surely must have missed and misunderstood a lot of things.

Ok, I'm not going to do that, because it'd be quite hard for me as I don't know your code.
You have all of my relevant code in the example. What is missing?


But I already know the difference should be huge. From what I understand you make each item very big - it's pos() is set to (0,0) and it's rect is defined by the polygon.
Here it seems I have missed something really important. I was unaware of pos().

Furthermore you should make use of the levelOfDetail while painting items - from a big distance you could paint polygons as rects or even just points.
Again. I was unaware of levelofDetail, I will study it. However, the description in Assistant is a bit cryptic, so I will have to test different settings. Will a higher value improve?


Gopala:
But to be frank enough, I personally feel gv framework is overkill.
I tend to have the same opinion. But the gv framework is so convenient! But on the other hand, it is the only thing I have looked at so far. Is it as easy to implement scroll and zoom for a regular widget?


pherthyl:
This may be useful to you.

http://labs.trolltech.com/blogs/2008...graphicsitems/
I definitely see this on Linux, but for some reason not on my MacOSX. On Linux, displaying the full chip took time, but was ok finally. Zooming in locked it up completely. On Linux, this was eliminated using Qt4.4.0. Or is this a note of a further improvement?

bnilsson
9th January 2008, 08:10
First:

From what I understand you make each item very big - it's pos() is set to (0,0) and it's rect is defined by the polygon.
This statement puzzles me.
I just do

QVector<QPointF> Tpz(4);
<fill in the 4 points>
QPolygonF Trapezoid(Tpz);
scene->addPolygon(Trapezoid,AreaShotPen);
Where does the pos() come in?

Secondly, can you apply levelofDetail to a high-level draw such as scene->addRect();?
Or do you have to create a custom QGraphicsItem and apply it to painter->drawRect() to do that?

Gopala Krishna
9th January 2008, 08:23
Secondly, can you apply levelofDetail to a high-level draw such as scene->addRect();?
Or do you have to create a custom QGraphicsItem and apply it to painter->drawRect() to do that?

You have to create a custom item. Have a look at the code for demos/chip/chip.cpp for reference.

Gopala Krishna
9th January 2008, 08:33
BTW can you explain the composition of a chip with a screen shot ? i think you can simplify the drawing by representing less items which draw sub polygons.
I mean I could see an array of rectangular items, with some polygons and rect inside.
The outside rect can be considered as one item.

wysota
9th January 2008, 09:50
You have all of my relevant code in the example. What is missing?
Knowledge what items represent. I don't want to go through all your code and learn it by trial and error. For example I don't know if you really need 4 points to represent a trapezoid or if those trapezoids have somehow "fixed" properties, for example always a 90deg. angle - then you just need 3 points, or fixed lengths.


However, the description in Assistant is a bit cryptic, so I will have to test different settings. Will a higher value improve?
It is nothing you may set. It's a value given by the view to the item's painting routine that tells it how far away the "camera" is from the item. The further, the less details may be seen, so drawing those details becomes obsolete.


I tend to have the same opinion. But the gv framework is so convenient!
I don't think it is an overkill. If you design the scene correctly, it will work fine. With a regular widget you'd probably want to have items as well.


Where does the pos() come in?
It's set to (0,0) by default. The way you do it makes your items very complicated, especially if you'll want later to interact with them somehow. If you have a trapezoid, make it span from (0,0) to the width and height of the trapezoid and them move it into an appropriate position using setPos(). This probably won't yield any performance gain, but will it easier to implement the ShapeItem that doesn't use paths or polygons that are really slow to draw.


Secondly, can you apply levelofDetail to a high-level draw such as scene->addRect();?
The rectangle item probably doesn't use LOD, so no. You have to implement your own item for that. It is most essential for your trapezoids. Simplify things wherever possible.

bnilsson
9th January 2008, 09:50
This thought has occurred to me, since the pattern is organized in exposure fields and subfields. So the items could be a FieldItem with child SubFieldsItem, which in turn has child ShapeItems. The ShapeItems are the actual stuff that are drawn by my microchip exposure machine which is using the data file as input, and the fields and subfields are placement parameters.
Will this item hierarchy in three levels, if implemented, give any performance gain?
The field content is usually unique for each field, so there is no memory to be gained by repetition. However, if the field and subfield boundaries are to be drawn, these items can be re-used by offset.

bnilsson
9th January 2008, 10:26
Knowledge what items represent. I don't want to go through all your code and learn it by trial and error. For example I don't know if you really need 4 points to represent a trapezoid or if those trapezoids have somehow "fixed" properties, for example always a 90deg. angle - then you just need 3 points, or fixed lengths.
Ok, now I understand.
I will have the following kinds of objects to draw:

FieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout is divided into fields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. Typically 800 by 800 micrometer in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the chip.
SubFieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout in the field is divided into subfields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. The subfield size is ALWAYS smaller or equal to the field size, typically 100 by 100 microns in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the current field.
The Real shapes below are ALWAYS contained and enclosed within one subfield, and thus always smaller.
XRectangle:
Should always be drawn. The X side is longer than the Y side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.
YRectangle:
Should always be drawn. The Y side is longer than the X side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.
XTrapezoid:
Top and bottom sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,x1,x2,x3,y3, referenced from the upper left corner of the current subfield.
YTrapezoid:
Left and right sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,y1,y2,x3,y3, referenced from the upper left corner of the current subfield.
Line:
Just a line from x0,y0 to x1,y1, referenced from the upper left corner of the current subfield.

Exposure dose index:
In the input data file, each Real shape may have a tag to control the exposure dose. Here we us colors (up to 63 colors) to present this.

Hope this helps.

bnilsson
9th January 2008, 10:33
About LOD:

t is nothing you may set. It's a value given by the view to the item's painting routine that tells it how far away the "camera" is from the item. The further, the less details may be seen, so drawing those details becomes obsolete.
So, why discuss it?:confused:
Or is there any way I can make use of it?

Gopala Krishna
9th January 2008, 10:41
About LOD:

So, why discuss it?:confused:
Or is there any way I can make use of it?

Ofcourse!
Snippet from chip demo is below. I have marked some lines with "==" comment.
See how the chip alters what exactly is drawn when level of detail is so and so.
When levelOfDetail is less, even though you draw everything, the user won't be able to see the full details of the chip so, why bother to draw everything ?


void Chip::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(widget);

QColor fillColor = (option->state & QStyle::State_Selected) ? color.dark(150) : color;
if (option->state & QStyle::State_MouseOver)
fillColor = fillColor.light(125);

//============Notice here============
if (option->levelOfDetail < 0.2) {
//===============================
if (option->levelOfDetail < 0.125) {
painter->fillRect(QRectF(0, 0, 110, 70), fillColor);
return; // also notice the return===========
}

painter->setPen(QPen(Qt::black, 0));
painter->setBrush(fillColor);
painter->drawRect(13, 13, 97, 57);
return;//========= notice this too
}

QPen oldPen = painter->pen();
QPen pen = oldPen;
int width = 0;
if (option->state & QStyle::State_Selected)
width += 2;

pen.setWidth(width);
painter->setBrush(QBrush(fillColor.dark(option->state & QStyle::State_Sunken ? 120 : 100)));

painter->drawRect(QRect(14, 14, 79, 39));
if (option->levelOfDetail >= 1) {
painter->setPen(QPen(Qt::gray, 1));
painter->drawLine(15, 54, 94, 54);
painter->drawLine(94, 53, 94, 15);
painter->setPen(QPen(Qt::black, 0));
}

// Draw text
if (option->levelOfDetail >= 2) {
QFont font("Times", 10);
font.setStyleStrategy(QFont::ForceOutline);
painter->setFont(font);
painter->save();
painter->scale(0.1, 0.1);
painter->drawText(170, 180, QString("Model: VSC-2000 (Very Small Chip) at %1x%2").arg(x).arg(y));
painter->drawText(170, 200, QString("Serial number: DLWR-WEER-123L-ZZ33-SDSJ"));
painter->drawText(170, 220, QString("Manufacturer: Chip Manufacturer"));
painter->restore();
}

// Draw lines
QVarLengthArray<QLineF, 36> lines;
if (option->levelOfDetail >= 0.5) {
for (int i = 0; i <= 10; i += (option->levelOfDetail > 0.5 ? 1 : 2)) {
lines.append(QLineF(18 + 7 * i, 13, 18 + 7 * i, 5));
lines.append(QLineF(18 + 7 * i, 54, 18 + 7 * i, 62));
}
for (int i = 0; i <= 6; i += (option->levelOfDetail > 0.5 ? 1 : 2)) {
lines.append(QLineF(5, 18 + i * 5, 13, 18 + i * 5));
lines.append(QLineF(94, 18 + i * 5, 102, 18 + i * 5));
}
}
if (option->levelOfDetail >= 0.4) {
const QLineF lineData[] = {
QLineF(25, 35, 35, 35),
QLineF(35, 30, 35, 40),
QLineF(35, 30, 45, 35),
QLineF(35, 40, 45, 35),
QLineF(45, 30, 45, 40),
QLineF(45, 35, 55, 35)
};
lines.append(lineData, 6);
}
painter->drawLines(lines.data(), lines.size());

// Draw red ink
if (stuff.size() > 1) {
painter->setPen(QPen(Qt::red, 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter->setBrush(Qt::NoBrush);
QPainterPath path;
path.moveTo(stuff.first());
for (int i = 1; i < stuff.size(); ++i)
path.lineTo(stuff.at(i));
painter->drawPath(path);
}
}

Gopala Krishna
9th January 2008, 10:54
Ok, now I understand.
I will have the following kinds of objects to draw:

FieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout is divided into fields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. Typically 800 by 800 micrometer in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the chip.
SubFieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout in the field is divided into subfields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. The subfield size is ALWAYS smaller or equal to the field size, typically 100 by 100 microns in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the current field.
The Real shapes below are ALWAYS contained and enclosed within one subfield, and thus always smaller.
XRectangle:
Should always be drawn. The X side is longer than the Y side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.
YRectangle:
Should always be drawn. The Y side is longer than the X side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.
XTrapezoid:
Top and bottom sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,x1,x2,x3,y3, referenced from the upper left corner of the current subfield.
YTrapezoid:
Left and right sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,y1,y2,x3,y3, referenced from the upper left corner of the current subfield.
Line:
Just a line from x0,y0 to x1,y1, referenced from the upper left corner of the current subfield.

Exposure dose index:
In the input data file, each Real shape may have a tag to control the exposure dose. Here we us colors (up to 63 colors) to present this.

Hope this helps.

May be you can have only one item to represent the field and its contents and by contents i don't mean child items.

I am using the terminology "item" to represent an entity on scene and which inherits QGraphicsItem.

The field item is the item responsible to draw its subfields and contents of subfield.

Now if levelOfDetail is very less, just draw the outer boundary of field item only.
If levelOfDetail is less, but not very less, then draw subfield boundary also.
Only if levelOfDetail is greater enough so that user can see detail, draw all the shapes.
Again you can finetune more by drawing rect when level of detail is medium and polygon if levelOfDetail is sufficiently large.

And for the values of levelOfDetail, you have to experiment.

Edit:

Chipsize 50000.000 um, 3844 fields, 246016 subfields, 246016 rects, 246016 polys
Chipsize 100000.000 um, 15625 fields, 1000000 subfields, 1000000 rects, 1000000 polys
Chipsize 125000.000 um, 24336 fields, 1557504 subfields, 1557504 rects, 1557504 polys

As you can see considering worst case, you can represent all your data by 24336 field items (instead of 24336 + 1557504 + 1557504 items! ) and chip demo has 50k items!!
I think your app can be smooth enough if you design it carefully :)
All the best :)

wysota
9th January 2008, 11:38
FieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout is divided into fields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. Typically 800 by 800 micrometer in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the chip.
This is nice. A rectangle which is child of the scene. Coordinates them come relative to the scene.


SubFieldBoundary:
This object is 'virtual', and the drawing of this is optional, to indicate for the viewer how the pattern layout in the field is divided into subfields.
It is always rectangular (special case quadratic), the same size and shape throughout the whole drawing. The subfield size is ALWAYS smaller or equal to the field size, typically 100 by 100 microns in size. The size is predefined in the file header, and the pattern data comes as position x,y referenced from the upper left corner of the current field.
A rectangle which is child of the field item. The coordinates then come relative to the field.


XRectangle:
Should always be drawn. The X side is longer than the Y side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.
Same as above.


YRectangle:
Should always be drawn. The Y side is longer than the X side. The input data comes as x0,y0,w,h, referenced from the upper left corner of the current subfield.

Same here.


XTrapezoid:
Top and bottom sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,x1,x2,x3,y3, referenced from the upper left corner of the current subfield.
Identified as four points. Child of the subfield. Coordinates relative to the subfield.


YTrapezoid:
Left and right sides parallell. Degenerated into triangles may occur. The input data comes as x0,y0,y1,y2,x3,y3, referenced from the upper left corner of the current subfield.
Same here.


Line:
Just a line from x0,y0 to x1,y1, referenced from the upper left corner of the current subfield.
Child of subfield item.

To sum things up:
You need the following items:
* Field - representing Field and Subfield
* Rectangle - representing X and Y rectangles
* Trapezoid - representing X and Y trapezoids
* Line - representing lines, obviously

These together will make it easier to manipulate all objects. All coordinates will be relative to their parents thus easier to calculate.

bnilsson
9th January 2008, 18:46
Thanks both of you for two interesting suggestions!
I am sure I will have more questions shortly!

bnilsson
19th January 2008, 13:36
I have tried to apply the idea of have Fields as the GraphicsItems to be added to the scene, and have the contents of the Field drawn "manually" in the paint method if the GraphicsItem. The result is very promising, I have no apparent memory problems anymore, and when I apply levelOfDetail it is also reasonably fast.
I store the contents of the field using a QList within the QGraphicsItem Field object. (Is this the best way?)

A few questions remain for me:
1) The first draw is always updated twice, maybe even three times. Is there any way to control this?
2) QGraphicsView keeps track of which Fields to update, whith the knowledge of their bounding boxes and if they are within the field of view. But when zooming in within a Field it is my own responsibility to decide what to draw (inside or outside the view), and for this I need to know the current bounding box of my visible view in the scene context. What methds can I use to get this information?
3) What is fastest to draw, four QLine-s or a QPolygon?

Gopala Krishna
19th January 2008, 14:24
I store the contents of the field using a QList within the QGraphicsItem Field object. (Is this the best way?)

It seems to be reasonable but if the size of list remains same after initial insertions probably you can try QVarLengthArray. but you should do it only when you discover memory hiccups.



1) The first draw is always updated twice, maybe even three times. Is there any way to control this?


May be you can hide the view till loading is going on and once loaded show the view. I am not sure about this.




2) QGraphicsView keeps track of which Fields to update, whith the knowledge of their bounding boxes and if they are within the field of view. But when zooming in within a Field it is my own responsibility to decide what to draw (inside or outside the view), and for this I need to know the current bounding box of my visible view in the scene context. What methds can I use to get this information?


I guess you can do something like

QGraphicsView *v = scene->activeView();
//you can use views() method to get a list of views using the scene
QPointF topLeft = v->mapToScene(v->viewport()->rect().normalized().topLeft());
QPointF botRight = v->mapToScene(v->viewport()->rect().normalized().bottomRight());

QRectF visibleRect(topLeft, botRight);
// This is in terms of scene now



3) What is fastest to draw, four QLine-s or a QPolygon?
You can try to use QVarLengthArray approach.


QVarLengthArray<QLine, 4> array(n);
array.append(QLine(..));
..

painter->drawLines(array.constData());

wysota
19th January 2008, 16:15
I store the contents of the field using a QList within the QGraphicsItem Field object. (Is this the best way?)

What's wrong with QGraphicsItem::childItems?



1) The first draw is always updated twice, maybe even three times. Is there any way to control this?
Hard to say without seeing the code. If you modify the scene after the view is shown for the first time or you use fitInView, then it might happen that the view is drawn twice.


2) QGraphicsView keeps track of which Fields to update, whith the knowledge of their bounding boxes and if they are within the field of view. But when zooming in within a Field it is my own responsibility to decide what to draw (inside or outside the view),
Hmm? Why? If you zoom in, the field and its subfields are visible so only they will be drawn. You store subfields as child items of a field, right?


3) What is fastest to draw, four QLine-s or a QPolygon?
If you draw the polygon using a painter path then lines are faster. If you draw the polygon and not polyline then definitely lines are faster. But using QPainter::drawPolyLine() will call drawLines() internally, so the overhead is minimal. If you draw lines, use QPainter::drawLines() instead of multiple calls to QPainter::drawLine().

bnilsson
19th January 2008, 19:58
What's wrong with QGraphicsItem::childItems?
I am not there yet, this will be the next version.
In the current version, the only QGraphicsitems are the fields, and the content is drawn by painter calls.

Hard to say without seeing the code. If you modify the scene after the view is shown for the first time or you use fitInView, then it might happen that the view is drawn twice.

This is what I do. Could you suggest an alternative way, without this effect?

Hmm? Why? If you zoom in, the field and its subfields are visible so only they will be drawn. You store subfields as child items of a field, right?
No, not in this version. See above.

If you draw the polygon using a painter path then lines are faster. If you draw the polygon and not polyline then definitely lines are faster. But using QPainter::drawPolyLine() will call drawLines() internally, so the overhead is minimal. If you draw lines, use QPainter::drawLines() instead of multiple calls to QPainter::drawLine().
Thanks for this, I will use it.
Any (performance-wise) preferred way to draw filled surfaces?

bnilsson
20th January 2008, 10:17
I have now made a first attempt to make a parent-child hierarchy implementation.
I am doing something like this:


Field = new QGraphicsRectItem(outRect);
.
.
SubField = new QGraphicsRectItem(outRect, Field);
.
.
XRect = new QGraphicsRectItem(outRect, SubField);

The result is using a remarkably small amount of memory, but the drawing performance is extremely poor, both compared to the "flat" item strategy. Why?
Another observation is that I used exactly the same placement calculations as for the "flat" version, and I expected that it all should turn out a mess since the child item should use the origin of its parent, not the global chip origin. Yet it worked the first time, which tell me I don't really understand how this works.
I will now make QGraphicItem subclasses for the Field, SubField and shape objects to see if it improves performance.

Gopala Krishna
20th January 2008, 10:28
Wait a second.. What did you try last time ? Did you implement FieldItem which also draws sub fields and internal shapes or did you use Q*Items for the subfields and internal shapes ?

If you had implemented FieldItem which draws everything inside it, then the performance you got should be better than that having child items. This is because more the items, more there is strain on bsp indexing and hence the whole mechanism slows down.

@Wysota: Am i wrong with the above assumption as you suggested the child items option ?

wysota
20th January 2008, 11:15
I am not there yet, this will be the next version.
In the current version, the only QGraphicsitems are the fields, and the content is drawn by painter calls.
That's not very efficient.


This is what I do. Could you suggest an alternative way, without this effect?
Try changing the order of commands or use a debugger to see why the second redraw is made.


Any (performance-wise) preferred way to draw filled surfaces?
Avoid complex shapes. Use levelOfDetail.


I have now made a first attempt to make a parent-child hierarchy implementation.
I am doing something like this:


Field = new QGraphicsRectItem(outRect);
.
.
SubField = new QGraphicsRectItem(outRect, Field);
.
.
XRect = new QGraphicsRectItem(outRect, SubField);

The result is using a remarkably small amount of memory, but the drawing performance is extremely poor, both compared to the "flat" item strategy. Why?
Do you mean you pass the same rectangle to the three items? I don't think this is a correct approach. And using custom items you might obtain better speed - use level of detail and modifies shapes and parameters like antialiasing.


Another observation is that I used exactly the same placement calculations as for the "flat" version, and I expected that it all should turn out a mess since the child item should use the origin of its parent, not the global chip origin. Yet it worked the first time, which tell me I don't really understand how this works.
Take a closer look at the "dragdroprobot" example - see how the robot is drawn.


@Wysota: Am i wrong with the above assumption as you suggested the child items option ?

No, you are right.

bnilsson
20th January 2008, 11:49
Wait a second.. What did you try last time ? Did you implement FieldItem which also draws sub fields and internal shapes or did you use Q*Items for the subfields and internal shapes ?

If you had implemented FieldItem which draws everything inside it, then the performance you got should be better than that having child items. This is because more the items, more there is strain on bsp indexing and hence the whole mechanism slows down.

@Wysota: Am i wrong with the above assumption as you suggested the child items option ?

In the version I referred to (let's call it v1.1) I used the QGraphicsitem subclass FieldItem which draws the field's boundary rectangle, and added it to the scene:


class FieldItem : public QGraphicsItem
.
Field = new FieldItem(&outRect,color,&fill);
scene->addItem(Field);

"color" and "fill" are pointers to the 64-entry colorlist and bool fill parameter.
Field->paint is responsible for drawing the subfield bounds and the pattern shapes, there are no other GraphicsItems than Fields. The FieldItem object holds a QList with the subfields and pattern shapes, which are added to the Field object by the methods addSubField and addRect:


MainWindowImpl::DrawSubFieldBounds() {
.
Field->addSubfield(&sfRect);
.
}
.
MainWindowImpl::DrawRectangle(const QRectF inRectangle) {
.
Field->addRect(&rRect, AreaShot);
.
}

As a summary, the performance is reasonable at the expense of complexity.

In the NEXT version (let's call it c1.2) I am using the full parent-child hierarchy with the convenience function QGraphicsRectItem, and ihis is what gives me the poor drawing performance but very light on memory consumprtion.
I will continue with this by subclassing to Field, SubField, and Shape and include levelOfDetail and as efficient drawing as possible.

bnilsson
20th January 2008, 12:00
That's not very efficient.


It seems you and Gopala Krishna do not agree on this :)



Try changing the order of commands or use a debugger to see why the second redraw is made.


Avoid complex shapes. Use levelOfDetail.

This would mean I cannot use QGraphicsRectItem, right? I have to make my own subclass?




Do you mean you pass the same rectangle to the three items? I don't think this is a correct approach.

Sorry, I was not very clear in this example. (downright confusing!:rolleyes:) I use the same name for the Rect, but in different methods. The outRect's are NOT the same.


And using custom items you might obtain better speed - use level of detail and modifies shapes and parameters like antialiasing.


Take a closer look at the "dragdroprobot" example - see how the robot is drawn.

I will.

wysota
20th January 2008, 14:28
It seems you and Gopala Krishna do not agree on this :)
We do on most things. I agree that more items mean more strain to the indexing, but if you want to decide what to draw and what to skip yourself without any index, it will be much slower. The depth of the index can be changed, so it's only your decision how deep it should be. And as your items don't move, the tree won't have to be rebuilt, so it will be very fast.


This would mean I cannot use QGraphicsRectItem, right? I have to make my own subclass?
Right. That's what I'm saying from the very beginning.

Gopala Krishna
20th January 2008, 14:37
We do on most things. I agree that more items mean more strain to the indexing, but if you want to decide what to draw and what to skip yourself without any index, it will be much slower. The depth of the index can be changed, so it's only your decision how deep it should be. And as your items don't move, the tree won't have to be rebuilt, so it will be very fast.

If that is the case, then i guess bnilsson can try disabling bsp indexing by using scene->setItemIndexMethod(QGraphicsScene::NoIndex);
It would also be nice to play around with bspTreeDepth as well if the disabling index doesn't help.

wysota
20th January 2008, 14:49
Disabling the index will make it harder to detect which items to draw without any benefit from disabling it. As the items don't move the use of an index doesn't cause any overhead.

What is important is to divide the "field" item into "subfield" and "subsubfield" items, so that indexing can show its power. The field itself is cheap to draw because you don't really draw anything but drawing all subitems instead of the set that is really visible yields a huge overhead.

bnilsson
21st January 2008, 07:39
My first attempt to subclass QGraphicsItem into FieldItem, SubFieldItem and ShapeItem and use them in a parent-child sceme gave even worse performance and memory consumption than using QGraphicsRectItem.
I will prepare the test project I posted before to use the parent-child item strategy and post it later so anyone interested can have a look and see where I am going wrong.

bnilsson
22nd January 2008, 20:25
Is there any advantage to use integers (QRect, QPoint, etc.) instead of floats (QRectF, QPointF, etc. ) regarding drawing performance?

wysota
22nd January 2008, 22:54
Yes, it's faster using ints when drawing. Calculations should be more or less equally fast. But in your case the overhead shouldn't be large. Of course it's wise to use either int or real variants depending on the level of detail.

bnilsson
27th January 2008, 18:04
Back again...

Here are two test projects with pattern simulation, one "flat" where the items are fields and the painter draws subfields and pattern shapes from a linked list, stored in each field object, and one "hieararcic" where the top items are fields and the subfields are childs to the fields and the pattern shapes are childs to the subfields.

The "flat"version is lean on memory and draws the simulated pattern very fast, 100,000 micron chipsize is no problem.
The "hierachic" version draws a lot of memory, and a chipsize of 50,000 can barely be drawn.

Please comment on these test apps, please suggest how the "hierarchic" version may be improved. I suspect that the "flat" version is fine for the simulated pattern, but may suffer for a real datafile if there is a lot of data in one field.

I noticed that there is a dramatic difference in performance if the item is using a small "local" size and placed by setPos() rather than having a "global" bounding box with large minimum and maximum numeric values. Example min=(0,0) max=(100,100) and setPos(10000,10000) vs. min =(10000,10000) max=(10100,10100) and no setPos.
Can you explain why?

Gopala Krishna
27th January 2008, 20:22
It does work on my system now :) and i still recommend the flat one as you can easily finetune the drawings of subfields (lod)
BTW zooming onto single subfield almost hangs your app on my system. Does it work smooth for you ?

Also as far as i could see you are directly representing the logical sizes as "onscreen" display size.
For eg with chipsize=50000
FieldSize= QSize(32000,32000)
SubFieldSize= QSize(4000,4000)

And you are using this size for each item!

If you need more optimization and if it is possible, do scale down each of these so that on screen "transformation free" size of each item is within (500,500). It is far easier to just multiply the coord by scale factor and then display in sidebar than actually drawing the item in those huge sizes!

Otherwise you can also try to use QStyleOptionGraphicsItem::exposedRect in FieldItem:: paint method and draw only visible part. But i guess this is quite hard and might not work as required.

wysota
27th January 2008, 21:30
I made my own experiments. With about 0.5M items the application was using about 80 megabytes of memory which gives an average of 160 bytes per item (including the memory used by all other components) which I think is not that bad. At that point the application was responsive although very slow. The slowdown is caused by the fact that even if I intend not to draw some item, the matrix still has to be produced and applied for each of them. Making the architecture ignore items that are sure not to be drawn would speed the app significantly.

See attached the code I used.

bnilsson
27th January 2008, 21:40
It does work on my system now :) and i still recommend the flat one as you can easily finetune the drawings of subfields (lod)
BTW zooming onto single subfield almost hangs your app on my system. Does it work smooth for you ?

This is a bug in Qt4.3, probably Linux-specific, will be fixed in Qt4.4.
I tried the Qt4.4 snapshot, and with this it is ok.


Also as far as i could see you are directly representing the logical sizes as "onscreen" display size.
For eg with chipsize=50000
FieldSize= QSize(32000,32000)
SubFieldSize= QSize(4000,4000)

And you are using this size for each item!

If you need more optimization and if it is possible, do scale down each of these so that on screen "transformation free" size of each item is within (500,500). It is far easier to just multiply the coord by scale factor and then display in sidebar than actually drawing the item in those huge sizes!

Unless there is a problem using large numbers, I find it an advantage to use integers with full internal data resolution. It is sometimes of interest to have the cursor position to show the exact position in the drawing. Int's also give a slight drawing performance advantage, right?


Otherwise you can also try to use QStyleOptionGraphicsItem::exposedRect in FieldItem:: paint method and draw only visible part. But i guess this is quite hard and might not work as required.
I will look into this.

bnilsson
27th January 2008, 21:48
I made my own experiments. With about 0.5M items the application was using about 80 megabytes of memory which gives an average of 160 bytes per item (including the memory used by all other components) which I think is not that bad. At that point the application was responsive although very slow. The slowdown is caused by the fact that even if I intend not to draw some item, the matrix still has to be produced and applied for each of them. Making the architecture ignore items that are sure not to be drawn would speed the app significantly.

Will this be someting for a future Qt release?


See attached the code I used.
I will study the code, I will probably learn a lot from it. Thanks!

wysota
27th January 2008, 22:05
Will this be someting for a future Qt release?

I don't think Andreas' team has such plans :) You'd have to implement it yourself by reimplementing drawItems() in the scene (I think).

Gopala Krishna
28th January 2008, 11:53
Making the architecture ignore items that are sure not to be drawn would speed the app significantly.

Is it true ? :confused: or did i misunderstand ?
I was under impression that GV framework doesn't draw items not visible on viewport (ofcourse i dont mean hidden items)

wysota
28th January 2008, 12:08
I was under impression that GV framework doesn't draw items not visible on viewport (ofcourse i dont mean hidden items)

Take a look at my code. I'm deciding whether to draw something or not based on the distance between the object and the camera (level of detail). If something is very far away (but still inside the camera's viewport) I decide not to draw it, but the whole painting environment is set up by the architecture anyway.