refactor: Move LineTool paintGL and paint2D logic to LineTool
Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
569
src/LineTool.cpp
569
src/LineTool.cpp
@@ -1,8 +1,11 @@
|
||||
#include "LineTool.h"
|
||||
#include "ViewportWidget.h"
|
||||
#include "Camera.h"
|
||||
#include <QMouseEvent>
|
||||
#include <QKeyEvent>
|
||||
#include <QPainter>
|
||||
#include <QOpenGLShaderProgram>
|
||||
#include <QtMath>
|
||||
|
||||
LineTool::LineTool(ViewportWidget* viewport)
|
||||
: SketchTool(viewport)
|
||||
@@ -42,10 +45,572 @@ void LineTool::keyPressEvent(QKeyEvent *event)
|
||||
|
||||
void LineTool::paintGL()
|
||||
{
|
||||
// To be implemented
|
||||
if (m_isDefiningLine) {
|
||||
QVector<GLfloat> vertices;
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
|
||||
QString dimInput = m_viewport->property("dimensionInput").toString();
|
||||
QString angleInput = m_viewport->property("angleInput").toString();
|
||||
bool lengthFromInput = false;
|
||||
bool angleFromInput = false;
|
||||
double inputLength = 0;
|
||||
double inputAngleDegrees = 0;
|
||||
|
||||
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 (angleFromInput) {
|
||||
QVector3D refDir;
|
||||
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, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
// Quadrant snapping
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::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 >= 0 && relativeMouseAngle < 90) { // Quadrant 1
|
||||
snappedAngle = inputAngleDegrees;
|
||||
} else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2
|
||||
snappedAngle = 180.0 - inputAngleDegrees;
|
||||
} else if (relativeMouseAngle < -90) { // Quadrant 3
|
||||
snappedAngle = -180.0 + inputAngleDegrees;
|
||||
} else { // Quadrant 4
|
||||
snappedAngle = -inputAngleDegrees;
|
||||
}
|
||||
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::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 = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
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());
|
||||
} else if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y());
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
vertices << m_firstLinePoint.X() << m_firstLinePoint.Y() << m_firstLinePoint.Z();
|
||||
vertices << worldPos.x() << worldPos.y() << worldPos.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, 2);
|
||||
|
||||
// Draw dimension line
|
||||
QVector3D lineVec = worldPos - startPos;
|
||||
float lineLength = lineVec.length();
|
||||
|
||||
if (lineLength > 1e-6) {
|
||||
double refAngle, lineAngle, angleDiff;
|
||||
{
|
||||
QVector3D refDir;
|
||||
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, 0, -1);
|
||||
}
|
||||
|
||||
if (angleFromInput) {
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
|
||||
double refAngleForQuadrant;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::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 (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = -refDir;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
refAngle = atan2(refDir.z(), refDir.x());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::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;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized();
|
||||
}
|
||||
|
||||
if (angleDiff < 0) {
|
||||
perpVec = -perpVec;
|
||||
}
|
||||
|
||||
float offset = 0.05f * -m_viewport->camera()->zoom();
|
||||
QVector3D dimStart = startPos + offset * perpVec;
|
||||
QVector3D dimEnd = worldPos + offset * perpVec;
|
||||
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
|
||||
float arrowLength = 0.02f * -m_viewport->camera()->zoom();
|
||||
float arrowWidth = 0.005f * -m_viewport->camera()->zoom();
|
||||
QVector3D lineDir = lineVec.normalized();
|
||||
|
||||
QVector3D arrow_base_end = dimEnd - arrowLength * lineDir;
|
||||
QVector3D arrowP1_end = arrow_base_end + arrowWidth * perpVec;
|
||||
QVector3D arrowP2_end = arrow_base_end - arrowWidth * perpVec;
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
vertices << arrowP1_end.x() << arrowP1_end.y() << arrowP1_end.z();
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
vertices << arrowP2_end.x() << arrowP2_end.y() << arrowP2_end.z();
|
||||
|
||||
QVector3D arrow_base_start = dimStart + arrowLength * lineDir;
|
||||
QVector3D arrowP1_start = arrow_base_start + arrowWidth * perpVec;
|
||||
QVector3D arrowP2_start = arrow_base_start - arrowWidth * perpVec;
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << arrowP1_start.x() << arrowP1_start.y() << arrowP1_start.z();
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << arrowP2_start.x() << arrowP2_start.y() << arrowP2_start.z();
|
||||
|
||||
m_viewport->shaderProgram()->setUniformValue(m_viewport->colorLoc(), QVector4D(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
glLineWidth(1.0f);
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, vertices.size() / 3);
|
||||
glLineWidth(2.0f);
|
||||
|
||||
// Draw angle dimension
|
||||
vertices.clear();
|
||||
const int numSegments = 30;
|
||||
const float radius = 0.1f * -m_viewport->camera()->zoom();
|
||||
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), 0, sin(angle));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) p = startPos + radius * QVector3D(cos(angle), sin(angle), 0);
|
||||
else p = startPos + radius * QVector3D(0, cos(angle), sin(angle));
|
||||
vertices << p.x() << p.y() << p.z();
|
||||
}
|
||||
glLineWidth(1.0f);
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINE_STRIP, 0, vertices.size() / 3);
|
||||
|
||||
// Arrowheads for arc
|
||||
QVector<GLfloat> arrowVertices;
|
||||
float arcArrowLength = 0.02f * -m_viewport->camera()->zoom();
|
||||
float arcArrowWidth = 0.005f * -m_viewport->camera()->zoom();
|
||||
|
||||
double sign = (angleDiff >= 0) ? 1.0 : -1.0;
|
||||
|
||||
// End arrowhead
|
||||
QVector3D endPoint(vertices[vertices.size()-3], vertices[vertices.size()-2], vertices[vertices.size()-1]);
|
||||
double endAngle = lineAngle;
|
||||
QVector3D radialDir_end, tangentDir_end;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
radialDir_end = QVector3D(cos(endAngle), 0, sin(endAngle));
|
||||
tangentDir_end = QVector3D(-sin(endAngle), 0, cos(endAngle));
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
radialDir_end = QVector3D(cos(endAngle), sin(endAngle), 0);
|
||||
tangentDir_end = QVector3D(-sin(endAngle), cos(endAngle), 0);
|
||||
} else {
|
||||
radialDir_end = QVector3D(0, cos(endAngle), sin(endAngle));
|
||||
tangentDir_end = QVector3D(0, -sin(endAngle), cos(endAngle));
|
||||
}
|
||||
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;
|
||||
arrowVertices << endPoint.x() << endPoint.y() << endPoint.z() << arc_arrowP1_end.x() << arc_arrowP1_end.y() << arc_arrowP1_end.z();
|
||||
arrowVertices << endPoint.x() << endPoint.y() << endPoint.z() << arc_arrowP2_end.x() << arc_arrowP2_end.y() << arc_arrowP2_end.z();
|
||||
|
||||
// Start arrowhead
|
||||
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), 0, sin(startAngle));
|
||||
tangentDir_start = QVector3D(-sin(startAngle), 0, cos(startAngle));
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
radialDir_start = QVector3D(cos(startAngle), sin(startAngle), 0);
|
||||
tangentDir_start = QVector3D(-sin(startAngle), cos(startAngle), 0);
|
||||
} else {
|
||||
radialDir_start = QVector3D(0, cos(startAngle), sin(startAngle));
|
||||
tangentDir_start = QVector3D(0, -sin(startAngle), cos(startAngle));
|
||||
}
|
||||
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;
|
||||
arrowVertices << startPoint.x() << startPoint.y() << startPoint.z() << arc_arrowP1_start.x() << arc_arrowP1_start.y() << arc_arrowP1_start.z();
|
||||
arrowVertices << startPoint.x() << startPoint.y() << startPoint.z() << arc_arrowP2_start.x() << arc_arrowP2_start.y() << arc_arrowP2_start.z();
|
||||
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(arrowVertices.constData(), arrowVertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, arrowVertices.size() / 3);
|
||||
glLineWidth(2.0f);
|
||||
}
|
||||
|
||||
if (!lengthFromInput && !angleFromInput && (m_viewport->isSnappingHorizontal() || m_viewport->isSnappingVertical())) {
|
||||
vertices.clear();
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QVector3D midPoint = (startPos + worldPos) / 2.0;
|
||||
const float indicatorSize = 0.02f * -m_viewport->camera()->zoom();
|
||||
const float indicatorOffset = 0.02f * -m_viewport->camera()->zoom();
|
||||
if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
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::XZ) {
|
||||
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::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() - indicatorSize << midPoint.z() + indicatorOffset;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorSize << midPoint.z() + indicatorOffset;
|
||||
}
|
||||
} else { // m_isSnappingVertical
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
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::XZ) {
|
||||
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::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() - indicatorSize;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() + indicatorSize;
|
||||
}
|
||||
}
|
||||
m_viewport->vbo().bind();
|
||||
m_viewport->vbo().allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LineTool::paint2D(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection)
|
||||
{
|
||||
// To be implemented
|
||||
if (m_isDefiningLine) {
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QString dimText;
|
||||
QString angleText;
|
||||
|
||||
QString dimInput = m_viewport->property("dimensionInput").toString();
|
||||
QString angleInput = m_viewport->property("angleInput").toString();
|
||||
bool lengthFromInput = false;
|
||||
bool angleFromInput = false;
|
||||
double inputLength = 0;
|
||||
double inputAngleDegrees = 0;
|
||||
double lineLength = 0;
|
||||
|
||||
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 (angleFromInput) {
|
||||
QVector3D refDir;
|
||||
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, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVec.y(), mouseVec.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVec.z(), mouseVec.y()));
|
||||
|
||||
double refAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngle = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::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 >= 0 && relativeMouseAngle < 90) { // Quadrant 1
|
||||
snappedAngle = inputAngleDegrees;
|
||||
} else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2
|
||||
snappedAngle = 180.0 - inputAngleDegrees;
|
||||
} else if (relativeMouseAngle < -90) { // Quadrant 3
|
||||
snappedAngle = -180.0 + inputAngleDegrees;
|
||||
} else { // Quadrant 4
|
||||
snappedAngle = -inputAngleDegrees;
|
||||
}
|
||||
|
||||
double finalAngleRad = qDegreesToRadians(refAngle + snappedAngle);
|
||||
QVector3D finalDir;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) finalDir = QVector3D(cos(finalAngleRad), 0, sin(finalAngleRad));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) finalDir = QVector3D(cos(finalAngleRad), sin(finalAngleRad), 0);
|
||||
else finalDir = QVector3D(0, cos(finalAngleRad), sin(finalAngleRad));
|
||||
|
||||
if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
} else {
|
||||
lineLength = QVector3D::dotProduct(mouseVec, finalDir);
|
||||
if (lineLength < 0) lineLength = 0;
|
||||
}
|
||||
worldPos = startPos + lineLength * finalDir;
|
||||
|
||||
} else if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
QVector3D currentMouseWorldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
worldPos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
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());
|
||||
} else if (m_viewport->isSnappingHorizontal()) {
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) worldPos.setZ(m_firstLinePoint.Z());
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) worldPos.setY(m_firstLinePoint.Y());
|
||||
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());
|
||||
}
|
||||
lineLength = (worldPos - startPos).length();
|
||||
}
|
||||
|
||||
QVector3D lineVec = worldPos - startPos;
|
||||
if (lineVec.length() > 1e-6) {
|
||||
double refAngle, lineAngle;
|
||||
QVector3D refDir;
|
||||
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, 0, -1);
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPosForText = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane());
|
||||
QVector3D mouseVecForText = currentMouseWorldPosForText - startPos;
|
||||
|
||||
if (angleFromInput) {
|
||||
if (mouseVecForText.length() > 1e-6) {
|
||||
double mouseAngle;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.y(), mouseVecForText.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.y()));
|
||||
|
||||
double refAngleForQuadrant;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) refAngleForQuadrant = qRadiansToDegrees(atan2(refDir.z(), refDir.x()));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::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 (m_viewport->property("isChainedLine").toBool()) {
|
||||
refDir = -refDir;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
refAngle = atan2(refDir.z(), refDir.x());
|
||||
lineAngle = atan2(lineVec.z(), lineVec.x());
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::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;
|
||||
|
||||
QVector3D perpVec;
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) {
|
||||
perpVec = QVector3D(-lineVec.z(), 0, lineVec.x()).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) {
|
||||
perpVec = QVector3D(-lineVec.y(), lineVec.x(), 0).normalized();
|
||||
} else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::YZ) {
|
||||
perpVec = QVector3D(0, -lineVec.z(), lineVec.y()).normalized();
|
||||
}
|
||||
|
||||
if (angleDiff < 0) {
|
||||
perpVec = -perpVec;
|
||||
}
|
||||
|
||||
float offset = 0.05f * -m_viewport->camera()->zoom();
|
||||
QVector3D dimStart = startPos + offset * perpVec;
|
||||
QVector3D dimEnd = worldPos + offset * perpVec;
|
||||
QVector3D textPos3D = (dimStart + dimEnd) / 2.0f + 0.015f * -m_viewport->camera()->zoom() * perpVec;
|
||||
|
||||
QVector3D screenPos = m_viewport->project(textPos3D, modelView, projection, m_viewport->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 (m_viewport->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;
|
||||
|
||||
angleText = angleFromInput ? angleInput : QString::number(qAbs(angleDiffDegrees), 'f', 1) + QChar(0x00B0);
|
||||
|
||||
const float radius = 0.1f * -m_viewport->camera()->zoom();
|
||||
double midAngle = refAngle + (lineAngle - refAngle) / 2.0;
|
||||
QVector3D textPos3DAngle;
|
||||
float textOffset = 0.035f * -m_viewport->camera()->zoom();
|
||||
|
||||
if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XY) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), 0, sin(midAngle));
|
||||
else if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), sin(midAngle), 0);
|
||||
else textPos3DAngle = startPos + (radius + textOffset) * QVector3D(0, cos(midAngle), sin(midAngle));
|
||||
|
||||
QVector3D screenPosAngle = m_viewport->project(textPos3DAngle, modelView, projection, m_viewport->rect());
|
||||
if (screenPosAngle.z() < 1.0f) {
|
||||
QRect angleTextRect = fm.boundingRect(angleText + "_");
|
||||
angleTextRect.moveCenter(screenPosAngle.toPoint());
|
||||
if (m_viewport->property("dimensionEditMode").toString() == "angle") {
|
||||
painter.fillRect(angleTextRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255));
|
||||
} else {
|
||||
painter.fillRect(angleTextRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50));
|
||||
}
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(angleTextRect, Qt::AlignCenter, angleText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,334 +289,8 @@ void ViewportWidget::paintGL()
|
||||
glDrawArrays(GL_LINES, 0, 8);
|
||||
}
|
||||
|
||||
if (m_isDefiningLine && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
||||
vertices.clear();
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
|
||||
QString dimInput = property("dimensionInput").toString();
|
||||
QString angleInput = property("angleInput").toString();
|
||||
bool lengthFromInput = false;
|
||||
bool angleFromInput = false;
|
||||
double inputLength = 0;
|
||||
double inputAngleDegrees = 0;
|
||||
|
||||
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 (angleFromInput) {
|
||||
QVector3D refDir;
|
||||
if (property("isChainedLine").toBool()) {
|
||||
refDir = property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) {
|
||||
refDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
refDir = QVector3D(0, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPos = unproject(m_currentMousePos, m_currentPlane);
|
||||
QVector3D mouseVec = currentMouseWorldPos - startPos;
|
||||
|
||||
// Quadrant snapping
|
||||
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 >= 0 && relativeMouseAngle < 90) { // Quadrant 1
|
||||
snappedAngle = inputAngleDegrees;
|
||||
} else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2
|
||||
snappedAngle = 180.0 - inputAngleDegrees;
|
||||
} else if (relativeMouseAngle < -90) { // Quadrant 3
|
||||
snappedAngle = -180.0 + inputAngleDegrees;
|
||||
} else { // Quadrant 4
|
||||
snappedAngle = -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(m_currentMousePos, 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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
worldPos = unproject(m_currentMousePos, m_currentPlane);
|
||||
if (m_isSnappingOrigin) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
} else if (m_isSnappingVertex) {
|
||||
worldPos.setX(m_snapVertex.X()); worldPos.setY(m_snapVertex.Y()); worldPos.setZ(m_snapVertex.Z());
|
||||
} else 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());
|
||||
}
|
||||
}
|
||||
|
||||
vertices << m_firstLinePoint.X() << m_firstLinePoint.Y() << m_firstLinePoint.Z();
|
||||
vertices << worldPos.x() << worldPos.y() << worldPos.z();
|
||||
|
||||
m_shaderProgram->setUniformValue(m_colorLoc, QVector4D(1.0f, 1.0f, 0.0f, 1.0f));
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
|
||||
// Draw dimension line
|
||||
QVector3D lineVec = worldPos - startPos;
|
||||
float lineLength = lineVec.length();
|
||||
|
||||
if (lineLength > 1e-6) {
|
||||
double refAngle, lineAngle, angleDiff;
|
||||
{
|
||||
QVector3D refDir;
|
||||
if (property("isChainedLine").toBool()) {
|
||||
refDir = property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 0, -1);
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
|
||||
float arrowLength = 0.02f * -m_camera->zoom();
|
||||
float arrowWidth = 0.005f * -m_camera->zoom();
|
||||
QVector3D lineDir = lineVec.normalized();
|
||||
|
||||
QVector3D arrow_base_end = dimEnd - arrowLength * lineDir;
|
||||
QVector3D arrowP1_end = arrow_base_end + arrowWidth * perpVec;
|
||||
QVector3D arrowP2_end = arrow_base_end - arrowWidth * perpVec;
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
vertices << arrowP1_end.x() << arrowP1_end.y() << arrowP1_end.z();
|
||||
vertices << dimEnd.x() << dimEnd.y() << dimEnd.z();
|
||||
vertices << arrowP2_end.x() << arrowP2_end.y() << arrowP2_end.z();
|
||||
|
||||
QVector3D arrow_base_start = dimStart + arrowLength * lineDir;
|
||||
QVector3D arrowP1_start = arrow_base_start + arrowWidth * perpVec;
|
||||
QVector3D arrowP2_start = arrow_base_start - arrowWidth * perpVec;
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << arrowP1_start.x() << arrowP1_start.y() << arrowP1_start.z();
|
||||
vertices << dimStart.x() << dimStart.y() << dimStart.z();
|
||||
vertices << arrowP2_start.x() << arrowP2_start.y() << arrowP2_start.z();
|
||||
|
||||
m_shaderProgram->setUniformValue(m_colorLoc, QVector4D(0.7f, 0.7f, 0.7f, 1.0f));
|
||||
glLineWidth(1.0f);
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, vertices.size() / 3);
|
||||
glLineWidth(2.0f);
|
||||
|
||||
// Draw angle dimension
|
||||
vertices.clear();
|
||||
const int numSegments = 30;
|
||||
const float radius = 0.1f * -m_camera->zoom();
|
||||
for (int i = 0; i <= numSegments; ++i) {
|
||||
double angle = refAngle + (lineAngle - refAngle) * i / numSegments;
|
||||
QVector3D p;
|
||||
if (m_currentPlane == SketchPlane::XY) p = startPos + radius * QVector3D(cos(angle), 0, sin(angle));
|
||||
else if (m_currentPlane == SketchPlane::XZ) p = startPos + radius * QVector3D(cos(angle), sin(angle), 0);
|
||||
else p = startPos + radius * QVector3D(0, cos(angle), sin(angle));
|
||||
vertices << p.x() << p.y() << p.z();
|
||||
}
|
||||
glLineWidth(1.0f);
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINE_STRIP, 0, vertices.size() / 3);
|
||||
|
||||
// Arrowheads for arc
|
||||
QVector<GLfloat> arrowVertices;
|
||||
float arcArrowLength = 0.02f * -m_camera->zoom();
|
||||
float arcArrowWidth = 0.005f * -m_camera->zoom();
|
||||
|
||||
double sign = (angleDiff >= 0) ? 1.0 : -1.0;
|
||||
|
||||
// End arrowhead
|
||||
QVector3D endPoint(vertices[vertices.size()-3], vertices[vertices.size()-2], vertices[vertices.size()-1]);
|
||||
double endAngle = lineAngle;
|
||||
QVector3D radialDir_end, tangentDir_end;
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
radialDir_end = QVector3D(cos(endAngle), 0, sin(endAngle));
|
||||
tangentDir_end = QVector3D(-sin(endAngle), 0, cos(endAngle));
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
radialDir_end = QVector3D(cos(endAngle), sin(endAngle), 0);
|
||||
tangentDir_end = QVector3D(-sin(endAngle), cos(endAngle), 0);
|
||||
} else {
|
||||
radialDir_end = QVector3D(0, cos(endAngle), sin(endAngle));
|
||||
tangentDir_end = QVector3D(0, -sin(endAngle), cos(endAngle));
|
||||
}
|
||||
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;
|
||||
arrowVertices << endPoint.x() << endPoint.y() << endPoint.z() << arc_arrowP1_end.x() << arc_arrowP1_end.y() << arc_arrowP1_end.z();
|
||||
arrowVertices << endPoint.x() << endPoint.y() << endPoint.z() << arc_arrowP2_end.x() << arc_arrowP2_end.y() << arc_arrowP2_end.z();
|
||||
|
||||
// Start arrowhead
|
||||
QVector3D startPoint(vertices[0], vertices[1], vertices[2]);
|
||||
double startAngle = refAngle;
|
||||
QVector3D radialDir_start, tangentDir_start;
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
radialDir_start = QVector3D(cos(startAngle), 0, sin(startAngle));
|
||||
tangentDir_start = QVector3D(-sin(startAngle), 0, cos(startAngle));
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
radialDir_start = QVector3D(cos(startAngle), sin(startAngle), 0);
|
||||
tangentDir_start = QVector3D(-sin(startAngle), cos(startAngle), 0);
|
||||
} else {
|
||||
radialDir_start = QVector3D(0, cos(startAngle), sin(startAngle));
|
||||
tangentDir_start = QVector3D(0, -sin(startAngle), cos(startAngle));
|
||||
}
|
||||
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;
|
||||
arrowVertices << startPoint.x() << startPoint.y() << startPoint.z() << arc_arrowP1_start.x() << arc_arrowP1_start.y() << arc_arrowP1_start.z();
|
||||
arrowVertices << startPoint.x() << startPoint.y() << startPoint.z() << arc_arrowP2_start.x() << arc_arrowP2_start.y() << arc_arrowP2_start.z();
|
||||
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(arrowVertices.constData(), arrowVertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, arrowVertices.size() / 3);
|
||||
glLineWidth(2.0f);
|
||||
}
|
||||
|
||||
if (!lengthFromInput && !angleFromInput && (m_isSnappingHorizontal || m_isSnappingVertical)) {
|
||||
vertices.clear();
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QVector3D midPoint = (startPos + worldPos) / 2.0;
|
||||
const float indicatorSize = 0.02f * -m_camera->zoom();
|
||||
const float indicatorOffset = 0.02f * -m_camera->zoom();
|
||||
if (m_isSnappingHorizontal) {
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
vertices << midPoint.x() - indicatorSize << midPoint.y() << midPoint.z() + indicatorOffset;
|
||||
vertices << midPoint.x() + indicatorSize << midPoint.y() << midPoint.z() + indicatorOffset;
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
vertices << midPoint.x() - indicatorSize << midPoint.y() + indicatorOffset << midPoint.z();
|
||||
vertices << midPoint.x() + indicatorSize << midPoint.y() + indicatorOffset << midPoint.z();
|
||||
} else if (m_currentPlane == SketchPlane::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() - indicatorSize << midPoint.z() + indicatorOffset;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorSize << midPoint.z() + indicatorOffset;
|
||||
}
|
||||
} else { // m_isSnappingVertical
|
||||
if (m_currentPlane == SketchPlane::XY) {
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() << midPoint.z() - indicatorSize;
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() << midPoint.z() + indicatorSize;
|
||||
} else if (m_currentPlane == SketchPlane::XZ) {
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() - indicatorSize << midPoint.z();
|
||||
vertices << midPoint.x() + indicatorOffset << midPoint.y() + indicatorSize << midPoint.z();
|
||||
} else if (m_currentPlane == SketchPlane::YZ) {
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() - indicatorSize;
|
||||
vertices << midPoint.x() << midPoint.y() + indicatorOffset << midPoint.z() + indicatorSize;
|
||||
}
|
||||
}
|
||||
m_vbo.bind();
|
||||
m_vbo.allocate(vertices.constData(), vertices.size() * sizeof(GLfloat));
|
||||
glDrawArrays(GL_LINES, 0, 2);
|
||||
}
|
||||
if (m_activeSketchTool) {
|
||||
m_activeSketchTool->paintGL();
|
||||
}
|
||||
|
||||
m_shaderProgram->release();
|
||||
@@ -755,240 +429,8 @@ void ViewportWidget::paintGL()
|
||||
}
|
||||
}
|
||||
|
||||
if (m_isDefiningLine && m_activeTool == static_cast<int>(ApplicationController::ToolType::Line)) {
|
||||
QVector3D worldPos;
|
||||
QVector3D startPos(m_firstLinePoint.X(), m_firstLinePoint.Y(), m_firstLinePoint.Z());
|
||||
QString dimText;
|
||||
QString angleText;
|
||||
|
||||
QString dimInput = property("dimensionInput").toString();
|
||||
QString angleInput = property("angleInput").toString();
|
||||
bool lengthFromInput = false;
|
||||
bool angleFromInput = false;
|
||||
double inputLength = 0;
|
||||
double inputAngleDegrees = 0;
|
||||
double lineLength = 0;
|
||||
|
||||
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 (angleFromInput) {
|
||||
QVector3D refDir;
|
||||
if (property("isChainedLine").toBool()) {
|
||||
refDir = property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) {
|
||||
refDir = QVector3D(1, 0, 0);
|
||||
} else { // YZ
|
||||
refDir = QVector3D(0, 0, -1);
|
||||
}
|
||||
}
|
||||
|
||||
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 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 >= 0 && relativeMouseAngle < 90) { // Quadrant 1
|
||||
snappedAngle = inputAngleDegrees;
|
||||
} else if (relativeMouseAngle >= 90 && relativeMouseAngle <= 180) { // Quadrant 2
|
||||
snappedAngle = 180.0 - inputAngleDegrees;
|
||||
} else if (relativeMouseAngle < -90) { // Quadrant 3
|
||||
snappedAngle = -180.0 + inputAngleDegrees;
|
||||
} else { // Quadrant 4
|
||||
snappedAngle = -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));
|
||||
|
||||
if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
} else {
|
||||
lineLength = QVector3D::dotProduct(mouseVec, finalDir);
|
||||
if (lineLength < 0) lineLength = 0;
|
||||
}
|
||||
worldPos = startPos + lineLength * finalDir;
|
||||
|
||||
} else if (lengthFromInput) {
|
||||
lineLength = inputLength;
|
||||
QVector3D currentMouseWorldPos = unproject(m_currentMousePos, 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);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
worldPos = unproject(m_currentMousePos, m_currentPlane);
|
||||
if (m_isSnappingOrigin) {
|
||||
worldPos.setX(0); worldPos.setY(0); worldPos.setZ(0);
|
||||
} else if (m_isSnappingVertex) {
|
||||
worldPos.setX(m_snapVertex.X()); worldPos.setY(m_snapVertex.Y()); worldPos.setZ(m_snapVertex.Z());
|
||||
} else 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());
|
||||
}
|
||||
lineLength = (worldPos - startPos).length();
|
||||
}
|
||||
|
||||
QVector3D lineVec = worldPos - startPos;
|
||||
if (lineVec.length() > 1e-6) {
|
||||
double refAngle, lineAngle;
|
||||
QVector3D refDir;
|
||||
if (property("isChainedLine").toBool()) {
|
||||
refDir = property("previousLineDirection").value<QVector3D>();
|
||||
} else {
|
||||
if (m_currentPlane == SketchPlane::XY || m_currentPlane == SketchPlane::XZ) refDir = QVector3D(1, 0, 0);
|
||||
else refDir = QVector3D(0, 0, -1);
|
||||
}
|
||||
|
||||
QVector3D currentMouseWorldPosForText = unproject(m_currentMousePos, m_currentPlane);
|
||||
QVector3D mouseVecForText = currentMouseWorldPosForText - startPos;
|
||||
|
||||
if (angleFromInput) {
|
||||
if (mouseVecForText.length() > 1e-6) {
|
||||
double mouseAngle;
|
||||
if (m_currentPlane == SketchPlane::XY) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.x()));
|
||||
else if (m_currentPlane == SketchPlane::XZ) mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.y(), mouseVecForText.x()));
|
||||
else mouseAngle = qRadiansToDegrees(atan2(mouseVecForText.z(), mouseVecForText.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());
|
||||
}
|
||||
|
||||
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_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;
|
||||
|
||||
angleText = angleFromInput ? angleInput : QString::number(qAbs(angleDiffDegrees), 'f', 1) + QChar(0x00B0);
|
||||
|
||||
const float radius = 0.1f * -m_camera->zoom();
|
||||
double midAngle = refAngle + (lineAngle - refAngle) / 2.0;
|
||||
QVector3D textPos3DAngle;
|
||||
float textOffset = 0.035f * -m_camera->zoom();
|
||||
|
||||
if (m_currentPlane == SketchPlane::XY) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), 0, sin(midAngle));
|
||||
else if (m_currentPlane == SketchPlane::XZ) textPos3DAngle = startPos + (radius + textOffset) * QVector3D(cos(midAngle), sin(midAngle), 0);
|
||||
else textPos3DAngle = startPos + (radius + textOffset) * QVector3D(0, cos(midAngle), sin(midAngle));
|
||||
|
||||
QVector3D screenPosAngle = project(textPos3DAngle, model, projection, rect());
|
||||
if (screenPosAngle.z() < 1.0f) {
|
||||
QRect angleTextRect = fm.boundingRect(angleText + "_");
|
||||
angleTextRect.moveCenter(screenPosAngle.toPoint());
|
||||
if (property("dimensionEditMode").toString() == "angle") {
|
||||
painter.fillRect(angleTextRect.adjusted(-4, -2, 4, 2), QColor(64, 128, 255));
|
||||
} else {
|
||||
painter.fillRect(angleTextRect.adjusted(-4, -2, 4, 2), QColor(50, 50, 50));
|
||||
}
|
||||
painter.setPen(Qt::white);
|
||||
painter.drawText(angleTextRect, Qt::AlignCenter, angleText);
|
||||
}
|
||||
}
|
||||
if (m_activeSketchTool) {
|
||||
m_activeSketchTool->paint2D(painter, model, projection);
|
||||
}
|
||||
|
||||
painter.end();
|
||||
|
||||
@@ -39,6 +39,20 @@ public:
|
||||
|
||||
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);
|
||||
QOpenGLShaderProgram* shaderProgram() { return m_shaderProgram; }
|
||||
QOpenGLBuffer& vbo() { return m_vbo; }
|
||||
int colorLoc() const { return m_colorLoc; }
|
||||
Camera* camera() const { return m_camera; }
|
||||
SketchPlane currentPlane() const { return m_currentPlane; }
|
||||
const QPoint& currentMousePos() const { return m_currentMousePos; }
|
||||
bool isSnappingOrigin() const { return m_isSnappingOrigin; }
|
||||
bool isSnappingVertex() const { return m_isSnappingVertex; }
|
||||
const gp_Pnt& snapVertex() const { return m_snapVertex; }
|
||||
bool isSnappingHorizontal() const { return m_isSnappingHorizontal; }
|
||||
bool isSnappingVertical() const { return m_isSnappingVertical; }
|
||||
|
||||
public slots:
|
||||
void onSketchModeStarted(SketchPlane plane);
|
||||
void onSketchModeEnded();
|
||||
@@ -64,8 +78,6 @@ protected:
|
||||
|
||||
private:
|
||||
void initShaders();
|
||||
QVector3D project(const QVector3D& worldCoord, const QMatrix4x4& modelView, const QMatrix4x4& projection, const QRect& viewport);
|
||||
QVector3D unproject(const QPoint& screenPos, SketchPlane plane);
|
||||
void drawAxisLabels(QPainter& painter, const QMatrix4x4& modelView, const QMatrix4x4& projection);
|
||||
void drawSketch(const SketchFeature* sketch);
|
||||
void drawSelectionPlanes();
|
||||
|
||||
Reference in New Issue
Block a user