diff --git a/src/CircleTool.cpp b/src/CircleTool.cpp index a1dc726..2383974 100644 --- a/src/CircleTool.cpp +++ b/src/CircleTool.cpp @@ -15,6 +15,10 @@ #include #include #include +#include +#include +#include +#include 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,134 +148,121 @@ void CircleTool::finalizeCreation() void CircleTool::paintGL() { - if (m_isDefining) { - QVector vertices; - QVector3D worldPos; - QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); + auto currentPlaneOpt = m_viewport->currentPlane(); + if (!m_isDefining || !currentPlaneOpt) return; + const auto& plane = currentPlaneOpt.value(); - QString diameterInput = m_viewport->property("diameterInput").toString(); - bool diameterFromInput = false; - double inputDiameter = 0; + QVector vertices; + QVector3D worldPos; + QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); - if (!diameterInput.isEmpty()) { - bool ok; - inputDiameter = diameterInput.toDouble(&ok); - if (ok) diameterFromInput = true; - } + QString diameterInput = m_viewport->property("diameterInput").toString(); + bool diameterFromInput = false; + double inputDiameter = 0; - QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - - double radius; - if (diameterFromInput) { - radius = inputDiameter / 2.0; - } else { - worldPos = mousePos; - if (m_viewport->isSnappingOrigin()) { - worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0); - } else if (m_viewport->isSnappingVertex()) { - worldPos.setX(m_viewport->snapVertex().X()); worldPos.setY(m_viewport->snapVertex().Y()); worldPos.setZ(m_viewport->snapVertex().Z()); - } - radius = (worldPos - centerPos).length(); - } - - const int segments = 64; - 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; - - 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(); - } - - 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, segments * 2); + if (!diameterInput.isEmpty()) { + bool ok; + inputDiameter = diameterInput.toDouble(&ok); + if (ok) diameterFromInput = true; } + + QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), plane); + + double radius; + if (diameterFromInput) { + radius = inputDiameter / 2.0; + } else { + worldPos = mousePos; + if (m_viewport->isSnappingOrigin()) { + 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()); + } + radius = (worldPos - centerPos).length(); + } + + 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 = centerPos + radius * (qCos(angle1) * u_axis + qSin(angle1) * v_axis); + QVector3D p2 = centerPos + radius * (qCos(angle2) * u_axis + qSin(angle2) * v_axis); + + vertices << p1.x() << p1.y() << p1.z(); + vertices << p2.x() << p2.y() << p2.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, segments * 2); } void CircleTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection) { - if (m_isDefining) { - QVector3D worldPos; - QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); + auto currentPlaneOpt = m_viewport->currentPlane(); + if (!m_isDefining || !currentPlaneOpt) return; + const auto& plane = currentPlaneOpt.value(); - QString diameterInput = m_viewport->property("diameterInput").toString(); - bool diameterFromInput = false; - double inputDiameter = 0; + QVector3D worldPos; + QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); - if (!diameterInput.isEmpty()) { - bool ok; - inputDiameter = diameterInput.toDouble(&ok); - if (ok) diameterFromInput = true; + QString diameterInput = m_viewport->property("diameterInput").toString(); + bool diameterFromInput = false; + double inputDiameter = 0; + + if (!diameterInput.isEmpty()) { + bool ok; + inputDiameter = diameterInput.toDouble(&ok); + if (ok) diameterFromInput = true; + } + + QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), plane); + QVector3D edgePos; + double diameter; + + if (diameterFromInput) { + diameter = inputDiameter; + QVector3D mouseDir = mousePos - centerPos; + if (mouseDir.lengthSquared() < 1e-9) { + 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()) { + 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()); + } + diameter = (edgePos - centerPos).length() * 2.0; + } - QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); - QVector3D edgePos; - double diameter; + painter.setRenderHint(QPainter::Antialiasing); + QFontMetrics fm(painter.font()); - if (diameterFromInput) { - 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); - } - } - edgePos = centerPos + mouseDir.normalized() * (diameter / 2.0); + // Diameter dimension + QVector3D diameterTextPos3D = (centerPos + edgePos) / 2.0f; + QVector3D screenPosD = m_viewport->project(diameterTextPos3D, modelView, projection, m_viewport->rect()); + if (screenPosD.z() < 1.0f) { + QString diameterText = diameterFromInput ? diameterInput : QString::number(diameter, 'f', 2); + QRect textRect = fm.boundingRect(diameterText + "__"); + textRect.moveCenter(screenPosD.toPoint()); + if (m_viewport->property("dimensionEditMode").toString() == "diameter") { + painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255)); } else { - edgePos = mousePos; - if (m_viewport->isSnappingOrigin()) { - edgePos.setX(0); edgePos.setY(0); edgePos.setZ(0); - } else if (m_viewport->isSnappingVertex()) { - edgePos.setX(m_viewport->snapVertex().X()); edgePos.setY(m_viewport->snapVertex().Y()); edgePos.setZ(m_viewport->snapVertex().Z()); - } - diameter = (edgePos - centerPos).length() * 2.0; - } - - painter.setRenderHint(QPainter::Antialiasing); - QFontMetrics fm(painter.font()); - - // Diameter dimension - QVector3D diameterTextPos3D = (centerPos + edgePos) / 2.0f; - QVector3D screenPosD = m_viewport->project(diameterTextPos3D, modelView, projection, m_viewport->rect()); - if (screenPosD.z() < 1.0f) { - QString diameterText = diameterFromInput ? diameterInput : QString::number(diameter, 'f', 2); - QRect textRect = fm.boundingRect(diameterText + "__"); - textRect.moveCenter(screenPosD.toPoint()); - if (m_viewport->property("dimensionEditMode").toString() == "diameter") { - painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255)); - } else { - painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50)); - } - painter.setPen(Qt::white); - painter.drawText(textRect, Qt::AlignCenter, diameterText); + painter.fillRect(textRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50)); } + painter.setPen(Qt::white); + painter.drawText(textRect, Qt::AlignCenter, diameterText); } }