ocs_doc_api: Phase 5 typed raster image create

- CreateRasterImage(RasterImageSpec) op (append-only).
- backend add_raster_image (RasterImage with file_path/insertion/u/v/size; the
  scene auto-registers the ImageDefinition on add_entity).
- facade create_raster_image; spec RasterImage constructor; api_reference +
  binding_schema regenerated; mocks + baseline.
- Test phase5_create_raster_image_registers_definition (asserts definition_handle
  auto-registered + 4-corner bounds) -> 610 host lib + 3 consistency green.
- Phase 5 complete.
This commit is contained in:
Sebastian committed 2026-09-06 10:28:51 +02:00
1 parent e6c132e0eb
commit 46a5922520
12 files changed
+109 -6

No files matched your search

+3
View File
@@ -81,6 +81,9 @@ pub trait DocApiBackend {
/// A viewport's view (target WCS + zoom height). Viewport-only.
fn viewport_view(&self, id: ObjectId) -> ApiResult<([f64; 3], f64)>;
/// Add a `RASTER_IMAGE` (host auto-registers the ImageDefinition).
fn add_raster_image(&mut self, spec: &crate::ops::RasterImageSpec) -> 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).
+6
View File
@@ -247,6 +247,12 @@ pub fn apply_op<B: DocApiBackend>(b: &mut B, op: Operation) -> ApiResult<Receipt
b.finalize_op();
OpOutcome::Updated(*id)
}
Operation::CreateRasterImage(spec) => {
b.push_undo(name);
let id = b.add_raster_image(spec)?;
b.finalize_op();
OpOutcome::NewId(id)
}
};
Ok(Receipt {
outcome: Some(outcome),
+13
View File
@@ -509,6 +509,19 @@ impl CurveCollection {
let (s, id) = self.create_curve(Curve2Spec::XLine { origin, direction })?;
Ok(XLine::new(s, id))
}
/// A RASTER_IMAGE placed at `insertion_point` (host auto-registers the image definition).
pub fn create_raster_image(&self, file_path: &str, insertion_point: [f64; 3], u_vector: [f64; 3], v_vector: [f64; 3], size: [f64; 2]) -> ApiResult<Entity> {
let receipt = self.session.apply_op(Operation::CreateRasterImage(crate::ops::RasterImageSpec {
file_path: file_path.to_string(),
insertion_point,
u_vector,
v_vector,
size,
}))?;
let id = receipt.outcome.and_then(|o| o.new_id()).ok_or_else(|| ApiError::Transport("create_raster_image returned no id".into()))?;
Ok(Entity::new(self.session.clone(), id))
}
/// A solid (or pattern) HATCH over a single closed polyline boundary.
pub fn create_hatch(&self, boundary: &[[f64; 2]], solid: bool) -> ApiResult<Entity> {
let receipt = self.session.apply_op(Operation::CreateHatch(crate::ops::HatchSpec {
+5 -1
View File
@@ -165,7 +165,11 @@ Paper-space viewport: a width×height window at center looking at view_target wi
## `Entity` (acadrust `RasterImage`, collection `entities`)
Raster image (read-mostly): GetEntity kind + coarse bounds (insertion + u*width + v*height); generic delete. No typed create in v1.
Raster image: create_raster_image(file_path, insertion, u, v, size) places an image (host auto-registers the ImageDefinition); bounds (4-corner bracket); delete.
### Constructors (`doc.entities()`)
- **create_raster_image**(`file_path: &str, insertion_point: [f64; 3], u_vector: [f64; 3], v_vector: [f64; 3], size: [f64; 2]`) -> `Entity`
## `Entity` (acadrust `Table`, collection `entities`)
+3 -1
View File
@@ -7,7 +7,7 @@
use serde::{Deserialize, Serialize};
use crate::id::ObjectId;
use crate::ops::{BoolOp, Curve2Spec, DimensionSpec, EntitySpec, HatchSpec, InsertSpec, MTextSpec, PlacementSpec, SolidPrimitive, TextSpec, ViewportSpec};
use crate::ops::{BoolOp, Curve2Spec, DimensionSpec, EntitySpec, HatchSpec, InsertSpec, MTextSpec, PlacementSpec, RasterImageSpec, SolidPrimitive, TextSpec, ViewportSpec};
/// A typed write operation (plan §5). Each variant is ONE atomic host call = one
/// undo step. Append new variants at the END only.
@@ -44,4 +44,6 @@ pub enum Operation {
SetAttribute { id: ObjectId, tag: String, value: String },
// viewport view
SetViewportView { id: ObjectId, view_target: [f64; 3], view_height: f64 },
// media
CreateRasterImage(RasterImageSpec),
}
+14
View File
@@ -115,6 +115,19 @@ pub struct DimensionSpec {
pub definition_point: [f64; 3],
}
/// Construction spec for a `RASTER_IMAGE`: an image file placed at
/// `insertion_point` with per-pixel world-unit vectors `u_vector`/`v_vector` and
/// pixel `size` (width, height). The host auto-registers the ImageDefinition.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct RasterImageSpec {
pub file_path: String,
pub insertion_point: [f64; 3],
pub u_vector: [f64; 3],
pub v_vector: [f64; 3],
/// Pixel size (width, height).
pub size: [f64; 2],
}
/// A rigid similarity (rotation + translation + optional uniform scale/reflection)
/// as a plain-data mirror of `cadkernel::brep::transform`'s `Placement`
/// (non-serde). Columns are the new basis axes; `origin` is the translation.
@@ -171,6 +184,7 @@ impl crate::gen::Operation {
CreateDimensionLinear(_) => "CreateDimensionLinear",
SetAttribute { .. } => "SetAttribute",
SetViewportView { .. } => "SetViewportView",
CreateRasterImage(_) => "CreateRasterImage",
}
}
}