Reply
Thread Tools
Posts: 61 | Thanked: 43 times | Joined on Aug 2008
#11
Originally Posted by Venemo View Post
StackOverflow might be a good place to ask.
http://stackoverflow.com/questions/3...a-drawing-code



If vertical lines are always ok when doing partial or full update then I don't think it's performance issue (updating blocks input) and I won't recommend using low priority thread to handle updating.

I'm clueless, but please show latest code.
 

The Following User Says Thank You to harriva For This Useful Post:
Posts: 341 | Thanked: 57 times | Joined on Nov 2009
#12
Alright, here's the latest code then ...

Here's Canvas.h: (was previously called 'Board' .. by Canvas I mean the widget which contains the image on which drawing is done)

Please note that only code relevant to this problem is mentioned here:

Code:
class Canvas : public QWidget
{
    Q_OBJECT

public:
    Canvas(QWidget *parent = 0);

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void mouseDoubleClickEvent(QMouseEvent *);
    void paintEvent(QPaintEvent *event);

private:
    void drawLineTo(const QPoint &endPoint);

    QImage image; //this is the image on which drawing is done
    QPoint lastPoint;
    QVector<QPoint> qPoints;
    //MainWindow *mainWindow;
    int minX;
    int minY;
    int maxX;
    int maxY;
    void connectingPointsCalculator3( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1);
};
ConnectingPointsCalculator3 function .. (used to output a QVector of all the points which need to be connected to make all those lines to give the slanted effect ... only the point coordinates are calculated in this function):

Code:
void Canvas::connectingPointsCalculator3( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1)
{
    inputqPoints.clear();
    bool steep;


    int i=2;

    if( qAbs(y1-y0)>qAbs(x1-x0))
    {
        steep = true;
    }
    if(steep==true)
    {
        swap(x0,y0);
        swap(x1,y1);
    }
    if(x0>x1)
    {
        swap(x0,x1);
        swap(y0,y1);
    }
    int deltax = x1-x0;
    int deltay = qAbs(y1-y0);
    int error = deltax/2;
    int ystep=0;
    int y=y0;
    if(y0<y1)
    {
        ystep=1;
    }
    else
    {
        ystep=-1;
    }
    inputqPoints.resize(1);
    if(steep==true)
    {
        inputqPoints.insert(0,QPoint(y0-5,x0-5));
        inputqPoints.insert(1,QPoint(y0+5,x0+5));
    }
    else
    {
        inputqPoints.insert(0,QPoint(x0-5,y0-5));
        inputqPoints.insert(1,QPoint(x0+5,y0+5));
    }
    bool switchedLanes = false;
    int x= x0;
    while(x<(x1+1))
    {
        if(switchedLanes==false)
        {
            error = error - deltay;
            if(error<0)
            {
                y=y+ystep;
                error = error + deltax;
                switchedLanes = true;
            }
        }
        else
        {
            switchedLanes=false;
        }


        if(steep==true)
        {
            inputqPoints.insert(i,QPoint(y-5,x-5));
            inputqPoints.insert(i+1,QPoint(y+5,x+5));
            if((y-5)<minX)
            {
                minX=y-5;
            }
            if((x-5)<minY)
            {
                minY=x-5;
            }
            if((y+5)>maxX)
            {
                maxX=y+5;
            }
            if((x+5)>maxY)
            {
                maxY=x+5;
            }
        }
        else
        {
            inputqPoints.insert(i,QPoint(x-5,y-5));
            inputqPoints.insert(i+1,QPoint(x+5,y+5));
            if((x-5)<minX)
            {
                minX=x-5;
            }
            if((y-5)<minY)
            {
                minY=y-5;
            }
            if((x+5)>maxX)
            {
                maxX=x+5;
            }
            if((y+5)>maxY)
            {
                maxY=y+5;
            }
        }
        if(switchedLanes==false)
        {
            x++;

        }
        i++;
        i++;

    }

}
Function used to actually do all the drawing on the QImage object named 'image':

