fix(snap): correct circle tangent point + no endpoint on closed curves
Two object-snap fixes: - Tangent on a circle built the snap point as `(cx + r·nx, cy, cy + r·ny)` — the y-offset landed in Z and Y was stuck at the centre, so the tangent point sat at the wrong place. Build it as `(cx + r·nx, cy + r·ny, cz)`. - Endpoint snapped to a full circle / ellipse: for tessellated curves it snaps the first/last point, but a closed curve's first/last is a seam, not an endpoint. Skip Endpoint for closed curves — identified by their Quadrant snap hints, which arcs never carry — so arcs still snap their real endpoints. Closes #274, closes #275 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
d0639b3e38
commit
e512e57a7c
1 changed files with 21 additions and 7 deletions
28
src/snap.rs
28
src/snap.rs
|
|
@ -802,14 +802,25 @@ impl Snapper {
|
|||
);
|
||||
}
|
||||
} else {
|
||||
// Tessellated curves (Circle, Arc, Ellipse): only arc endpoints.
|
||||
if let Some(&p) = wire.points.first() {
|
||||
try_pt(glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64), SnapType::Endpoint);
|
||||
}
|
||||
if wire.points.len() > 1 {
|
||||
if let Some(&p) = wire.points.last() {
|
||||
// Tessellated curves (Circle, Arc, Ellipse): only an OPEN
|
||||
// one (an arc) has real endpoints. A full circle / ellipse is
|
||||
// closed — its tessellation's first/last is a seam point, not
|
||||
// an endpoint — and is the only tessellated curve that carries
|
||||
// Quadrant snap hints (arcs never do), so emit no Endpoint for
|
||||
// those (#275).
|
||||
let closed = wire
|
||||
.snap_pts
|
||||
.iter()
|
||||
.any(|(_, h)| matches!(h, SnapHint::Quadrant));
|
||||
if !closed {
|
||||
if let Some(&p) = wire.points.first() {
|
||||
try_pt(glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64), SnapType::Endpoint);
|
||||
}
|
||||
if wire.points.len() > 1 {
|
||||
if let Some(&p) = wire.points.last() {
|
||||
try_pt(glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64), SnapType::Endpoint);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1101,7 +1112,10 @@ impl Snapper {
|
|||
} else {
|
||||
(1.0, 0.0)
|
||||
};
|
||||
let w = Vec3::new(cv.x + radius * nx, cv.y, cv.y + radius * ny);
|
||||
// Circle lies in its own plane at cv.z; the point
|
||||
// facing the cursor is center + radius·(nx, ny) in XY
|
||||
// (the y-offset must land in Y, not Z — #274).
|
||||
let w = Vec3::new(cv.x + radius * nx, cv.y + radius * ny, cv.z);
|
||||
(w, edge_d * edge_d)
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in a new issue