diff --git a/src/Mod/PartDesign/App/FeatureHole.cpp b/src/Mod/PartDesign/App/FeatureHole.cpp index 79c651dd4f..180c050585 100644 --- a/src/Mod/PartDesign/App/FeatureHole.cpp +++ b/src/Mod/PartDesign/App/FeatureHole.cpp @@ -2204,8 +2204,8 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len // Nomenclature and formulae according to Figure 1 of ISO 68-1 // this is the same for all metric and UTS threads as stated here: // https://en.wikipedia.org/wiki/File:ISO_and_UTS_Thread_Dimensions.svg - // Note that in the ISO standard, Dmaj is called D. - double Dmaj = threadDescription[threadType][threadSize].diameter / 2; // major diameter position + // Rmaj is half of the major diameter + double Rmaj = threadDescription[threadType][threadSize].diameter / 2; double Pitch = getThreadPitch(); double clearance; // clearance to be added on the diameter @@ -2213,6 +2213,8 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len clearance = CustomThreadClearance.getValue() / 2; else clearance = getThreadClassClearance() / 2; + double RmajC = Rmaj + clearance; + double marginZ = 0.001; BRepBuilderAPI_MakeWire mkThreadWire; double H; @@ -2220,47 +2222,70 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len if (threadTypeStr == "BSP") { H = 0.960491 * Pitch; // Height of Sharp V double radius = 0.137329 * Pitch; // radius of the crest - double h = 0.640627 * Pitch; // height of the thread // construct the cross section going counter-clockwise + // -------------- + // P | p4 + // 5/8P | p3 + // | crest + // 3/8P | p2 + // 0 | p1 + // -------------- + // | base-sharpV Rmaj H - gp_Pnt p1 = toPnt((Dmaj - h + clearance) * xDir + Pitch / 8 * zDir); - gp_Pnt p4 = toPnt((Dmaj - h + clearance) * xDir + 7 * Pitch / 8 * zDir); - gp_Pnt p5 = toPnt(0.9 * (Dmaj - h) * xDir + 7 * Pitch / 8 * zDir); - gp_Pnt p6 = toPnt(0.9 * (Dmaj - h) * xDir + Pitch / 8 * zDir); + // the little adjustment of p1 and p4 is here to prevent coincidencies + double marginX = std::tan(62.5 * M_PI / 180.0) * marginZ; - // Calculate positions for p2 and p3 based on the arc radius - double p23x = Dmaj + clearance - radius * (1 - std::cos(M_PI / 4)); + gp_Pnt p1 = toPnt( + (RmajC - 5 * H / 6 + marginX) * xDir + + marginZ * zDir + ); + gp_Pnt p4 = toPnt( + (RmajC - 5 * H / 6 + marginX) * xDir + + (Pitch - marginZ) * zDir + ); - gp_Pnt p2 = toPnt(p23x * xDir + 7 * Pitch / 16 * zDir); - gp_Pnt p3 = toPnt(p23x * xDir + 9 * Pitch / 16 * zDir); - gp_Pnt crest = toPnt((Dmaj + clearance) * xDir + Pitch / 2 * zDir); + // Calculate positions for p2 and p3 + double p23x = RmajC - radius * 0.58284013094; + + gp_Pnt p2 = toPnt(p23x * xDir + 3 * Pitch / 8 * zDir); + gp_Pnt p3 = toPnt(p23x * xDir + 5 * Pitch / 8 * zDir); + gp_Pnt crest = toPnt((RmajC) * xDir + Pitch / 2 * zDir); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p1, p2).Edge()); Handle(Geom_TrimmedCurve) arc1 = GC_MakeArcOfCircle(p2, crest, p3).Value(); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(arc1).Edge()); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p3, p4).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p4, p5).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p5, p6).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p6, p1).Edge()); + mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p4, p1).Edge()); } else { H = sqrt(3) / 2 * Pitch; // height of fundamental triangle - double h = 5 * H / 8; // height of the thread + double h = 7 * H / 8; // distance from Rmaj to the base // construct the cross section going counter-clockwise - // for graphical explanation of geometrical construction of p1-p6 see: - // https://forum.freecad.org/viewtopic.php?f=19&t=54284#p466570 - gp_Pnt p1 = toPnt((Dmaj - h + clearance) * xDir + Pitch / 8 * zDir); - gp_Pnt p2 = toPnt((Dmaj + clearance) * xDir + 7 * Pitch / 16 * zDir); - gp_Pnt p3 = toPnt((Dmaj + clearance) * xDir + 9 * Pitch / 16 * zDir); - gp_Pnt p4 = toPnt((Dmaj - h + clearance) * xDir + 7 * Pitch / 8 * zDir); - gp_Pnt p5 = toPnt(0.9 * (Dmaj - h) * xDir + 7 * Pitch / 8 * zDir); - gp_Pnt p6 = toPnt(0.9 * (Dmaj - h) * xDir + Pitch / 8 * zDir); + // pitch + // -------------- + // P | p4 + // 9/16P | p3 + // 7/16P | p2 + // 0 | p1 + // -------------- + // | base-sharpV Rmaj + + // the little adjustment of p1 and p4 is here to prevent coincidencies + double marginX = std::tan(60.0 * M_PI / 180.0) * marginZ; + gp_Pnt p1 = toPnt( + (RmajC - h + marginX) * xDir + + marginZ * zDir + ); + gp_Pnt p2 = toPnt((RmajC) * xDir + 7 * Pitch / 16 * zDir); + gp_Pnt p3 = toPnt((RmajC) * xDir + 9 * Pitch / 16 * zDir); + gp_Pnt p4 = toPnt( + (RmajC - h + marginX) * xDir + + (Pitch - marginZ) * zDir + ); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p1, p2).Edge()); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p2, p3).Edge()); mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p3, p4).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p4, p5).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p5, p6).Edge()); - mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p6, p1).Edge()); + mkThreadWire.Add(BRepBuilderAPI_MakeEdge(p4, p1).Edge()); } mkThreadWire.Build(); @@ -2299,7 +2324,7 @@ TopoDS_Shape Hole::makeThread(const gp_Vec& xDir, const gp_Vec& zDir, double len } double helixAngle = Tapered.getValue() ? TaperedAngle.getValue() - 90 : 0.0; - TopoDS_Shape helix = TopoShape().makeLongHelix(Pitch, helixLength, Dmaj, helixAngle, leftHanded); + TopoDS_Shape helix = TopoShape().makeLongHelix(Pitch, helixLength, Rmaj, helixAngle, leftHanded); gp_Pnt origo(0.0, 0.0, 0.0); gp_Dir dir_axis1(0.0, 0.0, 1.0); // pointing along the helix axis, as created.