|
| 1 | +import Testing |
| 2 | +import Helical |
| 3 | +import Cadova |
| 4 | + |
| 5 | +private func isClose(_ a: Double, _ b: Double, tolerance: Double = 1e-9) -> Bool { abs(a - b) < tolerance } |
| 6 | + |
| 7 | +struct TrapezoidalThreadformTests { |
| 8 | + @Test func `angle is sum of both flank angles`() { |
| 9 | + let symmetric = TrapezoidalThreadform(angle: 60°, crestWidth: 0.0625) |
| 10 | + #expect(symmetric.angle == 60°) |
| 11 | + |
| 12 | + let asymmetric = TrapezoidalThreadform(leadingFlankAngle: 7°, trailingFlankAngle: 45°, crestWidth: 0.1) |
| 13 | + #expect(asymmetric.angle == 52°) |
| 14 | + } |
| 15 | + |
| 16 | + @Test func `pitch diameter formula`() { |
| 17 | + // M3: major=3.0 + 2*(crestWidth - pitch/2)/(2*tan30°) ≈ 2.6752 |
| 18 | + let formM3 = TrapezoidalThreadform(angle: 60°, crestWidth: ScrewThread.m3.pitch / 8) |
| 19 | + #expect(isClose(formM3.pitchDiameter(for: .m3), 2.6752, tolerance: 1e-4)) |
| 20 | + |
| 21 | + // M8: same formula ≈ 7.1881 |
| 22 | + let formM8 = TrapezoidalThreadform(angle: 60°, crestWidth: ScrewThread.m8.pitch / 8) |
| 23 | + #expect(isClose(formM8.pitchDiameter(for: .m8), 7.1881, tolerance: 1e-4)) |
| 24 | + } |
| 25 | + |
| 26 | + @Test func `minimum pitch formula`() { |
| 27 | + // M3: crestWidth + depth*(tan30°+tan30°) = 0.0625 + 0.270633*2/√3 ≈ 0.375 |
| 28 | + let form = TrapezoidalThreadform(angle: 60°, crestWidth: ScrewThread.m3.pitch / 8) |
| 29 | + #expect(isClose(form.minimumPitch(for: .m3), 0.375, tolerance: 1e-6)) |
| 30 | + } |
| 31 | +} |
| 32 | + |
| 33 | +struct KnuckleThreadformTests { |
| 34 | + @Test func `minimum pitch is 2 × crest radius`() { |
| 35 | + // E27: h=1.25, pitch=3.62 → radius=(1.5625+3.2761)/5 ≈ 0.96772 |
| 36 | + // minimumPitch = 2*radius ≈ 1.93544 |
| 37 | + let e27 = ScrewThread.e27 |
| 38 | + let h = (e27.majorDiameter - e27.minorDiameter) / 2 |
| 39 | + let r = (h * h + e27.pitch * e27.pitch / 4) / (4 * h) |
| 40 | + let form: KnuckleThreadform = .knuckle(crestRadius: r, rootRadius: r) |
| 41 | + #expect(isClose(form.minimumPitch(for: e27), 2 * r)) |
| 42 | + #expect(isClose(form.minimumPitch(for: e27), 1.93544, tolerance: 1e-4)) |
| 43 | + } |
| 44 | + |
| 45 | + @Test func `pitch diameter formula`() { |
| 46 | + #expect(isClose(ScrewThread.e27.pitchDiameter, 25.75, tolerance: 1e-3)) |
| 47 | + } |
| 48 | +} |
0 commit comments