#include "RectangleTool.h" #include "ViewportWidget.h" #include "Camera.h" #include #include #include #include #include #include #include RectangleTool::RectangleTool(ViewportWidget* viewport) : SketchTool(viewport) { } void RectangleTool::activate() { SketchTool::activate(); m_dimensionModes << "height" << "width"; m_dimensionPropertyNames["height"] = "heightInput"; m_dimensionPropertyNames["width"] = "widthInput"; m_viewport->setProperty("widthInput", ""); m_viewport->setProperty("heightInput", ""); m_viewport->setProperty("dimensionEditMode", "height"); } void RectangleTool::mousePressEvent(QMouseEvent *event) { gp_Pnt p; if (!m_isDefining) { if (m_viewport->isSnappingOrigin()) { p.SetCoord(0, 0, 0); } else if (m_viewport->isSnappingVertex()) { p = m_viewport->snapVertex(); } else { QVector3D worldPos = m_viewport->unproject(event->pos(), m_viewport->currentPlane()); p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); } m_firstRectanglePoint = p; m_isDefining = true; m_viewport->setProperty("widthInput", ""); m_viewport->setProperty("heightInput", ""); m_viewport->setProperty("dimensionEditMode", "height"); } else { QVector3D worldPos; QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); QString widthInput = m_viewport->property("widthInput").toString(); QString heightInput = m_viewport->property("heightInput").toString(); bool widthFromInput = false, heightFromInput = false; double inputWidth = 0, inputHeight = 0; if (!widthInput.isEmpty()) { bool ok; inputWidth = widthInput.toDouble(&ok); if (ok) widthFromInput = true; } if (!heightInput.isEmpty()) { bool ok; inputHeight = heightInput.toDouble(&ok); if (ok) heightFromInput = true; } 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.z()); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { current_w = qAbs(mouseDir.x()); current_h = qAbs(mouseDir.y()); } else { // YZ current_w = qAbs(mouseDir.y()); current_h = qAbs(mouseDir.z()); } 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.setZ(startPos.z() + signZ * rect_h); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { worldPos.setX(startPos.x() + signX * rect_w); worldPos.setY(startPos.y() + signY * rect_h); } else { // YZ worldPos.setY(startPos.y() + signY * rect_w); worldPos.setZ(startPos.z() + signZ * rect_h); } } else { if (m_viewport->isSnappingOrigin()) { worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0); } 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()); } } p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); emit m_viewport->rectangleAdded(m_firstRectanglePoint, p); deactivate(); } } void RectangleTool::mouseMoveEvent(QMouseEvent *event) { // To be implemented } void RectangleTool::finalizeCreation() { QVector3D worldPos; QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); QString widthInput = m_viewport->property("widthInput").toString(); QString heightInput = m_viewport->property("heightInput").toString(); bool widthFromInput = false, heightFromInput = false; double inputWidth = 0, inputHeight = 0; if (!widthInput.isEmpty()) { bool ok; inputWidth = widthInput.toDouble(&ok); if (ok) widthFromInput = true; } if (!heightInput.isEmpty()) { bool ok; inputHeight = heightInput.toDouble(&ok); if (ok) heightFromInput = true; } 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.z()); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { current_w = qAbs(mouseDir.x()); current_h = qAbs(mouseDir.y()); } else { // YZ current_w = qAbs(mouseDir.y()); current_h = qAbs(mouseDir.z()); } 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.setZ(startPos.z() + signZ * rect_h); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { worldPos.setX(startPos.x() + signX * rect_w); worldPos.setY(startPos.y() + signY * rect_h); } else { // YZ worldPos.setY(startPos.y() + signY * rect_w); worldPos.setZ(startPos.z() + signZ * rect_h); } } else { worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); } gp_Pnt p; p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); emit m_viewport->rectangleAdded(m_firstRectanglePoint, p); deactivate(); } void RectangleTool::paintGL() { if (m_isDefining) { QVector vertices; QVector3D worldPos; QVector3D startPos(m_firstRectanglePoint.X(), m_firstRectanglePoint.Y(), m_firstRectanglePoint.Z()); QString widthInput = m_viewport->property("widthInput").toString(); QString heightInput = m_viewport->property("heightInput").toString(); bool widthFromInput = false; bool heightFromInput = false; double inputWidth = 0, inputHeight = 0; if (!widthInput.isEmpty()) { bool ok; inputWidth = widthInput.toDouble(&ok); if (ok) widthFromInput = true; } if (!heightInput.isEmpty()) { bool ok; inputHeight = heightInput.toDouble(&ok); if (ok) heightFromInput = true; } QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); 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.z()); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { current_w = qAbs(mouseDir.x()); current_h = qAbs(mouseDir.y()); } else { // YZ current_w = qAbs(mouseDir.y()); current_h = qAbs(mouseDir.z()); } 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.setZ(startPos.z() + signZ * rect_h); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { worldPos.setX(startPos.x() + signX * rect_w); worldPos.setY(startPos.y() + signY * rect_h); } else { // YZ worldPos.setY(startPos.y() + signY * rect_w); worldPos.setZ(startPos.z() + signZ * rect_h); } } 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()); } } QVector3D p1 = startPos; QVector3D p2, p3, p4; p3 = worldPos; 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(p1.y()); p4.setZ(p3.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(p3.y()); p4.setZ(p1.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()); } vertices << p1.x() << p1.y() << p1.z(); vertices << p2.x() << p2.y() << p2.z(); vertices << p2.x() << p2.y() << p2.z(); vertices << p3.x() << p3.y() << p3.z(); vertices << p3.x() << p3.y() << p3.z(); vertices << p4.x() << p4.y() << p4.z(); vertices << p4.x() << p4.y() << p4.z(); vertices << p1.x() << p1.y() << p1.z(); m_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()); QString widthInput = m_viewport->property("widthInput").toString(); QString heightInput = m_viewport->property("heightInput").toString(); bool widthFromInput = false; bool heightFromInput = false; double inputWidth = 0, inputHeight = 0; if (!widthInput.isEmpty()) { bool ok; inputWidth = widthInput.toDouble(&ok); if (ok) widthFromInput = true; } if (!heightInput.isEmpty()) { bool ok; inputHeight = heightInput.toDouble(&ok); if (ok) heightFromInput = true; } QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); 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.z()); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { current_w = qAbs(mouseDir.x()); current_h = qAbs(mouseDir.y()); } else { // YZ current_w = qAbs(mouseDir.y()); current_h = qAbs(mouseDir.z()); } 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.setZ(p1_3d.z() + signZ * rect_h); } else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { worldPos.setX(p1_3d.x() + signX * rect_w); worldPos.setY(p1_3d.y() + signY * rect_h); } else { // YZ worldPos.setY(p1_3d.y() + signY * rect_w); worldPos.setZ(p1_3d.z() + signZ * rect_h); } } 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()); } } QVector3D p3_3d = worldPos; QVector3D p2_3d, p4_3d; double w, h; 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(p1_3d.y()); p4_3d.setZ(p3_3d.z()); w = qAbs(p3_3d.x() - p1_3d.x()); h = qAbs(p3_3d.z() - p1_3d.z()); } else if (m_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(p3_3d.y()); p4_3d.setZ(p1_3d.z()); w = qAbs(p3_3d.x() - p1_3d.x()); h = qAbs(p3_3d.y() - p1_3d.y()); } else { // YZ p2_3d.setX(p1_3d.x()); p2_3d.setY(p3_3d.y()); p2_3d.setZ(p1_3d.z()); p4_3d.setX(p1_3d.x()); p4_3d.setY(p1_3d.y()); p4_3d.setZ(p3_3d.z()); w = qAbs(p3_3d.y() - p1_3d.y()); h = qAbs(p3_3d.z() - p1_3d.z()); } painter.setRenderHint(QPainter::Antialiasing); QFontMetrics fm(painter.font()); // Width dimension QVector3D widthTextPos3D = (p1_3d + p2_3d) / 2.0f; QVector3D screenPosW = 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)); if (m_viewport->property("dimensionEditMode").toString() == "width") { 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, widthText); } // Height dimension QVector3D heightTextPos3D = (p2_3d + p3_3d) / 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)); if (m_viewport->property("dimensionEditMode").toString() == "height") { 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, heightText); } } }