PDA

View Full Version : Best way to visualize a 2D triangulation?



bts
1st November 2011, 11:18
Hello!

I want to visualize a large 2D triangulation consisting of several million triangles. It works already
but the memory consumption is way too high:


class TriangulationScene : public QGraphicsScene
{
public:
TriangulationScene();
void scribble();
...
}

void TriangulationScene::scribble()
{
setItemIndexMethod(NoIndex);
for(vector<Triangle2*>::iterator it(vTriangles.begin());it!=vTriangles.end();++it)
{
Triangle2* pT(*it);
Point2* p0(pT->getCorner(0));
Point2* p1(pT->getCorner(1));
Point2* p2(pT->getCorner(2));
QPolygonF polygon;
polygon << QPointF(p0->x(),p0->y())<<QPointF(p1->x(),p1->y())<<QPointF(p2->x(),p2->y());
this->addPolygon(polygon);
}
}

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
TriangulationScene s;
QGraphicsView v(&s);
v.setDragMode(QGraphicsView::ScrollHandDrag);
v.resize(1024,768);
v.scale(100,100);
v.show();
return a.exec();
}

This way I need 1 GB for 2 million triangles. I see two possible workarounds:

1) Creating a picture of the triangulation. The drawback is that the picture will certainly
look ugly when zoomed in.

2) I could do it like shown above if I add only the small amount of triangles that must currently
be shown. However, this would require quite some work to implement updates when zooming
or scrolling is done.

Any better ideas? Is there a better class for my purpose than QGraphicsScene?

Thanks, best regards

Spitfire
1st November 2011, 12:08
You can drop the scene and use simple widget.

Just draw on the widget using paint event.
It will require less memory and may be even faster if done right, but it will require more work to implement.

In my test 1m polys in scene requires around 600mb of memory, when doing the same on a widget requires just ~90mb.

Qwt uses that technique and it works well.
Depends on what you need - you could try Qwt.

bts
1st November 2011, 15:01
You can drop the scene and use simple widget.

Just draw on the widget using paint event.
It will require less memory and may be even faster if done right, but it will require more work to implement.

In my test 1m polys in scene requires around 600mb of memory, when doing the same on a widget requires just ~90mb.

Qwt uses that technique and it works well.
Depends on what you need - you could try Qwt.


Thank you!

I'm new to Qwt, which classes do you have used for your test?

Spitfire
1st November 2011, 16:07
I haven't tested how well Qwt will perform in this case.
If you want to try Qwt here's simple example how to use it:


#include "mainwindow.h"

#include <QTime>

#include <qwt_plot.h>
#include <qwt_plot_curve.h>

MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
QwtPlot* plot = new QwtPlot(this);
plot->setAutoReplot(false);

qsrand(QTime::currentTime().msec());

int count = 100;

for(int i = 0; i < count; ++i)
{
QPointF start(qrand()%300, qrand()%300);

QPolygonF poly;
poly << start;
poly << QPointF(qrand()%300, qrand()%300);
poly << QPointF(qrand()%300, qrand()%300);
poly << start;

QwtPlotCurve* c = new QwtPlotCurve();
c->setData(poly);
c->attach(plot);
}

this->setCentralWidget(plot);
}But you may need to do some optimization for 1M triangles to get acceptable performance.

Here's how I've done the paint event test:


//testcanvas.h
#ifndef TESTCANVAS_H
#define TESTCANVAS_H

#include <QWidget>

class testcanvas : public QWidget
{
Q_OBJECT
public:
explicit testcanvas(QWidget *parent = 0);

protected:
void paintEvent(QPaintEvent *);

private:
QList<QPolygon> poly_list;
};

#endif // TESTCANVAS_H


//testcanvas.cpp
#include "testcanvas.h"

#include <QTime>
#include <QDebug>
#include <QPainter>

testcanvas::testcanvas(QWidget *parent) :
QWidget(parent),
poly_list( QList<QPolygon>() )
{
this->setMinimumSize(500, 500);

int count = 1000000;
qsrand(QTime::currentTime().msec());

QTime t;
t.start();

for(int i = 0; i < count; ++i)
{
QPolygon poly;
poly.append(QPoint(qrand()%500, qrand()%500));
poly.append(QPoint(qrand()%500, qrand()%500));
poly.append(QPoint(qrand()%500, qrand()%500));

poly_list.append(poly);
}

qDebug() << "Generating " << count << " polys took " << t.elapsed() << "ms.";
}

void testcanvas::paintEvent(QPaintEvent *)
{
QPainter p(this);

p.fillRect(this->rect(), Qt::green);

QTime t;
t.start();

int count = poly_list.size();
for(int i = 0; i < count; ++i)
{
p.drawPolygon(poly_list[i]);
}
qDebug() << "Drawing " << count << " polys took " << t.elapsed() << "ms.";
}


//mainwindow.cpp
#include "mainwindow.h"

#include "testcanvas.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
this->setCentralWidget(new testcanvas());
}


Generating 1000000 polys took 842 ms.
Drawing 1000000 polys took 26380 ms.
Memory footprint ~87MB

bts
2nd November 2011, 22:42
Thank you for your help! I will try that.

Best regards