feat: Generate faces from closed sketch wires

Co-authored-by: aider (gemini/gemini-2.5-pro) <aider@aider.chat>
This commit is contained in:
2026-02-17 17:52:17 -07:00
parent 2333a7cdb5
commit e2dfdf1600
3 changed files with 109 additions and 0 deletions

View File

@@ -158,6 +158,9 @@ void ApplicationController::addCircle(const gp_Pnt& center, double radius)
void ApplicationController::endSketch() void ApplicationController::endSketch()
{ {
if (m_activeSketch) {
m_activeSketch->buildShape();
}
m_activeSketch = nullptr; m_activeSketch = nullptr;
setActiveTool(ToolType::None); setActiveTool(ToolType::None);
emit sketchModeEnded(); emit sketchModeEnded();

View File

@@ -2,6 +2,17 @@
#include "SketchObject.h" #include "SketchObject.h"
#include "SketchLine.h" #include "SketchLine.h"
#include "SketchRectangle.h" #include "SketchRectangle.h"
#include "SketchCircle.h"
#include <BRepBuilderAPI_MakeEdge.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRep_Builder.hxx>
#include <TopoDS_Compound.hxx>
#include <TopoDS.hxx>
#include <gp_Circ.hxx>
#include <gp_Ax2.hxx>
#include <TopExp_Explorer.hxx>
#include <QJsonArray> #include <QJsonArray>
@@ -35,6 +46,99 @@ const TopoDS_Shape& SketchFeature::shape() const
return m_shape; return m_shape;
} }
void SketchFeature::buildShape()
{
m_shape.Nullify();
QList<TopoDS_Edge> lineEdges;
QList<TopoDS_Face> faces;
for (SketchObject* obj : m_objects) {
if (auto line = dynamic_cast<SketchLine*>(obj)) {
lineEdges.append(BRepBuilderAPI_MakeEdge(line->startPoint(), line->endPoint()).Edge());
} else if (auto rect = dynamic_cast<SketchRectangle*>(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<SketchCircle*>(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) void SketchFeature::addObject(SketchObject* object)
{ {
m_objects.append(object); m_objects.append(object);

View File

@@ -26,6 +26,8 @@ public:
const TopoDS_Shape& shape() const; const TopoDS_Shape& shape() const;
void buildShape();
void addObject(SketchObject* object); void addObject(SketchObject* object);
const QList<SketchObject*>& objects() const; const QList<SketchObject*>& objects() const;