QGraphicsScene中的Arc

use*_*872 2 c++ qt qgraphicsview qgraphicsscene

我想在QGraphicsScene中实现arc.我希望点击三个点时我的弧应被绘制,以便在点击三个点时绘制弧,其中第一个点将开始弧,第二个将是弧上的任何点,第三个将是弧的终点.我试过学习drawArc函数,但是对于startangle和spanangle感到困惑.我无法动态设置它们.请建议我继续下去.


我尝试了解决方案在我的项目中使用它,但是出现了以下错误:

error: cannot allocate an object of abstract type 'arc'
                 arcItem = new arc(++id, startP, midP, endP);
Run Code Online (Sandbox Code Playgroud)

你能帮帮我解决问题吗?我正在为我的项目提供一部分代码.在cadgraphicsscene的mousepress活动中,我做了以下事情.

cadgraphicsscene.cpp

    void CadGraphicsScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        // mousePressEvent in the graphicsScene
        if(mouseEvent->button() == Qt::LeftButton)
        {
            switch (entityMode)
            {

            case ArcMode:
                if (mFirstClick)
                {
                    startP = mouseEvent->scenePos();
                    mFirstClick = false;
                    mSecondClick = true;
                }

                else if (!mFirstClick && mSecondClick)
                {
                    midP = mouseEvent->scenePos();
                    mFirstClick = false;
                    mSecondClick = false;
                    mThirdClick = true;
                }

                else if (!mSecondClick && mThirdClick)
                {
                    endP = mouseEvent->scenePos();
                    mThirdClick = false;
                    mPaintFlag = true;
                }

                if (mPaintFlag)
                {
                    arcItem = new arc(++id, startP, midP, endP);
                    itemList.append(arcItem);
                    mUndoStack->push(new CadCommandAdd(this, arcItem));
                    setFlags();
                }
            }
        }
   } 
Run Code Online (Sandbox Code Playgroud)

arc.cpp

#include "arc.h"

arc::arc(int i, QPointF point1, QPointF point2, QPointF point3)
{
    // assigns id
    id = i;
    p1 = point1;
    p2 = point2;
    p3 = point3;

    lineBC(point2, point3);
    lineAC(point1, point3);
    lineBA(point2, point1);

    rad = qAbs(lineBC.length()/(2*qSin(qDegreesToRadians(lineAC.angleTo(lineBA)))));

    bisectorBC(lineBC.pointAt(0.5), lineBC.p2());
    bisectorBC.setAngle(lineBC.normalVector().angle());

    bisectorBA(lineBA.pointAt(0.5), lineBA.p2());
    bisectorBA.setAngle(lineBA.normalVector().angle());


    bisectorBA.intersect(bisectorBC, &center);

    ellipse = new QGraphicsEllipseItem(center.x() - rad, center.y() - rad, rad*2, rad*2);

    lineOA(center, point1);
    lineOC(center, point3);
}

arc::arc(int i, QLineF start, QLineF end)
{
    // assigns id
    id = i;

    lineOA.angle() = start;
    lineOC.angle() - lineOA.angle() = end;
}

int arc::type() const
{
    // Enable the use of qgraphicsitem_cast with arc item.
    return Type;
}

void arc::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                QWidget *widget)
{
    QPen paintpen;
    painter->setRenderHint(QPainter::Antialiasing);
    paintpen.setWidth(1);

    if (isSelected())
    {
        // sets brush for end points
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::red);
        painter->setPen(paintpen);

        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawArc(ellipse->boundingRect(),lineOA.angle(),lineOC.angle() - lineOA.angle());
    }
    else
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawArc(ellipse->boundingRect(),lineOA.angle(),lineOC.angle() - lineOA.angle());

    }
}
Run Code Online (Sandbox Code Playgroud)

include <QGraphicsItem>

#include "qmath.h"
class arc : public QObject, public QGraphicsItem
{
    Q_OBJECT
public:
    arc(int, QPointF, QPointF, QPointF);
    arc(int, QLineF, QLineF);


    virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                       QWidget *widget);
    enum { Type = UserType + 6 };
    int type() const;
    int id;

    QPointF startP, midP, endP, p1, p2, p3,center;
    QLineF lineBC;
    QLineF lineAC;
    QLineF lineBA;
    QLineF lineOA;
    QLineF lineOC;
    QLineF bisectorBC;
    QLineF bisectorBA;
    QGraphicsEllipseItem *ellipse;
    qreal rad;

private:
    QVector<QPointF> stuff;

};

#endif // ARC_H
Run Code Online (Sandbox Code Playgroud)

请帮帮我解决错误.

phy*_*att 12

听起来这可以通过一些相对简单的数学来解决:

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

这是我将数学翻译成Qt善良

// m_points is a QList<QPointF>
// 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, &center);

qDebug() << rad << center;
Run Code Online (Sandbox Code Playgroud)

QT QGraphicsScene绘图弧

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

把所有这些放在一个漂亮的小项目中会变成这样:

https://github.com/peteristhegreat/ThreePointsCircle

qt图形场景三点圈

main.cpp中

#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;
    w.show();

    return a.exec();
}
Run Code Online (Sandbox Code Playgroud)

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = 0);
    ~MainWindow();
};

#endif // MAINWINDOW_H
Run Code Online (Sandbox Code Playgroud)

mainwindow.cpp

#include "mainwindow.h"
#include <QGraphicsView>
#include <QGraphicsScene>
#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()
{

}
Run Code Online (Sandbox Code Playgroud)

graphicsscene.h

#ifndef GRAPHICSSCENE_H
#define GRAPHICSSCENE_H

#include <QGraphicsScene>
#include <QGraphicsSceneMouseEvent>
#include <QPointF>
#include <QList>

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 <QPointF> m_points;
};

#endif // GRAPHICSSCENE_H
Run Code Online (Sandbox Code Playgroud)

graphicsscene.cpp

#include "graphicsscene.h"
#include <QDebug>
#include <QGraphicsEllipseItem>
#include <QGraphicsPathItem>
#include <QPainterPath>
#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, &center);

        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);
}
Run Code Online (Sandbox Code Playgroud)