Exact profiles for splines of any degree (a degree-4…7 Bézier segment kind, Seg2::Bezier, extruded as B-spline edges) and for free-form curves cut by crossings (exact sub-curves whose ends are moved to the true crossing, found by Newton; polylines only where that fails)
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01AS5Tn3xieewUSg3uxrMVdL
This commit is contained in:
1 parent
f79b5c1045
commit
b9bc75670c
11 files changed
+389
-34
No files matched your search
@@ -41,7 +41,7 @@ pub(crate) fn wire(plane: &Plane, lp: &Loop2) -> Result<mt::Wire> {
|
||||
builder::circle_arc(a, b, p3(plane.to_world(s.mid())))
|
||||
}
|
||||
}
|
||||
Seg2::Cubic { .. } | Seg2::Conic { .. } => {
|
||||
Seg2::Cubic { .. } | Seg2::Conic { .. } | Seg2::Bezier { .. } => {
|
||||
crate::freeform::edge(plane, s, a, b).ok_or_else(|| KernelError::Invalid("profile curve".into()))?
|
||||
}
|
||||
};
|
||||
@@ -71,6 +71,7 @@ fn region_ok(r: &Region2) -> Result<()> {
|
||||
}
|
||||
Seg2::Cubic { p0, p1, p2, p3 } => p0.is_finite() && p1.is_finite() && p2.is_finite() && p3.is_finite(),
|
||||
Seg2::Conic { a, apex, b, w } => a.is_finite() && apex.is_finite() && b.is_finite() && w.is_finite() && w > 1e-9,
|
||||
Seg2::Bezier { n, p } => (4..=solvecraft_geom::MAX_BEZIER_DEGREE as u8).contains(&n) && p.iter().all(|q| q.is_finite()),
|
||||
};
|
||||
if !ok {
|
||||
return Err(KernelError::Invalid("non-finite profile".into()));
|
||||
@@ -417,7 +418,7 @@ fn revolve_touching_axis(plane: &Plane, lp: &Loop2, axis_origin: Vec2, d: Vec2)
|
||||
edges.push(match *s {
|
||||
Seg2::Line { .. } => builder::line(a, b),
|
||||
Seg2::Arc { .. } => builder::circle_arc(a, b, p3(plane.to_world(s.mid()))),
|
||||
Seg2::Cubic { .. } | Seg2::Conic { .. } => match crate::freeform::edge(plane, s, a, b) {
|
||||
Seg2::Cubic { .. } | Seg2::Conic { .. } | Seg2::Bezier { .. } => match crate::freeform::edge(plane, s, a, b) {
|
||||
Some(e) => e,
|
||||
None => builder::line(a, b),
|
||||
},
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! Free-form profile edges: cubic Béziers as B-spline curves and conics as rational quadratic
|
||||
//! Free-form profile edges: Béziers (cubic and higher) as B-spline curves and conics as rational quadratic
|
||||
//! NURBS curves (exact ellipses, parabolas and hyperbolas from sketches).
|
||||
|
||||
use solvecraft_geom::{Plane, Seg2};
|
||||
@@ -20,6 +20,10 @@ pub(crate) fn edge(plane: &Plane, s: &Seg2, a: &mt::Vertex, b: &mt::Vertex) -> O
|
||||
let curve = mt::NurbsCurve::new(mt::BSplineCurve::new(mt::KnotVec::bezier_knot(2), ctrl));
|
||||
Some(mt::Edge::new(a, b, mt::Curve::NurbsCurve(curve)))
|
||||
}
|
||||
Seg2::Bezier { n, ref p } => {
|
||||
let inner = p.get(1..(n as usize).clamp(1, solvecraft_geom::MAX_BEZIER_DEGREE))?;
|
||||
Some(mt::builder::bezier(a, b, inner.iter().map(|q| p3(plane.to_world(*q))).collect()))
|
||||
}
|
||||
Seg2::Line { .. } | Seg2::Arc { .. } => None,
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user