Search code examples
c++qtellipseqpainterqpainterpath

QPainter draws the ellipse at the very top left, ignoring the initial coords


I want to draw an ellipse using QPainter and QPainterPath.

I have a set of coordinates of my desired ellipse in form of a string, and want the ellipse to be drawn based on these coordinates.

However, the ellipse is rendered at the very edge on top left of the window, ignoring that the starting point is not there.

Assuming the string that contains the ellipse coordinates is coordinates, and M/132.861/30.3958 at the very beginning represents the starting point of the ellipse that should be drawn, AKA at (132.861 , 30.3958), we have:

void MainWindow::paintEvent(QPaintEvent *event) {
    QPainter painter(this);
    QPainterPath path;

    QString coordinates = "M/132.861/30.3958;L/132.519/33.5257;L/131.516/36.5653;L/129.884/39.4993;L/127.656/42.3123;"
                          "L/121.548/47.5134;L/113.459/52.0456;L/103.653/55.7858;L/92.3987/58.6107;L/79.9614/60.3972;"
                          "L/66.608/61.0221;L/53.2542/60.4032;L/40.8162/58.6224;L/29.5604/55.8026;L/19.7533/52.0669;"
                          "L/11.6613/47.5384;L/5.55107/42.34;L/3.32233/39.5281;L/1.68892/36.5948;L/0.684158/33.5556;"
                          "L/0.341357/30.4259;L/0.682737/27.296;L/1.68612/24.2563;L/3.31819/21.3223;L/5.54566/18.5094;"
                          "L/11.6536/13.3083;L/19.7434/8.77603;L/29.5488/5.0359;L/40.8034/2.211;L/53.2406/0.424508;"
                          "L/66.5941/-0.200436;L/79.9478/0.418446;L/92.3859/2.1993;L/103.642/5.01908;L/113.449/8.75477;"
                          "L/121.541/13.2833;L/127.651/18.4817;L/129.88/21.2936;L/131.513/24.2269;L/132.518/27.2661;L/132.861/30.3958";

    QStringList coordsList = coordinates.split(';');
    for (const QString &coord : coordsList) {
        QStringList parts = coord.split('/');
        if (parts.size() == 3) {
            QString command = parts[0];
            qreal x = parts[1].toFloat();
            qreal y = parts[2].toFloat();

            if (command == "M") {
                path.moveTo(x, y);
            } else if (command == "L") {
                path.lineTo(x, y);
            }
        }
    }

    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawPath(path);
}

However, the result is not as expected, since the starting point is not at the very top left of the window, but it is drawn that way for some reason:

Preview


Solution

  • If you want to draw the coordinates relative to the starting point, then you have to shift the origin:

    void MainWindow::paintEvent(QPaintEvent *event) {
        QPainter painter(this);
        QPainterPath path;
    
        QString coordinates = "M/132.861/30.3958;L/132.519/33.5257;L/131.516/36.5653;L/129.884/39.4993;L/127.656/42.3123;"
                              "L/121.548/47.5134;L/113.459/52.0456;L/103.653/55.7858;L/92.3987/58.6107;L/79.9614/60.3972;"
                              "L/66.608/61.0221;L/53.2542/60.4032;L/40.8162/58.6224;L/29.5604/55.8026;L/19.7533/52.0669;"
                              "L/11.6613/47.5384;L/5.55107/42.34;L/3.32233/39.5281;L/1.68892/36.5948;L/0.684158/33.5556;"
                              "L/0.341357/30.4259;L/0.682737/27.296;L/1.68612/24.2563;L/3.31819/21.3223;L/5.54566/18.5094;"
                              "L/11.6536/13.3083;L/19.7434/8.77603;L/29.5488/5.0359;L/40.8034/2.211;L/53.2406/0.424508;"
                              "L/66.5941/-0.200436;L/79.9478/0.418446;L/92.3859/2.1993;L/103.642/5.01908;L/113.449/8.75477;"
                              "L/121.541/13.2833;L/127.651/18.4817;L/129.88/21.2936;L/131.513/24.2269;L/132.518/27.2661;L/132.861/30.3958";
    
        qreal originx = 0;
        qreal originy = 0;    
        QStringList coordsList = coordinates.split(';');
        for (const QString &coord : coordsList) {
            QStringList parts = coord.split('/');
            if (parts.size() == 3) {
                QString command = parts[0];
                qreal x = parts[1].toFloat();
                qreal y = parts[2].toFloat();
    
                if (command == "M") {
                    originx = x;
                    originy = y;
                    path.moveTo(originx + x, originy + y);
                } else if (command == "L") {
                    path.lineTo(originx + x, originy + y);
                }
            }
        }
    
        painter.setRenderHint(QPainter::Antialiasing);
        painter.drawPath(path);
    }