From 577fb5f84608d9c9e016c6508ae63e40e0a4b99e Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 3 Mar 2026 15:44:13 -0700 Subject: [PATCH] refactor: Use gp_Ax2 for sketch plane definition and drawing Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/SketchFeature.cpp | 68 ++++++++++++++++++++++++++++++++--------- src/SketchFeature.h | 13 +++----- src/ViewportWidget.cpp | 69 ++++++++++++++++++------------------------ 3 files changed, 87 insertions(+), 63 deletions(-) diff --git a/src/SketchFeature.cpp b/src/SketchFeature.cpp index af3b069..fcb83b6 100644 --- a/src/SketchFeature.cpp +++ b/src/SketchFeature.cpp @@ -12,11 +12,37 @@ #include #include +#include +#include #include +#include + +namespace +{ + void gpPntToJson(const gp_Pnt& p, QJsonObject& json) { + json["x"] = p.X(); + json["y"] = p.Y(); + json["z"] = p.Z(); + } + + gp_Pnt jsonToGpPnt(const QJsonObject& json) { + return gp_Pnt(json["x"].toDouble(), json["y"].toDouble(), json["z"].toDouble()); + } + + void gpDirToJson(const gp_Dir& d, QJsonObject& json) { + json["x"] = d.X(); + json["y"] = d.Y(); + json["z"] = d.Z(); + } + + gp_Dir jsonToGpDir(const QJsonObject& json) { + return gp_Dir(json["x"].toDouble(), json["y"].toDouble(), json["z"].toDouble()); + } +} SketchFeature::SketchFeature(const QString& name) - : Feature(name) + : Feature(name), m_plane(gp_Pnt(0, 0, 0), gp::DZ()) { BRep_Builder builder; TopoDS_Compound compound; @@ -34,12 +60,12 @@ QString SketchFeature::type() const return "Sketch"; } -void SketchFeature::setPlane(SketchPlane plane) +void SketchFeature::setPlane(const gp_Ax2& plane) { m_plane = plane; } -SketchFeature::SketchPlane SketchFeature::plane() const +const gp_Ax2& SketchFeature::plane() const { return m_plane; } @@ -68,11 +94,14 @@ const QList& SketchFeature::objects() const void SketchFeature::read(const QJsonObject& json) { Feature::read(json); - if (json.contains("plane") && json["plane"].isString()) { - QString planeStr = json["plane"].toString(); - if (planeStr == "XY") m_plane = SketchPlane::XY; - else if (planeStr == "XZ") m_plane = SketchPlane::XZ; - else if (planeStr == "YZ") m_plane = SketchPlane::YZ; + if (json.contains("plane") && json["plane"].isObject()) { + QJsonObject planeJson = json["plane"].toObject(); + if (planeJson.contains("origin") && planeJson.contains("normal") && planeJson.contains("x_direction")) { + gp_Pnt origin = jsonToGpPnt(planeJson["origin"].toObject()); + gp_Dir normal = jsonToGpDir(planeJson["normal"].toObject()); + gp_Dir x_dir = jsonToGpDir(planeJson["x_direction"].toObject()); + m_plane = gp_Ax2(origin, normal, x_dir); + } } if (json.contains("objects") && json["objects"].isArray()) { @@ -100,13 +129,22 @@ void SketchFeature::read(const QJsonObject& json) void SketchFeature::write(QJsonObject& json) const { Feature::write(json); - QString planeStr; - switch (m_plane) { - case SketchPlane::XY: planeStr = "XY"; break; - case SketchPlane::XZ: planeStr = "XZ"; break; - case SketchPlane::YZ: planeStr = "YZ"; break; - } - json["plane"] = planeStr; + + QJsonObject planeJson; + + QJsonObject originJson; + gpPntToJson(m_plane.Location(), originJson); + planeJson["origin"] = originJson; + + QJsonObject normalJson; + gpDirToJson(m_plane.Direction(), normalJson); + planeJson["normal"] = normalJson; + + QJsonObject xDirJson; + gpDirToJson(m_plane.XDirection(), xDirJson); + planeJson["x_direction"] = xDirJson; + + json["plane"] = planeJson; QJsonArray objectsArray; for (const auto& object : m_objects) { diff --git a/src/SketchFeature.h b/src/SketchFeature.h index 5189dd0..303fd81 100644 --- a/src/SketchFeature.h +++ b/src/SketchFeature.h @@ -9,6 +9,7 @@ #define SKETCHFEATURE_H #include +#include #include #include "Feature.h" @@ -17,19 +18,13 @@ class SketchObject; class SketchFeature : public Feature { public: - enum class SketchPlane { - XY, - XZ, - YZ - }; - SketchFeature(const QString& name); ~SketchFeature(); QString type() const override; - void setPlane(SketchPlane plane); - SketchPlane plane() const; + void setPlane(const gp_Ax2& plane); + const gp_Ax2& plane() const; const TopoDS_Shape& shape() const; void addShape(const TopoDS_Shape& shape); @@ -41,7 +36,7 @@ public: void write(QJsonObject &json) const override; private: - SketchPlane m_plane; + gp_Ax2 m_plane; TopoDS_Shape m_shape; QList m_objects; }; diff --git a/src/ViewportWidget.cpp b/src/ViewportWidget.cpp index eaa7ff6..bfb8608 100644 --- a/src/ViewportWidget.cpp +++ b/src/ViewportWidget.cpp @@ -33,6 +33,8 @@ #include #include #include +#include +#include #include #include #include @@ -538,20 +540,11 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch) const int numSegments = 64; QVector3D u_axis, v_axis; - switch (sketch->plane()) { - case SketchFeature::SketchPlane::XY: // Top - u_axis = QVector3D(1, 0, 0); - v_axis = QVector3D(0, 1, 0); - break; - case SketchFeature::SketchPlane::XZ: // Front - u_axis = QVector3D(1, 0, 0); - v_axis = QVector3D(0, 0, 1); - break; - case SketchFeature::SketchPlane::YZ: // Right - u_axis = QVector3D(0, 1, 0); - v_axis = QVector3D(0, 0, 1); - break; - } + const auto& plane = sketch->plane(); + const auto& xDir = plane.XDirection(); + const auto& yDir = plane.YDirection(); + u_axis = QVector3D(xDir.X(), xDir.Y(), xDir.Z()); + v_axis = QVector3D(yDir.X(), yDir.Y(), yDir.Z()); for (int i = 0; i < numSegments; ++i) { double angle1 = 2.0 * M_PI * double(i) / double(numSegments); @@ -565,34 +558,32 @@ void ViewportWidget::drawSketch(const SketchFeature* sketch) } } else if (obj->type() == SketchObject::ObjectType::Rectangle) { auto rect = static_cast(obj); - const auto& p1 = rect->corner1(); - const auto& p3 = rect->corner2(); + const auto& plane = sketch->plane(); + const auto& p1_3d = rect->corner1(); + const auto& p3_3d = rect->corner2(); - gp_Pnt p2, p4; - if (sketch->plane() == SketchFeature::SketchPlane::XY) { - p2.SetCoord(p3.X(), p1.Y(), p1.Z()); - p4.SetCoord(p1.X(), p3.Y(), p1.Z()); - } else if (sketch->plane() == SketchFeature::SketchPlane::XZ) { - p2.SetCoord(p3.X(), p1.Y(), p1.Z()); - p4.SetCoord(p1.X(), p1.Y(), p3.Z()); - } else if (sketch->plane() == SketchFeature::SketchPlane::YZ) { - p2.SetCoord(p1.X(), p3.Y(), p1.Z()); - p4.SetCoord(p1.X(), p1.Y(), p3.Z()); - } + gp_Pnt2d p1_2d = ElCLib::To2d(p1_3d, plane); + gp_Pnt2d p3_2d = ElCLib::To2d(p3_3d, plane); - lineVertices << p1.X() << p1.Y() << p1.Z(); - lineVertices << p2.X() << p2.Y() << p2.Z(); - lineVertices << p2.X() << p2.Y() << p2.Z(); - lineVertices << p3.X() << p3.Y() << p3.Z(); - lineVertices << p3.X() << p3.Y() << p3.Z(); - lineVertices << p4.X() << p4.Y() << p4.Z(); - lineVertices << p4.X() << p4.Y() << p4.Z(); - lineVertices << p1.X() << p1.Y() << p1.Z(); + gp_Pnt2d p2_2d(p3_2d.X(), p1_2d.Y()); + gp_Pnt2d p4_2d(p1_2d.X(), p3_2d.Y()); - vertexCounts[p1] += 2; - vertexCounts[p2] += 2; - vertexCounts[p3] += 2; - vertexCounts[p4] += 2; + gp_Pnt p2_3d = ElCLib::To3d(p2_2d, plane); + gp_Pnt p4_3d = ElCLib::To3d(p4_2d, plane); + + lineVertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z(); + lineVertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z(); + lineVertices << p2_3d.X() << p2_3d.Y() << p2_3d.Z(); + lineVertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z(); + lineVertices << p3_3d.X() << p3_3d.Y() << p3_3d.Z(); + lineVertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z(); + lineVertices << p4_3d.X() << p4_3d.Y() << p4_3d.Z(); + lineVertices << p1_3d.X() << p1_3d.Y() << p1_3d.Z(); + + vertexCounts[p1_3d] += 2; + vertexCounts[p2_3d] += 2; + vertexCounts[p3_3d] += 2; + vertexCounts[p4_3d] += 2; } }