fix(trim): cut a closed ellipse at the right span
Two faults met on the same command, both of them older than the move to cadkernel and both hidden until ellipse previews started rendering truthfully. The survivor came back in two pieces. `trim_ellipse` handed its cuts to `trim_intervals`, which is the open-curve routine: it anchors on bounds at 0.0 and 1.0, so a closed ellipse gained invented cuts at the parameter seam and the surviving arc arrived split either side of it. Worse, a click in the wrapping piece landed in one of those two halves, so the wrong span disappeared. A closed ellipse now takes the cyclic route circles already used — find the cut-to-cut gap holding the click, keep everything else, and let end < start signal the wrap. The cut span was also short. That came from `line_ellipse`, fixed upstream in cadkernel 46e76cc: it returned the geometric angle at the centre rather than the ellipse parameter, which are the same thing only on a circle. On anything eccentric the cuts sat tens of degrees off where the line actually crossed, so the removed piece was consistently too small. The lock bump brings that fix in. Elliptical arcs, lines, rays, xlines and open splines keep using `trim_intervals`; nothing about the open-curve path changes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
d0cc3284d2
commit
06a0fc4ddf
2 changed files with 36 additions and 1 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
|
@ -946,7 +946,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
|
|||
[[package]]
|
||||
name = "cadkernel"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git#0e4b23845de75242e00f016feed9fc2341b4a85a"
|
||||
source = "git+https://github.com/HakanSeven12/cadkernel.git#46e76ccb737a3682ffccf5117e89879ebfd1e227"
|
||||
|
||||
[[package]]
|
||||
name = "calloop"
|
||||
|
|
|
|||
|
|
@ -847,6 +847,41 @@ fn trim_ellipse(orig: &EllipseEnt, ts: &[f64], t_click: f64) -> Vec<EntityType>
|
|||
let span = t1 - t0;
|
||||
let angle_at = |t: f64| t0 + span * t;
|
||||
|
||||
// A closed ellipse has no ends for `trim_intervals` to anchor on. Handing
|
||||
// it one makes it invent cuts at the parameter seam, so the survivor comes
|
||||
// back as two arcs either side of the seam instead of one joined across
|
||||
// it — and if the click lands in the wrapping piece, the wrong side goes.
|
||||
// Circles avoid this by treating the cuts cyclically; see `trim_circle`.
|
||||
if (span - TAU).abs() < 1e-9 {
|
||||
if ts.len() < 2 {
|
||||
return vec![];
|
||||
}
|
||||
let click = t_click.rem_euclid(1.0);
|
||||
// The gap holding the click, with the last one wrapping past 1.0 back
|
||||
// to the first cut.
|
||||
let gap = (0..ts.len()).find_map(|i| {
|
||||
let from = ts[i];
|
||||
let to = if i + 1 < ts.len() {
|
||||
ts[i + 1]
|
||||
} else {
|
||||
ts[0] + 1.0
|
||||
};
|
||||
let holds = |t: f64| t >= from - 1e-9 && t <= to + 1e-9;
|
||||
(holds(click) || holds(click + 1.0)).then_some((from, to))
|
||||
});
|
||||
let Some((from, to)) = gap else {
|
||||
return vec![];
|
||||
};
|
||||
// The survivor runs from the far edge of the removed gap all the way
|
||||
// round to its near edge. Leaving the end below the start is what
|
||||
// signals the wrap to everything downstream.
|
||||
let mut e = orig.clone();
|
||||
e.common.handle = Handle::NULL;
|
||||
e.start_parameter = angle_at(to % 1.0);
|
||||
e.end_parameter = angle_at(from % 1.0);
|
||||
return vec![EntityType::Ellipse(e)];
|
||||
}
|
||||
|
||||
trim_intervals(ts, t_click)
|
||||
.into_iter()
|
||||
.filter_map(|(ta, tb)| {
|
||||
|
|
|
|||
Loading…
Reference in a new issue