Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QML Canvas calculating area



  • Hi There,

    I am a newbie to QT but have a bit of experience with C++. this is my first project with Qt and QML.

    I want to develop a program that lets the user draw on a canvas (see picture below) and I would like to calculate the area of each contour. I figured out how-to-draw on a canvas.

    Red rectangle is the canvas area where the user will do a free-form sketch. The user draws the black free-form sketch.
    Now I would like to calculate the area on the left and right contour. User will always only draw from one edge to another edge.

    Example 1:
    area2.PNG

    . Below is another example of the free-form sketch. In the following sketch, I need to calculate the area of the three contours.

    2021-02-26 16_29_49-Hello World.png

    My question is, what is the best way to calculate the area of each contour?

    After watching a couple of YouTube videos, i figured out the interaction between C++ and QML. now I can access the mouse position in C++. (see code below)

    My initial thoughts are

    • start at canvas position (0,0) and start counting until I reach one point drawn by the user.
    • and repeat until i reach the end

    should I use a contour detection algorithm or OpenCV?
    any thoughts on how i should tackle this problem.

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlEngine>
    #include <QQmlContext>
    #include "canvasarea.h"
    
    
    int main(int argc, char *argv[])
    {
    #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
        const QUrl url(QStringLiteral("qrc:/main.qml"));
    
        QScopedArrayPointer<CanvasArea> canvasArea(new CanvasArea);
        engine.rootContext()->setContextProperty("canvasArea", canvasArea.data());
    
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
    
        return app.exec();
    }
    
    

    main.qml

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Controls 2.12
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        Row {
            id: colorTools
            anchors {
                horizontalCenter: parent.horizontalCenter
                top: parent.top
                topMargin: 8
            }
    
            property color paintColor: "#000000"
            spacing: 4
    
            Button {
                text: "Clear"
                onClicked: {
                    canvas.clear()
                    canvasArea.clearCanvas();
                }
            }
    
        }
    
        Rectangle{
            anchors.fill: canvas
            border.color: "#ff0000"
            border.width: 4;
        }
    
        Canvas {
            id: canvas
            width: 640
            height: 480
            anchors {
                left: parent.left
                top: colorTools.bottom
                margins: 8
            }
    
            property real lastX
            property real lastY
            property color color: colorTools.paintColor
    
            function clear() {
                var ctx = getContext('2d')
                ctx.reset();
                canvas.requestPaint();
            }
    
            onPaint: {
                var ctx = getContext('2d')
                ctx.lineWidth = 1.5
                ctx.strokeStyle = canvas.color
                ctx.beginPath()
                ctx.moveTo(lastX, lastY)
                lastX = area.mouseX
                lastY = area.mouseY
                ctx.lineTo(lastX, lastY)
                ctx.stroke()
                canvasArea.mouseCordinates(lastX, lastY)
            }
    
            MouseArea {
                id: area
                anchors.fill: parent
                onPressed: {
                    canvas.lastX = mouseX
                    canvas.lastY = mouseY
                }
                onPositionChanged: {
                    canvas.requestPaint()
                }
            }
        }
    
    
    }
    
    

    canvasarea.cpp

    #include "canvasarea.h"
    #include <QDebug>
    
    CanvasArea::CanvasArea(QObject *parent) : QObject(parent)
    {
    
    }
    
    void CanvasArea::mouseCordinates(int x, int y)
    {
        QPoint point(x , y);
        userContourLocations.append(point);
        qDebug() << "currentCursorPositon" << point;
    }
    
    void CanvasArea::clearCanvas()
    {
        userContourLocations.clear();
    }
    
    

    thankyou



  • Does Qt have any type of floodfill? Then you could count the pixels set and those not set as your area.


Log in to reply