Ruled Surface: strips off an edge chain, exact where possible (#762) (#1151)

Ruled Surface: strips off an edge chain in normal, tangent, angle or direction mode, exact planes/cylinders/cones where possible, mitred or round corners, stitched into one surface body. SurfaceRuled is noted under format 21. Closes #762.
This commit is contained in:
Irakli Kourtis authored and GitHub committed 2026-10-14 21:44:56 -04:00
1 parent ed22d663e4
commit 2a4907884b
24 files changed
+1343 -36

No files matched your search

+27 -2
View File
@@ -1,8 +1,9 @@
//! Evaluation of the surface features: Patch, Stitch, Thicken, Trim, Extend, Surface Extrude,
//! Revolve, Sweep and Loft, Offset, Untrim, Unstitch and Reverse Normal (kernel `surfaces`,
//! `surface_offset`, `surface_untrim`).
//! Revolve, Sweep and Loft, Offset, Ruled, Untrim, Unstitch and Reverse Normal (kernel `surfaces`,
//! `surface_offset`, `surface_ruled`, `surface_untrim`).
use super::*;
use crate::{RuledCorners, RuledMode};
use solidcraft_geom::Seg2;
pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature, st: &mut ModelState) -> Result<()> {
@@ -234,6 +235,30 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
st.bodies.push(ModelBody::traced_new(name, made, f.id));
Ok(())
}
FeatureKind::SurfaceRuled { body, edges, distance, mode, angle, direction, flip, corners, face } => {
let d = val(vals, distance, Kind::Length)?;
let mode = match mode {
RuledMode::Normal => kernel::RuledMode::Normal,
RuledMode::Tangent => kernel::RuledMode::Tangent,
RuledMode::Angle => {
let a = angle.as_ref().ok_or_else(|| DocError::Invalid("a ruled surface at an angle needs `angle`".into()))?;
kernel::RuledMode::Angle { angle: val(vals, a, Kind::Angle)?, reference: *direction }
}
RuledMode::Direction => kernel::RuledMode::Direction(
direction.ok_or_else(|| DocError::Invalid("a ruled surface along a direction needs `direction`".into()))?,
),
};
let corners = match corners {
RuledCorners::Mitre => kernel::RuledCorners::Mitre,
RuledCorners::Round => kernel::RuledCorners::Round,
};
let mb = st.body(body).cloned().ok_or_else(|| DocError::Unknown(format!("body `{body}`")))?;
let r = kernel::Ruled { distance: d, mode, flip: *flip, corners, face: *face };
let made = Traced::step(kernel::ruled_surface(&mb.body, edges, &r)?, &[&mb.traced()]);
let name = new_name(st, f, 0);
st.bodies.push(ModelBody::traced_new(name, made, f.id));
Ok(())
}
FeatureKind::SurfaceUntrim { face, holes, outer, in_place } => {
let i = st.bodies.iter().position(|b| b.name == face.body).ok_or_else(|| DocError::Unknown(format!("body `{}`", face.body)))?;
let Some(mb) = st.bodies.get(i).cloned() else { return Err(DocError::Invalid("body".into())) };