mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-05 03:25:58 +00:00
kernel: an SMLib blend's corner patch comes from the edges meeting there
SMLib leaves a corner patch where blends meet untagged, and blends() matches no single edge to it, so it had no origin, and the edges between two blend faces (two chamfers' mitre) none either. The history checks refused both (modify_history_tests' corner, whole-box and mitre cases on SMLib). Now a patch without origin is made in place of all the edges of the blend faces beside it, as truck records a corner, and every edge of a face new to the blend is where its two faces meet. modify_history_tests with SOLIDCRAFT_KERNEL=smlib: the three blend cases pass (28 of 30; the painted shell and the painted box cut's pieces are the shell's and boolean's). Truck: 30 of 30. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -87,7 +87,7 @@ mod imp {
|
||||
use super::Kind;
|
||||
use crate::blend_variable::RadiusSpline;
|
||||
use crate::body::Body;
|
||||
use crate::history::{BodyHistory, EdgeOrigin, History};
|
||||
use crate::history::{BodyHistory, Change, EdgeOrigin, FaceOrigin, History};
|
||||
use crate::native::{body_from_smlib_ordered, smlib_body_ordered};
|
||||
use crate::{KernelError, Result, guard, record};
|
||||
|
||||
@@ -221,7 +221,7 @@ mod imp {
|
||||
let operand = History::identity(body).edges;
|
||||
let replaced = blended(body, edges, &h);
|
||||
solidcraft_smlib::history::blends(&mut h, &operand, &replaced);
|
||||
Some(h)
|
||||
Some(with_corners(h))
|
||||
}
|
||||
Err(e) => {
|
||||
log::debug!(target: "smlib", "{what} history: {e}");
|
||||
@@ -234,6 +234,43 @@ mod imp {
|
||||
})
|
||||
}
|
||||
|
||||
/// `h` with each blend face still without origin (a corner patch where blends meet) made in
|
||||
/// place of all the edges of the blend faces next to it, as truck records a corner, and every
|
||||
/// edge of a face new to the blend recorded as where its faces meet (two chamfers' mitre is
|
||||
/// where the two chamfers meet).
|
||||
fn with_corners(mut h: History) -> History {
|
||||
let mut corners: Vec<(usize, BTreeSet<FaceOrigin>)> = Vec::new();
|
||||
for (i, f) in h.faces.iter().enumerate() {
|
||||
if f.change != Change::Generated || !f.origins.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let around: BTreeSet<FaceOrigin> = h
|
||||
.edges
|
||||
.iter()
|
||||
.filter(|e| e.faces.contains(&i))
|
||||
.flat_map(|e| e.faces.iter().filter(|g| **g != i))
|
||||
.filter_map(|g| h.faces.get(*g))
|
||||
.flat_map(|g| g.origins.iter().copied())
|
||||
.filter(|o| matches!(o, FaceOrigin::Edge { .. }))
|
||||
.collect();
|
||||
if !around.is_empty() {
|
||||
corners.push((i, around));
|
||||
}
|
||||
}
|
||||
for (i, origins) in corners {
|
||||
if let Some(f) = h.faces.get_mut(i) {
|
||||
*f = record::generated(origins.into_iter().collect());
|
||||
}
|
||||
}
|
||||
let faces = h.faces.clone();
|
||||
for e in &mut h.edges {
|
||||
if e.faces.iter().any(|f| faces.get(*f).is_some_and(|f| f.change == Change::Generated)) {
|
||||
e.origins = record::meeting(&e.faces, &faces);
|
||||
}
|
||||
}
|
||||
h
|
||||
}
|
||||
|
||||
/// The operand's edges the blend replaced: each picked edge, and every edge no result edge
|
||||
/// comes from (the rest of the tangent chains), in the operand's edge order.
|
||||
fn blended(body: &Body, picked: &[usize], h: &History) -> Vec<usize> {
|
||||
|
||||
Reference in New Issue
Block a user