One walk over the geometry a feature holds (3/3, #876) (#1028)

Moves the per-feature geometry handling (transforms, face points, profile selections, point expressions) into one geometry walk in feature_geometry.rs, with a golden record of what each feature kind moves. sheet.perforate holds no world geometry and joins the no-op arm.
This commit is contained in:
JIJINBEI authored and GitHub committed 2026-10-14 13:29:31 -04:00
1 parent f79dfe41b6
commit 1a456d2d1f
9 files changed
+709 -258

No files matched your search

-75
View File
@@ -1523,81 +1523,6 @@ impl FeatureKind {
FeatureKind::MeshConvert { .. } => "ConvertMesh",
}
}
/// Every expression the feature uses.
/// Points on faces the feature refers to (shell, draft, offset and replace faces, a hole's
/// placement), for persistent face names.
/// The feature's profile selections, each with its sketch.
pub fn profile_sels_mut(&mut self) -> Vec<(u64, &mut ProfileSel)> {
match self {
// A thin extrude follows curves; its profiles are not used.
FeatureKind::Extrude { thin: Some(_), .. } => Vec::new(),
FeatureKind::Extrude { sketch, profiles, .. }
| FeatureKind::Revolve { sketch, profiles, .. }
| FeatureKind::Sweep { sketch, profiles, .. }
| FeatureKind::Emboss { sketch, profiles, .. }
| FeatureKind::SheetBase { sketch, profiles, .. } => vec![(*sketch, profiles)],
FeatureKind::Patch { sketch: Some(sk), profiles, .. }
| FeatureKind::SurfaceExtrude { sketch: sk, profiles: Some(profiles), .. }
| FeatureKind::SurfaceRevolve { sketch: sk, profiles: Some(profiles), .. }
| FeatureKind::SurfaceSweep { sketch: sk, profiles: Some(profiles), .. } => {
vec![(*sk, profiles)]
}
FeatureKind::Loft { sections, .. } => sections.iter_mut().filter(|s| s.point.is_none()).map(|s| (s.sketch, &mut s.profiles)).collect(),
FeatureKind::SurfaceLoft { sections } => sections.iter_mut().filter_map(|s| Some((s.sketch, s.profiles.as_mut()?))).collect(),
_ => Vec::new(),
}
}
/// Profile selections and their source sketches without cloning feature data.
pub fn profile_sels(&self) -> Vec<(u64, &ProfileSel)> {
match self {
// A thin extrude follows curves; its profiles are not used.
FeatureKind::Extrude { thin: Some(_), .. } => Vec::new(),
FeatureKind::Extrude { sketch, profiles, .. }
| FeatureKind::Revolve { sketch, profiles, .. }
| FeatureKind::Sweep { sketch, profiles, .. }
| FeatureKind::Emboss { sketch, profiles, .. }
| FeatureKind::SheetBase { sketch, profiles, .. } => vec![(*sketch, profiles)],
FeatureKind::Patch { sketch: Some(sketch), profiles, .. }
| FeatureKind::SurfaceExtrude { sketch, profiles: Some(profiles), .. }
| FeatureKind::SurfaceRevolve { sketch, profiles: Some(profiles), .. }
| FeatureKind::SurfaceSweep { sketch, profiles: Some(profiles), .. } => {
vec![(*sketch, profiles)]
}
FeatureKind::Loft { sections, .. } => {
sections.iter().filter(|section| section.point.is_none()).map(|section| (section.sketch, &section.profiles)).collect()
}
FeatureKind::SurfaceLoft { sections } => sections.iter().filter_map(|s| Some((s.sketch, s.profiles.as_ref()?))).collect(),
_ => Vec::new(),
}
}
pub fn face_points_mut(&mut self) -> Vec<&mut Vec3> {
match self {
FeatureKind::Shell { faces, .. }
| FeatureKind::Draft { faces, .. }
| FeatureKind::OffsetFace { faces, .. }
| FeatureKind::DeleteFace { faces, .. }
| FeatureKind::SurfaceOffset { faces, .. }
| FeatureKind::SplitFace { faces, .. }
| FeatureKind::ReplaceFace { faces, .. } => faces.iter_mut().collect(),
FeatureKind::Hole { position, points: None, to, .. } => std::iter::once(position).chain(to.iter_mut()).collect(),
FeatureKind::Hole { to: Some(t), .. } => vec![t],
FeatureKind::Extrude { extent, .. } => extent.to.iter_mut().chain(extent.from.iter_mut()).collect(),
FeatureKind::Revolve { to: Some(p), .. } => vec![p],
FeatureKind::Thread { face, .. } => vec![face],
FeatureKind::Emboss { face: Some(face), .. } => vec![&mut face.at],
FeatureKind::Boss { position, .. } | FeatureKind::SnapFit { position, .. } | FeatureKind::Rest { position, .. } => vec![position],
// With bend edges the fixed face is found by name (a plate keeps its point).
FeatureKind::SheetConvert { face, bends, .. } if !bends.is_empty() => vec![face],
_ => Vec::new(),
}
}
pub fn face_points(&self) -> Vec<Vec3> {
let mut k = self.clone();
k.face_points_mut().into_iter().map(|p| *p).collect()
}
}
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]