diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index 9f74c09..326150d 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -733,25 +733,101 @@ void ViewportWidget::mousePressEvent(QMouseEvent *event) if (m_currentPlane != SketchPlane::NONE && m_activeTool == static_cast(ApplicationController::ToolType::Line)) { gp_Pnt p; - if (m_isSnappingOrigin) { - p.SetCoord(0, 0, 0); - } else if (m_isSnappingVertex) { - p = m_snapVertex; - } else { - QVector3D worldPos = unproject(event->pos(), m_currentPlane); - if (m_isSnappingHorizontal) { - if (m_currentPlane == SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z()); - else if (m_currentPlane == SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y()); - else if (m_currentPlane == SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z()); - } else if (m_isSnappingVertical) { - if (m_currentPlane == SketchPlane::XY) worldPos.setX(m_firstLinePoint.X()); - else if (m_currentPlane == SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X()); - else if (m_currentPlane == SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y()); - } - p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); - } + QString dimInput = property("dimensionInput").toString(); + QString angleInput = property("angleInput").toString(); + bool lengthFromInput = false; + bool angleFromInput = false; + double inputLength = 0; + double inputAngleDegrees = 0; - if (!m_isDefiningLine) { + if (m_isDefiningLine) { + if (!dimInput.isEmpty()) { + bool ok; + inputLength = dimInput.toDouble(&ok); + if (ok) lengthFromInput = true; + } + if (!angleInput.isEmpty()) { + bool ok; + inputAngleDegrees = angleInput.toDouble(&ok); + if (ok) angleFromInput = true; + } + } + + if (m_isDefiningLine && (lengthFromInput || angleFromInput)) { + QVector3D worldPos; + QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z()); + + if (angleFromInput) { + QVector3D refDir; + if (property("isChainedLine").toBool()) { + refDir = property("previousLineDirection").value(); + } else { + if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) refDir = QVector3D(1, 0, 0); + else refDir = QVector3D(0, 1, 0); + } + QVector3D currentMouseWorldPos = unproject(event->pos(), m_currentPlane); + QVector3D mouseVec = currentMouseWorldPos - startPos; + double mouseAngle; + if (m_currentPlane == SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x())); + else if (m_currentPlane == SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x())); + else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y())); + double refAngle; + if (m_currentPlane == SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); + else if (m_currentPlane == SketchPlane::XZ) refAngle = qRadiansToDegrees(atan2(refDir.y(), refDir.x())); + else refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.y())); + double relativeMouseAngle = mouseAngle - refAngle; + while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0; + while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0; + double snappedAngle = 0; + if (relativeMouseAngle >= -45 && relativeMouseAngle < 45) snappedAngle = inputAngleDegrees; + else if (relativeMouseAngle >= 45 && relativeMouseAngle < 135) snappedAngle = 180 - inputAngleDegrees; + else if (relativeMouseAngle >= 135 || relativeMouseAngle < -135) snappedAngle = inputAngleDegrees + 180.0; + else snappedAngle = 360 - inputAngleDegrees; + double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle); + QVector3D finalDir; + if (m_currentPlane == SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad)); + else if (m_currentPlane == SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0); + else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad)); + double lineLength; + if (lengthFromInput) lineLength = inputLength; + else { + lineLength = QVector3D::dotProduct(mouseVec, finalDir); + if (lineLength < 0) lineLength = 0; + } + worldPos = startPos + lineLength * finalDir; + } else if (lengthFromInput) { + QVector3D currentMouseWorldPos = unproject(event->pos(), m_currentPlane); + QVector3D dir = (currentMouseWorldPos - startPos); + if (dir.length() > 1e-6) { + dir.normalize(); + worldPos = startPos + inputLength * dir; + } else { + if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) worldPos = startPos + QVector3D(inputLength, 0, 0); + else worldPos = startPos + QVector3D(0, inputLength, 0); + } + } + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + } else { + if (m_isSnappingOrigin) { + p.SetCoord(0, 0, 0); + } else if (m_isSnappingVertex) { + p = m_snapVertex; + } else { + QVector3D worldPos = unproject(event->pos(), m_currentPlane); + if (m_isSnappingHorizontal) { + if (m_currentPlane == SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z()); + else if (m_currentPlane == SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y()); + else if (m_currentPlane == SketchPlane::YZ) worldPos.setZ(m_firstLinePoint.Z()); + } else if (m_isSnappingVertical) { + if (m_currentPlane == SketchPlane::XY) worldPos.setX(m_firstLinePoint.X()); + else if (m_currentPlane == SketchPlane::XZ) worldPos.setX(m_firstLinePoint.X()); + else if (m_currentPlane == SketchPlane::YZ) worldPos.setY(m_firstLinePoint.Y()); + } + p.SetCoord(worldPos.x(), worldPos.y(), worldPos.z()); + } + } + + if (!m_isDefiningLine) { m_firstLinePoint = p; m_isDefiningLine = true; setProperty("dimensionInput", QVariant(""));