Skip to content

Commit

Permalink
Revert "[PD] Revert 316506f, back to shell algo for some helix cases (F…
Browse files Browse the repository at this point in the history
…reeCAD#15678)"

This reverts commit dcfae6a.
  • Loading branch information
chennes committed Aug 6, 2024
1 parent 270bb01 commit 74e5c3f
Show file tree
Hide file tree
Showing 3 changed files with 12 additions and 79 deletions.
85 changes: 9 additions & 76 deletions src/Mod/PartDesign/App/FeatureHelix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -232,78 +232,12 @@ App::DocumentObjectExecReturn* Helix::execute()

// generate the helix path
TopoDS_Shape path = generateHelixPath();
TopoDS_Shape auxpath = generateHelixPath(1.0);

// Use MakePipe for frenet ( Angle is 0 ) calculations, faster than MakePipeShell
if ( Angle.getValue() == 0 ) {
TopoDS_Shape face = Part::FaceMakerCheese::makeFace(wires);
face.Move(invObjLoc);
BRepOffsetAPI_MakePipe mkPS(TopoDS::Wire(path), face, GeomFill_Trihedron::GeomFill_IsFrenet, Standard_False);
result = mkPS.Shape();
} else {
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));

// Frenet mode doesn't place the face quite right on an angled helix, so
// use the auxiliary spine to force that.
mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxiliary

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

if (!mkPS.IsReady())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Could not build"));
mkPS.Build();

shells.push_back(mkPS.Shape());

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()));
}
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);

BRepBuilderAPI_Sewing sewer;
sewer.SetTolerance(Precision::Confusion());
sewer.Add(front);
sewer.Add(back);

for (TopoDS_Shape& s : shells)
sewer.Add(s);
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));
}
}
if (!mkSolid.IsDone())
return new App::DocumentObjectExecReturn(QT_TRANSLATE_NOOP("Exception", "Error: Result is not a solid"));

result = mkSolid.Shape();
}
}

TopoDS_Shape face = Part::FaceMakerCheese::makeFace(wires);
face.Move(invObjLoc);
BRepOffsetAPI_MakePipe mkPS(TopoDS::Wire(path), face, GeomFill_Trihedron::GeomFill_IsFrenet, Standard_False);
mkPS.Build();
result = mkPS.Shape();

BRepClass3d_SolidClassifier SC(result);
SC.PerformInfinitePoint(Precision::Confusion());
Expand Down Expand Up @@ -401,7 +335,7 @@ void Helix::updateAxis()
Axis.setValue(dir.x, dir.y, dir.z);
}

TopoDS_Shape Helix::generateHelixPath(double startOffset0)
TopoDS_Shape Helix::generateHelixPath()
{
double turns = Turns.getValue();
double height = Height.getValue();
Expand Down Expand Up @@ -447,7 +381,7 @@ TopoDS_Shape Helix::generateHelixPath(double startOffset0)
bool turned = axisOffset < 0;
// since the factor does not only change the radius but also the path position, we must shift its offset back
// using the square of the factor
double startOffset = 10000.0 * std::fabs(startOffset0 + profileCenter * axisVector - baseVector * axisVector);
double startOffset = 10000.0 * std::fabs(baseVector * axisVector);

if (radius < Precision::Confusion()) {
// in this case ensure that axis is not in the sketch plane
Expand All @@ -464,8 +398,7 @@ TopoDS_Shape Helix::generateHelixPath(double startOffset0)
radiusTop = radius + height * tan(Base::toRadians(angle));

//build the helix path
//TopoShape helix = TopoShape().makeLongHelix(pitch, height, radius, angle, leftHanded);
TopoDS_Shape path = TopoShape().makeSpiralHelix(radius, radiusTop, height, turns, 1, leftHanded);
TopoDS_Shape path = TopoShape().makeSpiralHelix(radius, radiusTop, height, turns, 1000, leftHanded);

/*
* The helix wire is created with the axis coinciding with z-axis and the start point at (radius, 0, 0)
Expand Down
2 changes: 1 addition & 1 deletion src/Mod/PartDesign/App/FeatureHelix.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ class PartDesignExport Helix : public ProfileBased
void updateAxis();

/// generate helix and move it to the right location.
TopoDS_Shape generateHelixPath(double startOffset0 = 0.0);
TopoDS_Shape generateHelixPath();

// project shape on plane. Used for detecting self intersection.
TopoDS_Shape projectShape(const TopoDS_Shape& input, const gp_Ax2& plane);
Expand Down
4 changes: 2 additions & 2 deletions src/Mod/PartDesign/PartDesignTests/TestHelix.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def testCircleQ1(self):

profileSketch.addGeometry(Part.Circle(FreeCAD.Vector(2, 0, 0), FreeCAD.Vector(0,0,1), 0.5) )
self.Doc.recompute()
self.assertAlmostEqual(helix.Shape.Volume, 100.63, places=2)
self.assertAlmostEqual(helix.Shape.Volume, 100.63,places=2)


def testRectangle(self):
Expand Down Expand Up @@ -174,7 +174,7 @@ def testCone(self):
helix.Mode = 0
helix.Reversed = True
self.Doc.recompute()
self.assertAlmostEqual(helix.Shape.Volume/1e5, 3.8828, places=3)
self.assertAlmostEqual(helix.Shape.Volume/1e5, 3.8828,places=4)

def tearDown(self):
FreeCAD.closeDocument("PartDesignTestHelix")
Expand Down

0 comments on commit 74e5c3f

Please sign in to comment.