ocs_doc_api: Phase 2b-b (Hatch)

- CreateHatch(HatchSpec) op + GetHatchBoundary query (append-only).
- HatchSpec{boundary: Vec<[f64;2]>, solid}; executor validates >= 3 boundary points.
- backend add_hatch (Line-edge BoundaryPath, solid/pattern) + hatch_boundary
  (reconstruct loops from Line edges; non-line edges -> Unsupported).
- Hatch bounds from boundary edges; facade create_hatch + Entity handle.
- spec Hatch family; api_reference + binding_schema regenerated; mocks + baseline.
- Test phase2b_hatch_create_boundary_bounds_delete -> 606 host lib + 8 crate + 3 consistency green.
This commit is contained in:
Sebastian committed 2026-09-06 09:24:11 +02:00
1 parent fc0e2c2c9d
commit ba8e5ed0cd
16 files changed
+223 -3

No files matched your search

+10
View File
@@ -23,6 +23,8 @@ struct MockBackend {
kinds: HashMap<ObjectId, String>,
/// Stored text content for Text/MText annotations.
text_values: HashMap<ObjectId, String>,
/// Stored hatch boundary loops.
hatch_boundaries: HashMap<ObjectId, Vec<Vec<[f64; 2]>>>,
}
impl MockBackend {
@@ -96,6 +98,14 @@ impl DocApiBackend for MockBackend {
fn text_content(&self, id: ObjectId) -> ApiResult<String> {
self.text_values.get(&id).cloned().ok_or(ApiError::UnknownId(id))
}
fn add_hatch(&mut self, spec: &ocs_doc_api::ops::HatchSpec) -> ApiResult<ObjectId> {
let id = self.alloc("Hatch");
self.hatch_boundaries.insert(id, vec![spec.boundary.clone()]);
Ok(id)
}
fn hatch_boundary(&self, id: ObjectId) -> ApiResult<Vec<Vec<[f64; 2]>>> {
self.hatch_boundaries.get(&id).cloned().ok_or(ApiError::UnknownId(id))
}
fn add_vertex(&mut self, id: ObjectId, _at: usize, _point: [f64; 3]) -> ApiResult<()> {
if self.entity_exists(id) {
Ok(())
@@ -56,6 +56,7 @@ fn operation_variants() -> Vec<String> {
Operation::CreateText(ocs_doc_api::ops::TextSpec { value: String::new(), insertion_point: [0.0; 3], height: 0.0, rotation: 0.0 }),
Operation::CreateMText(ocs_doc_api::ops::MTextSpec { value: String::new(), insertion_point: [0.0; 3], height: 0.0 }),
Operation::SetTextContent { id: ObjectId::from_u64(0), value: String::new() },
Operation::CreateHatch(ocs_doc_api::ops::HatchSpec { boundary: vec![], solid: true }),
];
// Derive the variant names by serializing a probe of each and reading the
// bincode variant index -> name map is not available; instead match by
@@ -81,6 +82,7 @@ fn query_variants() -> Vec<String> {
Query::GetIntersects { a: ObjectId::from_u64(0), b: ObjectId::from_u64(0) },
Query::GetGeometryRevision,
Query::GetTextContent { id: ObjectId::from_u64(0) },
Query::GetHatchBoundary { id: ObjectId::from_u64(0) },
];
marker
.iter()
@@ -134,6 +136,7 @@ const OPERATION_BASELINE: &[&str] = &[
"CreateText",
"CreateMText",
"SetTextContent",
"CreateHatch",
];
/// Recorded baseline of the `Query` variant order.
@@ -145,6 +148,7 @@ const QUERY_BASELINE: &[&str] = &[
"GetIntersects",
"GetGeometryRevision",
"GetTextContent",
"GetHatchBoundary",
];
#[test]