Surface Revolve: sheets turned from open curves and profiles (#824)

Surface Revolve turns open curves and closed profile boundaries about a sketch axis into surface bodies, with cone apexes and sphere poles where a chain ends on the axis, and a closed shell made solid. Adds the SurfaceRevolve feature (format 18 note), the surface.revolve command, a dialog with Edit Feature support and analytic kernel and engine tests.

Part of #757.
This commit is contained in:
Irakli Kourtis authored and GitHub committed 2026-10-13 20:30:41 -04:00
1 parent b41ad23e3f
commit 2eb292dd4a
16 files changed
+411 -83

No files matched your search

+37 -10
View File
@@ -98,17 +98,28 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
let d = val(vals, &extent.distance, Kind::Length)?;
let off = extent.start_offset.as_deref().map(|e| val(vals, e, Kind::Length)).transpose()?.unwrap_or(0.0);
let (a, b) = extent_sides(vals, extent, d, extent.direction)?;
let mut chains: Vec<Vec<Seg2>> = Vec::new();
if let Some(sel) = profiles {
for r in solidcraft_sketch::merge_regions(&select_profiles(&ss, sel)?) {
chains.extend(std::iter::once(r.outer).chain(r.holes).map(|lp| lp.segs));
let body = kernel::extrude_sheet(&ss.plane, &sheet_chains(&ss, profiles.as_ref(), curves)?, a + off, b + off)?;
let name = new_name(st, f, 0);
st.bodies.push(ModelBody::new(name, body, f.id));
Ok(())
}
FeatureKind::SurfaceRevolve { sketch, profiles, curves, axis, angle, angle2, symmetric } => {
let ss = sketch_in_feature_frame(
doc,
st.sketch(*sketch).ok_or_else(|| DocError::Unknown(format!("sketch {sketch} (it must come earlier in the timeline)")))?,
f.component,
)?;
let (o, d) = revolve_axis(&ss, axis)?;
let a = val(vals, angle, Kind::Angle)?;
let (start, sweep) = match (angle2, symmetric) {
(Some(a2), _) => {
let a2 = val(vals, a2, Kind::Angle)?;
(-a2, a + a2)
}
}
chains.extend(curve_chains(&ss, curves)?);
if chains.is_empty() {
return Err(DocError::Invalid("pick the profiles or curves to extrude".into()));
}
let body = kernel::extrude_sheet(&ss.plane, &chains, a + off, b + off)?;
(None, true) => (-a / 2.0, a),
(None, false) => (0.0, a),
};
let body = kernel::revolve_sheet(&ss.plane, &sheet_chains(&ss, profiles.as_ref(), curves)?, o, d, start, sweep)?;
let name = new_name(st, f, 0);
st.bodies.push(ModelBody::new(name, body, f.id));
Ok(())
@@ -148,6 +159,22 @@ pub(super) fn eval(doc: &Document, vals: &BTreeMap<String, Value>, f: &Feature,
}
}
/// What a surface builder sweeps: the boundary loops of the picked profiles, then the picked
/// curves chained end to end.
fn sheet_chains(ss: &SolvedSketch, profiles: Option<&ProfileSel>, curves: &[String]) -> Result<Vec<Vec<Seg2>>> {
let mut chains: Vec<Vec<Seg2>> = Vec::new();
if let Some(sel) = profiles {
for r in solidcraft_sketch::merge_regions(&select_profiles(ss, sel)?) {
chains.extend(std::iter::once(r.outer).chain(r.holes).map(|lp| lp.segs));
}
}
chains.extend(curve_chains(ss, curves)?);
if chains.is_empty() {
return Err(DocError::Invalid("pick the profiles or curves".into()));
}
Ok(chains)
}
/// Most sketch curves one feature chains.
const MAX_CHAIN_CURVES: usize = 1000;