Compare commits
19 Commits
f9cac02e06
..
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 4f1a8b22ac | |||
| 1b1d2eab11 | |||
| 6d92349938 | |||
| aa8127c5f8 | |||
| b75e355698 | |||
| 4cebb8d552 | |||
| d7e9d784cc | |||
| f942a424f3 | |||
| e37959ca89 | |||
| 64ff7396c2 | |||
| 79c78f0601 | |||
| 96371b0aa6 | |||
| e363595eb5 | |||
| 228540e095 | |||
| e960c30b48 | |||
| 0469853a2c | |||
| 577fb5f846 | |||
| 08904feb1e | |||
| 125e97df50 |
@@ -13,6 +13,16 @@
|
||||
#include "SketchCircle.h"
|
||||
#include "MainWindow.h"
|
||||
|
||||
#include <BRepBuilderAPI_MakeEdge.hxx>
|
||||
#include <BRepBuilderAPI_MakeWire.hxx>
|
||||
#include <GC_MakeSegment.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Circ.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
|
||||
#include <QInputDialog>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
@@ -117,26 +127,12 @@ void ApplicationController::beginSketchCreation()
|
||||
emit planeSelectionModeStarted();
|
||||
}
|
||||
|
||||
void ApplicationController::onPlaneSelected(ViewportWidget::SketchPlane plane)
|
||||
void ApplicationController::onPlaneSelected(const gp_Ax2& plane)
|
||||
{
|
||||
auto feature = new SketchFeature("Sketch");
|
||||
m_activeSketch = feature;
|
||||
|
||||
switch (plane) {
|
||||
case ViewportWidget::SketchPlane::XY:
|
||||
feature->setPlane(SketchFeature::SketchPlane::XY);
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::XZ:
|
||||
feature->setPlane(SketchFeature::SketchPlane::XZ);
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::YZ:
|
||||
feature->setPlane(SketchFeature::SketchPlane::YZ);
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::NONE:
|
||||
delete feature;
|
||||
m_activeSketch = nullptr;
|
||||
return;
|
||||
}
|
||||
feature->setPlane(plane);
|
||||
|
||||
m_document->addFeature(feature);
|
||||
emit sketchModeStarted(plane);
|
||||
@@ -146,6 +142,10 @@ void ApplicationController::addLine(const gp_Pnt& start, const gp_Pnt& end)
|
||||
{
|
||||
if (m_activeSketch) {
|
||||
m_activeSketch->addObject(new SketchLine(start, end));
|
||||
|
||||
Handle(Geom_TrimmedCurve) segment = GC_MakeSegment(start, end);
|
||||
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(segment);
|
||||
m_activeSketch->addShape(edge);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,6 +153,27 @@ void ApplicationController::addRectangle(const gp_Pnt& corner1, const gp_Pnt& co
|
||||
{
|
||||
if (m_activeSketch) {
|
||||
m_activeSketch->addObject(new SketchRectangle(corner1, corner2));
|
||||
|
||||
const auto& plane = m_activeSketch->plane();
|
||||
|
||||
gp_Pnt2d p1_2d(gp_Vec(plane.Location(), corner1).Dot(plane.XDirection()), gp_Vec(plane.Location(), corner1).Dot(plane.YDirection()));
|
||||
gp_Pnt2d p3_2d(gp_Vec(plane.Location(), corner2).Dot(plane.XDirection()), gp_Vec(plane.Location(), corner2).Dot(plane.YDirection()));
|
||||
|
||||
gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y());
|
||||
gp_Pnt2d p4_2d(p1_2d.X(), p3_2d.Y());
|
||||
|
||||
gp_Pnt p2_3d = ElCLib::To3d(plane, p2_2d);
|
||||
gp_Pnt p4_3d = ElCLib::To3d(plane, p4_2d);
|
||||
|
||||
TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(corner1, p2_3d);
|
||||
TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(p2_3d, corner2);
|
||||
TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(corner2, p4_3d);
|
||||
TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(p4_3d, corner1);
|
||||
|
||||
BRepBuilderAPI_MakeWire wireMaker(e1, e2, e3, e4);
|
||||
if (wireMaker.IsDone()) {
|
||||
m_activeSketch->addShape(wireMaker.Shape());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +181,13 @@ void ApplicationController::addCircle(const gp_Pnt& center, double radius)
|
||||
{
|
||||
if (m_activeSketch) {
|
||||
m_activeSketch->addObject(new SketchCircle(center, radius));
|
||||
|
||||
const auto& sketchPlane = m_activeSketch->plane();
|
||||
gp_Ax2 axis(center, sketchPlane.Direction());
|
||||
|
||||
gp_Circ circle(axis, radius);
|
||||
TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circle);
|
||||
m_activeSketch->addShape(edge);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
#define APPLICATIONCONTROLLER_H
|
||||
|
||||
#include <QObject>
|
||||
#include "ViewportWidget.h" // For SketchPlane enum
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
|
||||
class Document;
|
||||
class MainWindow;
|
||||
@@ -47,12 +47,12 @@ public slots:
|
||||
bool saveDocumentAs();
|
||||
|
||||
void beginSketchCreation();
|
||||
void onPlaneSelected(ViewportWidget::SketchPlane plane);
|
||||
void onPlaneSelected(const gp_Ax2& plane);
|
||||
void endSketch();
|
||||
|
||||
signals:
|
||||
void planeSelectionModeStarted();
|
||||
void sketchModeStarted(ViewportWidget::SketchPlane plane);
|
||||
void sketchModeStarted(const gp_Ax2& plane);
|
||||
void sketchModeEnded();
|
||||
void currentFileChanged(const QString& path);
|
||||
void activeToolChanged(ToolType tool);
|
||||
|
||||
+23
-19
@@ -6,7 +6,8 @@
|
||||
// - use a right-handed, Z-up coordinate system to match Open CASCADE
|
||||
|
||||
#include "Camera.h"
|
||||
#include "ViewportWidget.h"
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
#include <QApplication>
|
||||
#include <QWheelEvent>
|
||||
#include <QPropertyAnimation>
|
||||
@@ -202,25 +203,28 @@ void Camera::restoreState()
|
||||
setZoom(m_savedZoom);
|
||||
}
|
||||
|
||||
void Camera::animateToPlaneView(int plane)
|
||||
void Camera::animateToPlaneView(const gp_Ax2& plane)
|
||||
{
|
||||
float targetXRot = xRotation();
|
||||
float targetYRot = yRotation();
|
||||
switch (static_cast<ViewportWidget::SketchPlane>(plane)) {
|
||||
case ViewportWidget::SketchPlane::XY: // Top view
|
||||
targetXRot = 90 * 16;
|
||||
targetYRot = 0;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::XZ: // Front view
|
||||
targetXRot = 0;
|
||||
targetYRot = 0;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::YZ: // Right view
|
||||
targetXRot = 0;
|
||||
targetYRot = -90 * 16;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::NONE:
|
||||
break;
|
||||
const auto& normal = plane.Direction();
|
||||
QVector3D n(normal.X(), normal.Y(), normal.Z());
|
||||
QVector3D d;
|
||||
|
||||
// This logic preserves the quirky view directions of the original implementation.
|
||||
// For XZ-like planes (normal is mostly along Y), the view is aligned WITH the plane normal.
|
||||
// For other planes, it's aligned AGAINST the normal.
|
||||
if (qAbs(n.y()) > 0.99) {
|
||||
d = n;
|
||||
} else {
|
||||
d = -n;
|
||||
}
|
||||
|
||||
float targetXRot = qRadiansToDegrees(asin(-d.z())) * 16.0f;
|
||||
float targetYRot;
|
||||
|
||||
if (qAbs(d.z()) > 0.9999) { // Top/bottom-like view, Y rotation is arbitrary
|
||||
targetYRot = 0; // Set to 0 for stability
|
||||
} else {
|
||||
targetYRot = qRadiansToDegrees(atan2(d.x(), d.y())) * 16.0f;
|
||||
}
|
||||
|
||||
auto* animGroup = new QParallelAnimationGroup(this);
|
||||
|
||||
+3
-1
@@ -14,6 +14,8 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
|
||||
#include <gp_Ax2.hxx>
|
||||
|
||||
class Camera : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
@@ -46,7 +48,7 @@ public:
|
||||
void saveState();
|
||||
void restoreState();
|
||||
|
||||
void animateToPlaneView(int plane);
|
||||
void animateToPlaneView(const gp_Ax2& plane);
|
||||
void animateRestoreState();
|
||||
void animateToHomeView();
|
||||
|
||||
|
||||
+47
-53
@@ -15,6 +15,10 @@
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <cmath>
|
||||
#include <QtMath>
|
||||
#include <optional>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
|
||||
CircleTool::CircleTool(ViewportWidget* viewport)
|
||||
: SketchTool(viewport)
|
||||
@@ -35,14 +39,18 @@ void CircleTool::activate()
|
||||
|
||||
void CircleTool::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
gp_Pnt p;
|
||||
if (!m_isDefining) {
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
p.SetCoord(0, 0, 0);
|
||||
p = plane.Location();
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
p = m_viewport->snapVertex();
|
||||
} else {
|
||||
QVector3D worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D worldPos = m_viewport->unproject(event->pos(), plane);
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
}
|
||||
m_centerPoint = p;
|
||||
@@ -70,24 +78,22 @@ void CircleTool::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (diameterFromInput) {
|
||||
QVector3D mousePos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D mousePos = m_viewport->unproject(event->pos(), plane);
|
||||
QVector3D mouseDir = mousePos - centerPos;
|
||||
if (mouseDir.lengthSquared() < 1e-9) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
mouseDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
mouseDir = QVector3D(0, 1, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
mouseDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
double radius = inputDiameter / 2.0;
|
||||
worldPos = centerPos + mouseDir.normalized() * radius;
|
||||
} else {
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
worldPos.setX(origin.X()); worldPos.setY(origin.Y()); worldPos.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos = QVector3D(m_viewport->snapVertex().X(), m_viewport->snapVertex().Y(), m_viewport->snapVertex().Z());
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
worldPos = m_viewport->unproject(event->pos(), plane);
|
||||
}
|
||||
}
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
@@ -103,6 +109,10 @@ void CircleTool::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void CircleTool::finalizeCreation()
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPos;
|
||||
QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z());
|
||||
|
||||
@@ -117,19 +127,16 @@ void CircleTool::finalizeCreation()
|
||||
}
|
||||
|
||||
if (diameterFromInput) {
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseDir = mousePos - centerPos;
|
||||
if (mouseDir.lengthSquared() < 1e-9) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
mouseDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
mouseDir = QVector3D(0, 1, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
mouseDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
double radius = inputDiameter / 2.0;
|
||||
worldPos = centerPos + mouseDir.normalized() * radius;
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
}
|
||||
|
||||
gp_Pnt p;
|
||||
@@ -141,7 +148,10 @@ void CircleTool::finalizeCreation()
|
||||
|
||||
void CircleTool::paintGL()
|
||||
{
|
||||
if (m_isDefining) {
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!m_isDefining || !currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector<GLfloat> vertices;
|
||||
QVector3D worldPos;
|
||||
QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z());
|
||||
@@ -156,7 +166,7 @@ void CircleTool::paintGL()
|
||||
if (ok) diameterFromInput = true;
|
||||
}
|
||||
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
|
||||
double radius;
|
||||
if (diameterFromInput) {
|
||||
@@ -164,7 +174,8 @@ void CircleTool::paintGL()
|
||||
} else {
|
||||
worldPos = mousePos;
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
worldPos.setX(origin.X()); worldPos.setY(origin.Y()); worldPos.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z());
|
||||
}
|
||||
@@ -172,34 +183,18 @@ void CircleTool::paintGL()
|
||||
}
|
||||
|
||||
const int segments = 64;
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D u_axis(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D v_axis(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
for (int i = 0; i < segments; ++i) {
|
||||
double angle1 = i * 2.0 * M_PI / segments;
|
||||
double angle2 = (i + 1) * 2.0 * M_PI / segments;
|
||||
|
||||
QVector3D p1, p2;
|
||||
QVector3D p1 = centerPos + radius * (qCos(angle1) * u_axis + qSin(angle1) * v_axis);
|
||||
QVector3D p2 = centerPos + radius * (qCos(angle2) * u_axis + qSin(angle2) * v_axis);
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
p1.setX(centerPos.x() + radius * qCos(angle1));
|
||||
p1.setY(centerPos.y() + radius * qSin(angle1));
|
||||
p1.setZ(centerPos.z());
|
||||
p2.setX(centerPos.x() + radius * qCos(angle2));
|
||||
p2.setY(centerPos.y() + radius * qSin(angle2));
|
||||
p2.setZ(centerPos.z());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
p1.setX(centerPos.x() + radius * qCos(angle1));
|
||||
p1.setY(centerPos.y());
|
||||
p1.setZ(centerPos.z() + radius * qSin(angle1));
|
||||
p2.setX(centerPos.x() + radius * qCos(angle2));
|
||||
p2.setY(centerPos.y());
|
||||
p2.setZ(centerPos.z() + radius * qSin(angle2));
|
||||
} else { // YZ
|
||||
p1.setX(centerPos.x());
|
||||
p1.setY(centerPos.y() + radius * qCos(angle1));
|
||||
p1.setZ(centerPos.z() + radius * qSin(angle1));
|
||||
p2.setX(centerPos.x());
|
||||
p2.setY(centerPos.y() + radius * qCos(angle2));
|
||||
p2.setZ(centerPos.z() + radius * qSin(angle2));
|
||||
}
|
||||
vertices << p1.x() << p1.y() << p1.z();
|
||||
vertices << p2.x() << p2.y() << p2.z();
|
||||
}
|
||||
@@ -208,12 +203,14 @@ void CircleTool::paintGL()
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, segments * 2);
|
||||
}
|
||||
}
|
||||
|
||||
void CircleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
{
|
||||
if (m_isDefining) {
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!m_isDefining || !currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPos;
|
||||
QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z());
|
||||
|
||||
@@ -227,7 +224,7 @@ void CircleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const Q
|
||||
if (ok) diameterFromInput = true;
|
||||
}
|
||||
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D edgePos;
|
||||
double diameter;
|
||||
|
||||
@@ -235,17 +232,15 @@ void CircleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const Q
|
||||
diameter = inputDiameter;
|
||||
QVector3D mouseDir = mousePos - centerPos;
|
||||
if (mouseDir.lengthSquared() < 1e-9) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
mouseDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
mouseDir = QVector3D(0, 1, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
mouseDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
edgePos = centerPos + mouseDir.normalized() * (diameter / 2.0);
|
||||
} else {
|
||||
edgePos = mousePos;
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
edgePos.setX(0); edgePos.setY(0); edgePos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
edgePos.setX(origin.X()); edgePos.setY(origin.Y()); edgePos.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
edgePos.setX(m_viewport->snapVertex().X()); edgePos.setY(m_viewport->snapVertex().Y()); edgePos.setZ(m_viewport->snapVertex().Z());
|
||||
}
|
||||
@@ -270,5 +265,4 @@ void CircleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const Q
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(textRect, Qt::AlignCenter, diameterText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+240
-235
@@ -13,6 +13,13 @@
|
||||
#include <QPainter>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QtMath>
|
||||
#include <optional>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Dir2d.hxx>
|
||||
#include <gp_Vec2d.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
|
||||
LineTool::LineTool(ViewportWidget* viewport)
|
||||
: SketchTool(viewport)
|
||||
@@ -34,6 +41,10 @@ void LineTool::activate()
|
||||
|
||||
void LineTool::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
gp_Pnt p;
|
||||
QString dimInput = m_viewport->property("dimensionInput").toString();
|
||||
QString angleInput = m_viewport->property("angleInput").toString();
|
||||
@@ -64,19 +75,23 @@ void LineTool::mousePressEvent(QMouseEvent *event)
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 1, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(event->pos(), plane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPos.x(), currentMouseWorldPos.y(), currentMouseWorldPos.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngle = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
double relativeMouseAngle = mouseAngle - refAngle;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0;
|
||||
@@ -91,10 +106,9 @@ void LineTool::mousePressEvent(QMouseEvent *event)
|
||||
snappedAngle = -inputAngleDegrees;
|
||||
}
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir2d finalDir2d(cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir finalDir3d = ElCLib::To3d(plane, finalDir2d);
|
||||
QVector3D finalDir(finalDir3d.X(), finalDir3d.Y(), finalDir3d.Z());
|
||||
double lineLength;
|
||||
if (lengthFromInput) lineLength = inputLength;
|
||||
else {
|
||||
@@ -103,34 +117,37 @@ void LineTool::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
worldPos = startPos + lineLength * finalDir;
|
||||
} else if (lengthFromInput) {
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(event->pos(), plane);
|
||||
QVector3D dir = (currentMouseWorldPos - startPos);
|
||||
if (dir.length() > 1e-6) {
|
||||
dir.normalize();
|
||||
worldPos = startPos + inputLength * dir;
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0);
|
||||
else worldPos = startPos + QVector3D(0, inputLength, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
worldPos = startPos + inputLength * QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
}
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
} else {
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
p.SetCoord(0, 0, 0);
|
||||
p = plane.Location();
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
p = m_viewport->snapVertex();
|
||||
} else {
|
||||
QVector3D worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D worldPosQ = m_viewport->unproject(event->pos(), plane);
|
||||
gp_Pnt worldPos(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
|
||||
if (m_viewport->isSnappingHorizontal() || m_viewport->isSnappingVertical()) {
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPos).Dot(plane.YDirection()));
|
||||
gp_Pnt2d firstPoint2d(gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.XDirection()), gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.YDirection()));
|
||||
if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setY(m_firstLinePoint.Y());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
} else if (m_viewport->isSnappingVertical()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y());
|
||||
worldPos2d.SetY(firstPoint2d.Y());
|
||||
} else { // vertical
|
||||
worldPos2d.SetX(firstPoint2d.X());
|
||||
}
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
worldPos = ElCLib::To3d(plane, worldPos2d);
|
||||
}
|
||||
p = worldPos;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -157,27 +174,27 @@ void LineTool::mousePressEvent(QMouseEvent *event)
|
||||
|
||||
void LineTool::mouseMoveEvent(QMouseEvent *event)
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!m_isDefining || !currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
bool oldIsSnappingHorizontal = m_viewport->isSnappingHorizontal();
|
||||
bool oldIsSnappingVertical = m_viewport->isSnappingVertical();
|
||||
m_viewport->setSnappingHorizontal(false);
|
||||
m_viewport->setSnappingVertical(false);
|
||||
|
||||
if (m_isDefining && !m_viewport->isSnappingOrigin() && !m_viewport->isSnappingVertex()) {
|
||||
QVector3D worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QVector3D delta = worldPos - startPos;
|
||||
QVector3D worldPosQ = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt worldPos(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
gp_Pnt startPos = m_firstLinePoint;
|
||||
|
||||
if (delta.length() > 1e-6) {
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPos).Dot(plane.YDirection()));
|
||||
gp_Pnt2d startPos2d(gp_Vec(plane.Location(), startPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPos).Dot(plane.YDirection()));
|
||||
gp_Vec2d delta(startPos2d, worldPos2d);
|
||||
|
||||
if (delta.Magnitude() > 1e-6) {
|
||||
const double snapAngleThreshold = qDegreesToRadians(2.0);
|
||||
double angle = 0;
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
angle = atan2(delta.y(), delta.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
angle = atan2(delta.z(), delta.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
angle = atan2(delta.z(), delta.y());
|
||||
}
|
||||
double angle = atan2(delta.Y(), delta.X());
|
||||
|
||||
if (qAbs(sin(angle)) < sin(snapAngleThreshold)) {
|
||||
m_viewport->setSnappingHorizontal(true);
|
||||
@@ -194,6 +211,10 @@ void LineTool::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void LineTool::finalizeCreation()
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
// This is duplicated from paintGL to ensure consistent line creation
|
||||
@@ -220,19 +241,23 @@ void LineTool::finalizeCreation()
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 1, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPos.x(), currentMouseWorldPos.y(), currentMouseWorldPos.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngle = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
double relativeMouseAngle = mouseAngle - refAngle;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0;
|
||||
@@ -247,10 +272,9 @@ void LineTool::finalizeCreation()
|
||||
snappedAngle = -inputAngleDegrees;
|
||||
}
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir2d finalDir2d(cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir finalDir3d = ElCLib::To3d(plane, finalDir2d);
|
||||
QVector3D finalDir(finalDir3d.X(), finalDir3d.Y(), finalDir3d.Z());
|
||||
double lineLength;
|
||||
if (lengthFromInput) lineLength = inputLength;
|
||||
else {
|
||||
@@ -259,17 +283,17 @@ void LineTool::finalizeCreation()
|
||||
}
|
||||
worldPos = startPos + lineLength * finalDir;
|
||||
} else if (lengthFromInput) {
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D dir = (currentMouseWorldPos - startPos);
|
||||
if (dir.length() > 1e-6) {
|
||||
dir.normalize();
|
||||
worldPos = startPos + inputLength * dir;
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0);
|
||||
else worldPos = startPos + QVector3D(0, inputLength, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
worldPos = startPos + inputLength * QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
}
|
||||
|
||||
gp_Pnt p;
|
||||
@@ -289,6 +313,10 @@ void LineTool::finalizeCreation()
|
||||
void LineTool::paintGL()
|
||||
{
|
||||
if (m_isDefining) {
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector<GLfloat> vertices;
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
@@ -316,26 +344,24 @@ void LineTool::paintGL()
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
refDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
refDir = QVector3D(0, 1, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
// Quadrant snapping
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPos.x(), currentMouseWorldPos.y(), currentMouseWorldPos.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngle = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
|
||||
double relativeMouseAngle = mouseAngle - refAngle;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
@@ -353,10 +379,9 @@ void LineTool::paintGL()
|
||||
}
|
||||
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir2d finalDir2d(cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir finalDir3d = ElCLib::To3d(plane, finalDir2d);
|
||||
QVector3D finalDir(finalDir3d.X(), finalDir3d.Y(), finalDir3d.Z());
|
||||
|
||||
double lineLength;
|
||||
if (lengthFromInput) {
|
||||
@@ -368,33 +393,34 @@ void LineTool::paintGL()
|
||||
worldPos = startPos + lineLength * finalDir;
|
||||
|
||||
} else if (lengthFromInput) {
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D dir = (currentMouseWorldPos - startPos);
|
||||
if (dir.length() > 1e-6) {
|
||||
dir.normalize();
|
||||
worldPos = startPos + inputLength * dir;
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos = startPos + QVector3D(inputLength, 0, 0);
|
||||
} else {
|
||||
worldPos = startPos + QVector3D(0, inputLength, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
worldPos = startPos + inputLength * QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt worldPosPnt(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
worldPosPnt = plane.Location();
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z());
|
||||
} else if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setY(m_firstLinePoint.Y());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
} else if (m_viewport->isSnappingVertical()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y());
|
||||
worldPosPnt = m_viewport->snapVertex();
|
||||
} else if (m_viewport->isSnappingHorizontal() || m_viewport->isSnappingVertical()) {
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPosPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPosPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d firstPoint2d(gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.XDirection()), gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.YDirection()));
|
||||
if (m_viewport->isSnappingHorizontal()) {
|
||||
worldPos2d.SetY(firstPoint2d.Y());
|
||||
} else { // vertical
|
||||
worldPos2d.SetX(firstPoint2d.X());
|
||||
}
|
||||
worldPosPnt = ElCLib::To3d(plane, worldPos2d);
|
||||
}
|
||||
worldPos.setX(worldPosPnt.X()); worldPos.setY(worldPosPnt.Y()); worldPos.setZ(worldPosPnt.Z());
|
||||
}
|
||||
|
||||
vertices << m_firstLinePoint.X() << m_firstLinePoint.Y() << m_firstLinePoint.Z();
|
||||
@@ -416,23 +442,25 @@ void LineTool::paintGL()
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 1, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
|
||||
if (angleFromInput) {
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPos.x(), currentMouseWorldPos.y(), currentMouseWorldPos.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
double refAngleForQuadrant;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngleForQuadrant = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
|
||||
double relativeMouseAngle = mouseAngle - refAngleForQuadrant;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
@@ -447,16 +475,14 @@ void LineTool::paintGL()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
refAngle = atan2(refDir.y(), refDir.x());
|
||||
lineAngle = atan2(lineVec.y(), lineVec.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
refAngle = atan2(refDir.z(), refDir.x());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.x());
|
||||
} else { // YZ
|
||||
refAngle = atan2(refDir.z(), refDir.y());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.y());
|
||||
}
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
gp_Dir lineDirGp(lineVec.x(), lineVec.y(), lineVec.z());
|
||||
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
gp_Dir2d lineDir2d(lineDirGp.Dot(plane.XDirection()), lineDirGp.Dot(plane.YDirection()));
|
||||
|
||||
refAngle = atan2(refDir2d.Y(), refDir2d.X());
|
||||
lineAngle = atan2(lineDir2d.Y(), lineDir2d.X());
|
||||
|
||||
angleDiff = lineAngle - refAngle;
|
||||
while (angleDiff <= -M_PI) angleDiff += 2 * M_PI;
|
||||
@@ -466,14 +492,11 @@ void LineTool::paintGL()
|
||||
|
||||
vertices.clear();
|
||||
|
||||
QVector3D perpVec;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized();
|
||||
}
|
||||
gp_Dir lineDirGp(lineVec.x(), lineVec.y(), lineVec.z());
|
||||
gp_Dir2d lineDir2d(lineDirGp.Dot(plane.XDirection()), lineDirGp.Dot(plane.YDirection()));
|
||||
gp_Dir2d perpDir2d(-lineDir2d.Y(), lineDir2d.X());
|
||||
gp_Dir perpDir3d = ElCLib::To3d(plane, perpDir2d);
|
||||
QVector3D perpVec(perpDir3d.X(), perpDir3d.Y(), perpDir3d.Z());
|
||||
|
||||
if (angleDiff < 0) {
|
||||
perpVec = -perpVec;
|
||||
@@ -520,9 +543,11 @@ void LineTool::paintGL()
|
||||
for (int i = 0; i <= numSegments; ++i) {
|
||||
double angle = refAngle + (lineAngle - refAngle) * i / numSegments;
|
||||
QVector3D p;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) p = startPos + radius * QVector3D(cos(angle), sin(angle), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) p = startPos + radius * QVector3D(cos(angle), 0, sin(angle));
|
||||
else p = startPos + radius * QVector3D(0, cos(angle), sin(angle));
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D u_axis(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D v_axis(yDir.X(), yDir.Y(), yDir.Z());
|
||||
p = startPos + radius * (cos(angle) * u_axis + sin(angle) * v_axis);
|
||||
vertices << p.x() << p.y() << p.z();
|
||||
}
|
||||
glLineWidth(1.0f);
|
||||
@@ -540,17 +565,13 @@ void LineTool::paintGL()
|
||||
// End arrowhead
|
||||
QVector3D endPoint(vertices[vertices.size()-3], vertices[vertices.size()-2], vertices[vertices.size()-1]);
|
||||
double endAngle = lineAngle;
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D u_axis(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D v_axis(yDir.X(), yDir.Y(), yDir.Z());
|
||||
QVector3D radialDir_end, tangentDir_end;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
radialDir_end = QVector3D(cos(endAngle), sin(endAngle), 0);
|
||||
tangentDir_end = QVector3D(-sin(endAngle), cos(endAngle), 0);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
radialDir_end = QVector3D(cos(endAngle), 0, sin(endAngle));
|
||||
tangentDir_end = QVector3D(-sin(endAngle), 0, cos(endAngle));
|
||||
} else {
|
||||
radialDir_end = QVector3D(0, cos(endAngle), sin(endAngle));
|
||||
tangentDir_end = QVector3D(0, -sin(endAngle), cos(endAngle));
|
||||
}
|
||||
radialDir_end = cos(endAngle) * u_axis + sin(endAngle) * v_axis;
|
||||
tangentDir_end = -sin(endAngle) * u_axis + cos(endAngle) * v_axis;
|
||||
QVector3D arc_arrow_base_end = endPoint - sign * arcArrowLength * tangentDir_end;
|
||||
QVector3D arc_arrowP1_end = arc_arrow_base_end + arcArrowWidth * radialDir_end;
|
||||
QVector3D arc_arrowP2_end = arc_arrow_base_end - arcArrowWidth * radialDir_end;
|
||||
@@ -561,16 +582,8 @@ void LineTool::paintGL()
|
||||
QVector3D startPoint(vertices[0], vertices[1], vertices[2]);
|
||||
double startAngle = refAngle;
|
||||
QVector3D radialDir_start, tangentDir_start;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
radialDir_start = QVector3D(cos(startAngle), sin(startAngle), 0);
|
||||
tangentDir_start = QVector3D(-sin(startAngle), cos(startAngle), 0);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
radialDir_start = QVector3D(cos(startAngle), 0, sin(startAngle));
|
||||
tangentDir_start = QVector3D(-sin(startAngle), 0, cos(startAngle));
|
||||
} else {
|
||||
radialDir_start = QVector3D(0, cos(startAngle), sin(startAngle));
|
||||
tangentDir_start = QVector3D(0, -sin(startAngle), cos(startAngle));
|
||||
}
|
||||
radialDir_start = cos(startAngle) * u_axis + sin(startAngle) * v_axis;
|
||||
tangentDir_start = -sin(startAngle) * u_axis + cos(startAngle) * v_axis;
|
||||
QVector3D arc_arrow_base_start = startPoint + sign * arcArrowLength * tangentDir_start;
|
||||
QVector3D arc_arrowP1_start = arc_arrow_base_start + arcArrowWidth * radialDir_start;
|
||||
QVector3D arc_arrowP2_start = arc_arrow_base_start - arcArrowWidth * radialDir_start;
|
||||
@@ -589,29 +602,21 @@ void LineTool::paintGL()
|
||||
QVector3D midPoint = (startPos + worldPos) / 2.0;
|
||||
const float indicatorSize = 0.02f * -m_viewport->camera()->zoom();
|
||||
const float indicatorOffset = 0.02f * -m_viewport->camera()->zoom();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D u_axis(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D v_axis(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
QVector3D p1, p2;
|
||||
if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
vertices << midPoint.x() - indicatorSize << midPoint.y() + indicatorOffset << midPoint.z();
|
||||
vertices << midPoint.x() + indicatorSize << midPoint.y() + indicatorOffset << midPoint.z();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
vertices << midPoint.x() - indicatorSize << midPoint.y() << midPoint.z() + indicatorOffset;
|
||||
vertices << midPoint.x() + indicatorSize << midPoint.y() << midPoint.z() + indicatorOffset;
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() - indicatorSize << midPoint.z() + indicatorOffset;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorSize << midPoint.z() + indicatorOffset;
|
||||
}
|
||||
p1 = midPoint - indicatorSize * v_axis + indicatorOffset * u_axis;
|
||||
p2 = midPoint + indicatorSize * v_axis + indicatorOffset * u_axis;
|
||||
} else { // m_isSnappingVertical
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() - indicatorSize << midPoint.z();
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() + indicatorSize << midPoint.z();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() << midPoint.z() - indicatorSize;
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() << midPoint.z() + indicatorSize;
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() - indicatorSize;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() + indicatorSize;
|
||||
}
|
||||
p1 = midPoint - indicatorSize * u_axis + indicatorOffset * v_axis;
|
||||
p2 = midPoint + indicatorSize * u_axis + indicatorOffset * v_axis;
|
||||
}
|
||||
vertices << p1.x() << p1.y() << p1.z();
|
||||
vertices << p2.x() << p2.y() << p2.z();
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
@@ -622,6 +627,10 @@ void LineTool::paintGL()
|
||||
void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
{
|
||||
if (m_isDefining) {
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QString dimText;
|
||||
@@ -651,25 +660,24 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
refDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
refDir = QVector3D(0, 1, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPos.x(), currentMouseWorldPos.y(), currentMouseWorldPos.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngle = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
|
||||
double relativeMouseAngle = mouseAngle - refAngle;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
@@ -687,10 +695,9 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
}
|
||||
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir2d finalDir2d(cos(finalAngleRad), sin(finalAngleRad));
|
||||
gp_Dir finalDir3d = ElCLib::To3d(plane, finalDir2d);
|
||||
QVector3D finalDir(finalDir3d.X(), finalDir3d.Y(), finalDir3d.Z());
|
||||
|
||||
if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
@@ -702,33 +709,34 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
|
||||
} else if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D dir = (currentMouseWorldPos - startPos);
|
||||
if (dir.length() > 1e-6) {
|
||||
dir.normalize();
|
||||
worldPos = startPos + inputLength * dir;
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos = startPos + QVector3D(inputLength, 0, 0);
|
||||
} else {
|
||||
worldPos = startPos + QVector3D(0, inputLength, 0);
|
||||
}
|
||||
const auto& xDir = plane.XDirection();
|
||||
worldPos = startPos + inputLength * QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt worldPosPnt(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
worldPosPnt = plane.Location();
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z());
|
||||
} else if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setY(m_firstLinePoint.Y());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z());
|
||||
} else if (m_viewport->isSnappingVertical()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y());
|
||||
worldPosPnt = m_viewport->snapVertex();
|
||||
} else if (m_viewport->isSnappingHorizontal() || m_viewport->isSnappingVertical()) {
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPosPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPosPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d firstPoint2d(gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.XDirection()), gp_Vec(plane.Location(), m_firstLinePoint).Dot(plane.YDirection()));
|
||||
if (m_viewport->isSnappingHorizontal()) {
|
||||
worldPos2d.SetY(firstPoint2d.Y());
|
||||
} else { // vertical
|
||||
worldPos2d.SetX(firstPoint2d.X());
|
||||
}
|
||||
worldPosPnt = ElCLib::To3d(plane, worldPos2d);
|
||||
}
|
||||
worldPos.setX(worldPosPnt.X()); worldPos.setY(worldPosPnt.Y()); worldPos.setZ(worldPosPnt.Z());
|
||||
lineLength = (worldPos - startPos).length();
|
||||
}
|
||||
|
||||
@@ -739,24 +747,26 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
if (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = m_viewport->property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY || m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 1, 0);
|
||||
const auto& xDir = plane.XDirection();
|
||||
refDir = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPosForText = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D currentMouseWorldPosForText = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
QVector3D mouseVecForText = currentMouseWorldPosForText - startPos;
|
||||
|
||||
if (angleFromInput) {
|
||||
if (mouseVecForText.length() > 1e-6) {
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.y(), mouseVecForText.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.y()));
|
||||
gp_Pnt startPnt(startPos.x(), startPos.y(), startPos.z());
|
||||
gp_Pnt mousePnt(currentMouseWorldPosForText.x(), currentMouseWorldPosForText.y(), currentMouseWorldPosForText.z());
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
|
||||
double refAngleForQuadrant;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.y(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.y()));
|
||||
gp_Pnt2d startPnt2d(gp_Vec(plane.Location(), startPnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPnt).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePnt2d(gp_Vec(plane.Location(), mousePnt).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePnt).Dot(plane.YDirection()));
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
|
||||
gp_Vec2d mouseVec2d(startPnt2d, mousePnt2d);
|
||||
double mouseAngle = qRadiansToDegrees(atan2(mouseVec2d.Y(), mouseVec2d.X()));
|
||||
double refAngleForQuadrant = qRadiansToDegrees(atan2(refDir2d.Y(), refDir2d.X()));
|
||||
|
||||
double relativeMouseAngle = mouseAngle - refAngleForQuadrant;
|
||||
while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0;
|
||||
@@ -772,30 +782,23 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
refAngle = atan2(refDir.y(), refDir.x());
|
||||
lineAngle = atan2(lineVec.y(), lineVec.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
refAngle = atan2(refDir.z(), refDir.x());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.x());
|
||||
} else { // YZ
|
||||
refAngle = atan2(refDir.z(), refDir.y());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.y());
|
||||
}
|
||||
gp_Dir refDirGp(refDir.x(), refDir.y(), refDir.z());
|
||||
gp_Dir lineDirGp(lineVec.x(), lineVec.y(), lineVec.z());
|
||||
|
||||
gp_Dir2d refDir2d(refDirGp.Dot(plane.XDirection()), refDirGp.Dot(plane.YDirection()));
|
||||
gp_Dir2d lineDir2d(lineDirGp.Dot(plane.XDirection()), lineDirGp.Dot(plane.YDirection()));
|
||||
|
||||
refAngle = atan2(refDir2d.Y(), refDir2d.X());
|
||||
lineAngle = atan2(lineDir2d.Y(), lineDir2d.X());
|
||||
|
||||
double angleDiff = lineAngle - refAngle;
|
||||
while (angleDiff <= -M_PI) angleDiff += 2 * M_PI;
|
||||
while (angleDiff > M_PI) angleDiff -= 2 * M_PI;
|
||||
lineAngle = refAngle + angleDiff;
|
||||
|
||||
QVector3D perpVec;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized();
|
||||
}
|
||||
gp_Dir2d perpDir2d(-lineDir2d.Y(), lineDir2d.X());
|
||||
gp_Dir perpDir3d = ElCLib::To3d(plane, perpDir2d);
|
||||
QVector3D perpVec(perpDir3d.X(), perpDir3d.Y(), perpDir3d.Z());
|
||||
|
||||
if (angleDiff < 0) {
|
||||
perpVec = -perpVec;
|
||||
@@ -838,9 +841,11 @@ void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMa
|
||||
QVector3D textPos3DAngle;
|
||||
float textOffset = 0.035f * -m_viewport->camera()->zoom();
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), sin(midAngle), 0);
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), 0, sin(midAngle));
|
||||
else textPos3DAngle = startPos + (radius + textOffset) * QVector3D(0, cos(midAngle), sin(midAngle));
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D u_axis(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D v_axis(yDir.X(), yDir.Y(), yDir.Z());
|
||||
textPos3DAngle = startPos + (radius + textOffset) * (cos(midAngle) * u_axis + sin(midAngle) * v_axis);
|
||||
|
||||
QVector3D screenPosAngle = m_viewport->project(textPos3DAngle, modelView, projection, m_viewport->rect());
|
||||
if (screenPosAngle.z() < 1.0f) {
|
||||
|
||||
+142
-178
@@ -15,6 +15,11 @@
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <cmath>
|
||||
#include <QtMath>
|
||||
#include <optional>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
|
||||
RectangleTool::RectangleTool(ViewportWidget* viewport)
|
||||
: SketchTool(viewport)
|
||||
@@ -35,14 +40,18 @@ void RectangleTool::activate()
|
||||
|
||||
void RectangleTool::mousePressEvent(QMouseEvent *event)
|
||||
{
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
gp_Pnt p;
|
||||
if (!m_isDefining) {
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
p.SetCoord(0, 0, 0);
|
||||
p = plane.Location();
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
p = m_viewport->snapVertex();
|
||||
} else {
|
||||
QVector3D worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D worldPos = m_viewport->unproject(event->pos(), plane);
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
}
|
||||
m_firstRectanglePoint = p;
|
||||
@@ -51,8 +60,8 @@ void RectangleTool::mousePressEvent(QMouseEvent *event)
|
||||
m_viewport->setProperty("heightInput", "");
|
||||
m_viewport->setProperty("dimensionEditMode", "height");
|
||||
} else {
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
QVector3D worldPosQ;
|
||||
gp_Pnt startPos = m_firstRectanglePoint;
|
||||
|
||||
QString widthInput = m_viewport->property("widthInput").toString();
|
||||
QString heightInput = m_viewport->property("heightInput").toString();
|
||||
@@ -71,45 +80,35 @@ void RectangleTool::mousePressEvent(QMouseEvent *event)
|
||||
}
|
||||
|
||||
if (widthFromInput || heightFromInput) {
|
||||
QVector3D mousePos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
QVector3D mouseDir = mousePos - startPos;
|
||||
double current_w, current_h;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.y());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
} else { // YZ
|
||||
current_w = qAbs(mouseDir.y());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
}
|
||||
QVector3D mousePosQ = m_viewport->unproject(event->pos(), plane);
|
||||
gp_Pnt mousePos(mousePosQ.x(), mousePosQ.y(), mousePosQ.z());
|
||||
|
||||
gp_Pnt2d startPos2d(gp_Vec(plane.Location(), startPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPos).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePos2d(gp_Vec(plane.Location(), mousePos).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePos).Dot(plane.YDirection()));
|
||||
|
||||
double current_w = qAbs(mousePos2d.X() - startPos2d.X());
|
||||
double current_h = qAbs(mousePos2d.Y() - startPos2d.Y());
|
||||
|
||||
double rect_w = widthFromInput ? inputWidth : current_w;
|
||||
double rect_h = heightFromInput ? inputHeight : current_h;
|
||||
int signX = (mouseDir.x() >= 0) ? 1 : -1;
|
||||
int signY = (mouseDir.y() >= 0) ? 1 : -1;
|
||||
int signZ = (mouseDir.z() >= 0) ? 1 : -1;
|
||||
worldPos = startPos;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setY(startPos.y() + signY * rect_h);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
} else { // YZ
|
||||
worldPos.setY(startPos.y() + signY * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
}
|
||||
|
||||
int signX = (mousePos2d.X() >= startPos2d.X()) ? 1 : -1;
|
||||
int signY = (mousePos2d.Y() >= startPos2d.Y()) ? 1 : -1;
|
||||
|
||||
gp_Pnt2d endPos2d(startPos2d.X() + signX * rect_w, startPos2d.Y() + signY * rect_h);
|
||||
gp_Pnt endPos3d = ElCLib::To3d(plane, endPos2d);
|
||||
worldPosQ = QVector3D(endPos3d.X(), endPos3d.Y(), endPos3d.Z());
|
||||
} else {
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
worldPosQ.setX(origin.X()); worldPosQ.setY(origin.Y()); worldPosQ.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos = QVector3D(m_viewport->snapVertex().X(), m_viewport->snapVertex().Y(), m_viewport->snapVertex().Z());
|
||||
worldPosQ = QVector3D(m_viewport->snapVertex().X(), m_viewport->snapVertex().Y(), m_viewport->snapVertex().Z());
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane());
|
||||
worldPosQ = m_viewport->unproject(event->pos(), plane);
|
||||
}
|
||||
}
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
p.SetCoord(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
emit m_viewport->rectangleAdded(m_firstRectanglePoint, p);
|
||||
deactivate();
|
||||
}
|
||||
@@ -122,8 +121,12 @@ void RectangleTool::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void RectangleTool::finalizeCreation()
|
||||
{
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPosQ;
|
||||
gp_Pnt startPos = m_firstRectanglePoint;
|
||||
|
||||
QString widthInput = m_viewport->property("widthInput").toString();
|
||||
QString heightInput = m_viewport->property("heightInput").toString();
|
||||
@@ -142,41 +145,30 @@ void RectangleTool::finalizeCreation()
|
||||
}
|
||||
|
||||
if (widthFromInput || heightFromInput) {
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mouseDir = mousePos - startPos;
|
||||
double current_w, current_h;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.y());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
} else { // YZ
|
||||
current_w = qAbs(mouseDir.y());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
}
|
||||
QVector3D mousePosQ = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt mousePos(mousePosQ.x(), mousePosQ.y(), mousePosQ.z());
|
||||
|
||||
gp_Pnt2d startPos2d(gp_Vec(plane.Location(), startPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPos).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePos2d(gp_Vec(plane.Location(), mousePos).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePos).Dot(plane.YDirection()));
|
||||
|
||||
double current_w = qAbs(mousePos2d.X() - startPos2d.X());
|
||||
double current_h = qAbs(mousePos2d.Y() - startPos2d.Y());
|
||||
|
||||
double rect_w = widthFromInput ? inputWidth : current_w;
|
||||
double rect_h = heightFromInput ? inputHeight : current_h;
|
||||
int signX = (mouseDir.x() >= 0) ? 1 : -1;
|
||||
int signY = (mouseDir.y() >= 0) ? 1 : -1;
|
||||
int signZ = (mouseDir.z() >= 0) ? 1 : -1;
|
||||
worldPos = startPos;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setY(startPos.y() + signY * rect_h);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
} else { // YZ
|
||||
worldPos.setY(startPos.y() + signY * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
}
|
||||
|
||||
int signX = (mousePos2d.X() >= startPos2d.X()) ? 1 : -1;
|
||||
int signY = (mousePos2d.Y() >= startPos2d.Y()) ? 1 : -1;
|
||||
|
||||
gp_Pnt2d endPos2d(startPos2d.X() + signX * rect_w, startPos2d.Y() + signY * rect_h);
|
||||
gp_Pnt endPos3d = ElCLib::To3d(plane, endPos2d);
|
||||
worldPosQ = QVector3D(endPos3d.X(), endPos3d.Y(), endPos3d.Z());
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
worldPosQ = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
}
|
||||
|
||||
gp_Pnt p;
|
||||
p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z());
|
||||
p.SetCoord(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
|
||||
emit m_viewport->rectangleAdded(m_firstRectanglePoint, p);
|
||||
deactivate();
|
||||
@@ -184,10 +176,14 @@ void RectangleTool::finalizeCreation()
|
||||
|
||||
void RectangleTool::paintGL()
|
||||
{
|
||||
if (m_isDefining) {
|
||||
if (!m_isDefining) return;
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector<GLfloat> vertices;
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
QVector3D worldPosQ;
|
||||
gp_Pnt startPos = m_firstRectanglePoint;
|
||||
|
||||
QString widthInput = m_viewport->property("widthInput").toString();
|
||||
QString heightInput = m_viewport->property("heightInput").toString();
|
||||
@@ -206,82 +202,70 @@ void RectangleTool::paintGL()
|
||||
if (ok) heightFromInput = true;
|
||||
}
|
||||
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mousePosQ = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt mousePos(mousePosQ.x(), mousePosQ.y(), mousePosQ.z());
|
||||
|
||||
if (widthFromInput || heightFromInput) {
|
||||
QVector3D mouseDir = mousePos - startPos;
|
||||
double current_w, current_h;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.y());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
} else { // YZ
|
||||
current_w = qAbs(mouseDir.y());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
}
|
||||
gp_Pnt2d startPos2d(gp_Vec(plane.Location(), startPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), startPos).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePos2d(gp_Vec(plane.Location(), mousePos).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePos).Dot(plane.YDirection()));
|
||||
|
||||
double current_w = qAbs(mousePos2d.X() - startPos2d.X());
|
||||
double current_h = qAbs(mousePos2d.Y() - startPos2d.Y());
|
||||
|
||||
double rect_w = widthFromInput ? inputWidth : current_w;
|
||||
double rect_h = heightFromInput ? inputHeight : current_h;
|
||||
int signX = (mouseDir.x() >= 0) ? 1 : -1;
|
||||
int signY = (mouseDir.y() >= 0) ? 1 : -1;
|
||||
int signZ = (mouseDir.z() >= 0) ? 1 : -1;
|
||||
worldPos = startPos;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setY(startPos.y() + signY * rect_h);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos.setX(startPos.x() + signX * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
} else { // YZ
|
||||
worldPos.setY(startPos.y() + signY * rect_w);
|
||||
worldPos.setZ(startPos.z() + signZ * rect_h);
|
||||
}
|
||||
|
||||
int signX = (mousePos2d.X() >= startPos2d.X()) ? 1 : -1;
|
||||
int signY = (mousePos2d.Y() >= startPos2d.Y()) ? 1 : -1;
|
||||
|
||||
gp_Pnt2d endPos2d(startPos2d.X() + signX * rect_w, startPos2d.Y() + signY * rect_h);
|
||||
gp_Pnt endPos3d = ElCLib::To3d(plane, endPos2d);
|
||||
worldPosQ = QVector3D(endPos3d.X(), endPos3d.Y(), endPos3d.Z());
|
||||
} else {
|
||||
worldPos = mousePos;
|
||||
worldPosQ = mousePosQ;
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
worldPosQ.setX(origin.X()); worldPosQ.setY(origin.Y()); worldPosQ.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z());
|
||||
worldPosQ.setX(m_viewport->snapVertex().X()); worldPosQ.setY(m_viewport->snapVertex().Y()); worldPosQ.setZ(m_viewport->snapVertex().Z());
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D p1 = startPos;
|
||||
QVector3D p2, p3, p4;
|
||||
p3 = worldPos;
|
||||
gp_Pnt p1_3d = startPos;
|
||||
gp_Pnt p3_3d(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
gp_Pnt2d p1_2d(gp_Vec(plane.Location(), p1_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p1_3d).Dot(plane.YDirection()));
|
||||
gp_Pnt2d p3_2d(gp_Vec(plane.Location(), p3_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p3_3d).Dot(plane.YDirection()));
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
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_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
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_viewport->currentPlane() == ViewportWidget::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());
|
||||
}
|
||||
gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y());
|
||||
gp_Pnt2d p4_2d(p1_2d.X(), p3_2d.Y());
|
||||
|
||||
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();
|
||||
gp_Pnt p2_3d = ElCLib::To3d(plane, p2_2d);
|
||||
gp_Pnt p4_3d = ElCLib::To3d(plane, p4_2d);
|
||||
|
||||
vertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z();
|
||||
vertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z();
|
||||
vertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z();
|
||||
vertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z();
|
||||
vertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z();
|
||||
vertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z();
|
||||
vertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z();
|
||||
vertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z();
|
||||
|
||||
m_viewport->shaderProgram()->setUniformValue(m_viewport->colorLoc(), QVector4D(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 8);
|
||||
}
|
||||
}
|
||||
|
||||
void RectangleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
{
|
||||
if (m_isDefining) {
|
||||
QVector3D worldPos;
|
||||
QVector3D p1_3d(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z());
|
||||
if (!m_isDefining) return;
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) return;
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
|
||||
QVector3D worldPosQ;
|
||||
gp_Pnt p1_3d = m_firstRectanglePoint;
|
||||
|
||||
QString widthInput = m_viewport->property("widthInput").toString();
|
||||
QString heightInput = m_viewport->property("heightInput").toString();
|
||||
@@ -300,77 +284,58 @@ void RectangleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, cons
|
||||
if (ok) heightFromInput = true;
|
||||
}
|
||||
|
||||
QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mousePosQ = m_viewport->unproject(m_viewport->currentMousePos(), plane);
|
||||
gp_Pnt mousePos(mousePosQ.x(), mousePosQ.y(), mousePosQ.z());
|
||||
|
||||
if (widthFromInput || heightFromInput) {
|
||||
QVector3D mouseDir = mousePos - p1_3d;
|
||||
double current_w, current_h;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.y());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
current_w = qAbs(mouseDir.x());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
} else { // YZ
|
||||
current_w = qAbs(mouseDir.y());
|
||||
current_h = qAbs(mouseDir.z());
|
||||
}
|
||||
gp_Pnt2d startPos2d(gp_Vec(plane.Location(), p1_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p1_3d).Dot(plane.YDirection()));
|
||||
gp_Pnt2d mousePos2d(gp_Vec(plane.Location(), mousePos).Dot(plane.XDirection()), gp_Vec(plane.Location(), mousePos).Dot(plane.YDirection()));
|
||||
|
||||
double current_w = qAbs(mousePos2d.X() - startPos2d.X());
|
||||
double current_h = qAbs(mousePos2d.Y() - startPos2d.Y());
|
||||
|
||||
double rect_w = widthFromInput ? inputWidth : current_w;
|
||||
double rect_h = heightFromInput ? inputHeight : current_h;
|
||||
int signX = (mouseDir.x() >= 0) ? 1 : -1;
|
||||
int signY = (mouseDir.y() >= 0) ? 1 : -1;
|
||||
int signZ = (mouseDir.z() >= 0) ? 1 : -1;
|
||||
worldPos = p1_3d;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
worldPos.setX(p1_3d.x() + signX * rect_w);
|
||||
worldPos.setY(p1_3d.y() + signY * rect_h);
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
worldPos.setX(p1_3d.x() + signX * rect_w);
|
||||
worldPos.setZ(p1_3d.z() + signZ * rect_h);
|
||||
} else { // YZ
|
||||
worldPos.setY(p1_3d.y() + signY * rect_w);
|
||||
worldPos.setZ(p1_3d.z() + signZ * rect_h);
|
||||
}
|
||||
int signX = (mousePos2d.X() >= startPos2d.X()) ? 1 : -1;
|
||||
int signY = (mousePos2d.Y() >= startPos2d.Y()) ? 1 : -1;
|
||||
|
||||
gp_Pnt2d endPos2d(startPos2d.X() + signX * rect_w, startPos2d.Y() + signY * rect_h);
|
||||
gp_Pnt endPos3d = ElCLib::To3d(plane, endPos2d);
|
||||
worldPosQ = QVector3D(endPos3d.X(), endPos3d.Y(), endPos3d.Z());
|
||||
} else {
|
||||
worldPos = mousePos;
|
||||
worldPosQ = mousePosQ;
|
||||
if (m_viewport->isSnappingOrigin()) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
const auto& origin = plane.Location();
|
||||
worldPosQ.setX(origin.X()); worldPosQ.setY(origin.Y()); worldPosQ.setZ(origin.Z());
|
||||
} else if (m_viewport->isSnappingVertex()) {
|
||||
worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z());
|
||||
worldPosQ.setX(m_viewport->snapVertex().X()); worldPosQ.setY(m_viewport->snapVertex().Y()); worldPosQ.setZ(m_viewport->snapVertex().Z());
|
||||
}
|
||||
}
|
||||
QVector3D p3_3d = worldPos;
|
||||
QVector3D p2_3d, p4_3d;
|
||||
gp_Pnt p3_3d(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
gp_Pnt p2_3d, p4_3d;
|
||||
|
||||
double w, h;
|
||||
gp_Pnt2d p1_2d(gp_Vec(plane.Location(), p1_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p1_3d).Dot(plane.YDirection()));
|
||||
gp_Pnt2d p3_2d(gp_Vec(plane.Location(), p3_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p3_3d).Dot(plane.YDirection()));
|
||||
gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y());
|
||||
p2_3d = ElCLib::To3d(plane, p2_2d);
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::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(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 if (m_viewport->currentPlane() == ViewportWidget::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(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 { // 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());
|
||||
}
|
||||
double w = qAbs(p3_2d.X() - p1_2d.X());
|
||||
double h = qAbs(p3_2d.Y() - p1_2d.Y());
|
||||
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
QFontMetrics fm(painter.font());
|
||||
|
||||
QVector3D p1_q(p1_3d.X(), p1_3d.Y(), p1_3d.Z());
|
||||
QVector3D p2_q(p2_3d.X(), p2_3d.Y(), p2_3d.Z());
|
||||
QVector3D p3_q(p3_3d.X(), p3_3d.Y(), p3_3d.Z());
|
||||
|
||||
// Width dimension
|
||||
QVector3D widthTextPos3D = (p1_3d + p2_3d) / 2.0f;
|
||||
QVector3D widthTextPos3D = (p1_q + p2_q) / 2.0f;
|
||||
QVector3D screenPosW = m_viewport->project(widthTextPos3D, modelView, projection, m_viewport->rect());
|
||||
if (screenPosW.z() < 1.0f) {
|
||||
QString widthText = widthFromInput ? widthInput : 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));
|
||||
textRect.moveCenter(screenPosW.toPoint() + QPoint(0, (p3_2d.Y() > p1_2d.Y()) ? -15 : 15));
|
||||
if (m_viewport->property("dimensionEditMode").toString() == "width") {
|
||||
painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255));
|
||||
} else {
|
||||
@@ -381,12 +346,12 @@ void RectangleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, cons
|
||||
}
|
||||
|
||||
// Height dimension
|
||||
QVector3D heightTextPos3D = (p2_3d + p3_3d) / 2.0f;
|
||||
QVector3D heightTextPos3D = (p2_q + p3_q) / 2.0f;
|
||||
QVector3D screenPosH = m_viewport->project(heightTextPos3D, modelView, projection, m_viewport->rect());
|
||||
if (screenPosH.z() < 1.0f) {
|
||||
QString heightText = heightFromInput ? heightInput : QString::number(h, 'f', 2);
|
||||
QRect textRect = fm.boundingRect(heightText + "__");
|
||||
textRect.moveCenter(screenPosH.toPoint() + QPoint((p3_3d.x() > p1_3d.x()) ? 15 : -15, 0));
|
||||
textRect.moveCenter(screenPosH.toPoint() + QPoint((p3_2d.X() > p1_2d.X()) ? 15 : -15, 0));
|
||||
if (m_viewport->property("dimensionEditMode").toString() == "height") {
|
||||
painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255));
|
||||
} else {
|
||||
@@ -395,5 +360,4 @@ void RectangleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, cons
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(textRect, Qt::AlignCenter, heightText);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+66
-15
@@ -10,11 +10,44 @@
|
||||
#include "SketchLine.h"
|
||||
#include "SketchRectangle.h"
|
||||
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <gp_Pnt.hxx>
|
||||
#include <gp_Dir.hxx>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
namespace
|
||||
{
|
||||
void gpPntToJson(const gp_Pnt& p, QJsonObject& json) {
|
||||
json["x"] = p.X();
|
||||
json["y"] = p.Y();
|
||||
json["z"] = p.Z();
|
||||
}
|
||||
|
||||
gp_Pnt jsonToGpPnt(const QJsonObject& json) {
|
||||
return gp_Pnt(json["x"].toDouble(), json["y"].toDouble(), json["z"].toDouble());
|
||||
}
|
||||
|
||||
void gpDirToJson(const gp_Dir& d, QJsonObject& json) {
|
||||
json["x"] = d.X();
|
||||
json["y"] = d.Y();
|
||||
json["z"] = d.Z();
|
||||
}
|
||||
|
||||
gp_Dir jsonToGpDir(const QJsonObject& json) {
|
||||
return gp_Dir(json["x"].toDouble(), json["y"].toDouble(), json["z"].toDouble());
|
||||
}
|
||||
}
|
||||
|
||||
SketchFeature::SketchFeature(const QString& name)
|
||||
: Feature(name)
|
||||
: Feature(name), m_plane(gp_Pnt(0, 0, 0), gp::DZ())
|
||||
{
|
||||
BRep_Builder builder;
|
||||
TopoDS_Compound compound;
|
||||
builder.MakeCompound(compound);
|
||||
m_shape = compound;
|
||||
}
|
||||
|
||||
SketchFeature::~SketchFeature()
|
||||
@@ -27,12 +60,12 @@ QString SketchFeature::type() const
|
||||
return "Sketch";
|
||||
}
|
||||
|
||||
void SketchFeature::setPlane(SketchPlane plane)
|
||||
void SketchFeature::setPlane(const gp_Ax2& plane)
|
||||
{
|
||||
m_plane = plane;
|
||||
}
|
||||
|
||||
SketchFeature::SketchPlane SketchFeature::plane() const
|
||||
const gp_Ax2& SketchFeature::plane() const
|
||||
{
|
||||
return m_plane;
|
||||
}
|
||||
@@ -42,6 +75,12 @@ const TopoDS_Shape& SketchFeature::shape() const
|
||||
return m_shape;
|
||||
}
|
||||
|
||||
void SketchFeature::addShape(const TopoDS_Shape& shape)
|
||||
{
|
||||
BRep_Builder builder;
|
||||
builder.Add(m_shape, shape);
|
||||
}
|
||||
|
||||
void SketchFeature::addObject(SketchObject* object)
|
||||
{
|
||||
m_objects.append(object);
|
||||
@@ -55,11 +94,14 @@ const QList<SketchObject*>& SketchFeature::objects() const
|
||||
void SketchFeature::read(const QJsonObject& json)
|
||||
{
|
||||
Feature::read(json);
|
||||
if (json.contains("plane") && json["plane"].isString()) {
|
||||
QString planeStr = json["plane"].toString();
|
||||
if (planeStr == "XY") m_plane = SketchPlane::XY;
|
||||
else if (planeStr == "XZ") m_plane = SketchPlane::XZ;
|
||||
else if (planeStr == "YZ") m_plane = SketchPlane::YZ;
|
||||
if (json.contains("plane") && json["plane"].isObject()) {
|
||||
QJsonObject planeJson = json["plane"].toObject();
|
||||
if (planeJson.contains("origin") && planeJson.contains("normal") && planeJson.contains("x_direction")) {
|
||||
gp_Pnt origin = jsonToGpPnt(planeJson["origin"].toObject());
|
||||
gp_Dir normal = jsonToGpDir(planeJson["normal"].toObject());
|
||||
gp_Dir x_dir = jsonToGpDir(planeJson["x_direction"].toObject());
|
||||
m_plane = gp_Ax2(origin, normal, x_dir);
|
||||
}
|
||||
}
|
||||
|
||||
if (json.contains("objects") && json["objects"].isArray()) {
|
||||
@@ -87,13 +129,22 @@ void SketchFeature::read(const QJsonObject& json)
|
||||
void SketchFeature::write(QJsonObject& json) const
|
||||
{
|
||||
Feature::write(json);
|
||||
QString planeStr;
|
||||
switch (m_plane) {
|
||||
case SketchPlane::XY: planeStr = "XY"; break;
|
||||
case SketchPlane::XZ: planeStr = "XZ"; break;
|
||||
case SketchPlane::YZ: planeStr = "YZ"; break;
|
||||
}
|
||||
json["plane"] = planeStr;
|
||||
|
||||
QJsonObject planeJson;
|
||||
|
||||
QJsonObject originJson;
|
||||
gpPntToJson(m_plane.Location(), originJson);
|
||||
planeJson["origin"] = originJson;
|
||||
|
||||
QJsonObject normalJson;
|
||||
gpDirToJson(m_plane.Direction(), normalJson);
|
||||
planeJson["normal"] = normalJson;
|
||||
|
||||
QJsonObject xDirJson;
|
||||
gpDirToJson(m_plane.XDirection(), xDirJson);
|
||||
planeJson["x_direction"] = xDirJson;
|
||||
|
||||
json["plane"] = planeJson;
|
||||
|
||||
QJsonArray objectsArray;
|
||||
for (const auto& object : m_objects) {
|
||||
|
||||
+5
-9
@@ -9,6 +9,7 @@
|
||||
#define SKETCHFEATURE_H
|
||||
|
||||
#include <TopoDS_Shape.hxx>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <QList>
|
||||
#include "Feature.h"
|
||||
|
||||
@@ -17,21 +18,16 @@ class SketchObject;
|
||||
class SketchFeature : public Feature
|
||||
{
|
||||
public:
|
||||
enum class SketchPlane {
|
||||
XY,
|
||||
XZ,
|
||||
YZ
|
||||
};
|
||||
|
||||
SketchFeature(const QString& name);
|
||||
~SketchFeature();
|
||||
|
||||
QString type() const override;
|
||||
|
||||
void setPlane(SketchPlane plane);
|
||||
SketchPlane plane() const;
|
||||
void setPlane(const gp_Ax2& plane);
|
||||
const gp_Ax2& plane() const;
|
||||
|
||||
const TopoDS_Shape& shape() const;
|
||||
void addShape(const TopoDS_Shape& shape);
|
||||
|
||||
void addObject(SketchObject* object);
|
||||
const QList<SketchObject*>& objects() const;
|
||||
@@ -40,7 +36,7 @@ public:
|
||||
void write(QJsonObject &json) const override;
|
||||
|
||||
private:
|
||||
SketchPlane m_plane;
|
||||
gp_Ax2 m_plane;
|
||||
TopoDS_Shape m_shape;
|
||||
QList<SketchObject*> m_objects;
|
||||
};
|
||||
|
||||
+47
-42
@@ -13,6 +13,7 @@
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QPainter>
|
||||
#include <QVector>
|
||||
#include <gp_Ax2.hxx>
|
||||
|
||||
namespace {
|
||||
struct GridParams {
|
||||
@@ -62,7 +63,7 @@ void SketchGrid::initializeGL()
|
||||
m_vbo.release();
|
||||
}
|
||||
|
||||
void SketchGrid::paintGL(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
void SketchGrid::paintGL(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
{
|
||||
GLint previous_vao = 0;
|
||||
glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &previous_vao);
|
||||
@@ -77,12 +78,19 @@ void SketchGrid::paintGL(SketchPlane plane, QOpenGLShaderProgram* shaderProgram,
|
||||
QOpenGLContext::currentContext()->extraFunctions()->glBindVertexArray(previous_vao);
|
||||
}
|
||||
|
||||
void SketchGrid::drawGridLines(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
void SketchGrid::drawGridLines(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
{
|
||||
auto params = getGridParams(-m_viewport->camera()->uiCameraDistance());
|
||||
const float minorIncrement = params.minorIncrement;
|
||||
const int gridSize = params.gridSize;
|
||||
|
||||
const auto& origin = plane.Location();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D originVec(origin.X(), origin.Y(), origin.Z());
|
||||
QVector3D xDirVec(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D yDirVec(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
QVector<GLfloat> minorLines;
|
||||
QVector<GLfloat> majorLines;
|
||||
|
||||
@@ -93,16 +101,14 @@ void SketchGrid::drawGridLines(SketchPlane plane, QOpenGLShaderProgram* shaderPr
|
||||
|
||||
float pos = i * minorIncrement;
|
||||
QVector<GLfloat>& current_vector = (i % 5 == 0) ? majorLines : minorLines;
|
||||
if (plane == XY) {
|
||||
current_vector << pos << -gridSize << 0 << pos << gridSize << 0;
|
||||
current_vector << -gridSize << pos << 0 << gridSize << pos << 0;
|
||||
} else if (plane == XZ) {
|
||||
current_vector << pos << 0 << -gridSize << pos << 0 << gridSize;
|
||||
current_vector << -gridSize << 0 << pos << gridSize << 0 << pos;
|
||||
} else { // YZ
|
||||
current_vector << 0 << pos << -gridSize << 0 << pos << gridSize;
|
||||
current_vector << 0 << -gridSize << pos << 0 << gridSize << pos;
|
||||
}
|
||||
|
||||
QVector3D p1 = originVec + pos * xDirVec - gridSize * yDirVec;
|
||||
QVector3D p2 = originVec + pos * xDirVec + gridSize * yDirVec;
|
||||
current_vector << p1.x() << p1.y() << p1.z() << p2.x() << p2.y() << p2.z();
|
||||
|
||||
QVector3D p3 = originVec - gridSize * xDirVec + pos * yDirVec;
|
||||
QVector3D p4 = originVec + gridSize * xDirVec + pos * yDirVec;
|
||||
current_vector << p3.x() << p3.y() << p3.z() << p4.x() << p4.y() << p4.z();
|
||||
}
|
||||
|
||||
m_vbo.bind();
|
||||
@@ -120,50 +126,51 @@ void SketchGrid::drawGridLines(SketchPlane plane, QOpenGLShaderProgram* shaderPr
|
||||
glDrawArrays(GL_LINES, 0, majorLines.size() / 3);
|
||||
}
|
||||
|
||||
void SketchGrid::drawAxes(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
void SketchGrid::drawAxes(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc)
|
||||
{
|
||||
auto params = getGridParams(-m_viewport->camera()->uiCameraDistance());
|
||||
const int axisLength = params.gridSize;
|
||||
|
||||
const auto& origin = plane.Location();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D originVec(origin.X(), origin.Y(), origin.Z());
|
||||
QVector3D xDirVec(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D yDirVec(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
QVector<GLfloat> vertices;
|
||||
|
||||
glLineWidth(2.0f);
|
||||
m_vbo.bind();
|
||||
|
||||
// X Axis (Red)
|
||||
if (plane == XY || plane == XZ) {
|
||||
vertices.clear();
|
||||
vertices << -axisLength << 0 << 0 << axisLength << 0 << 0;
|
||||
QVector3D p1 = originVec - axisLength * xDirVec;
|
||||
QVector3D p2 = originVec + axisLength * xDirVec;
|
||||
vertices << p1.x() << p1.y() << p1.z() << p2.x() << p2.y() << p2.z();
|
||||
shaderProgram->setUniformValue(colorLoc, QVector4D(1.0f, 0.0f, 0.0f, 1.0f));
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
}
|
||||
|
||||
// Y Axis (Green)
|
||||
if (plane == XY || plane == YZ) {
|
||||
vertices.clear();
|
||||
vertices << 0 << -axisLength << 0 << 0 << axisLength << 0;
|
||||
QVector3D p3 = originVec - axisLength * yDirVec;
|
||||
QVector3D p4 = originVec + axisLength * yDirVec;
|
||||
vertices << p3.x() << p3.y() << p3.z() << p4.x() << p4.y() << p4.z();
|
||||
shaderProgram->setUniformValue(colorLoc, QVector4D(0.0f, 1.0f, 0.0f, 1.0f));
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
}
|
||||
// Z Axis (Blue)
|
||||
if (plane == XZ || plane == YZ) {
|
||||
vertices.clear();
|
||||
vertices << 0 << 0 << -axisLength << 0 << 0 << axisLength;
|
||||
shaderProgram->setUniformValue(colorLoc, QVector4D(0.0f, 0.0f, 1.0f, 1.0f));
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
}
|
||||
|
||||
// Origin dot
|
||||
glPointSize(5.0f);
|
||||
vertices.clear();
|
||||
vertices << 0.0f << 0.0f << 0.0f;
|
||||
vertices << originVec.x() << originVec.y() << originVec.z();
|
||||
shaderProgram->setUniformValue(colorLoc, QVector4D(1.0f, 1.0f, 1.0f, 1.0f)); // White
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
}
|
||||
|
||||
void SketchGrid::paintAxisLabels(QPainter& painter, SketchGrid::SketchPlane plane, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
void SketchGrid::paintAxisLabels(QPainter& painter, const gp_Ax2& plane, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
{
|
||||
painter.setPen(Qt::white);
|
||||
painter.setFont(QFont("Arial", 10));
|
||||
@@ -172,15 +179,21 @@ void SketchGrid::paintAxisLabels(QPainter& painter, SketchGrid::SketchPlane plan
|
||||
const float majorIncrement = params.majorIncrement;
|
||||
const int range = params.gridSize;
|
||||
|
||||
auto drawLabelsForAxis = [&](int axis_idx) {
|
||||
const auto& origin = plane.Location();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D originVec(origin.X(), origin.Y(), origin.Z());
|
||||
QVector3D xDirVec(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D yDirVec(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
auto drawLabelsForAxis = [&](const QVector3D& axisDir) {
|
||||
int numLabels = range / majorIncrement;
|
||||
for (int i = -numLabels; i <= numLabels; ++i) {
|
||||
if (i == 0)
|
||||
continue;
|
||||
|
||||
float val = i * majorIncrement;
|
||||
QVector3D worldCoord;
|
||||
worldCoord[axis_idx] = val;
|
||||
QVector3D worldCoord = originVec + val * axisDir;
|
||||
|
||||
QVector3D screenPos = m_viewport->project(worldCoord, modelView, projection, m_viewport->rect());
|
||||
if (screenPos.z() < 1.0f) { // Not clipped
|
||||
@@ -189,14 +202,6 @@ void SketchGrid::paintAxisLabels(QPainter& painter, SketchGrid::SketchPlane plan
|
||||
}
|
||||
};
|
||||
|
||||
if (plane == SketchGrid::XY) {
|
||||
drawLabelsForAxis(0); // X
|
||||
drawLabelsForAxis(1); // Y
|
||||
} else if (plane == SketchGrid::XZ) {
|
||||
drawLabelsForAxis(0); // X
|
||||
drawLabelsForAxis(2); // Z
|
||||
} else if (plane == SketchGrid::YZ) {
|
||||
drawLabelsForAxis(1); // Y
|
||||
drawLabelsForAxis(2); // Z
|
||||
}
|
||||
drawLabelsForAxis(xDirVec);
|
||||
drawLabelsForAxis(yDirVec);
|
||||
}
|
||||
|
||||
+5
-10
@@ -12,6 +12,7 @@
|
||||
#include <QMatrix4x4>
|
||||
#include <QOpenGLVertexArrayObject>
|
||||
#include <QOpenGLBuffer>
|
||||
#include <gp_Ax2.hxx>
|
||||
|
||||
class QOpenGLShaderProgram;
|
||||
class QPainter;
|
||||
@@ -20,22 +21,16 @@ class ViewportWidget;
|
||||
class SketchGrid : protected QOpenGLFunctions
|
||||
{
|
||||
public:
|
||||
enum SketchPlane {
|
||||
XY = 1,
|
||||
XZ = 2,
|
||||
YZ = 3
|
||||
};
|
||||
|
||||
explicit SketchGrid(ViewportWidget* viewport);
|
||||
~SketchGrid();
|
||||
|
||||
void initializeGL();
|
||||
void paintGL(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
void paintAxisLabels(QPainter& painter, SketchPlane plane, const QMatrix4x4& modelView, const QMatrix4x4& projection);
|
||||
void paintGL(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
void paintAxisLabels(QPainter& painter, const gp_Ax2& plane, const QMatrix4x4& modelView, const QMatrix4x4& projection);
|
||||
|
||||
private:
|
||||
void drawGridLines(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
void drawAxes(SketchPlane plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
void drawGridLines(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
void drawAxes(const gp_Ax2& plane, QOpenGLShaderProgram* shaderProgram, int colorLoc);
|
||||
|
||||
QOpenGLVertexArrayObject m_vao;
|
||||
QOpenGLBuffer m_vbo;
|
||||
|
||||
+62
-90
@@ -19,6 +19,11 @@
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QVector>
|
||||
#include <QtMath>
|
||||
#include <optional>
|
||||
#include <gp_Ax2.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#include <ElCLib.hxx>
|
||||
|
||||
Snapping::Snapping(ViewportWidget* viewport) : m_viewport(viewport)
|
||||
{
|
||||
@@ -30,23 +35,15 @@ bool Snapping::update(const QPoint& mousePos)
|
||||
bool oldIsSnappingVertex = m_isSnappingVertex;
|
||||
|
||||
bool shouldSnap = false;
|
||||
if (m_viewport->currentPlane() != ViewportWidget::SketchPlane::NONE && m_viewport->activeTool() != static_cast<int>(ApplicationController::ToolType::None)) {
|
||||
QVector3D worldPos = m_viewport->unproject(mousePos, m_viewport->currentPlane());
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (currentPlaneOpt && m_viewport->activeTool() != static_cast<int>(ApplicationController::ToolType::None)) {
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
QVector3D worldPosQ = m_viewport->unproject(mousePos, plane);
|
||||
gp_Pnt worldPos(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
const float snapRectHalfSize = 0.0075f * -m_viewport->camera()->zoom();
|
||||
|
||||
switch (m_viewport->currentPlane()) {
|
||||
case ViewportWidget::SketchPlane::XY:
|
||||
shouldSnap = qAbs(worldPos.x()) < snapRectHalfSize && qAbs(worldPos.y()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::XZ:
|
||||
shouldSnap = qAbs(worldPos.x()) < snapRectHalfSize && qAbs(worldPos.z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::YZ:
|
||||
shouldSnap = qAbs(worldPos.y()) < snapRectHalfSize && qAbs(worldPos.z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::NONE:
|
||||
break;
|
||||
}
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPos).Dot(plane.YDirection()));
|
||||
shouldSnap = qAbs(worldPos2d.X()) < snapRectHalfSize && qAbs(worldPos2d.Y()) < snapRectHalfSize;
|
||||
}
|
||||
|
||||
m_isSnappingOrigin = shouldSnap;
|
||||
@@ -55,8 +52,11 @@ bool Snapping::update(const QPoint& mousePos)
|
||||
}
|
||||
|
||||
m_isSnappingVertex = false;
|
||||
if (!m_isSnappingOrigin && m_viewport->document() && m_viewport->currentPlane() != ViewportWidget::SketchPlane::NONE && m_viewport->activeTool() != static_cast<int>(ApplicationController::ToolType::None)) {
|
||||
QVector3D worldPos = m_viewport->unproject(mousePos, m_viewport->currentPlane());
|
||||
if (!m_isSnappingOrigin && m_viewport->document() && currentPlaneOpt && m_viewport->activeTool() != static_cast<int>(ApplicationController::ToolType::None)) {
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
QVector3D worldPosQ = m_viewport->unproject(mousePos, plane);
|
||||
gp_Pnt worldPos(worldPosQ.x(), worldPosQ.y(), worldPosQ.z());
|
||||
gp_Pnt2d worldPos2d(gp_Vec(plane.Location(), worldPos).Dot(plane.XDirection()), gp_Vec(plane.Location(), worldPos).Dot(plane.YDirection()));
|
||||
const float snapRectHalfSize = 0.0075f * -m_viewport->camera()->zoom();
|
||||
|
||||
for (Feature* feature : m_viewport->document()->features()) {
|
||||
@@ -66,20 +66,8 @@ bool Snapping::update(const QPoint& mousePos)
|
||||
auto line = static_cast<const SketchLine*>(obj);
|
||||
const gp_Pnt vertices[] = {line->startPoint(), line->endPoint()};
|
||||
for (const auto& vertex : vertices) {
|
||||
bool isClose = false;
|
||||
switch (m_viewport->currentPlane()) {
|
||||
case ViewportWidget::SketchPlane::XY:
|
||||
isClose = qAbs(worldPos.x() - vertex.X()) < snapRectHalfSize && qAbs(worldPos.y() - vertex.Y()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::XZ:
|
||||
isClose = qAbs(worldPos.x() - vertex.X()) < snapRectHalfSize && qAbs(worldPos.z() - vertex.Z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::YZ:
|
||||
isClose = qAbs(worldPos.y() - vertex.Y()) < snapRectHalfSize && qAbs(worldPos.z() - vertex.Z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::NONE:
|
||||
break;
|
||||
}
|
||||
gp_Pnt2d vertex2d(gp_Vec(plane.Location(), vertex).Dot(plane.XDirection()), gp_Vec(plane.Location(), vertex).Dot(plane.YDirection()));
|
||||
bool isClose = qAbs(worldPos2d.X() - vertex2d.X()) < snapRectHalfSize && qAbs(worldPos2d.Y() - vertex2d.Y()) < snapRectHalfSize;
|
||||
|
||||
if (isClose) {
|
||||
m_isSnappingVertex = true;
|
||||
@@ -89,37 +77,23 @@ bool Snapping::update(const QPoint& mousePos)
|
||||
}
|
||||
} else if (obj->type() == SketchObject::ObjectType::Rectangle) {
|
||||
auto rect = static_cast<const SketchRectangle*>(obj);
|
||||
const auto& rectPlane = sketch->plane();
|
||||
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(), p3.Y(), p1.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::XZ) {
|
||||
p2.SetCoord(p3.X(), p1.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::YZ) {
|
||||
p2.SetCoord(p1.X(), p3.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
}
|
||||
gp_Pnt2d p1_2d(gp_Vec(rectPlane.Location(), p1).Dot(rectPlane.XDirection()), gp_Vec(rectPlane.Location(), p1).Dot(rectPlane.YDirection()));
|
||||
gp_Pnt2d p3_2d(gp_Vec(rectPlane.Location(), p3).Dot(rectPlane.XDirection()), gp_Vec(rectPlane.Location(), p3).Dot(rectPlane.YDirection()));
|
||||
|
||||
gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y());
|
||||
gp_Pnt2d p4_2d(p1_2d.X(), p3_2d.Y());
|
||||
|
||||
gp_Pnt p2 = ElCLib::To3d(rectPlane, p2_2d);
|
||||
gp_Pnt p4 = ElCLib::To3d(rectPlane, p4_2d);
|
||||
|
||||
const gp_Pnt vertices[] = {p1, p2, p3, p4};
|
||||
for (const auto& vertex : vertices) {
|
||||
bool isClose = false;
|
||||
switch (m_viewport->currentPlane()) {
|
||||
case ViewportWidget::SketchPlane::XY:
|
||||
isClose = qAbs(worldPos.x() - vertex.X()) < snapRectHalfSize && qAbs(worldPos.y() - vertex.Y()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::XZ:
|
||||
isClose = qAbs(worldPos.x() - vertex.X()) < snapRectHalfSize && qAbs(worldPos.z() - vertex.Z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::YZ:
|
||||
isClose = qAbs(worldPos.y() - vertex.Y()) < snapRectHalfSize && qAbs(worldPos.z() - vertex.Z()) < snapRectHalfSize;
|
||||
break;
|
||||
case ViewportWidget::SketchPlane::NONE:
|
||||
break;
|
||||
}
|
||||
gp_Pnt2d vertex2d(gp_Vec(plane.Location(), vertex).Dot(plane.XDirection()), gp_Vec(plane.Location(), vertex).Dot(plane.YDirection()));
|
||||
bool isClose = qAbs(worldPos2d.X() - vertex2d.X()) < snapRectHalfSize && qAbs(worldPos2d.Y() - vertex2d.Y()) < snapRectHalfSize;
|
||||
|
||||
if (isClose) {
|
||||
m_isSnappingVertex = true;
|
||||
@@ -144,43 +118,41 @@ void Snapping::paintGL() const
|
||||
}
|
||||
|
||||
QVector<GLfloat> vertices;
|
||||
auto currentPlaneOpt = m_viewport->currentPlane();
|
||||
if (!currentPlaneOpt) {
|
||||
return;
|
||||
}
|
||||
const auto& plane = currentPlaneOpt.value();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
QVector3D X(xDir.X(), xDir.Y(), xDir.Z());
|
||||
QVector3D Y(yDir.X(), yDir.Y(), yDir.Z());
|
||||
const float rectSize = 0.0075f * -m_viewport->camera()->zoom();
|
||||
|
||||
if (m_isSnappingOrigin) {
|
||||
const float rectSize = 0.0075f * -m_viewport->camera()->zoom();
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
vertices << -rectSize << -rectSize << 0 << rectSize << -rectSize << 0;
|
||||
vertices << rectSize << -rectSize << 0 << rectSize << rectSize << 0;
|
||||
vertices << rectSize << rectSize << 0 << -rectSize << rectSize << 0;
|
||||
vertices << -rectSize << rectSize << 0 << -rectSize << -rectSize << 0;
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
vertices << -rectSize << 0 << -rectSize << rectSize << 0 << -rectSize;
|
||||
vertices << rectSize << 0 << -rectSize << rectSize << 0 << rectSize;
|
||||
vertices << rectSize << 0 << rectSize << -rectSize << 0 << rectSize;
|
||||
vertices << -rectSize << 0 << rectSize << -rectSize << 0 << -rectSize;
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
vertices << 0 << -rectSize << -rectSize << 0 << rectSize << -rectSize;
|
||||
vertices << 0 << rectSize << -rectSize << 0 << rectSize << rectSize;
|
||||
vertices << 0 << rectSize << rectSize << 0 << -rectSize << rectSize;
|
||||
vertices << 0 << -rectSize << rectSize << 0 << -rectSize << -rectSize;
|
||||
}
|
||||
const auto& o = plane.Location();
|
||||
QVector3D O(o.X(), o.Y(), o.Z());
|
||||
|
||||
QVector3D p1 = O - rectSize * X - rectSize * Y;
|
||||
QVector3D p2 = O + rectSize * X - rectSize * Y;
|
||||
QVector3D p3 = O + rectSize * X + rectSize * Y;
|
||||
QVector3D p4 = O - rectSize * X + rectSize * Y;
|
||||
vertices << p1.x() << p1.y() << p1.z() << p2.x() << p2.y() << p2.z();
|
||||
vertices << p2.x() << p2.y() << p2.z() << p3.x() << p3.y() << p3.z();
|
||||
vertices << p3.x() << p3.y() << p3.z() << p4.x() << p4.y() << p4.z();
|
||||
vertices << p4.x() << p4.y() << p4.z() << p1.x() << p1.y() << p1.z();
|
||||
} else if (m_isSnappingVertex) {
|
||||
const float rectSize = 0.0075f * -m_viewport->camera()->zoom();
|
||||
const auto& v = m_snapVertex;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
vertices << v.X() - rectSize << v.Y() - rectSize << v.Z() << v.X() + rectSize << v.Y() - rectSize << v.Z();
|
||||
vertices << v.X() + rectSize << v.Y() - rectSize << v.Z() << v.X() + rectSize << v.Y() + rectSize << v.Z();
|
||||
vertices << v.X() + rectSize << v.Y() + rectSize << v.Z() << v.X() - rectSize << v.Y() + rectSize << v.Z();
|
||||
vertices << v.X() - rectSize << v.Y() + rectSize << v.Z() << v.X() - rectSize << v.Y() - rectSize << v.Z();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
vertices << v.X() - rectSize << v.Y() << v.Z() - rectSize << v.X() + rectSize << v.Y() << v.Z() - rectSize;
|
||||
vertices << v.X() + rectSize << v.Y() << v.Z() - rectSize << v.X() + rectSize << v.Y() << v.Z() + rectSize;
|
||||
vertices << v.X() + rectSize << v.Y() << v.Z() + rectSize << v.X() - rectSize << v.Y() << v.Z() + rectSize;
|
||||
vertices << v.X() - rectSize << v.Y() << v.Z() + rectSize << v.X() - rectSize << v.Y() << v.Z() - rectSize;
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
vertices << v.X() << v.Y() - rectSize << v.Z() - rectSize << v.X() << v.Y() + rectSize << v.Z() - rectSize;
|
||||
vertices << v.X() << v.Y() + rectSize << v.Z() - rectSize << v.X() << v.Y() + rectSize << v.Z() + rectSize;
|
||||
vertices << v.X() << v.Y() + rectSize << v.Z() + rectSize << v.X() << v.Y() - rectSize << v.Z() + rectSize;
|
||||
vertices << v.X() << v.Y() - rectSize << v.Z() + rectSize << v.X() << v.Y() - rectSize << v.Z() - rectSize;
|
||||
}
|
||||
QVector3D V(v.X(), v.Y(), v.Z());
|
||||
|
||||
QVector3D p1 = V - rectSize * X - rectSize * Y;
|
||||
QVector3D p2 = V + rectSize * X - rectSize * Y;
|
||||
QVector3D p3 = V + rectSize * X + rectSize * Y;
|
||||
QVector3D p4 = V - rectSize * X + rectSize * Y;
|
||||
vertices << p1.x() << p1.y() << p1.z() << p2.x() << p2.y() << p2.z();
|
||||
vertices << p2.x() << p2.y() << p2.z() << p3.x() << p3.y() << p3.z();
|
||||
vertices << p3.x() << p3.y() << p3.z() << p4.x() << p4.y() << p4.z();
|
||||
vertices << p4.x() << p4.y() << p4.z() << p1.x() << p1.y() << p1.z();
|
||||
}
|
||||
m_viewport->shaderProgram()->setUniformValue(m_viewport->colorLoc(), QVector4D(1.0f, 1.0f, 0.0f, 0.5f));
|
||||
m_viewport->vbo().bind();
|
||||
|
||||
+88
-80
@@ -33,9 +33,15 @@
|
||||
#include <QApplication>
|
||||
#include <cmath>
|
||||
#include <QtMath>
|
||||
#include <ElCLib.hxx>
|
||||
#include <gp_Pnt2d.hxx>
|
||||
#include <gp_Vec.hxx>
|
||||
#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 {
|
||||
@@ -60,7 +66,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));
|
||||
@@ -143,12 +149,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) {
|
||||
@@ -205,8 +211,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());
|
||||
@@ -233,9 +239,11 @@ 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));
|
||||
if (m_currentPlane) {
|
||||
m_camera->startRotation(unproject(event->pos(), m_currentPlane.value()));
|
||||
update();
|
||||
}
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
if (m_viewCube->handleMousePress(event->pos(), width(), height())) {
|
||||
@@ -245,10 +253,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;
|
||||
@@ -268,8 +276,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();
|
||||
}
|
||||
@@ -289,8 +306,10 @@ void ViewportWidget::mouseMoveEvent(QMouseEvent *event)
|
||||
|
||||
void ViewportWidget::wheelEvent(QWheelEvent *event)
|
||||
{
|
||||
QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane);
|
||||
if (m_currentPlane) {
|
||||
QVector3D worldPos = unproject(event->position().toPoint(), m_currentPlane.value());
|
||||
m_camera->wheelEvent(event, worldPos);
|
||||
}
|
||||
}
|
||||
|
||||
void ViewportWidget::keyPressEvent(QKeyEvent *event)
|
||||
@@ -303,8 +322,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;
|
||||
}
|
||||
@@ -369,19 +388,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();
|
||||
}
|
||||
|
||||
@@ -393,7 +412,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();
|
||||
}
|
||||
|
||||
@@ -465,7 +484,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();
|
||||
|
||||
@@ -494,17 +513,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;
|
||||
}
|
||||
@@ -538,20 +553,11 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
||||
|
||||
const int numSegments = 64;
|
||||
QVector3D u_axis, v_axis;
|
||||
switch (sketch->plane()) {
|
||||
case SketchFeature::SketchPlane::XY: // Top
|
||||
u_axis = QVector3D(1, 0, 0);
|
||||
v_axis = QVector3D(0, 1, 0);
|
||||
break;
|
||||
case SketchFeature::SketchPlane::XZ: // Front
|
||||
u_axis = QVector3D(1, 0, 0);
|
||||
v_axis = QVector3D(0, 0, 1);
|
||||
break;
|
||||
case SketchFeature::SketchPlane::YZ: // Right
|
||||
u_axis = QVector3D(0, 1, 0);
|
||||
v_axis = QVector3D(0, 0, 1);
|
||||
break;
|
||||
}
|
||||
const auto& plane = sketch->plane();
|
||||
const auto& xDir = plane.XDirection();
|
||||
const auto& yDir = plane.YDirection();
|
||||
u_axis = QVector3D(xDir.X(), xDir.Y(), xDir.Z());
|
||||
v_axis = QVector3D(yDir.X(), yDir.Y(), yDir.Z());
|
||||
|
||||
for (int i = 0; i < numSegments; ++i) {
|
||||
double angle1 = 2.0 * M_PI * double(i) / double(numSegments);
|
||||
@@ -565,34 +571,32 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch)
|
||||
}
|
||||
} else if (obj->type() == SketchObject::ObjectType::Rectangle) {
|
||||
auto rect = static_cast<const SketchRectangle*>(obj);
|
||||
const auto& p1 = rect->corner1();
|
||||
const auto& p3 = rect->corner2();
|
||||
const auto& plane = sketch->plane();
|
||||
const auto& p1_3d = rect->corner1();
|
||||
const auto& p3_3d = rect->corner2();
|
||||
|
||||
gp_Pnt p2, p4;
|
||||
if (sketch->plane() == SketchFeature::SketchPlane::XY) {
|
||||
p2.SetCoord(p3.X(), p1.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p3.Y(), p1.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::XZ) {
|
||||
p2.SetCoord(p3.X(), p1.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
} else if (sketch->plane() == SketchFeature::SketchPlane::YZ) {
|
||||
p2.SetCoord(p1.X(), p3.Y(), p1.Z());
|
||||
p4.SetCoord(p1.X(), p1.Y(), p3.Z());
|
||||
}
|
||||
gp_Pnt2d p1_2d(gp_Vec(plane.Location(), p1_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p1_3d).Dot(plane.YDirection()));
|
||||
gp_Pnt2d p3_2d(gp_Vec(plane.Location(), p3_3d).Dot(plane.XDirection()), gp_Vec(plane.Location(), p3_3d).Dot(plane.YDirection()));
|
||||
|
||||
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();
|
||||
gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y());
|
||||
gp_Pnt2d p4_2d(p1_2d.X(), p3_2d.Y());
|
||||
|
||||
vertexCounts[p1] += 2;
|
||||
vertexCounts[p2] += 2;
|
||||
vertexCounts[p3] += 2;
|
||||
vertexCounts[p4] += 2;
|
||||
gp_Pnt p2_3d = ElCLib::To3d(plane, p2_2d);
|
||||
gp_Pnt p4_3d = ElCLib::To3d(plane, p4_2d);
|
||||
|
||||
lineVertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z();
|
||||
lineVertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z();
|
||||
lineVertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z();
|
||||
lineVertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z();
|
||||
lineVertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z();
|
||||
lineVertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z();
|
||||
lineVertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z();
|
||||
lineVertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z();
|
||||
|
||||
vertexCounts[p1_3d] += 2;
|
||||
vertexCounts[p2_3d] += 2;
|
||||
vertexCounts[p3_3d] += 2;
|
||||
vertexCounts[p4_3d] += 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -711,52 +715,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