Persistent naming: joint origins on faces and circular ends, and face appearances, store the face's name and find it by name first (a joint whose face is gone reports it instead of attaching elsewhere)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 11:37:33 +00:00
1 parent e7aff4fef0
commit e7a85b30f7
4 files changed
+62 -9

No files matched your search

+12 -1
View File
@@ -354,6 +354,16 @@ fn appearance(s: &mut Session, p: &Value) -> Result<Value> {
if bodies.is_empty() && faces.is_empty() && comps.is_empty() {
return Err(bad(cmd, "give `bodies`, `faces` or `components`"));
}
// Persistent names of the picked faces.
let st_names: Vec<(String, solvecraft_geom::Vec3, Option<String>)> = faces
.iter()
.map(|(b, pt)| {
let n = st.body(b).and_then(|mb| {
solvecraft_doc::appearance::face_index_at(mb, *pt).and_then(|i| solvecraft_doc::naming::face_names(mb).get(i).cloned())
});
(b.clone(), *pt, n)
})
.collect();
let a = &mut s.doc_mut().appearances;
for b in &bodies {
match &look {
@@ -368,7 +378,8 @@ fn appearance(s: &mut Session, p: &Value) -> Result<Value> {
if a.faces.len() >= 100_000 {
return Err(bad(cmd, "too many face appearances"));
}
a.faces.push(FaceLook { body: body.clone(), point: *pt, look: l.clone() });
let name = st_names.iter().find(|(b, p, _)| b == body && p.dist(*pt) < 1e-12).and_then(|(_, _, n)| n.clone());
a.faces.push(FaceLook { body: body.clone(), point: *pt, look: l.clone(), name });
}
}
for c in &comps {
+5 -2
View File
@@ -131,8 +131,11 @@ fn origin_param(s: &Session, v: Option<&Value>, cmd: &str) -> Result<JointOrigin
let local = |p: Vec3| solvecraft_doc::apply_point(&inv, p);
let local_dir = |d: Vec3| solvecraft_doc::apply_vector(&inv, d);
let snap = match what {
"face" => Snap::FaceCenter { pick: local(world) },
"circle" => Snap::CircleCenter { pick: local(world) },
"face" | "circle" => {
let pick = local(world);
let face = solvecraft_doc::naming::face_names_at(&s.model.state(), &[pick]).into_iter().next().filter(|n| !n.is_empty());
if what == "face" { Snap::FaceCenter { pick, face } } else { Snap::CircleCenter { pick, face } }
}
"point" => Snap::Point { point: local(world), z: v.get("z").and_then(vec3).map(local_dir) },
_ => {
let f = v.get("frame").cloned().unwrap_or_default();