Arc in QGraphicsScene

前端 未结 2 881
梦如初夏
梦如初夏 2020-12-04 00:37

I want to implement arc in QGraphicsScene. I want that on clicking of three points my arc should be drawn such that on clicking of three points arc is drawn where first poin

2条回答
  •  Happy的楠姐
    2020-12-04 01:24

    This sounds like it could be solved with some relatively simple math:

    https://www.google.com/search?q=define%20circle%20three%20points

    https://math.stackexchange.com/a/213678

    https://www.khanacademy.org/math/geometry/triangle-properties/perpendicular_bisectors/v/three-points-defining-a-circle

    Here is my translation of the math into Qt goodness

    // m_points is a QList
    // use math to define the circle
    QLineF lineBC(m_points.at(1), m_points.at(2));
    QLineF lineAC(m_points.at(0), m_points.at(2));
    QLineF lineBA(m_points.at(1), m_points.at(0));
    qreal rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));
    
    QLineF bisectorBC(lineBC.pointAt(0.5), lineBC.p2());
    bisectorBC.setAngle(lineBC.normalVector().angle());
    
    QLineF bisectorBA(lineBA.pointAt(0.5), lineBA.p2());
    bisectorBA.setAngle(lineBA.normalVector().angle());
    
    QPointF center;
    bisectorBA.intersect(bisectorBC, ¢er);
    
    qDebug() << rad << center;
    

    QT QGraphicsScene Drawing Arc

    QPainterPath* path = new QPainterPath();
    path->arcMoveTo(0,0,50,50,20);
    path->arcTo(0,0,50,50,20, 90);
    scene.addPath(*path);
    

    Putting all of this together into a nice little project turns into this:

    https://github.com/peteristhegreat/ThreePointsCircle

    qt graphics scene three points circle

    main.cpp

    #include "mainwindow.h"
    #include 
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include 
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include 
    #include 
    #include "graphicsscene.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent)
    {
        QGraphicsView * view = new QGraphicsView;
    
        GraphicsScene * scene = new GraphicsScene();
        view->setScene(scene);
    
        view->setSceneRect(-300,-300, 300, 300);
        this->resize(600, 600);
    
        this->setCentralWidget(view);
    }
    
    MainWindow::~MainWindow()
    {
    
    }
    

    graphicsscene.h

    #ifndef GRAPHICSSCENE_H
    #define GRAPHICSSCENE_H
    
    #include 
    #include 
    #include 
    #include 
    
    class GraphicsScene : public QGraphicsScene
    {
        Q_OBJECT
    public:
        explicit GraphicsScene(QObject *parent = 0);
        virtual void mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent);
        virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent);
        virtual void mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent);
        virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent * mouseEvent);
    signals:
    
    public slots:
    
    private:
        QList  m_points;
    };
    
    #endif // GRAPHICSSCENE_H
    

    graphicsscene.cpp

    #include "graphicsscene.h"
    #include 
    #include 
    #include 
    #include 
    #include "qmath.h"
    
    GraphicsScene::GraphicsScene(QObject *parent) :
        QGraphicsScene(parent)
    {
        this->setBackgroundBrush(Qt::gray);
    }
    
    void GraphicsScene::mouseDoubleClickEvent(QGraphicsSceneMouseEvent * mouseEvent)
    {
        qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
        QGraphicsScene::mouseDoubleClickEvent(mouseEvent);
    }
    
    void GraphicsScene::mouseMoveEvent(QGraphicsSceneMouseEvent * mouseEvent)
    {
        qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
        QGraphicsScene::mouseMoveEvent(mouseEvent);
    }
    
    void GraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent * mouseEvent)
    {
        qDebug() << Q_FUNC_INFO << mouseEvent->scenePos();
        QGraphicsScene::mousePressEvent(mouseEvent);
    }
    
    void GraphicsScene::mouseReleaseEvent(QGraphicsSceneMouseEvent * me)
    {
        qDebug() << Q_FUNC_INFO << me->scenePos();
        int radius = 20;
        QGraphicsEllipseItem * ellipse = this->addEllipse(me->scenePos().x() - radius, me->scenePos().y() - radius, radius*2, radius*2);
    
        ellipse->setBrush(Qt::white);
        m_points.append(me->scenePos());
        if(m_points.size() == 3)
        {
            // use math to define the circle
            QLineF lineBC(m_points.at(1), m_points.at(2));
            QLineF lineAC(m_points.at(0), m_points.at(2));
            QLineF lineBA(m_points.at(1), m_points.at(0));
            qreal rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));
    
            QLineF bisectorBC(lineBC.pointAt(0.5), lineBC.p2());
            bisectorBC.setAngle(lineBC.normalVector().angle());
    
            QLineF bisectorBA(lineBA.pointAt(0.5), lineBA.p2());
            bisectorBA.setAngle(lineBA.normalVector().angle());
    
            QPointF center;
            bisectorBA.intersect(bisectorBC, ¢er);
    
            qDebug() << rad << center;
    
            bool drawCircle = true;
    
            QGraphicsEllipseItem * ellipse = new QGraphicsEllipseItem(center.x() - rad, center.y() - rad, rad*2, rad*2);
            if(drawCircle)
                this->addItem(ellipse);
    
            // add arc
            // this->addItem(path);
            QPainterPath path;
            QLineF lineOA(center, m_points.at(0));
            QLineF lineOC(center, m_points.at(2));
            path.arcMoveTo(ellipse->boundingRect(),lineOA.angle());
            path.arcTo(ellipse->boundingRect(), lineOA.angle(), lineOC.angle() - lineOA.angle());
            QGraphicsPathItem * pathItem = new QGraphicsPathItem(path);
            pathItem->setPen(QPen(Qt::red,10));
            this->addItem(pathItem);
    
            if(!drawCircle)
                delete ellipse;
            m_points.clear();
        }
    
        QGraphicsScene::mouseReleaseEvent(me);
    }
    

提交回复
热议问题