JOIN: an elliptical arc named twice is one object, so the joined result stays (fixes #725) (#739)

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Marco Arnulfo 2026-10-13 11:07:02 +02:00 committed by GitHub
parent 2483993218
commit 6394c7c6f3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 23 additions and 0 deletions

View File

@ -228,6 +228,9 @@ fn ends(sp: &Spline) -> (Vec2, Vec2) {
/// larger arc or the full ellipse (gaps between them close). Otherwise the objects joined end
/// to end with the first one become one spline. The first joined object keeps its handle.
pub(crate) fn join_curves(s: &mut Session, hs: &[Handle]) -> Result<Option<Handle>> {
// A handle named twice is one object: a repeat would join it with itself or remove the result.
let mut seen = std::collections::HashSet::new();
let hs: Vec<Handle> = hs.iter().copied().filter(|h| seen.insert(*h)).collect();
let d = s.doc()?;
let ents: Vec<Entity> = hs.iter().filter_map(|h| d.entity(*h).map(|e| (**e).clone())).collect();
if !ents.iter().any(|e| matches!(e.kind, EntityKind::Ellipse(_) | EntityKind::Spline(_))) {

View File

@ -262,6 +262,26 @@ fn join_merges_elliptical_arcs_on_one_ellipse() {
assert_eq!(count(&s), 1);
}
#[test]
fn join_names_an_elliptical_arc_twice_without_losing_it() {
// The same arc twice is one object: nothing to join, and the arc stays.
let mut s = Session::new();
let a = arc_on_ellipse(&mut s, 0.0, 90.0);
let before = ellipse(&s, &a);
assert!(s.execute("join", &json!({ "handles": [a, a] })).is_err());
assert_eq!(count(&s), 1);
assert_eq!(ellipse(&s, &a), before);
// Repeating the source next to a second arc still merges the two into the source.
let mut s = Session::new();
let a = arc_on_ellipse(&mut s, 0.0, 90.0);
let b = arc_on_ellipse(&mut s, 90.0, 180.0);
let r = s.execute("join", &json!({ "handles": [a, a, b] })).unwrap();
assert_eq!(h(&r), a);
let m = ellipse(&s, &a);
assert!(m.start.abs() < 1e-9 && (m.end - PI).abs() < 1e-9, "{m:?}");
assert_eq!(count(&s), 1);
}
#[test]
fn join_makes_one_spline_from_lines_arcs_polylines_and_splines() {
let mut s = Session::new();