From 7f304bf1f3a80f9c398f2d21b97bc6301f5bad57 Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Mon, 16 Feb 2026 20:28:17 -0700 Subject: [PATCH] fix: Position linear dimension opposite angle to avoid overlap Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/ViewportWidget.cpp | 188 ++++++++++++++++++++++------------------- 1 file changed, 99 insertions(+), 89 deletions(-) diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index 2de9b2a..17d7099 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -318,6 +318,60 @@ void ViewportWidget::paintGL() float lineLength = lineVec.length(); if (lineLength > 1e-6) { + double refAngle, lineAngle, angleDiff; + { + 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); + } + + if (angleFromInput) { + QVector3D currentMouseWorldPos = unproject(m_currentMousePos, 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 refAngleForQuadrant; + if (m_currentPlane == SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); + else if (m_currentPlane == SketchPlane::XZ) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.y(), refDir.x())); + else refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.y())); + + double relativeMouseAngle = mouseAngle - refAngleForQuadrant; + while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0; + while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0; + + if (relativeMouseAngle >= 90 || relativeMouseAngle < -90) { + refDir = -refDir; + } + } else { + if (property("isChainedLine").toBool()) { + refDir = -refDir; + } + } + + if (m_currentPlane == SketchPlane::XY) { + refAngle = atan2(refDir.z(), refDir.x()); + lineAngle = atan2(lineVec.z(), lineVec.x()); + } else if (m_currentPlane == SketchPlane::XZ) { + refAngle = atan2(refDir.y(), refDir.x()); + lineAngle = atan2(lineVec.y(), lineVec.x()); + } else { // YZ + refAngle = atan2(refDir.z(), refDir.y()); + lineAngle = atan2(lineVec.z(), lineVec.y()); + } + + angleDiff = lineAngle - refAngle; + while (angleDiff <= -M_PI) angleDiff += 2 * M_PI; + while (angleDiff > M_PI) angleDiff -= 2 * M_PI; + lineAngle = refAngle + angleDiff; + } + vertices.clear(); QVector3D perpVec; @@ -329,6 +383,10 @@ void ViewportWidget::paintGL() perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized(); } + if (angleDiff >= 0) { + perpVec = -perpVec; + } + float offset = 0.05f * -m_camera->zoom(); QVector3D dimStart = startPos + offset * perpVec; QVector3D dimEnd = worldPos + offset * perpVec; @@ -365,58 +423,6 @@ void ViewportWidget::paintGL() // Draw angle dimension vertices.clear(); - 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); - } - - if (angleFromInput) { - QVector3D currentMouseWorldPos = unproject(m_currentMousePos, 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 refAngleForQuadrant; - if (m_currentPlane == SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x())); - else if (m_currentPlane == SketchPlane::XZ) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.y(), refDir.x())); - else refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.y())); - - double relativeMouseAngle = mouseAngle - refAngleForQuadrant; - while (relativeMouseAngle <= -180.0) relativeMouseAngle += 360.0; - while (relativeMouseAngle > 180.0) relativeMouseAngle -= 360.0; - - if (relativeMouseAngle >= 90 || relativeMouseAngle < -90) { - refDir = -refDir; - } - } else { - if (property("isChainedLine").toBool()) { - refDir = -refDir; - } - } - - double refAngle, lineAngle; - if (m_currentPlane == SketchPlane::XY) { - refAngle = atan2(refDir.z(), refDir.x()); - lineAngle = atan2(lineVec.z(), lineVec.x()); - } else if (m_currentPlane == SketchPlane::XZ) { - refAngle = atan2(refDir.y(), refDir.x()); - lineAngle = atan2(lineVec.y(), lineVec.x()); - } else { // YZ - refAngle = atan2(refDir.z(), refDir.y()); - lineAngle = atan2(lineVec.z(), lineVec.y()); - } - - double angleDiff = lineAngle - refAngle; - while (angleDiff <= -M_PI) angleDiff += 2 * M_PI; - while (angleDiff > M_PI) angleDiff -= 2 * M_PI; - lineAngle = refAngle + angleDiff; - const int numSegments = 30; const float radius = 0.1f * -m_camera->zoom(); for (int i = 0; i <= numSegments; ++i) { @@ -651,41 +657,7 @@ void ViewportWidget::paintGL() QVector3D lineVec = worldPos - startPos; if (lineVec.length() > 1e-6) { - QVector3D perpVec; - if (m_currentPlane == SketchPlane::XY) { - perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized(); - } else if (m_currentPlane == SketchPlane::XZ) { - perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized(); - } else if (m_currentPlane == SketchPlane::YZ) { - perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized(); - } - - float offset = 0.05f * -m_camera->zoom(); - QVector3D dimStart = startPos + offset * perpVec; - QVector3D dimEnd = worldPos + offset * perpVec; - QVector3D textPos3D = (dimStart + dimEnd) / 2.0f + 0.015f * -m_camera->zoom() * perpVec; - - QVector3D screenPos = project(textPos3D, model, projection, rect()); - - painter.setRenderHint(QPainter::Antialiasing); - QFontMetrics fm(painter.font()); - - if (screenPos.z() < 1.0f) { - dimText = lengthFromInput ? dimInput : QString::number(lineLength, 'f', 2); - - QRect textRect = fm.boundingRect(dimText + "_"); - textRect.moveCenter(screenPos.toPoint()); - - if (property("dimensionEditMode").toString() == "length") { - 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, dimText); - } - - // Angle dimension text + double refAngle, lineAngle; QVector3D refDir; if (property("isChainedLine").toBool()) { refDir = property("previousLineDirection").value(); @@ -723,7 +695,6 @@ void ViewportWidget::paintGL() } } - double refAngle, lineAngle; if (m_currentPlane == SketchPlane::XY) { refAngle = atan2(refDir.z(), refDir.x()); lineAngle = atan2(lineVec.z(), lineVec.x()); @@ -740,7 +711,46 @@ void ViewportWidget::paintGL() while (angleDiff > M_PI) angleDiff -= 2 * M_PI; lineAngle = refAngle + angleDiff; - double angleDiffDegrees = qRadiansToDegrees(lineAngle - refAngle); + QVector3D perpVec; + if (m_currentPlane == SketchPlane::XY) { + perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized(); + } else if (m_currentPlane == SketchPlane::XZ) { + perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized(); + } else if (m_currentPlane == SketchPlane::YZ) { + perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized(); + } + + if (angleDiff >= 0) { + perpVec = -perpVec; + } + + float offset = 0.05f * -m_camera->zoom(); + QVector3D dimStart = startPos + offset * perpVec; + QVector3D dimEnd = worldPos + offset * perpVec; + QVector3D textPos3D = (dimStart + dimEnd) / 2.0f + 0.015f * -m_camera->zoom() * perpVec; + + QVector3D screenPos = project(textPos3D, model, projection, rect()); + + painter.setRenderHint(QPainter::Antialiasing); + QFontMetrics fm(painter.font()); + + if (screenPos.z() < 1.0f) { + dimText = lengthFromInput ? dimInput : QString::number(lineLength, 'f', 2); + + QRect textRect = fm.boundingRect(dimText + "_"); + textRect.moveCenter(screenPos.toPoint()); + + if (property("dimensionEditMode").toString() == "length") { + 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, dimText); + } + + // Angle dimension text + double angleDiffDegrees = qRadiansToDegrees(angleDiff); while (angleDiffDegrees <= -180.0) angleDiffDegrees += 360.0; while (angleDiffDegrees > 180.0) angleDiffDegrees -= 360.0;