Jim Knopf
Jim Knopf

Reputation: 1

How to improve memory-consumption when drawing polygons, (poly-)lines and points in Qt?

I'm currently struggling with populating a qgraphicsscene with many (> 1Million) objects (Polygons, Lines, Points). What I've observed is, that when creating randomly 100000 Polygons, I'm already ending up withe 130MB memory consumption. (The simple example below is based on a default Qt-Project using the View.cpp of the chip-demo example)

QtGrafikTestBasic::QtGrafikTestBasic(QWidget *parent): QMainWindow(parent)
{
    ui.setupUi(this);
    QSplitter *h1Splitter = new QSplitter;
    QSplitter *vSplitter = new QSplitter;
    vSplitter->addWidget(h1Splitter);

    View* view = new View("asdf");
    h1Splitter->addWidget(view);

    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(vSplitter);
    setLayout(layout);
    setCentralWidget(view);

    QBrush *brush = new QBrush();
    brush->setColor(Qt::blue);
    brush->setStyle(Qt::SolidPattern);
    QPen *pen = new QPen();
    pen->setWidth(0);

    QGraphicsScene *scene = new QGraphicsScene;
    srand ( time(NULL) );
    int m_PolyWidth = 10;

    for (int i = 0 ; i < 100000; i++)
    {
        double lBaseX = rand() % ((int)floor(width())  - m_PolyWidth);
        double lBaseY = rand() % ((int)floor(height()) - m_PolyWidth);

        QPolygonF polygon;
        polygon << QPointF(lBaseX, lBaseY);
        polygon << QPointF(lBaseX + m_PolyWidth, lBaseY);
        polygon << QPointF(lBaseX + m_PolyWidth, lBaseY + m_PolyWidth);
        polygon << QPointF(lBaseX, lBaseY + m_PolyWidth);

        scene->addPolygon(polygon, *pen, *brush);
    }
    view->view()->setScene(scene);
 }

So what am I doint wrong here / where can I improve? I've read some posts of creating an own class like the chip-example, so I simply used the chip example but also there I've encountered the problem that as soon as I change the part which uniformly distributes the chips from item->setPos(QPointF(i, j)); to a random distribution item->setPos(QPointF(lBaseX, lBaseY));, the memory consumption explodes also here...

So, what is the most performant and least memory-consuming way of drawing polygons, (poly-)lines and points in Qt?

Upvotes: 0

Views: 304

Answers (1)

TheDarkKnight
TheDarkKnight

Reputation: 27629

When you call addPolygon on the graphics scene, it creates a QGraphicsPolygonItem and adds that to the scene.

Each item you add has various properties that include position, orientation, brush, pen and allows the scene to handle collision detection. Also, each item is going to have its paint function called, which is quite an overhead.

The first thing to do here is to see what performance you'd gain with using a QPainterPath. Create a QPainterPath and add the polygons to that: -

QPainterPath* painterPath = new QPainterPath;
for (int i = 0 ; i < 100000; i++)
{
    double lBaseX = rand() % ((int)floor(width())  - m_PolyWidth);
    double lBaseY = rand() % ((int)floor(height()) - m_PolyWidth);

    QPolygonF polygon;
    polygon << QPointF(lBaseX, lBaseY);
    polygon << QPointF(lBaseX + m_PolyWidth, lBaseY);
    polygon << QPointF(lBaseX + m_PolyWidth, lBaseY + m_PolyWidth);
    polygon << QPointF(lBaseX, lBaseY + m_PolyWidth);

    painterPath->addPolygon(polygon);
}

If you add the painterPath to a class derived from QGraphicsItem, you can then get the painterPath to draw in the item's paint function: -

 painter.drawPath(painterPath);

This will be considerably quicker. Just ensure you're not adding the polygons to the painter path inside the paint function. The paint function should do nothing, but render the item.

Upvotes: 1

Related Questions