#include "CircleTool.h" #include "ViewportWidget.h" #include "Camera.h" #include #include #include #include #include #include #include CircleTool::CircleTool(ViewportWidget* viewport) : SketchTool(viewport) { } void CircleTool::activate() { SketchTool::activate(); m_dimensionModes.clear(); m_dimensionModes << "diameter"; m_dimensionPropertyNames.clear(); m_dimensionPropertyNames["diameter"] = "diameterInput"; m_viewport->setProperty("diameterInput", ""); m_viewport->setProperty("dimensionEditMode", "diameter"); } void CircleTool::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_centerPoint = p; m_isDefining = true; m_dimensionModes.clear(); m_dimensionModes << "diameter"; m_dimensionPropertyNames.clear(); m_dimensionPropertyNames["diameter"] = "diameterInput"; m_viewport->setProperty("diameterInput", ""); m_viewport->setProperty("dimensionEditMode", "diameter"); } else { QVector3D worldPos; QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); 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; } if (diameterFromInput) { QVector3D mousePos = m_viewport->unproject(event->pos(), m_viewport->currentPlane()); 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); } } double radius = inputDiameter / 2.0; worldPos = centerPos + mouseDir.normalized() * radius; } 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->circleAdded(m_centerPoint, m_centerPoint.Distance(p)); deactivate(); } } void CircleTool::mouseMoveEvent(QMouseEvent *event) { // To be implemented } void CircleTool::finalizeCreation() { QVector3D worldPos; QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); 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; } if (diameterFromInput) { QVector3D mousePos = m_viewport->unproject(m_viewport->currentMousePos(), m_viewport->currentPlane()); 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); } } double radius = inputDiameter / 2.0; worldPos = centerPos + mouseDir.normalized() * radius; } 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->circleAdded(m_centerPoint, m_centerPoint.Distance(p)); deactivate(); } void CircleTool::paintGL() { if (m_isDefining) { QVector vertices; QVector3D worldPos; QVector3D centerPos(m_centerPoint.X(), m_centerPoint.Y(), m_centerPoint.Z()); 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(), 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()); 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 if (m_viewport->currentPlane() == ViewportWidget::SketchPlane::XZ) { 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 { // 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); } } 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()); 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(), m_viewport->currentPlane()); QVector3D edgePos; double diameter; 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); } 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); } } }