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
18
src/snap.rs
18
src/snap.rs
|
|
@ -802,7 +802,17 @@ impl Snapper {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Tessellated curves (Circle, Arc, Ellipse): only arc endpoints.
|
// 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() {
|
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);
|
try_pt(glam::DVec3::new(p[0] as f64, p[1] as f64, p[2] as f64), SnapType::Endpoint);
|
||||||
}
|
}
|
||||||
|
|
@ -814,6 +824,7 @@ impl Snapper {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ── Midpoint ───────────────────────────────────────────────────────
|
// ── Midpoint ───────────────────────────────────────────────────────
|
||||||
// Only explicit vertex sets (Line, LwPolyline) contribute per-segment
|
// Only explicit vertex sets (Line, LwPolyline) contribute per-segment
|
||||||
|
|
@ -1101,7 +1112,10 @@ impl Snapper {
|
||||||
} else {
|
} else {
|
||||||
(1.0, 0.0)
|
(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)
|
(w, edge_d * edge_d)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue