Variable-radius fillets through middle points: radii at positions along the edge, straight or smooth between

kernel::fillet_variable_points(body, edge, start, [(position, radius)...], smooth): the radius law is a B-spline of the edge parameter (straight pieces, or C1 cubic pieces with Catmull-Rom slopes), and since every section's arc is affine in its radius the blend is exactly a rational B-spline (degree 2 across, the law's degree along) with B-spline contact curves on the faces. The largest radius along the edge decides whether the blend fits. Fillet type variable takes mid: [[position, radius expr], ...] and smooth; middle radii are parameters of the feature (Mid radius) and follow user parameters. Tests: straight pieces against (1 - pi/4) L (a^2 + ab + b^2) / 3 per piece, smooth against the integrated law, either end as start, refusals; engine test with a parameter-driven middle radius.

Refs #9

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RjGw4gA5ZvKrU8MQP6sBgT
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-10 06:06:33 +00:00
1 parent a7fe0429f0
commit be18bd6573
8 files changed
+192 -19

No files matched your search

+12 -3
View File
@@ -773,8 +773,16 @@ pub enum FilletStyle {
Constant,
/// `radius` is the chord: the width across the blend.
Chord,
/// `radius` at the end of each edge nearest `start`, `radius2` at the other, linear between.
Variable { radius2: String, start: Vec3 },
/// `radius` at the end of each edge nearest `start`, `radius2` at the other; `mid` radii at
/// positions between (0 to 1 from the start end); straight between them, or `smooth`.
Variable {
radius2: String,
start: Vec3,
#[serde(default, skip_serializing_if = "Vec::is_empty")]
mid: Vec<(f64, String)>,
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
smooth: bool,
},
}
impl FilletStyle {
@@ -1148,8 +1156,9 @@ impl FeatureKind {
}
FeatureKind::Fillet { radius, style, .. } => {
v.push(radius);
if let FilletStyle::Variable { radius2, .. } = style {
if let FilletStyle::Variable { radius2, mid, .. } = style {
v.push(radius2);
v.extend(mid.iter().map(|(_, r)| r.as_str()));
}
}
FeatureKind::Chamfer { distance, distance2, angle, .. } => {