Exact free-form profiles: geom Seg2 gains cubic Béziers and conics (rational quadratics: exact length, area, split, tangents); sketch ellipses, conics, text, fit splines and control splines up to degree 3 enter profiles as exact segments wherever a loop uses a whole segment, and the kernel builds them as B-spline / NURBS edges (an extruded ellipse is three faces with the exact volume)

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
bherbruckandClaude Opus 5.5 committed 2026-10-08 02:16:00 +00:00
1 parent 8b4ec13d3b
commit 31030ed008
13 files changed
+447 -31

No files matched your search

+7 -3
View File
@@ -1106,10 +1106,14 @@ fn path_segments(ps: &SolvedSketch, ids: &[String], start: Vec3) -> Result<Vec<k
let n = ps.plane.normal();
Ok(segs
.iter()
.map(|s| match *s {
solvecraft_geom::Seg2::Line { a, b } => kernel::PathSeg::Line { a: w(a), b: w(b) },
.flat_map(|s| match *s {
solvecraft_geom::Seg2::Line { a, b } => vec![kernel::PathSeg::Line { a: w(a), b: w(b) }],
solvecraft_geom::Seg2::Arc { center, sweep, .. } => {
kernel::PathSeg::Arc { a: w(s.start()), center: w(center), axis: n * sweep.signum(), angle: sweep.abs() }
vec![kernel::PathSeg::Arc { a: w(s.start()), center: w(center), axis: n * sweep.signum(), angle: sweep.abs() }]
}
// Free-form path curves are followed as polylines.
solvecraft_geom::Seg2::Cubic { .. } | solvecraft_geom::Seg2::Conic { .. } => {
s.polyline(1e-2).windows(2).map(|q| kernel::PathSeg::Line { a: w(q[0]), b: w(q[1]) }).collect()
}
})
.collect())
+1 -2
View File
@@ -424,7 +424,7 @@ fn tilted_circle(plane: &Plane, pts: &[Vec3]) -> Option<Vec<LinkGeom>> {
return Some(vec![LinkGeom::Ellipse { c: plane.to_local(c), major: plane.to_local(c + u * r), minor: r * cosang }]);
}
// Sweep from the first point along the polyline's direction.
let (p0, p1) = (*pts.first()?, *pts.last()?);
let p0 = *pts.first()?;
let e1 = (p0 - c).normalized()?;
let e2 = n.cross(e1);
let ang = |p: Vec3| (p - c).dot(e2).atan2((p - c).dot(e1));
@@ -439,7 +439,6 @@ fn tilted_circle(plane: &Plane, pts: &[Vec3]) -> Option<Vec<LinkGeom>> {
}
sweep += d;
}
let _ = p1;
let k = ((sweep.abs() / std::f64::consts::FRAC_PI_2).ceil() as usize).clamp(1, 8);
let h = sweep / k as f64;
let at = |t: f64| c + (e1 * t.cos() + e2 * t.sin()) * r;