forked from 1b-agent/opencadstudio-upstream
ocs_doc_api: outstanding methods — loft + bulge-arc polyline profiles
- Loft{profiles} op (append-only); executor resolves each profile to curve sets
all-or-nothing; backend loft() -> brep::loft on XY plane; facade solids().loft.
- entity_to_profile_curves: convert LwVertex.bulge to geom2d::Curve::Arc via
bulge_arc_segment (theta = 4*atan(bulge)), so bulged polyline profiles sweep
correctly instead of erroring Unsupported.
- spec loft; api_reference + binding_schema regenerated; mocks + baseline.
- Tests: loft_two_profiles_produces_solid, bulge_arc_polyline_profile_converts_to_arc
(semicircle radius=5 for bulge=1) -> 612 host lib + 3 consistency green.
This commit is contained in:
1 parent
46a5922520
commit
e216a7bf94
13 files changed
+176
-21
No files matched your search
@@ -84,6 +84,10 @@ pub trait DocApiBackend {
|
||||
/// Add a `RASTER_IMAGE` (host auto-registers the ImageDefinition).
|
||||
fn add_raster_image(&mut self, spec: &crate::ops::RasterImageSpec) -> ApiResult<ObjectId>;
|
||||
|
||||
/// Loft a solid through >= 2 profile curve sets (each already resolved to
|
||||
/// `geom2d::Curve`s on the XY plane). Returns the fresh `ObjectId`.
|
||||
fn loft(&mut self, sections: &[Vec<cadkernel::geom2d::Curve>]) -> ApiResult<ObjectId>;
|
||||
|
||||
/// Can `id` be modified in place right now (exists, is the expected family,
|
||||
/// not on a locked layer)? Read-only pre-check used before mutations.
|
||||
/// Default: existence + not-locked (backends narrow the family check).
|
||||
|
||||
@@ -253,6 +253,22 @@ pub fn apply_op<B: DocApiBackend>(b: &mut B, op: Operation) -> ApiResult<Receipt
|
||||
b.finalize_op();
|
||||
OpOutcome::NewId(id)
|
||||
}
|
||||
Operation::Loft { profiles } => {
|
||||
// Resolve every profile to its curve set BEFORE push_undo (all-or-nothing).
|
||||
if profiles.len() < 2 {
|
||||
return Err(ApiError::validation(name, "loft needs >= 2 profiles"));
|
||||
}
|
||||
let mut sections = Vec::with_capacity(profiles.len());
|
||||
for (i, p) in profiles.iter().enumerate() {
|
||||
let curves = profile_curves(b, *p, name)
|
||||
.map_err(|e| at_index(name, i, e))?;
|
||||
sections.push(curves);
|
||||
}
|
||||
b.push_undo(name);
|
||||
let id = b.loft(§ions)?;
|
||||
b.finalize_op();
|
||||
OpOutcome::NewId(id)
|
||||
}
|
||||
};
|
||||
Ok(Receipt {
|
||||
outcome: Some(outcome),
|
||||
|
||||
@@ -452,6 +452,13 @@ impl SolidCollection {
|
||||
.ok_or_else(|| ApiError::Transport("revolve returned no id".into()))?;
|
||||
Ok(Solid::new(self.session.clone(), id))
|
||||
}
|
||||
/// Loft a solid through >= 2 profile entities (polylines/circles/arcs).
|
||||
pub fn loft(&self, profiles: &[impl HasId]) -> ApiResult<Solid> {
|
||||
let ids: Vec<ObjectId> = profiles.iter().map(|p| p.id()).collect();
|
||||
let receipt = self.session.apply_op(Operation::Loft { profiles: ids })?;
|
||||
let id = receipt.outcome.and_then(|o| o.new_id()).ok_or_else(|| ApiError::Transport("loft returned no id".into()))?;
|
||||
Ok(Solid::new(self.session.clone(), id))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
|
||||
@@ -18,6 +18,7 @@ B-rep solid. Host resolves bodies via the solid_models cache (lift-on-miss from
|
||||
- **create_wedge**(`origin: [f64; 3], size: [f64; 3]`) -> `Solid`
|
||||
- **extrude**(`profile: EntityRef, direction: [f64; 3]`) -> `Solid`
|
||||
- **revolve**(`profile: EntityRef, pivot: [f64; 3], axis: [f64; 3], angle: f64`) -> `Solid`
|
||||
- **loft**(`profiles: &[EntityRef]`) -> `Solid`
|
||||
|
||||
### Methods
|
||||
|
||||
|
||||
@@ -46,4 +46,6 @@ pub enum Operation {
|
||||
SetViewportView { id: ObjectId, view_target: [f64; 3], view_height: f64 },
|
||||
// media
|
||||
CreateRasterImage(RasterImageSpec),
|
||||
// multi-profile solid
|
||||
Loft { profiles: Vec<ObjectId> },
|
||||
}
|
||||
@@ -185,6 +185,7 @@ impl crate::gen::Operation {
|
||||
SetAttribute { .. } => "SetAttribute",
|
||||
SetViewportView { .. } => "SetViewportView",
|
||||
CreateRasterImage(_) => "CreateRasterImage",
|
||||
Loft { .. } => "Loft",
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user