mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 10:35:58 +00:00
doc: the faceted thread groove is gone; the groove is SMLib's exact screw sweep
thread_groove built the faceted mesh groove truck cut; nothing calls it since the thread
cut is SMLib's screw sweep (kernel::sweep_helix) and a B-rep boolean. With it go
GrooveShape's facet count and the refusal it fed ("the modelled thread is too fine for this
diameter"): an exact groove has no chord error, so a fine thread on a large diameter is cut
as drawn. Dimensions that are not finite are still refused.
kernel::sweep_helix_mesh is now called only by crates/engine/src/thread_tests.rs.
(not built: base in progress)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017itGh5fpMEousnZ91cYcVt
This commit is contained in:
+8
-26
@@ -520,19 +520,8 @@ fn thread_on_impl(
|
||||
})
|
||||
}
|
||||
|
||||
/// The helical space between the teeth of a modelled ISO metric thread (ISO 68-1 basic
|
||||
/// profile, 60° flanks): cut from the shaft (external) or the hole wall (internal), running from
|
||||
/// `start` to `end` along the axis. `radius` is the face's own radius; `open` says which ends
|
||||
/// of the threaded length are free ends of the face.
|
||||
/// The groove of [`thread_groove_shape`] as the faceted solid the truck kernel cuts.
|
||||
fn thread_groove(t: &ThreadInfo, radius: f64, open: (bool, bool)) -> Result<solidcraft_geom::Mesh> {
|
||||
let g = thread_groove_shape(t, radius, open)?;
|
||||
Ok(kernel::sweep_helix_mesh(&g.plane, &g.section, g.base, g.axis, g.pitch, g.turns, g.stations)?)
|
||||
}
|
||||
|
||||
/// A thread's groove as a screw sweep: its trapezoid `section` in `plane` (an axial plane
|
||||
/// through `base`), carried `turns` turns about `axis` through `base`, rising `pitch` per turn;
|
||||
/// `stations` per turn where it is faceted.
|
||||
/// through `base`), carried `turns` turns about `axis` through `base`, rising `pitch` per turn.
|
||||
struct GrooveShape {
|
||||
plane: Plane,
|
||||
section: [Vec2; 4],
|
||||
@@ -540,10 +529,12 @@ struct GrooveShape {
|
||||
axis: Vec3,
|
||||
pitch: f64,
|
||||
turns: f64,
|
||||
stations: usize,
|
||||
}
|
||||
|
||||
/// The shape of [`thread_groove`].
|
||||
/// The helical space between the teeth of a modelled ISO metric thread (ISO 68-1 basic
|
||||
/// profile, 60° flanks): cut from the shaft (external) or the hole wall (internal), running from
|
||||
/// `start` to `end` along the axis. `radius` is the face's own radius; `open` says which ends
|
||||
/// of the threaded length are free ends of the face.
|
||||
fn thread_groove_shape(t: &ThreadInfo, radius: f64, open: (bool, bool)) -> Result<GrooveShape> {
|
||||
let (p, d) = (t.pitch, t.major_diameter);
|
||||
let h = p * 3f64.sqrt() / 2.0;
|
||||
@@ -611,26 +602,17 @@ fn thread_groove_shape(t: &ThreadInfo, radius: f64, open: (bool, bool)) -> Resul
|
||||
let base = t.axis_point + k * s0;
|
||||
let plane = Plane { origin: base, x: u, y: *k };
|
||||
let section = [Vec2::new(r0, -w0), Vec2::new(r1, -w1), Vec2::new(r1, w1), Vec2::new(r0, w0)];
|
||||
// Keep radial chord error below 1% of the pitch, rather than a fixed fraction of the
|
||||
// diameter. At 48 stations a large fine thread cuts too deeply; its outer tool facets
|
||||
// can even dip under the shaft surface. The existing coarse sizes still use 48.
|
||||
let outer = r0.abs().max(r1.abs());
|
||||
if !outer.is_finite() {
|
||||
if !(r0.is_finite() && r1.is_finite()) {
|
||||
return Err(DocError::Invalid("thread dimensions are too large".into()));
|
||||
}
|
||||
let angle = (1.0 - (p * 0.01 / outer).min(1.0)).acos();
|
||||
let stations = (std::f64::consts::PI / angle).ceil().max(48.0);
|
||||
if !stations.is_finite() || stations > 720.0 {
|
||||
return Err(DocError::Invalid("the modelled thread is too fine for this diameter; use a cosmetic thread".into()));
|
||||
}
|
||||
// The kernel rotates positively about its sweep axis. Reversing both that axis and the
|
||||
// pitch mirrors the angular motion while the lift stays +k * p per turn. The physical
|
||||
// axis, start/end, radial profile and station count remain exactly as for a right thread.
|
||||
// axis, start/end and radial profile remain exactly as for a right thread.
|
||||
let (sweep_axis, sweep_pitch) = match t.handedness {
|
||||
crate::ThreadHandedness::Right => (*k, p),
|
||||
crate::ThreadHandedness::Left => (-*k, -p),
|
||||
};
|
||||
Ok(GrooveShape { plane, section, base, axis: sweep_axis, pitch: sweep_pitch, turns: (s1 - s0) / p, stations: stations as usize })
|
||||
Ok(GrooveShape { plane, section, base, axis: sweep_axis, pitch: sweep_pitch, turns: (s1 - s0) / p })
|
||||
}
|
||||
|
||||
/// What a modelled external thread turns off a shaft thicker than its major diameter before it
|
||||
|
||||
Reference in New Issue
Block a user