在网格中绘制具有捕捉功能的线条

Drawing Line in grid with snap Functionality

本文关键字:功能 网格 绘制      更新时间:2023-10-16

我想在网格中画一条线并实现对齐功能。我已经绘制了网格和线条,但未实现捕捉功能。我如何在其中实现该功能。我绘制了如下网格:

void CadGraphicsScene::drawBackground(QPainter *painter, const QRectF &rect)
{
    if (isGridVisible)
    {
       const int gridSize = 50;
        const int realLeft = static_cast<int>(std::floor(rect.left()));
        const int realRight = static_cast<int>(std::ceil(rect.right()));
        const int realTop = static_cast<int>(std::floor(rect.top()));
        const int realBottom = static_cast<int>(std::ceil(rect.bottom()));
        // Draw grid.
        const int firstLeftGridLine = realLeft - (realLeft % gridSize);
        const int firstTopGridLine = realTop - (realTop % gridSize);
        QVarLengthArray<QLine, 100> lines;
        for (qreal x = firstLeftGridLine; x <= realRight; x += gridSize)
            lines.append(QLine(x, realTop, x, realBottom));
        for (qreal y = firstTopGridLine; y <= realBottom; y += gridSize)
            lines.append(QLine(realLeft, y, realRight, y));
        painter->setPen(QPen(QColor(220, 220, 220), 0.0));
        painter->drawLines(lines.data(), lines.size());
        // Draw axes.
        painter->setPen(QPen(Qt::lightGray, 0.0));
        painter->drawLine(0, realTop, 0, realBottom);
        painter->drawLine(realLeft, 0, realRight, 0);
    }
}

我的线路类如下:

#include "line.h"
Line::Line(int i, QPointF p1, QPointF p2)
{
    // assigns id
    id = i;
    // set values of start point and end point of line
    startP = p1;
    endP = p2;
}
int Line::type() const
{
    // Enable the use of qgraphicsitem_cast with line item.
    return Type;
}
QRectF Line::boundingRect() const
{
    qreal extra = 1.0;
    // bounding rectangle for line
    return QRectF(line().p1(), QSizeF(line().p2().x() - line().p1().x(),
                                      line().p2().y() - line().p1().y()))
            .normalized()
            .adjusted(-extra, -extra, extra, extra);
}
void Line::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
                  QWidget *widget)
{
    // draws/paints the path of line
    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);
        painter->drawEllipse(startP, 2, 2);
        painter->drawEllipse(endP, 2, 2);
        // sets pen for line path
        paintpen.setStyle(Qt::DashLine);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawLine(startP, endP);
    }
    else
    {
        painter->setBrush(Qt::SolidPattern);
        paintpen.setColor(Qt::black);
        painter->setPen(paintpen);
        painter->drawEllipse(startP, 2, 2);
        painter->drawEllipse(endP, 2, 2);
        painter->drawLine(startP, endP);
    }
}

啪.cpp

#include "snap.h"
#include <QApplication>
    Snap::Snap(const QRect& rect, QGraphicsItem* parent,
               QGraphicsScene* scene):
    QGraphicsRectItem(QRectF())
    {
        setFlags(QGraphicsItem::ItemIsSelectable |
                QGraphicsItem::ItemIsMovable |
                QGraphicsItem::ItemSendsGeometryChanges);
    }
    void Snap::mousePressEvent(QGraphicsSceneMouseEvent *event){
        offset = pos() - computeTopLeftGridPoint(pos());
        QGraphicsRectItem::mousePressEvent(event);
    }
    QVariant Snap::itemChange(GraphicsItemChange change,
    const QVariant &value)
    {
        if (change == ItemPositionChange && scene()) {
            QPointF newPos = value.toPointF();
            if(QApplication::mouseButtons() == Qt::LeftButton &&
                qobject_cast<CadGraphicsScene*> (scene())){
                    QPointF closestPoint = computeTopLeftGridPoint(newPos);
                    return closestPoint+=offset;
                }
            else
                return newPos;
        }
        else
            return QGraphicsItem::itemChange(change, value);
    }
    QPointF Snap::computeTopLeftGridPoint(const QPointF& pointP){
       CadGraphicsScene* customScene = qobject_cast<CadGraphicsScene*> (scene());
        int gridSize = customScene->getGridSize();
        qreal xV = floor(pointP.x()/gridSize)*gridSize;
        qreal yV = floor(pointP.y()/gridSize)*gridSize;
        return QPointF(xV, yV);
    }

任何人都可以帮我解决这个问题吗?

在要捕捉的项目的MouseMoveEvent中:

检查项目与下一个网格线之间的距离是否低于特定距离(项目捕捉的距离)。然后更改位置,以便您的项目移动到下一个网格线。

在伪中:

if( distance(Item.Position, Grid.NextLine) < SnapDistance)
    line.Position = Grid.MextLine.Position

不过,您必须将 X 和 Y 分开才能正常工作。