refactor: Implement Rectangle tool with snapping and dimensions
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
@@ -6,6 +6,7 @@
|
||||
#include "FeatureBrowser.h"
|
||||
#include "SketchFeature.h"
|
||||
#include "SketchLine.h"
|
||||
#include "SketchRectangle.h"
|
||||
#include "SketchObject.h"
|
||||
#include "ApplicationController.h"
|
||||
#include <QMouseEvent>
|
||||
@@ -196,6 +197,47 @@ void ViewportWidget::paintGL()
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (m_isDefiningRectangle && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
||||
vertices.clear();
|
||||
QVector3D worldPos = unproject(m_currentMousePos, m_currentPlane);
|
||||
QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
|
||||
if (m_isSnappingOrigin) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
} else if (m_isSnappingVertex) {
|
||||
worldPos.setX(m_snapVertex.X()); worldPos.setY(m_snapVertex.Y()); worldPos.setZ(m_snapVertex.Z());
|
||||
}
|
||||
|
||||
QVector3D p1 = startPos;
|
||||
QVector3D p2, p3, p4;
|
||||
p3 = worldPos;
|
||||
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
p2.setX(p3.x()); p2.setY(p1.y()); p2.setZ(p1.z());
|
||||
p4.setX(p1.x()); p4.setY(p1.y()); p4.setZ(p3.z());
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
p2.setX(p3.x()); p2.setY(p1.y()); p2.setZ(p1.z());
|
||||
p4.setX(p1.x()); p4.setY(p3.y()); p4.setZ(p1.z());
|
||||
} else if (m_currentPlane == SketchPlane::YZ) {
|
||||
p2.setX(p1.x()); p2.setY(p3.y()); p2.setZ(p1.z());
|
||||
p4.setX(p1.x()); p4.setY(p1.y()); p4.setZ(p3.z());
|
||||
}
|
||||
|
||||
vertices << p1.x() << p1.y() << p1.z();
|
||||
vertices << p2.x() << p2.y() << p2.z();
|
||||
vertices << p2.x() << p2.y() << p2.z();
|
||||
vertices << p3.x() << p3.y() << p3.z();
|
||||
vertices << p3.x() << p3.y() << p3.z();
|
||||
vertices << p4.x() << p4.y() << p4.z();
|
||||
vertices << p4.x() << p4.y() << p4.z();
|
||||
vertices << p1.x() << p1.y() << p1.z();
|
||||
|
||||
m_shaderProgram->setUniformValue(m_colorLoc, QVector4D(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 8);
|
||||
}
|
||||
|
||||
if (m_isDefiningLine && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
||||
vertices.clear();
|
||||
QVector3D worldPos;
|
||||
@@ -544,6 +586,65 @@ void ViewportWidget::paintGL()
|
||||
}
|
||||
m_featureBrowser->paint(painter, width(), height());
|
||||
|
||||
if (m_isDefiningRectangle && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
||||
QVector3D worldPos = unproject(m_currentMousePos, m_currentPlane);
|
||||
if (m_isSnappingOrigin) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
} else if (m_isSnappingVertex) {
|
||||
worldPos.setX(m_snapVertex.X()); worldPos.setY(m_snapVertex.Y()); worldPos.setZ(m_snapVertex.Z());
|
||||
}
|
||||
|
||||
QVector3D p1_3d(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
QVector3D p3_3d = worldPos;
|
||||
QVector3D p2_3d, p4_3d;
|
||||
|
||||
double w, h;
|
||||
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
p2_3d.setX(p3_3d.x()); p2_3d.setY(p1_3d.y()); p2_3d.setZ(p1_3d.z());
|
||||
p4_3d.setX(p1_3d.x()); p4_3d.setY(p1_3d.y()); p4_3d.setZ(p3_3d.z());
|
||||
w = qAbs(p3_3d.x() - p1_3d.x());
|
||||
h = qAbs(p3_3d.z() - p1_3d.z());
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
p2_3d.setX(p3_3d.x()); p2_3d.setY(p1_3d.y()); p2_3d.setZ(p1_3d.z());
|
||||
p4_3d.setX(p1_3d.x()); p4_3d.setY(p3_3d.y()); p4_3d.setZ(p1_3d.z());
|
||||
w = qAbs(p3_3d.x() - p1_3d.x());
|
||||
h = qAbs(p3_3d.y() - p1_3d.y());
|
||||
} else { // YZ
|
||||
p2_3d.setX(p1_3d.x()); p2_3d.setY(p3_3d.y()); p2_3d.setZ(p1_3d.z());
|
||||
p4_3d.setX(p1_3d.x()); p4_3d.setY(p1_3d.y()); p4_3d.setZ(p3_3d.z());
|
||||
w = qAbs(p3_3d.y() - p1_3d.y());
|
||||
h = qAbs(p3_3d.z() - p1_3d.z());
|
||||
}
|
||||
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QFontMetrics fm(painter.font());
|
||||
|
||||
// Width dimension
|
||||
QVector3D widthTextPos3D = (p1_3d + p2_3d) / 2.0f;
|
||||
QVector3D screenPosW = project(widthTextPos3D, model, projection, rect());
|
||||
if (screenPosW.z() < 1.0f) {
|
||||
QString widthText = QString::number(w, 'f', 2);
|
||||
QRect textRect = fm.boundingRect(widthText + "__");
|
||||
textRect.moveCenter(screenPosW.toPoint() + QPoint(0, (p3_3d.z() > p1_3d.z() || p3_3d.y() > p1_3d.y()) ? -15 : 15));
|
||||
painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50));
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(textRect, Qt::AlignCenter, widthText);
|
||||
}
|
||||
|
||||
// Height dimension
|
||||
QVector3D heightTextPos3D = (p2_3d + p3_3d) / 2.0f;
|
||||
QVector3D screenPosH = project(heightTextPos3D, model, projection, rect());
|
||||
if (screenPosH.z() < 1.0f) {
|
||||
QString heightText = QString::number(h, 'f', 2);
|
||||
QRect textRect = fm.boundingRect(heightText + "__");
|
||||
textRect.moveCenter(screenPosH.toPoint() + QPoint((p3_3d.x() > p1_3d.x()) ? 15 : -15, 0));
|
||||
painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50));
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(textRect, Qt::AlignCenter, heightText);
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isDefiningLine && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
@@ -802,6 +903,28 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast<int>(ApplicationController::ToolType::Rectangle)) {
|
||||
gp_Pnt p;
|
||||
if (m_isSnappingOrigin) {
|
||||
p.SetCoord(0, 0, 0);
|
||||
} else if (m_isSnappingVertex) {
|
||||
p = m_snapVertex;
|
||||
} else {
|
||||
QVector3D worldPos = unproject(event->pos(), m_currentPlane);
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
}
|
||||
|
||||
if (!m_isDefiningRectangle) {
|
||||
m_firstRectanglePoint = p;
|
||||
m_isDefiningRectangle = true;
|
||||
} else {
|
||||
emit rectangleAdded(m_firstRectanglePoint, p);
|
||||
m_isDefiningRectangle = false;
|
||||
}
|
||||
update();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
||||
gp_Pnt p;
|
||||
QString dimInput = property("dimensionInput").toString();
|
||||
@@ -1202,6 +1325,12 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
||||
update();
|
||||
return;
|
||||
}
|
||||
if (m_isDefiningRectangle) {
|
||||
m_isDefiningRectangle = false;
|
||||
emit toolDeactivated();
|
||||
update();
|
||||
return;
|
||||
}
|
||||
if (m_isSelectingPlane) {
|
||||
m_isSelectingPlane = false;
|
||||
m_highlightedPlane = SketchPlane::NONE;
|
||||
@@ -1394,6 +1523,7 @@ void ViewportWidget::onActiveToolChanged(int tool)
|
||||
{
|
||||
m_activeTool = tool;
|
||||
m_isDefiningLine = false;
|
||||
m_isDefiningRectangle = false;
|
||||
|
||||
if (tool == static_cast<int>(ApplicationController::ToolType::None)) {
|
||||
unsetCursor();
|
||||
@@ -1499,6 +1629,36 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
||||
|
||||
vertexCounts[start]++;
|
||||
vertexCounts[end]++;
|
||||
} else if (obj->type() == SketchObject::ObjectType::Rectangle) {
|
||||
auto rect = static_cast<const SketchRectangle*>(obj);
|
||||
const auto& p1 = rect->corner1();
|
||||
const auto& p3 = rect->corner2();
|
||||
|
||||
gp_Pnt p2, p4;
|
||||
if (sketch->plane() == SketchFeature::SketchPlane::XY) {
|
||||
p2.SetCoord(p3.X(), p1.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::XZ) {
|
||||
p2.SetCoord(p3.X(), p1.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p3.Y(), p1.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::YZ) {
|
||||
p2.SetCoord(p1.X(), p3.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
}
|
||||
|
||||
lineVertices << p1.X() << p1.Y() << p1.Z();
|
||||
lineVertices << p2.X() << p2.Y() << p2.Z();
|
||||
lineVertices << p2.X() << p2.Y() << p2.Z();
|
||||
lineVertices << p3.X() << p3.Y() << p3.Z();
|
||||
lineVertices << p3.X() << p3.Y() << p3.Z();
|
||||
lineVertices << p4.X() << p4.Y() << p4.Z();
|
||||
lineVertices << p4.X() << p4.Y() << p4.Z();
|
||||
lineVertices << p1.X() << p1.Y() << p1.Z();
|
||||
|
||||
vertexCounts[p1] += 2;
|
||||
vertexCounts[p2] += 2;
|
||||
vertexCounts[p3] += 2;
|
||||
vertexCounts[p4] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user