refactor: Eliminate SketchPlane enum, use gp_Ax2 for all plane operations
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
+59
-43
@@ -38,6 +38,9 @@
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QVector>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
|
||||
struct PntComparator {
|
||||
bool operator()(const gp_Pnt& a, const gp_Pnt& b) const {
|
||||
@@ -62,7 +65,7 @@ ViewportWidget::ViewportWidget(QWidget *parent)
|
||||
setMouseTracking(true);
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
|
||||
m_currentPlane = SketchPlane::XY;
|
||||
m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ());
|
||||
|
||||
m_toolIcons.insert(static_cast<int>(ApplicationController::ToolType::Line), new QSvgRenderer(QString(":/icons/line.svg"), this));
|
||||
m_toolIcons.insert(static_cast<int>(ApplicationController::ToolType::Rectangle), new QSvgRenderer(QString(":/icons/rectangle.svg"), this));
|
||||
@@ -145,12 +148,12 @@ void ViewportWidget::paintGL()
|
||||
|
||||
// Sketch grid rendering
|
||||
if (m_isSelectingPlane) {
|
||||
if (m_highlightedPlane != SketchPlane::NONE) {
|
||||
m_sketchGrid->paintGL(static_cast<SketchGrid::SketchPlane>(m_highlightedPlane), m_shaderProgram, m_colorLoc);
|
||||
if (m_highlightedPlane) {
|
||||
m_sketchGrid->paintGL(m_highlightedPlane.value(), m_shaderProgram, m_colorLoc);
|
||||
}
|
||||
}
|
||||
if (m_currentPlane != SketchPlane::NONE) {
|
||||
m_sketchGrid->paintGL(static_cast<SketchGrid::SketchPlane>(m_currentPlane), m_shaderProgram, m_colorLoc);
|
||||
if (m_currentPlane) {
|
||||
m_sketchGrid->paintGL(m_currentPlane.value(), m_shaderProgram, m_colorLoc);
|
||||
}
|
||||
|
||||
if (m_isSelectingPlane) {
|
||||
@@ -207,8 +210,8 @@ void ViewportWidget::paintGL()
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
QPainter painter(this);
|
||||
if (m_currentPlane != SketchPlane::NONE) {
|
||||
m_sketchGrid->paintAxisLabels(painter, static_cast<SketchGrid::SketchPlane>(m_currentPlane), model, projection);
|
||||
if (m_currentPlane) {
|
||||
m_sketchGrid->paintAxisLabels(painter, m_currentPlane.value(), model, projection);
|
||||
}
|
||||
m_featureBrowser->paint(painter, width(), height());
|
||||
m_viewCube->paint2D(painter, width(), height());
|
||||
@@ -235,8 +238,10 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
||||
m_camera->mousePressEvent(event);
|
||||
|
||||
if (event->button() == Qt::MiddleButton && !(QApplication::keyboardModifiers() & Qt::ShiftModifier)) {
|
||||
m_camera->startRotation(unproject(event->pos(), m_currentPlane));
|
||||
update();
|
||||
if (m_currentPlane) {
|
||||
m_camera->startRotation(unproject(event->pos(), m_currentPlane.value()));
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
@@ -247,10 +252,10 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (m_isSelectingPlane) {
|
||||
if (m_highlightedPlane != SketchPlane::NONE) {
|
||||
emit planeSelected(m_highlightedPlane);
|
||||
if (m_highlightedPlane) {
|
||||
emit planeSelected(m_highlightedPlane.value());
|
||||
m_isSelectingPlane = false;
|
||||
m_highlightedPlane = SketchPlane::NONE;
|
||||
m_highlightedPlane.reset();
|
||||
update();
|
||||
}
|
||||
return;
|
||||
@@ -270,8 +275,17 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
m_currentMousePos = event->pos();
|
||||
|
||||
if (m_isSelectingPlane) {
|
||||
SketchPlane newHighlight = checkPlaneSelection(m_currentMousePos);
|
||||
if (newHighlight != m_highlightedPlane) {
|
||||
auto newHighlight = checkPlaneSelection(m_currentMousePos);
|
||||
bool needsUpdate = newHighlight.has_value() != m_highlightedPlane.has_value();
|
||||
if (!needsUpdate && newHighlight) {
|
||||
// Very basic check, assumes planes are one of the 3 cardinal ones
|
||||
// and checkPlaneSelection returns them consistently.
|
||||
if (!newHighlight->Direction().IsEqual(m_highlightedPlane->Direction(), 1e-9)) {
|
||||
needsUpdate = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (needsUpdate) {
|
||||
m_highlightedPlane = newHighlight;
|
||||
update();
|
||||
}
|
||||
@@ -291,8 +305,10 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void ViewportWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane);
|
||||
m_camera->wheelEvent(event, worldPos);
|
||||
if (m_currentPlane) {
|
||||
QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane.value());
|
||||
m_camera->wheelEvent(event, worldPos);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
||||
@@ -305,8 +321,8 @@ void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
||||
if (event->key() == Qt::Key_Escape) {
|
||||
if (m_isSelectingPlane) {
|
||||
m_isSelectingPlane = false;
|
||||
m_highlightedPlane = SketchPlane::NONE;
|
||||
m_currentPlane = SketchPlane::XY;
|
||||
m_highlightedPlane.reset();
|
||||
m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ());
|
||||
update();
|
||||
return;
|
||||
}
|
||||
@@ -371,19 +387,19 @@ bool ViewportWidget::focusNextPrevChild(bool next)
|
||||
return QOpenGLWidget::focusNextPrevChild(next);
|
||||
}
|
||||
|
||||
void ViewportWidget::onSketchModeStarted(SketchPlane plane)
|
||||
void ViewportWidget::onSketchModeStarted(const gp_Ax2& plane)
|
||||
{
|
||||
m_currentPlane = plane;
|
||||
|
||||
m_camera->saveState();
|
||||
m_camera->animateToPlaneView(static_cast<int>(plane));
|
||||
m_camera->animateToPlaneView(plane);
|
||||
}
|
||||
|
||||
void ViewportWidget::onPlaneSelectionModeStarted()
|
||||
{
|
||||
m_isSelectingPlane = true;
|
||||
m_highlightedPlane = SketchPlane::NONE;
|
||||
m_currentPlane = SketchPlane::NONE;
|
||||
m_highlightedPlane.reset();
|
||||
m_currentPlane.reset();
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -395,7 +411,7 @@ void ViewportWidget::onSketchModeEnded()
|
||||
void ViewportWidget::onRestoreStateAnimationFinished()
|
||||
{
|
||||
// Return to showing the base XY grid when not in a sketch
|
||||
m_currentPlane = SketchPlane::XY;
|
||||
m_currentPlane = gp_Ax2(gp::Origin(), gp::DZ());
|
||||
update();
|
||||
}
|
||||
|
||||
@@ -467,7 +483,7 @@ void ViewportWidget::onActiveToolChanged(int tool)
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D ViewportWidget::unproject(const QPoint& screenPos, SketchPlane plane)
|
||||
QVector3D ViewportWidget::unproject(const QPoint& screenPos, const gp_Ax2& plane)
|
||||
{
|
||||
QMatrix4x4 model = m_camera->modelViewMatrix();
|
||||
|
||||
@@ -496,17 +512,13 @@ QVector3D ViewportWidget::unproject(const QPoint& screenPos, SketchPlane plane)
|
||||
QVector3D rayOrigin(nearPoint_world);
|
||||
QVector3D rayDir = (QVector3D(farPoint_world) - rayOrigin).normalized();
|
||||
|
||||
QVector3D planeNormal;
|
||||
switch (plane) {
|
||||
case SketchPlane::XY: planeNormal = QVector3D(0, 0, 1); break;
|
||||
case SketchPlane::XZ: planeNormal = QVector3D(0, 1, 0); break;
|
||||
case SketchPlane::YZ: planeNormal = QVector3D(1, 0, 0); break;
|
||||
case SketchPlane::NONE: return QVector3D();
|
||||
}
|
||||
const auto& planeNormalDir = plane.Direction();
|
||||
QVector3D planeNormal(planeNormalDir.X(), planeNormalDir.Y(), planeNormalDir.Z());
|
||||
|
||||
float denom = QVector3D::dotProduct(planeNormal, rayDir);
|
||||
if (qAbs(denom) > 1e-6) {
|
||||
QVector3D p0(0,0,0);
|
||||
const auto& planeOriginPnt = plane.Location();
|
||||
QVector3D p0(planeOriginPnt.X(), planeOriginPnt.Y(), planeOriginPnt.Z());
|
||||
float t = QVector3D::dotProduct(p0 - rayOrigin, planeNormal) / denom;
|
||||
return rayOrigin + t * rayDir;
|
||||
}
|
||||
@@ -702,52 +714,56 @@ void ViewportWidget::drawSelectionPlanes()
|
||||
// XY Plane (Top)
|
||||
QVector<GLfloat> xyQuad = { planeOffset, -planeOffset, 0, planeOffset + planeSize, -planeOffset, 0,
|
||||
planeOffset + planeSize, -planeOffset - planeSize, 0, planeOffset, -planeOffset - planeSize, 0 };
|
||||
drawPlane(xyQuad, m_highlightedPlane == SketchPlane::XY);
|
||||
drawPlane(xyQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DZ(), 1e-9));
|
||||
|
||||
// XZ Plane (Front)
|
||||
QVector<GLfloat> xzQuad = { planeOffset, 0, planeOffset, planeOffset + planeSize, 0, planeOffset,
|
||||
planeOffset + planeSize, 0, planeOffset + planeSize, planeOffset, 0, planeOffset + planeSize };
|
||||
drawPlane(xzQuad, m_highlightedPlane == SketchPlane::XZ);
|
||||
drawPlane(xzQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DY(), 1e-9));
|
||||
|
||||
// YZ Plane (Right)
|
||||
QVector<GLfloat> yzQuad = { 0, -planeOffset, planeOffset, 0, -planeOffset, planeOffset + planeSize,
|
||||
0, -planeOffset - planeSize, planeOffset + planeSize, 0, -planeOffset - planeSize, planeOffset };
|
||||
drawPlane(yzQuad, m_highlightedPlane == SketchPlane::YZ);
|
||||
drawPlane(yzQuad, m_highlightedPlane && m_highlightedPlane->Direction().IsEqual(gp::DX(), 1e-9));
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
ViewportWidget::SketchPlane ViewportWidget::checkPlaneSelection(const QPoint& screenPos)
|
||||
std::optional<gp_Ax2> ViewportWidget::checkPlaneSelection(const QPoint& screenPos)
|
||||
{
|
||||
const float planeSize = 5.0f;
|
||||
const float planeOffset = 1.0f;
|
||||
|
||||
gp_Ax2 yzPlane(gp_Pnt(0, 0, 0), gp::DX());
|
||||
gp_Ax2 xzPlane(gp_Pnt(0, 0, 0), gp::DY());
|
||||
gp_Ax2 xyPlane(gp_Pnt(0, 0, 0), gp::DZ());
|
||||
|
||||
QVector3D intersection;
|
||||
|
||||
// Check front to back to handle overlaps
|
||||
// YZ plane (Right)
|
||||
intersection = unproject(screenPos, SketchPlane::YZ);
|
||||
intersection = unproject(screenPos, yzPlane);
|
||||
if (intersection.y() >= -planeOffset - planeSize && intersection.y() <= -planeOffset &&
|
||||
intersection.z() >= planeOffset && intersection.z() <= planeOffset + planeSize) {
|
||||
return SketchPlane::YZ;
|
||||
return gp_Ax2(gp_Pnt(0, -planeOffset, planeOffset), gp::DX());
|
||||
}
|
||||
|
||||
// XZ plane (Front)
|
||||
intersection = unproject(screenPos, SketchPlane::XZ);
|
||||
intersection = unproject(screenPos, xzPlane);
|
||||
if (intersection.x() >= planeOffset && intersection.x() <= planeOffset + planeSize &&
|
||||
intersection.z() >= planeOffset && intersection.z() <= planeOffset + planeSize) {
|
||||
return SketchPlane::XZ;
|
||||
return gp_Ax2(gp_Pnt(planeOffset, 0, planeOffset), gp::DY());
|
||||
}
|
||||
|
||||
// XY plane (Top)
|
||||
intersection = unproject(screenPos, SketchPlane::XY);
|
||||
intersection = unproject(screenPos, xyPlane);
|
||||
if (intersection.x() >= planeOffset && intersection.x() <= planeOffset + planeSize &&
|
||||
intersection.y() >= -planeOffset - planeSize && intersection.y() <= -planeOffset) {
|
||||
return SketchPlane::XY;
|
||||
return gp_Ax2(gp_Pnt(planeOffset, -planeOffset, 0), gp::DZ());
|
||||
}
|
||||
|
||||
return SketchPlane::NONE;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
|
||||
+9
-14
@@ -15,6 +15,8 @@
|
||||
#include <QVector3D>
|
||||
#include <QRect>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <optional>
|
||||
#include <QMap>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
@@ -35,26 +37,19 @@ class ViewportWidget : public QOpenGLWidget, protected QOpenGLFunctions
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
enum class SketchPlane {
|
||||
NONE,
|
||||
XY,
|
||||
XZ,
|
||||
YZ
|
||||
};
|
||||
|
||||
explicit ViewportWidget(QWidget *parent = nullptr);
|
||||
~ViewportWidget();
|
||||
|
||||
void setDocument(Document* document);
|
||||
|
||||
QVector3D project(const QVector3D& worldCoord, const QMatrix4x4& modelView, const QMatrix4x4& projection, const QRect& viewport);
|
||||
QVector3D unproject(const QPoint& screenPos, SketchPlane plane);
|
||||
QVector3D unproject(const QPoint& screenPos, const gp_Ax2& plane);
|
||||
QOpenGLShaderProgram* shaderProgram() { return m_shaderProgram; }
|
||||
QOpenGLBuffer& vbo() { return m_vbo; }
|
||||
int colorLoc() const { return m_colorLoc; }
|
||||
Camera* camera() const { return m_camera; }
|
||||
Document* document() const { return m_document; }
|
||||
SketchPlane currentPlane() const { return m_currentPlane; }
|
||||
std::optional<gp_Ax2> currentPlane() const { return m_currentPlane; }
|
||||
const QPoint& currentMousePos() const { return m_currentMousePos; }
|
||||
bool isSnappingOrigin() const;
|
||||
bool isSnappingVertex() const;
|
||||
@@ -69,7 +64,7 @@ public:
|
||||
void deactivateActiveTool();
|
||||
|
||||
public slots:
|
||||
void onSketchModeStarted(SketchPlane plane);
|
||||
void onSketchModeStarted(const gp_Ax2& plane);
|
||||
void onSketchModeEnded();
|
||||
void onPlaneSelectionModeStarted();
|
||||
void onActiveToolChanged(int tool);
|
||||
@@ -78,7 +73,7 @@ signals:
|
||||
void lineAdded(const gp_Pnt& start, const gp_Pnt& end);
|
||||
void rectangleAdded(const gp_Pnt& corner1, const gp_Pnt& corner2);
|
||||
void circleAdded(const gp_Pnt& center, double radius);
|
||||
void planeSelected(SketchPlane plane);
|
||||
void planeSelected(const gp_Ax2& plane);
|
||||
void toolDeactivated();
|
||||
|
||||
private slots:
|
||||
@@ -100,7 +95,7 @@ private:
|
||||
void initShaders();
|
||||
void drawSketch(const SketchFeature* sketch);
|
||||
void drawSelectionPlanes();
|
||||
ViewportWidget::SketchPlane checkPlaneSelection(const QPoint& screenPos);
|
||||
std::optional<gp_Ax2> checkPlaneSelection(const QPoint& screenPos);
|
||||
|
||||
QMatrix4x4 projection;
|
||||
QOpenGLShaderProgram* m_shaderProgram = nullptr;
|
||||
@@ -116,10 +111,10 @@ private:
|
||||
SketchGrid* m_sketchGrid = nullptr;
|
||||
FeatureBrowser* m_featureBrowser = nullptr;
|
||||
Document* m_document = nullptr;
|
||||
SketchPlane m_currentPlane = SketchPlane::NONE;
|
||||
std::optional<gp_Ax2> m_currentPlane;
|
||||
|
||||
bool m_isSelectingPlane = false;
|
||||
SketchPlane m_highlightedPlane = SketchPlane::NONE;
|
||||
std::optional<gp_Ax2> m_highlightedPlane;
|
||||
|
||||
int m_activeTool = 0;
|
||||
SketchTool* m_activeSketchTool = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user