Files
cadcraft/crates/io/tests/closed_spline.rs
Valentin KleinandClaude Opus 5.5 c55feb79da SPLINE Close is periodic, options report; POLYGON typed radius has a flat bottom; CIRCLE rejects bad input (fixes #238) (#240)
SPLINE Close now builds a smooth closed (periodic) curve through the fit points
instead of repeating the first point. The geometry gets Spline::from_fit_points_closed:
chord-length parameters including the closing chord, a periodic knot vector, and the
first three control points repeated at the end. The fit data no longer duplicates the
first point. DXF writes group 70 bit 2 (periodic) for it, and a file whose closed spline
needs refitting is refitted closed. SPLINEDIT Close/refit/move and fit-point grips keep
a closed spline periodic.

SPLINE Method asks Fit/CV, and CV continues as SPLINE by control vertices. Knots, Object,
start/end Tangency and toLerance report "not available yet" and stay at the prompt.
Garbage text reports "Point or option keyword required.".

POLYGON with a typed radius puts the bottom edge horizontal for Inscribed and for
Circumscribed. The JSON form uses the same orientation when no angle is given.

CIRCLE reports "Point or option keyword required." for an invalid token at the centre
prompt, and "Invalid point." at the 3P/2P point prompts, then asks again.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 15:34:24 -04:00

26 lines
1.2 KiB
Rust

//! A closed fit-point spline is periodic: DXF flags it closed + periodic (group 70 bits 1 and 2)
//! and it reads back as the same smooth closed curve.
use cadcraft_doc::{Common, Drawing, EntityKind, Space};
use cadcraft_geom::{Spline, Vec2};
#[test]
fn closed_fit_spline_roundtrips_as_periodic() {
let fit = [Vec2::new(0.0, 0.0), Vec2::new(4.0, 0.0), Vec2::new(4.0, 3.0), Vec2::new(0.0, 3.0)];
let sp = Spline::from_fit_points_closed(&fit);
let mut d = Drawing::new_metric();
d.add(&Space::Model, Common::default(), EntityKind::Spline(sp.clone())).unwrap();
let bytes = cadcraft_io::write(&d, "a.dxf").unwrap();
let text = String::from_utf8(bytes.clone()).unwrap();
let spline = &text[text.find("SPLINE").unwrap()..];
assert!(spline.contains("70\r\n11\r\n"), "planar + closed + periodic");
let back = cadcraft_io::read(&bytes, "a.dxf").unwrap();
let Some(EntityKind::Spline(r)) = back.model.iter().map(|e| e.kind.clone()).next() else { panic!("no spline") };
assert!(r.closed && r.is_periodic());
assert_eq!(r.fit.len(), 4);
for i in 0..=20 {
let t = i as f64 / 20.0;
assert!(r.eval(t).near(sp.eval(t), 1e-9));
}
}