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:
Sebastian committed 2026-09-06 10:44:37 +02:00
1 parent 46a5922520
commit e216a7bf94
13 files changed
+176 -21

No files matched your search

@@ -207,6 +207,14 @@ impl DocApiBackend for MockBackend {
fn add_raster_image(&mut self, _spec: &ocs_doc_api::ops::RasterImageSpec) -> ApiResult<ObjectId> {
Ok(self.alloc("RasterImage"))
}
fn loft(&mut self, sections: &[Vec<cadkernel::geom2d::Curve>]) -> ApiResult<ObjectId> {
if sections.len() < 2 {
return Err(ApiError::validation("Loft", "loft needs >= 2 profiles"));
}
let body = cadkernel::brep::make::cuboid([0.0, 0.0, 0.0], [1.0; 3])
.ok_or_else(|| ApiError::geometry(GeometryErrorKind::InvalidInput, "make cuboid"))?;
self.store_solid(&body)
}
fn set_viewport_view(&mut self, id: ObjectId, view_target: [f64; 3], view_height: f64) -> ApiResult<()> {
if !self.entity_exists(id) {
return Err(ApiError::UnknownId(id));