From 9c142ccb8bf6413cfc8ea101ace7ee479c7f35ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20=C3=96sterberg?= Date: Sun, 9 Jan 2022 22:13:15 +0100 Subject: [PATCH] PartDesign: Improve orientation behaviour for conical helices (#5363) * PartDesign: Improve orientation behavior for conical helices As identified in the forum https://forum.freecadweb.org/viewtopic.php?f=3&t=65136 The Freenet orientation mode does not give expected results for helices with cone angle. By using an auxiliary helix that is axially offset it is guaranteed that the orientation frame is always consistent with a cylindrical coordinate system. Results will be the same as before when cone angle is 0. --- src/Mod/PartDesign/App/FeatureHelix.cpp | 17 ++++++++++++----- src/Mod/PartDesign/App/FeatureHelix.h | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/Mod/PartDesign/App/FeatureHelix.cpp b/src/Mod/PartDesign/App/FeatureHelix.cpp index cc77422642..1c57d1b65a 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.cpp +++ b/src/Mod/PartDesign/App/FeatureHelix.cpp @@ -227,6 +227,8 @@ App::DocumentObjectExecReturn* Helix::execute(void) // generate the helix path TopoDS_Shape path = generateHelixPath(); + TopoDS_Shape auxpath = generateHelixPath(1.0); + std::vector wires; try { @@ -249,7 +251,9 @@ App::DocumentObjectExecReturn* Helix::execute(void) mkPS.SetTolerance(Precision::Confusion()); mkPS.SetTransitionMode(BRepBuilderAPI_Transformed); - mkPS.SetMode(true); //This is for frenet + + //mkPS.SetMode(true); //This is for frenet + mkPS.SetMode(TopoDS::Wire(auxpath), true); // this is for auxilliary for (TopoDS_Wire& wire : wires) { wire.Move(invObjLoc); @@ -398,7 +402,7 @@ void Helix::updateAxis(void) Axis.setValue(dir.x, dir.y, dir.z); } -TopoDS_Shape Helix::generateHelixPath(void) +TopoDS_Shape Helix::generateHelixPath(double startOffset0) { double turns = Turns.getValue(); double height = Height.getValue(); @@ -436,8 +440,11 @@ TopoDS_Shape Helix::generateHelixPath(void) // Find out in what quadrant relative to the axis the profile is located, and the exact position. Base::Vector3d profileCenter = getProfileCenterPoint(); - double axisOffset = profileCenter * start - b * start; - double startOffset = profileCenter * v - b * v; + + // The factor of 100 below ensures that profile size is small compared to the curvature of the helix. + // This improves the issue reported in https://forum.freecadweb.org/viewtopic.php?f=10&t=65048 + double axisOffset = 100 * (profileCenter * start - b * start); + double startOffset = startOffset0 + profileCenter * v - b * v; double radius = std::fabs(axisOffset); bool turned = axisOffset < 0; @@ -445,7 +452,7 @@ TopoDS_Shape Helix::generateHelixPath(void) // in this case ensure that axis is not in the sketch plane if (std::fabs(v * normal) < Precision::Confusion()) throw Base::ValueError("Error: Result is self intersecting"); - radius = 1.0; //fallback to radius 1 + radius = 1000.0; //fallback to radius 1000 } bool growthMode = std::string(Mode.getValueAsString()).find("growth") != std::string::npos; diff --git a/src/Mod/PartDesign/App/FeatureHelix.h b/src/Mod/PartDesign/App/FeatureHelix.h index 99494feee1..02b0735eb6 100644 --- a/src/Mod/PartDesign/App/FeatureHelix.h +++ b/src/Mod/PartDesign/App/FeatureHelix.h @@ -80,7 +80,7 @@ protected: void updateAxis(void); /// generate helix and move it to the right location. - TopoDS_Shape generateHelixPath(void); + TopoDS_Shape generateHelixPath(double startOffset0 = 0.0); // project shape on plane. Used for detecting self intersection. TopoDS_Shape projectShape(const TopoDS_Shape& input, const gp_Ax2& plane);