mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-05 19:45:54 +00:00
Kernel: a body moved by a non-rigid matrix keeps each face's source and paint on that face
transform_matrix moves a body by a matrix that is not a rigid motion through SMLib, which numbers the moved body's faces afresh, then attached the input's face sources and paint in the input's face order. Planar certificates landed on the wrong faces (a reflected, sheared plate's hole walls and caps no longer lay on their certified planes). Each moved face now takes the source and paint of the face its history names; a face with no known origin takes no source, and with no history at all the paint stays as it was. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -100,7 +100,14 @@ fn construction_planes_follow_reflected_and_sheared_affine_images() {
|
||||
[[-1., 0., 0., 0.], [0.4, 2., 0., 0.], [0., 0.3, 1., 0.], [8., 9., 10., 1.]],
|
||||
] {
|
||||
let placed = transform_matrix(&body, m).unwrap();
|
||||
for (original, transformed) in body.face_sources().unwrap().iter().zip(placed.face_sources().unwrap()) {
|
||||
// SMLib numbers the placed faces afresh: each is matched with the face its history names.
|
||||
let history = placed.history().unwrap();
|
||||
let originals = body.face_sources().unwrap();
|
||||
for (f, transformed) in placed.face_sources().unwrap().iter().enumerate() {
|
||||
let [crate::history::FaceOrigin::Face { operand: 0, face }] = history.faces[f].origins.as_slice() else {
|
||||
panic!("face {f} has no one origin")
|
||||
};
|
||||
let original = &originals[*face];
|
||||
let (
|
||||
Some(FaceSource::Box { producer: a, axis: aa, high: ah, plane: ap }),
|
||||
Some(FaceSource::Box { producer: b, axis: ba, high: bh, plane: bp }),
|
||||
|
||||
@@ -141,15 +141,44 @@ pub fn transform_matrix(body: &Body, m: [[f64; 4]; 4]) -> Result<Body> {
|
||||
return placed.with_history(history, &[body]);
|
||||
}
|
||||
let sources = body.transformed_sources(m)?;
|
||||
let placed = match Rigid::of_matrix(&m) {
|
||||
let (placed, sources, paint) = match Rigid::of_matrix(&m) {
|
||||
Some(motion) => {
|
||||
let moved = Body::from_record(body.record().moved(&motion))?;
|
||||
let history = History::identity(&moved);
|
||||
moved.with_history(history, &[body])?
|
||||
(moved.with_history(history, &[body])?, sources, body.paint().cloned())
|
||||
}
|
||||
None => {
|
||||
// SMLib numbers the moved body's faces afresh: each face's source and paint follow it
|
||||
// by the history (a face whose origin is not known keeps no source; with no history
|
||||
// the paint stays as it was).
|
||||
let placed = transformed(body, &m)?;
|
||||
let origin: Vec<Option<usize>> = (0..placed.face_count()).map(|f| moved_from(placed.history(), f)).collect();
|
||||
let sources = sources.map(|s| std::sync::Arc::new(origin.iter().map(|o| o.and_then(|j| s.get(j).cloned().flatten())).collect()));
|
||||
let paint = body.paint().cloned().map(|mut p| {
|
||||
if placed.history().is_none() {
|
||||
return p;
|
||||
}
|
||||
p.faces = p
|
||||
.faces
|
||||
.iter()
|
||||
.flat_map(|fp| {
|
||||
origin.iter().enumerate().filter(|(_, o)| **o == Some(fp.face)).map(|(face, _)| crate::FacePaint { face, ..fp.clone() })
|
||||
})
|
||||
.collect();
|
||||
p
|
||||
});
|
||||
(placed, sources, paint)
|
||||
}
|
||||
None => transformed(body, &m)?,
|
||||
};
|
||||
Ok(placed.with_color(body.color()).with_paint(body.paint().cloned()).with_face_sources(sources).inherit_regularization_protection(body))
|
||||
Ok(placed.with_color(body.color()).with_paint(paint).with_face_sources(sources).inherit_regularization_protection(body))
|
||||
}
|
||||
|
||||
/// The face of the operand that face `f` of a moved body is, by the move's history.
|
||||
fn moved_from(history: Option<&History>, f: usize) -> Option<usize> {
|
||||
match history?.faces.get(f)?.origins.as_slice() {
|
||||
[crate::history::FaceOrigin::Face { operand: 0, face }] => Some(*face),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// `body` moved by a matrix that is not a rigid motion, in SMLib, its history from SMLib's tags.
|
||||
|
||||
Reference in New Issue
Block a user