diff --git a/src/Mod/PartDesign/App/FeatureHelix.cpp b/src/Mod/PartDesign/App/FeatureHelix.cpp index 3b61cecbce29..3aa6e0c9e917 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.cpp +++ b/src/Mod/PartDesign/App/FeatureHelix.cpp @@ -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> wiresections; - for (TopoDS_Wire& wire : wires) - wiresections.emplace_back(1, wire); - - //build all shells - std::vector shells; - std::vector frontwires, backwires; - for (std::vector& 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()); @@ -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(); @@ -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 @@ -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) diff --git a/src/Mod/PartDesign/App/FeatureHelix.h b/src/Mod/PartDesign/App/FeatureHelix.h index 531ded92d60c..3a4a3a7cb7e8 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.h +++ b/src/Mod/PartDesign/App/FeatureHelix.h @@ -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); diff --git a/src/Mod/PartDesign/PartDesignTests/TestHelix.py b/src/Mod/PartDesign/PartDesignTests/TestHelix.py index d89b3cb1a2e2..fb5c91792870 100644 --- a/src/Mod/PartDesign/PartDesignTests/TestHelix.py +++ b/src/Mod/PartDesign/PartDesignTests/TestHelix.py @@ -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): @@ -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")