Code:
void Canvas::drawLineTo(const QPoint &endPoint)
{
    QPainter painter(&image);

    painter.setPen(QPen(Qt::black,1,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
    qPoints.clear();
    minX =999999;
    minY =999999;
    maxX =-999999;
    maxY =-999999;
    painter.setPen(Qt::blue);
    painter.drawEllipse(lastPoint,8,8);
    painter.setPen(Qt::red);
    painter.drawEllipse(endPoint,4,4);
    connectingPointsCalculator3(qPoints,lastPoint.x(),lastPoint.y(),endPoint.x(),endPoint.y());
    painter.setPen(Qt::black);
    painter.drawLines(qPoints);

    update (QRect(QPoint(minX,minY), QPoint(maxX,maxY)).normalized());
    //update();
    modified = true;
    lastPoint = endPoint;
}
3 functions to do the initialization within the Canvas object:

Code:
Canvas::Canvas(QWidget *parent)
{
    setAttribute(Qt::WA_StaticContents);
    reset();
    qPoints.clear();
}

void Canvas::reset()
{
    resizeImage(&image,QSize(800,400));
    image.fill(qRgb(255, 255, 255));
    update();
}

void Canvas::resizeImage(QImage *image, const QSize &newSize)
{
    if (image->size() == newSize)
        return;

    QImage newImage(newSize, QImage::Format_RGB32);
    QPainter painter(&newImage);
    painter.drawImage(QPoint(0, 0), *image);
    *image = newImage;
}
Drawing event functions:

Code:
void Canvas::mousePressEvent(QMouseEvent *event)
{
    if(event->button() & Qt::LeftButton)
    {
        scribbling=true;
        lastPoint=event->pos();
    }
}

void Canvas::mouseMoveEvent(QMouseEvent *event)
{
    if((event->buttons() & Qt::LeftButton) && scribbling==true)
    {
        drawLineTo(event->pos());
    }
}

void Canvas::mouseReleaseEvent(QMouseEvent *event)
{
    if((event->button()&Qt::LeftButton)&&scribbling==true)
    {
        drawLineTo(event->pos());
        scribbling=false;
    }
}
Canvas paintEvent():

Code:
void Canvas::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    QRect dirtyRect = event->rect();
    painter.drawImage(dirtyRect, image, dirtyRect);
}
A Canvas class object called 'canvas' in contained within my main window. In my main window's constructor, 'canvas' is initialized and set as the main central widget .. if you need code for my Main Window as well, please let me know ... And please help me figure this silly bug out :P
 
Posts: 61 | Thanked: 43 times | Joined on Aug 2008
#13
ConnectingPointsCalculator3 is interesting... "minX=y-5;"
How did you verify that it gave correct x points out?
 

The Following User Says Thank You to harriva For This Useful Post:
Posts: 341 | Thanked: 57 times | Joined on Nov 2009
#14
Originally Posted by harriva View Post
ConnectingPointsCalculator3 is interesting... "minX=y-5;"
How did you verify that it gave correct x points out?
No this is correct ... the concept of 'x' and 'y' may be switched earlier in this same code depending on the orientation of the line .. but if you look at the end, when the coordinate is finally being saved into the QVector structure, its being saved as both (x,y) and (y,x), depending on which scheme was being used, to counter any earlier x/y swaps ...

output has been verified because I've checked the final list of points calculated for a number of different orientations .. its always correct ..

EDIT: Besides, I even tried updating the entire region using just update(), completely ignoring min/max X/Y values .. even then it was the same result ..

Last edited by ahmadka; 2010-06-15 at 14:49.
 
mikec's Avatar
Posts: 1,366 | Thanked: 1,185 times | Joined on Jan 2006
#15
Well right now its running in semi-fullscreen mode .. only the top bar is showing ... How do I switch to 100% fullscreen ? I doubt this will solve the issue though ..



Just tried this too .. Same result as before .. A little slower though ..[/QUOTE]

In PR1.2 the top level window bypasses the compositor. I dont think this is the case unless its in fullscreen this will have big impact on performance.

ui.showFullScreen does the job.

to be sure you can turn the compositor off
http://doc.qt.nokia.com/qt-maemo-4.6...es-maemo5.html
__________________
N900_Email_Options Wiki Page
 
Posts: 61 | Thanked: 43 times | Joined on Aug 2008
#16
Originally Posted by ahmadka View Post
output has been verified because I've checked the final list of points calculated for a number of different orientations .. its always correct ..

EDIT: Besides, I even tried updating the entire region using just update(), completely ignoring min/max X/Y values .. even then it was the same result ..
I had my doubts about your connectingPointsCalculator3 and it didn't seem to be giving me correct points when I tested it. Want to try my code?


Code:
// Add if needed
//#include <qmath.h>

void connectingPointsCalculator4( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1)
{
    inputqPoints.clear();

    float i = qMax(qAbs(x0-x1), qAbs(y0-y1));

    for(int j = 0; j<=i; j++)
    {
	inputqPoints.append(QPoint(qRound(x0-(((x0-x1)/i)*j)-5), qRound(y0-(((y0-y1)/i)*j)-5)));
	inputqPoints.append(QPoint(qRound(x0-(((x0-x1)/i)*j)+5), qRound(y0-(((y0-y1)/i)*j)+5)));
    }
}
 

The Following User Says Thank You to harriva For This Useful Post:
Posts: 341 | Thanked: 57 times | Joined on Nov 2009
#17
alright will try out your code today and post the results then ..
 
w00t's Avatar
Posts: 1,055 | Thanked: 4,107 times | Joined on Oct 2009 @ Norway
#18
One thing:

Originally Posted by gri View Post
Without thinking a lot about it:

You could try to paint into a QPixmap. Store your points and only append them to the pixmap. Only if the widget is resized, you'll generate a new pixmap or resize it.
That would consume some (not a lot) memory and stops your n900 from slowing down. Maybe it even helps with the update problems.

EDIT: Oops, just saw you seem to already draw onto a image ...
Just to interject briefly (it may not be helpful in this particular case, but..): what gri said was still correct.

It looks like you're redrawing all points (onto an image) whenever things change. This will work, but it isn't too efficient. Ideally, you should have a QPixmap you render to as needed, and keep it up to date, drawing it directly from the pixmap when paintEvent is used, and invalidating the pixmap when the widget resizes.
__________________
i'm a Qt expert and former Jolla sailor (forever sailing, in spirit).
if you like, read more about me.
if you find me entertaining, or useful, thank me. if you don't, then tell me why.
 
Posts: 341 | Thanked: 57 times | Joined on Nov 2009
#19
Originally Posted by harriva View Post
I had my doubts about your connectingPointsCalculator3 and it didn't seem to be giving me correct points when I tested it. Want to try my code?


Code:
// Add if needed
//#include <qmath.h>

void connectingPointsCalculator4( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1)
{
    inputqPoints.clear();

    float i = qMax(qAbs(x0-x1), qAbs(y0-y1));

    for(int j = 0; j<=i; j++)
    {
	inputqPoints.append(QPoint(qRound(x0-(((x0-x1)/i)*j)-5), qRound(y0-(((y0-y1)/i)*j)-5)));
	inputqPoints.append(QPoint(qRound(x0-(((x0-x1)/i)*j)+5), qRound(y0-(((y0-y1)/i)*j)+5)));
    }
}
okay i finally got time to look at this .. After a quick look, it seems that based on your code you are allowing diagonal lines .. I actually need code in which a strict diagonal path is not allowed .. This will help clear what I'm trying to say:



The right one is what I would like .. While the code you posted, although very quick and to the point, is doing the one on the left ..


EDIT: Never mind, got the effect I wanted with a simple tweak:

Code:
void Canvas::connectingPointsCalculator4( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1)
{
    inputqPoints.clear();

    float i = qMax(qAbs(x0-x1), qAbs(y0-y1));

    int x=0, y=0;
    int xprevious,yprevious;
    bool oneRoundComplete = false;

    for(int j = 0; j<=i; j++)
    {
        xprevious = x;
        yprevious = y;
        x = qRound(x0-(((x0-x1)/i)*j));
        y = qRound(y0-(((y0-y1)/i)*j));
        if(oneRoundComplete==true)
        {
            if(x!=xprevious && y!=yprevious)
            {
                inputqPoints.append(QPoint(xprevious-5, y-5));
                inputqPoints.append(QPoint(xprevious+5, y+5));
            }
        }
        inputqPoints.append(QPoint(x-5, y-5));
        inputqPoints.append(QPoint(x+5, y+5));
        oneRoundComplete = true;
    }
}

Last edited by ahmadka; 2010-06-23 at 20:36.
 
Posts: 61 | Thanked: 43 times | Joined on Aug 2008
#20
Or you could have used qCeil and qFloor.
Code:
void connectingPointsCalculator4( QVector<QPoint>& inputqPoints, int x0, int y0, int x1, int y1)
{
    inputqPoints.clear();

    float i = qAbs(x0-x1) + qAbs(y0-y1) ;
    if(!i) return;

    for(int j = 0; j<=i; j++)
    {
	inputqPoints.append(QPoint(qCeil(x0-(((x0-x1)/i)*j)+5), qFloor(y0-(((y0-y1)/i)*j)+5)));
	inputqPoints.append(QPoint(qCeil(x0-(((x0-x1)/i)*j)-5), qFloor(y0-(((y0-y1)/i)*j)-5)));
    }
}
 
Reply


 
Forum Jump


All times are GMT. The time now is 12:54.