Skip to content

Commit

Permalink
PartDesign: Fix #9377 - issue with accuracy in AdditiveHelix (#11312)
Browse files Browse the repository at this point in the history
* Correct precision issue in PartDesign::AdditiveHelix

* Simplify getting the end wires

* Remove extraneous loop per @FlachyJoe

* Switch to using mkPS.Shape per @FlachyJoe

* Incorporate guarded efficiency improvement
  • Loading branch information
bgbsww committed Nov 30, 2023
1 parent b1a96bd commit 94ca51b
Showing 1 changed file with 24 additions and 57 deletions.
81 changes: 24 additions & 57 deletions src/Mod/PartDesign/App/FeatureHelix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,75 +227,42 @@ App::DocumentObjectExecReturn* Helix::execute()
return new App::DocumentObjectExecReturn(e.what());
}

std::vector<std::vector<TopoDS_Wire>> wiresections;
for (TopoDS_Wire& wire : wires)
wiresections.emplace_back(1, wire);

//build all shells
std::vector<TopoDS_Shape> shells;
std::vector<TopoDS_Wire> frontwires, backwires;
for (std::vector<TopoDS_Wire>& wires : wiresections) {

BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));

mkPS.SetTolerance(Precision::Confusion());
mkPS.SetTransitionMode(BRepBuilderAPI_Transformed);

if (Angle.getValue() == 0) {
mkPS.SetMode(true); //This is for frenet
} else {
mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxiliary
}

for (TopoDS_Wire& wire : wires) {
wire.Move(invObjLoc);
mkPS.Add(wire);
}
BRepOffsetAPI_MakePipeShell mkPS(TopoDS::Wire(path));

if (!mkPS.IsReady())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Could not build"));
mkPS.SetTolerance(Precision::Confusion());
mkPS.SetTransitionMode(BRepBuilderAPI_Transformed);

shells.push_back(mkPS.Shape());
mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxiliary

if (!mkPS.Shape().Closed()) {
// shell is not closed - use simulate to get the end wires
TopTools_ListOfShape sim;
mkPS.Simulate(2, sim);

frontwires.push_back(TopoDS::Wire(sim.First()));
backwires.push_back(TopoDS::Wire(sim.Last()));
}
if (Angle.getValue() == 0) {
mkPS.SetMode(true); // This is for frenet, quicker than auxiliary
// but can introduce to much error, checked below
} else {
mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxiliary
}

BRepBuilderAPI_MakeSolid mkSolid;

if (!frontwires.empty()) {
// build the end faces, sew the shell and build the final solid
TopoDS_Shape front = Part::FaceMakerCheese::makeFace(frontwires);
TopoDS_Shape back = Part::FaceMakerCheese::makeFace(backwires);
for (TopoDS_Wire& wire : wires) {
wire.Move(invObjLoc);
mkPS.Add(wire);
}

BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
sewer.Add(front);
sewer.Add(back);
if (!mkPS.IsReady())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Could not build"));

for (TopoDS_Shape& s : shells)
sewer.Add(s);
mkPS.Build();

sewer.Perform();
mkSolid.Add(TopoDS::Shell(sewer.SewedShape()));
}
else {
// shells are already closed - add them directly
for (TopoDS_Shape& s : shells) {
mkSolid.Add(TopoDS::Shell(s));
}
//check for error value at pipe creation and re-build if needed
if (Angle.getValue() == 0 && mkPS.ErrorOnSurface() < Precision::Confusion() / 2.0 ) {
Base::Console().Log("PartDesign_Helix : Fall back to auxiliary mode\n");
mkPS.SetMode(TopoDS::Wire(auxpath), true);
mkPS.Build();
}

if (!mkSolid.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Result is not a solid"));
if (!mkPS.MakeSolid())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Could not make solid helix with open wire"));

TopoDS_Shape result = mkSolid.Shape();
TopoDS_Shape result = mkPS.Shape();

BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
Expand Down

0 comments on commit 94ca51b

Please sign in to comment.