From e2dfdf1600352924e7dbb3f58c5e8d0bd93fa70d Mon Sep 17 00:00:00 2001 From: Tanner Collin Date: Tue, 17 Feb 2026 17:52:17 -0700 Subject: [PATCH] feat: Generate faces from closed sketch wires Co-authored-by: aider (gemini/gemini-2.5-pro) --- src/ApplicationController.cpp | 3 + src/SketchFeature.cpp | 104 ++++++++++++++++++++++++++++++++++ src/SketchFeature.h | 2 + 3 files changed, 109 insertions(+) diff --git a/src/ApplicationController.cpp b/src/ApplicationController.cpp index 43ae3d9..787dac6 100644 --- a/src/ApplicationController.cpp +++ b/src/ApplicationController.cpp @@ -158,6 +158,9 @@ void ApplicationController::addCircle(const gp_Pnt& center, double radius) void ApplicationController::endSketch() { + if (m_activeSketch) { + m_activeSketch->buildShape(); + } m_activeSketch = nullptr; setActiveTool(ToolType::None); emit sketchModeEnded(); diff --git a/src/SketchFeature.cpp b/src/SketchFeature.cpp index eae6d17..a10c6dc 100644 --- a/src/SketchFeature.cpp +++ b/src/SketchFeature.cpp @@ -2,6 +2,17 @@ #include "SketchObject.h" #include "SketchLine.h" #include "SketchRectangle.h" +#include "SketchCircle.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include #include @@ -35,6 +46,99 @@ const TopoDS_Shape& SketchFeature::shape() const return m_shape; } +void SketchFeature::buildShape() +{ + m_shape.Nullify(); + QList lineEdges; + QList faces; + + for (SketchObject* obj : m_objects) { + if (auto line = dynamic_cast(obj)) { + lineEdges.append(BRepBuilderAPI_MakeEdge(line->startPoint(), line->endPoint()).Edge()); + } else if (auto rect = dynamic_cast(obj)) { + const gp_Pnt& c1 = rect->corner1(); + const gp_Pnt& c2 = rect->corner2(); + gp_Pnt other_corner1, other_corner2; + + if (m_plane == SketchPlane::XY) { + other_corner1.SetCoord(c1.X(), c2.Y(), c1.Z()); + other_corner2.SetCoord(c2.X(), c1.Y(), c1.Z()); + } else if (m_plane == SketchPlane::XZ) { + other_corner1.SetCoord(c1.X(), c1.Y(), c2.Z()); + other_corner2.SetCoord(c2.X(), c1.Y(), c1.Z()); + } else { // YZ + other_corner1.SetCoord(c1.X(), c1.Y(), c2.Z()); + other_corner2.SetCoord(c1.X(), c2.Y(), c1.Z()); + } + + TopoDS_Edge e1 = BRepBuilderAPI_MakeEdge(c1, other_corner1).Edge(); + TopoDS_Edge e2 = BRepBuilderAPI_MakeEdge(other_corner1, c2).Edge(); + TopoDS_Edge e3 = BRepBuilderAPI_MakeEdge(c2, other_corner2).Edge(); + TopoDS_Edge e4 = BRepBuilderAPI_MakeEdge(other_corner2, c1).Edge(); + BRepBuilderAPI_MakeWire wireBuilder(e1, e2, e3, e4); + if (wireBuilder.IsDone()) { + BRepBuilderAPI_MakeFace faceBuilder(wireBuilder.Wire()); + if (faceBuilder.IsDone()) { + faces.append(faceBuilder.Face()); + } + } + } else if (auto circle = dynamic_cast(obj)) { + const gp_Pnt& center = circle->center(); + double radius = circle->radius(); + gp_Dir normal; + switch (m_plane) { + case SketchPlane::XY: normal = gp::DZ(); break; + case SketchPlane::XZ: normal = gp::DY(); break; + case SketchPlane::YZ: normal = gp::DX(); break; + } + gp_Ax2 axis(center, normal); + gp_Circ circ(axis, radius); + TopoDS_Edge edge = BRepBuilderAPI_MakeEdge(circ).Edge(); + BRepBuilderAPI_MakeWire wireBuilder(edge); + if(wireBuilder.IsDone()) { + BRepBuilderAPI_MakeFace faceBuilder(wireBuilder.Wire()); + if (faceBuilder.IsDone()) { + faces.append(faceBuilder.Face()); + } + } + } + } + + if (!lineEdges.isEmpty()) { + BRepBuilderAPI_MakeWire wireBuilder; + wireBuilder.Add(lineEdges); + if (wireBuilder.IsDone()) { + TopoDS_Shape wiresShape = wireBuilder.Shape(); + TopExp_Explorer explorer(wiresShape, TopAbs_WIRE); + for (; explorer.More(); explorer.Next()) { + TopoDS_Wire wire = TopoDS::Wire(explorer.Current()); + if (wire.Closed()) { + BRepBuilderAPI_MakeFace faceBuilder(wire); + if (faceBuilder.IsDone()) { + faces.append(faceBuilder.Face()); + } + } + } + } + } + + if (faces.isEmpty()) { + return; + } + + if (faces.size() == 1) { + m_shape = faces.first(); + } else { + TopoDS_Compound compound; + BRep_Builder builder; + builder.MakeCompound(compound); + for (const auto& face : faces) { + builder.Add(compound, face); + } + m_shape = compound; + } +} + void SketchFeature::addObject(SketchObject* object) { m_objects.append(object); diff --git a/src/SketchFeature.h b/src/SketchFeature.h index 7af7e29..881c8b7 100644 --- a/src/SketchFeature.h +++ b/src/SketchFeature.h @@ -26,6 +26,8 @@ public: const TopoDS_Shape& shape() const; + void buildShape(); + void addObject(SketchObject* object); const QList& objects() const;