Chamfers with two distances or a distance and an angle (distance2 / angle, flip for which face comes first), on straight edges between planar faces; pattern copies keep them
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
a762391697
commit
551d068ae2
7 files changed
+147
-17
No files matched your search
@@ -176,6 +176,15 @@ pub enum FeatureKind {
|
||||
Chamfer {
|
||||
edges: Vec<Vec3>,
|
||||
distance: String,
|
||||
/// Unequal chamfers: the distance along the second face…
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
distance2: Option<String>,
|
||||
/// …or the angle the chamfer makes with the first face.
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
angle: Option<String>,
|
||||
/// Swap which face is the first (by default the one facing up most).
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
flip: bool,
|
||||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||||
body: Option<String>,
|
||||
},
|
||||
@@ -923,7 +932,11 @@ impl FeatureKind {
|
||||
}
|
||||
FeatureKind::Revolve { angle, .. } => v.push(angle),
|
||||
FeatureKind::Fillet { radius, .. } => v.push(radius),
|
||||
FeatureKind::Chamfer { distance, .. } => v.push(distance),
|
||||
FeatureKind::Chamfer { distance, distance2, angle, .. } => {
|
||||
v.push(distance);
|
||||
v.extend(distance2.iter().map(String::as_str));
|
||||
v.extend(angle.iter().map(String::as_str));
|
||||
}
|
||||
FeatureKind::Box { length, width, height, .. } => v.extend([length.as_str(), width, height]),
|
||||
FeatureKind::Cylinder { radius, height, .. } => v.extend([radius.as_str(), height]),
|
||||
FeatureKind::Sphere { radius, .. } => v.push(radius),
|
||||
|
||||
+29
-9
@@ -1726,10 +1726,9 @@ fn replay(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &mut
|
||||
let moved: Vec<Vec3> = edges.iter().map(|p| crate::apply_point(m, *p)).collect();
|
||||
let ti = blend_target(st, &None, &moved)?;
|
||||
let Some(mb) = st.bodies.get(ti).cloned() else { continue };
|
||||
let nb = if matches!(src.kind, FeatureKind::Fillet { .. }) {
|
||||
kernel::fillet(&mb.body, &moved, r)?
|
||||
} else {
|
||||
kernel::chamfer(&mb.body, &moved, r)?
|
||||
let nb = match &src.kind {
|
||||
FeatureKind::Chamfer { distance2, angle, flip, .. } => chamfer_with(vals, &mb.body, &moved, r, distance2, angle, *flip)?,
|
||||
_ => kernel::fillet(&mb.body, &moved, r)?,
|
||||
};
|
||||
if let Some(slot) = st.bodies.get_mut(ti) {
|
||||
*slot = ModelBody::new(mb.name, nb, mb.feature);
|
||||
@@ -1819,6 +1818,27 @@ fn face_plane(st: &ModelState, picked: &Plane, at: Vec3, name: Option<&str>) ->
|
||||
}
|
||||
}
|
||||
|
||||
/// A chamfer, equal or by its second distance or angle.
|
||||
fn chamfer_with(
|
||||
vals: &BTreeMap<String, Value>,
|
||||
b: &kernel::Body,
|
||||
edges: &[Vec3],
|
||||
d: f64,
|
||||
distance2: &Option<String>,
|
||||
angle: &Option<String>,
|
||||
flip: bool,
|
||||
) -> Result<kernel::Body> {
|
||||
let side = match (distance2, angle) {
|
||||
(Some(e), _) => Some(kernel::ChamferSide::Distance(val(vals, e, Kind::Length)?)),
|
||||
(None, Some(e)) => Some(kernel::ChamferSide::Angle(val(vals, e, Kind::Angle)?)),
|
||||
(None, None) => None,
|
||||
};
|
||||
Ok(match side {
|
||||
Some(s) => kernel::chamfer_sides(b, edges, d, s, flip)?,
|
||||
None => kernel::chamfer(b, edges, d)?,
|
||||
})
|
||||
}
|
||||
|
||||
fn eval_feature(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &mut ModelState, warning: &mut Option<String>) -> Result<()> {
|
||||
match &f.kind {
|
||||
FeatureKind::SheetBase { .. }
|
||||
@@ -2000,7 +2020,7 @@ fn eval_feature(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st:
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
FeatureKind::Fillet { edges, radius, body } | FeatureKind::Chamfer { edges, distance: radius, body } => {
|
||||
FeatureKind::Fillet { edges, radius, body } | FeatureKind::Chamfer { edges, distance: radius, body, .. } => {
|
||||
let r = val(vals, radius, Kind::Length)?;
|
||||
let ti = blend_target(st, body, edges)?;
|
||||
let Some(mb) = st.bodies.get(ti) else { return Err(DocError::Invalid("body".into())) };
|
||||
@@ -2042,10 +2062,10 @@ fn eval_feature(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st:
|
||||
} else {
|
||||
resolve_edges(&mb.body, edges, &f.edge_refs, warning)?
|
||||
};
|
||||
let nb = if matches!(f.kind, FeatureKind::Fillet { .. }) {
|
||||
kernel::fillet(&mb.body, &edges, r)?
|
||||
} else {
|
||||
kernel::chamfer(&mb.body, &edges, r)?
|
||||
let nb = match &f.kind {
|
||||
FeatureKind::Fillet { .. } => kernel::fillet(&mb.body, &edges, r)?,
|
||||
FeatureKind::Chamfer { distance2, angle, flip, .. } => chamfer_with(vals, &mb.body, &edges, r, distance2, angle, *flip)?,
|
||||
_ => return Err(DocError::Invalid("blend".into())),
|
||||
};
|
||||
let (name, feat) = (mb.name.clone(), mb.feature);
|
||||
if let Some(slot) = st.bodies.get_mut(ti) {
|
||||
|
||||
@@ -49,7 +49,15 @@ impl FeatureKind {
|
||||
}
|
||||
FeatureKind::Revolve { angle, .. } => v.push(("Angle", angle, A)),
|
||||
FeatureKind::Fillet { radius, .. } => v.push(("Radius", radius, L)),
|
||||
FeatureKind::Chamfer { distance, .. } => v.push(("Distance", distance, L)),
|
||||
FeatureKind::Chamfer { distance, distance2, angle, .. } => {
|
||||
v.push(("Distance", distance, L));
|
||||
if let Some(d) = distance2 {
|
||||
v.push(("Distance 2", d, L));
|
||||
}
|
||||
if let Some(a) = angle {
|
||||
v.push(("Angle", a, A));
|
||||
}
|
||||
}
|
||||
FeatureKind::Box { length, width, height, .. } => {
|
||||
v.push(("Length", length, L));
|
||||
v.push(("Width", width, L));
|
||||
|
||||
Reference in new issue
Block a user