mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-03 02:25:55 +00:00
* claim: #5388 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Sketch: rebuilding a projection keeps the sketch's own curves on its points (#5388) When a projected face changed shape, update_link rebuilt the link with drop_link_entities, whose remove_points also deleted every curve using a projected point: a circle the user drew on a projected hole's centre vanished, and the extrude on it lost its profile. Before the projected points go, the sketch's own curves on them move to a free point at the same place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1186,11 +1186,31 @@ impl Sketch {
|
||||
let keep = self.links.clone();
|
||||
self.remove_curves(&curves);
|
||||
let pts = self.link_points(id);
|
||||
self.free_own_curves(&pts);
|
||||
self.remove_points(&pts);
|
||||
// Removal prunes empty links; this one stays.
|
||||
self.links = keep;
|
||||
}
|
||||
|
||||
/// The sketch's own curves that use one of `pts` (a circle drawn on a projected hole's
|
||||
/// centre) move onto a free point of their own at the same place, so removing `pts` doesn't
|
||||
/// delete them with the link (#5388). Constraints on `pts` still go with them.
|
||||
fn free_own_curves(&mut self, pts: &[usize]) {
|
||||
for &p in pts {
|
||||
let own: Vec<usize> = self.curves.iter().enumerate().filter(|(_, c)| c.link.is_none() && c.kind.uses(p)).map(|(i, _)| i).collect();
|
||||
if own.is_empty() {
|
||||
continue;
|
||||
}
|
||||
let Some(pos) = self.points.get(p).map(|q| q.pos) else { continue };
|
||||
let Ok(free) = self.add_point(pos, None) else { continue };
|
||||
for ci in own {
|
||||
if let Some(c) = self.curves.get_mut(ci) {
|
||||
c.kind.map_points(&|q| if q == p { free } else { q });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Mark a link as lost (its reference was not found); its geometry stays as it was.
|
||||
pub fn set_link_lost(&mut self, id: &str, lost: bool) {
|
||||
if let Some(l) = self.links.iter_mut().find(|l| l.id == id) {
|
||||
|
||||
@@ -423,3 +423,38 @@ fn edge_on_face_saved_as_a_line_pair_keeps_the_line_an_offset_follows() {
|
||||
let end = sk.points[sk.link_points(&link)[1]].pos;
|
||||
assert_eq!(end, Vec2::new(17.0, 5.0), "the line moved to the new geometry");
|
||||
}
|
||||
|
||||
/// #5388: a circle the user drew on a projected hole's centre survives when the face changes
|
||||
/// shape and its projection is rebuilt (a second hole added to the face).
|
||||
#[test]
|
||||
fn rebuilt_face_keeps_a_users_circle_on_its_projected_centre() {
|
||||
let mut sk = Sketch::new();
|
||||
let hole = |c: Vec2| LinkGeom::Circle(c, 2.1);
|
||||
let face_with = |holes: &[Vec2]| square(15.0).into_iter().chain(holes.iter().map(|c| hole(*c))).collect::<Vec<_>>();
|
||||
let link = sk.add_link(LinkKind::Project, face(), &face_with(&[Vec2::ZERO])).unwrap();
|
||||
// The projected hole's centre point.
|
||||
let centre = sk
|
||||
.link_curves(&link)
|
||||
.into_iter()
|
||||
.find_map(|i| match sk.curves[i].kind {
|
||||
CurveKind::Circle { c, .. } => Some(c),
|
||||
_ => None,
|
||||
})
|
||||
.unwrap();
|
||||
let mine = sk.add_curve(CurveKind::Circle { c: centre, r: 5.25 }, Some("c_mine")).unwrap();
|
||||
assert!(sk.curves[mine].link.is_none());
|
||||
// The face gains two more holes: the projection's shape changes, so it is rebuilt.
|
||||
assert!(sk.update_link(&link, &face_with(&[Vec2::ZERO, Vec2::new(-10.0, 0.0), Vec2::new(10.0, 0.0)])).unwrap());
|
||||
let kept = sk.curves.iter().find(|c| c.id == "c_mine").expect("the user's circle survives the rebuild");
|
||||
assert!(kept.link.is_none());
|
||||
match kept.kind {
|
||||
CurveKind::Circle { c, r } => {
|
||||
assert_eq!(r, 5.25);
|
||||
let p = &sk.points[c];
|
||||
assert!(p.link.is_none(), "it sits on a point of its own, not a projected one");
|
||||
assert!(p.pos.len() < 1e-9, "still at the hole's centre: {:?}", p.pos);
|
||||
}
|
||||
ref k => panic!("not a circle: {k:?}"),
|
||||
}
|
||||
assert_eq!(sk.link_curves(&link).len(), 4 + 3, "the projection is the new outline and holes");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user