diff --git a/src/Mod/Part/App/PrimitiveFeature.cpp b/src/Mod/Part/App/PrimitiveFeature.cpp index 119078c35f..c6d0d4d749 100644 --- a/src/Mod/Part/App/PrimitiveFeature.cpp +++ b/src/Mod/Part/App/PrimitiveFeature.cpp @@ -850,16 +850,15 @@ App::DocumentObjectExecReturn *Helix::execute(void) Standard_Real myRadius = Radius.getValue(); Standard_Real myAngle = Angle.getValue(); Standard_Boolean myLocalCS = LocalCoord.getValue() ? Standard_True : Standard_False; - //Standard_Boolean myStyle = Style.getValue() ? Standard_True : Standard_False; - TopoShape helix; + Standard_Real nbTurns = myHeight / myPitch; + + Standard_Real myRadiusTop = myRadius + myHeight * tan(Base::toRadians(myAngle)); + TopoShape spirhelix; // work around for OCC bug #23314 (FC #0954) // the exact conditions for failure are unknown. building the helix 1 turn at a time // seems to always work. - this->Shape.setValue(helix.makeLongHelix(myPitch, myHeight, myRadius, myAngle, myLocalCS)); -// if (myHeight / myPitch > 50.0) -// this->Shape.setValue(helix.makeLongHelix(myPitch, myHeight, myRadius, myAngle, myLocalCS)); -// else -// this->Shape.setValue(helix.makeHelix(myPitch, myHeight, myRadius, myAngle, myLocalCS, myStyle)); + TopoDS_Shape myHelix = spirhelix.makeSpiralHelix(myRadius, myRadiusTop, myHeight, nbTurns, 2, myLocalCS); + this->Shape.setValue(myHelix); } catch (Standard_Failure& e) { @@ -913,30 +912,16 @@ App::DocumentObjectExecReturn *Spiral::execute(void) Standard_Real myNumRot = Rotations.getValue(); Standard_Real myRadius = Radius.getValue(); Standard_Real myGrowth = Growth.getValue(); - Standard_Real myAngle = 45.0; - Standard_Real myPitch = myGrowth / tan(Base::toRadians(myAngle)); - Standard_Real myHeight = myPitch * myNumRot; - TopoShape helix; + Standard_Real myRadiusTop = myRadius + myGrowth * myNumRot; + TopoShape spirhelix; if (myGrowth < Precision::Confusion()) Standard_Failure::Raise("Growth too small"); - if (myNumRot < Precision::Confusion()) Standard_Failure::Raise("Number of rotations too small"); - // spiral suffers from same bug as helix (FC bug #0954) - // So, we use same work around for OCC bug #23314 - TopoDS_Shape myHelix = helix.makeLongHelix(myPitch, myHeight, myRadius, myAngle, Standard_False); - - Handle(Geom_Plane) aPlane = new Geom_Plane(gp_Pnt(0.0,0.0,0.0), gp::DZ()); - Standard_Real range = (myNumRot+1) * myGrowth + 1 + myRadius; - BRepBuilderAPI_MakeFace mkFace(aPlane, -range, range, -range, range -#if OCC_VERSION_HEX >= 0x060502 - , Precision::Confusion() -#endif - ); - BRepProj_Projection proj(myHelix, mkFace.Face(), gp::DZ()); - this->Shape.setValue(proj.Shape()); - + + TopoDS_Shape mySpiral = spirhelix.makeSpiralHelix(myRadius, myRadiusTop, 0, myNumRot, 2, Standard_False); + this->Shape.setValue(mySpiral); return Primitive::execute(); } catch (Standard_Failure& e) { diff --git a/src/Mod/Part/App/TopoShape.cpp b/src/Mod/Part/App/TopoShape.cpp index cf74b1a384..b877e78ff7 100644 --- a/src/Mod/Part/App/TopoShape.cpp +++ b/src/Mod/Part/App/TopoShape.cpp @@ -2505,7 +2505,7 @@ TopoDS_Shape TopoShape::makeLongHelix(Standard_Real pitch, Standard_Real height, TopoDS_Shape TopoShape::makeSpiralHelix(Standard_Real radiusbottom, Standard_Real radiustop, Standard_Real height, Standard_Real nbturns, - Standard_Real breakperiod) const + Standard_Real breakperiod, Standard_Boolean leftHanded) const { // 1000 periods is an OCCT limit. The 3D curve gets truncated // if he 2D curve spans beyond this limit. @@ -2516,8 +2516,9 @@ TopoDS_Shape TopoShape::makeSpiralHelix(Standard_Real radiusbottom, Standard_Rea if (nbturns <= 0) Standard_Failure::Raise("Number of turns must be greater than 0"); - Standard_Real nbFullTurns = floor(nbturns/breakperiod); - Standard_Real partTurn = nbturns - nbFullTurns*breakperiod; + Standard_Real nbPeriods = nbturns/breakperiod; + Standard_Real nbFullPeriods = floor(nbPeriods); + Standard_Real partPeriod = nbPeriods - nbFullPeriods; // A Bezier curve is used below, to get a periodic surface also for spirals. TColgp_Array1OfPnt poles(1,2); @@ -2532,19 +2533,21 @@ TopoDS_Shape TopoShape::makeSpiralHelix(Standard_Real radiusbottom, Standard_Rea gp_Pnt2d beg(0, 0); gp_Pnt2d end(0, 0); - gp_Vec2d dir(2.0 * M_PI, height / nbturns); + gp_Vec2d dir(breakperiod * 2.0 * M_PI, 1 / nbPeriods); + if (leftHanded == Standard_True) + dir = gp_Vec2d(-breakperiod * 2.0 * M_PI, 1 / nbPeriods); Handle(Geom2d_TrimmedCurve) segm; TopoDS_Edge edgeOnSurf; BRepBuilderAPI_MakeWire mkWire; - for (unsigned long i = 0; i < nbFullTurns; i++) { + for (unsigned long i = 0; i < nbFullPeriods; i++) { end = beg.Translated(dir); segm = GCE2d_MakeSegment(beg , end); edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf); mkWire.Add(edgeOnSurf); beg = end; } - if (partTurn > Precision::Confusion()) { - dir.Scale(partTurn); + if (partPeriod > Precision::Confusion()) { + dir.Scale(partPeriod); end = beg.Translated(dir); segm = GCE2d_MakeSegment(beg , end); edgeOnSurf = BRepBuilderAPI_MakeEdge(segm , surf); diff --git a/src/Mod/Part/App/TopoShape.h b/src/Mod/Part/App/TopoShape.h index 990fec2828..07c43b6628 100644 --- a/src/Mod/Part/App/TopoShape.h +++ b/src/Mod/Part/App/TopoShape.h @@ -259,7 +259,8 @@ public: Standard_Real radius, Standard_Real angle=0, Standard_Boolean left=Standard_False) const; TopoDS_Shape makeSpiralHelix(Standard_Real radiusbottom, Standard_Real radiustop, - Standard_Real height, Standard_Real nbturns=1, Standard_Real breakperiod=1) const; + Standard_Real height, Standard_Real nbturns=1, Standard_Real breakperiod=1, + Standard_Boolean left=Standard_False) const; TopoDS_Shape makeThread(Standard_Real pitch, Standard_Real depth, Standard_Real height, Standard_Real radius) const; TopoDS_Shape makeLoft(const TopTools_ListOfShape& profiles, Standard_Boolean isSolid,