PDA

View Full Version : Fast drawingPolygons



CROmpir
14th December 2014, 00:10
Hi everyone,
i am working on a project where i need to draw lot of polygons. Is there any way to draw it without Timer? I am using QPainter... My problem is that i dont know how to draw a lot of polygons in short time, miliseconds.

Here is my code,

#include "widget.h"
#include "ui_widget.h"
#include "polygonpoints.h"


Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);


timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(AdvanceState()));
timer->start(1);

}

Widget::~Widget()
{
delete ui;
}
void Widget::AdvanceState(){
this->setAttribute(Qt::WA_NoSystemBackground,true);
if(brojac<300){
update();
std::cout << ++brojac << std::endl;
}
}

void Widget::paintEvent(QPaintEvent *event)
{

//std::cout << ++brojac << std::endl;
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
int N=9; // broj vrhova
x.set_x(N);
x.generate();
//int N = 4; //broj vrhova
QPointF *points = new QPointF[N];
for(int i = 0; i < N; ++i){
points[i].setX(x.vertices[i].get(0));
points[i].setY(x.vertices[i].get(1));
}

painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QColor(qrand() % 255, qrand() % 255, qrand() % 255, 128)));
painter.drawPolygon(points,N);

delete[] points;

}

stampede
14th December 2014, 10:53
Why are you generating a new set of data on each paintEvent ? Typically a paintEvent should only present the current state of the widget, so prepare the data elsewhere and simply display it in paintEvent.
Btw. you can set the widget's attributes once in the constructor.

CROmpir
14th December 2014, 11:37
I understand, but this code isn't optimized. I just want to know how can i update() widget, 10000 times for example, but without timer. Is there any solution or idea?

stampede
14th December 2014, 12:13
Why do you want to update a widget exactly 10000 times ?

CROmpir
14th December 2014, 13:08
Okej, first i want to draw polygon, then do some calculations, then i want to draw another one at Random place, again calculations, ... Many times... But idea is that i can see it in Widget as i draw them.. In Real i will need much more polygons, Like 1 million..

anda_skoa
14th December 2014, 13:28
If you are looking for a different method of stepping through a time interval, have a look at QTimeLine.

Cheers,
_

stampede
14th December 2014, 13:33
But idea is that i can see it in Widget as i draw them.. In Real i will need much more polygons, Like 1 million..
So simply create a method to update the data periodically and display it in paintEvent, pretty much something like you already have, but with "generate()" moved to AdvanceState. AdvanceState() should represent a single step in your calculations, used to update the data. Using a timer for this task seems reasonable.
If you want to limit the number of steps in your "simulation" use a member variable


#include "widget.h"
#include "ui_widget.h"
#include "polygonpoints.h"


Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
this->setAttribute(Qt::WA_NoSystemBackground,true);

this->stepsToDo = 10000;
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(AdvanceState()));
timer->start(1);

}

Widget::~Widget()
{
delete ui;
}
void Widget::AdvanceState(){

if(this->stepsToDo){
// generate new polygon or do whatever is required for a single step
--this->stepsToDo;
update(); // update requests will be scheduled, this is not an immediate repaint
} else{
this->timer->stop();
}
}

void Widget::paintEvent(QPaintEvent *event)
{

QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
// present the data generated in AdvanceStep()
}

Btw. human eye can process around 10 separate images per second if I remember correctly, you can't even notice if you try to display millions of different polygons in a short time.

wysota
14th December 2014, 14:00
Okej, first i want to draw polygon, then do some calculations, then i want to draw another one at Random place, again calculations, ... Many times... But idea is that i can see it in Widget as i draw them.. In Real i will need much more polygons, Like 1 million..

If you only add polygons and never remove them then paint on a pixmap and then "blit" the pixmap to the widget. When a next polygon comes, draw just this one polygon on the pixmap that already contains all the previous ones and re-blit the pixmap to the widget. If you combine that with repainting only that area of the pixmap which contains the new polygon, it should be super fast.

Other than that, you can always use OpenGL. And I don't think you really need to draw the widget at 1kHz, 20Hz would be more than enough.

CROmpir
15th December 2014, 09:21
Thanks all for quick answers. I have another problem, my palette color is always black, but i set it to be white. Any suggestions? Also, what is the best solution to draw some polygons, and then delete some of them? How can i remove something what i draw?

d_stranz
16th December 2014, 00:06
my palette color is always black, but i set it to be white. Any suggestions?

Yes, show us the code where you think you are setting the palette to white.


Also, what is the best solution to draw some polygons, and then delete some of them?

Create a data structure (like QVector< QPolygon * >) to keep track of your polygons. When you want to remove one, erase it from the vector and delete it. Call update() and draw the contents of the vector.

wysota
16th December 2014, 06:54
QVector is not a right data type, it doesn't respond well to adding/removing items from arbitrary positions in the vector. I would start with QGraphicsView and QGraphicsScene.