forked from 1b-agent/opencadstudio-upstream
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:
1 parent
fc0e2c2c9d
commit
ba8e5ed0cd
16 files changed
+223
-3
No files matched your search
@@ -54,6 +54,12 @@ pub trait DocApiBackend {
|
||||
/// The text content of a Text/MText annotation. `Unsupported` for other kinds.
|
||||
fn text_content(&self, id: ObjectId) -> ApiResult<String>;
|
||||
|
||||
/// Add a `HATCH` (single closed polyline boundary); returns the fresh `ObjectId`.
|
||||
fn add_hatch(&mut self, spec: &crate::ops::HatchSpec) -> ApiResult<ObjectId>;
|
||||
|
||||
/// A hatch's boundary loops (outer + islands) as closed polylines.
|
||||
fn hatch_boundary(&self, id: ObjectId) -> ApiResult<Vec<Vec<[f64; 2]>>>;
|
||||
|
||||
/// 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).
|
||||
|
||||
@@ -211,6 +211,16 @@ pub fn apply_op<B: DocApiBackend>(b: &mut B, op: Operation) -> ApiResult<Receipt
|
||||
b.finalize_op();
|
||||
OpOutcome::Updated(*id)
|
||||
}
|
||||
Operation::CreateHatch(spec) => {
|
||||
// Validate the boundary (>= 3 points) before committing.
|
||||
if spec.boundary.len() < 3 {
|
||||
return Err(ApiError::validation(name, "hatch boundary needs >= 3 points"));
|
||||
}
|
||||
b.push_undo(name);
|
||||
let id = b.add_hatch(spec)?;
|
||||
b.finalize_op();
|
||||
OpOutcome::NewId(id)
|
||||
}
|
||||
};
|
||||
Ok(Receipt {
|
||||
outcome: Some(outcome),
|
||||
@@ -249,6 +259,7 @@ pub fn apply_queries<B: DocApiBackend>(b: &mut B, queries: Vec<Query>) -> ApiRes
|
||||
}
|
||||
Query::GetGeometryRevision => QueryResult::Revision(b.revision()),
|
||||
Query::GetTextContent { id } => QueryResult::TextContent(b.text_content(id)?),
|
||||
Query::GetHatchBoundary { id } => QueryResult::HatchBoundary(b.hatch_boundary(id)?),
|
||||
};
|
||||
results.push(r);
|
||||
}
|
||||
|
||||
@@ -465,6 +465,16 @@ impl CurveCollection {
|
||||
let (s, id) = self.create_curve(Curve2Spec::XLine { origin, direction })?;
|
||||
Ok(XLine::new(s, 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 {
|
||||
boundary: boundary.to_vec(),
|
||||
solid,
|
||||
}))?;
|
||||
let id = receipt.outcome.and_then(|o| o.new_id()).ok_or_else(|| ApiError::Transport("create_hatch returned no id".into()))?;
|
||||
Ok(Entity::new(self.session.clone(), id))
|
||||
}
|
||||
|
||||
/// Single-line TEXT annotation.
|
||||
pub fn create_text(&self, value: &str, insertion_point: [f64; 3], height: f64, rotation: f64) -> ApiResult<Text> {
|
||||
let receipt = self.session.apply_op(Operation::CreateText(crate::ops::TextSpec {
|
||||
|
||||
@@ -113,6 +113,18 @@ Multi-line text annotation. content()/set_content() read+replace the value; tran
|
||||
- **content**(``) -> `String` — query `GetTextContent`
|
||||
- **set_content**(`value: &str`) -> `()` — op `SetTextContent`
|
||||
|
||||
## `Entity` (acadrust `Hatch`, collection `curves`)
|
||||
|
||||
Filled region over a closed polyline boundary. boundary() returns the loops; bounds from boundary; generic delete.
|
||||
|
||||
### Constructors (`doc.curves()`)
|
||||
|
||||
- **create_hatch**(`boundary: &[[f64; 2]], solid: bool`) -> `Entity`
|
||||
|
||||
### Methods
|
||||
|
||||
- **boundary**(``) -> `Vec<Vec<[f64; 2]>>` — query `GetHatchBoundary`
|
||||
|
||||
## `Entity` (acadrust `Insert`, collection `entities`)
|
||||
|
||||
Block reference. Place an existing BlockRecord by name; transform moves its insert point.
|
||||
|
||||
@@ -258,6 +258,25 @@
|
||||
],
|
||||
"name": "MText"
|
||||
},
|
||||
{
|
||||
"acadrust_variant": "Hatch",
|
||||
"collection": "curves",
|
||||
"handle": "Entity",
|
||||
"methods": [
|
||||
{
|
||||
"args": [],
|
||||
"bulk": false,
|
||||
"fixed": null,
|
||||
"kind": "query",
|
||||
"name": "boundary",
|
||||
"op": null,
|
||||
"query": "GetHatchBoundary",
|
||||
"read_only": true,
|
||||
"returns": "Vec<Vec<[f64; 2]>>"
|
||||
}
|
||||
],
|
||||
"name": "Hatch"
|
||||
},
|
||||
{
|
||||
"acadrust_variant": "Insert",
|
||||
"collection": "entities",
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::id::ObjectId;
|
||||
use crate::ops::{BoolOp, Curve2Spec, EntitySpec, InsertSpec, MTextSpec, PlacementSpec, SolidPrimitive, TextSpec, ViewportSpec};
|
||||
use crate::ops::{BoolOp, Curve2Spec, EntitySpec, HatchSpec, InsertSpec, MTextSpec, PlacementSpec, 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.
|
||||
@@ -36,4 +36,6 @@ pub enum Operation {
|
||||
CreateText(TextSpec),
|
||||
CreateMText(MTextSpec),
|
||||
SetTextContent { id: ObjectId, value: String },
|
||||
// hatch
|
||||
CreateHatch(HatchSpec),
|
||||
}
|
||||
@@ -21,4 +21,6 @@ pub enum Query {
|
||||
GetGeometryRevision,
|
||||
/// The text content of a Text/MText annotation.
|
||||
GetTextContent { id: ObjectId },
|
||||
/// The boundary loops of a Hatch (outer + islands) as polylines.
|
||||
GetHatchBoundary { id: ObjectId },
|
||||
}
|
||||
@@ -96,6 +96,16 @@ pub struct MTextSpec {
|
||||
pub height: f64,
|
||||
}
|
||||
|
||||
/// Construction spec for a `HATCH` with a single closed polyline boundary
|
||||
/// (straight segments). `solid` selects solid fill vs a pattern (pattern naming
|
||||
/// is a later refinement).
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct HatchSpec {
|
||||
/// Closed boundary as an ordered polyline (first==last implied; closed).
|
||||
pub boundary: Vec<[f64; 2]>,
|
||||
pub solid: bool,
|
||||
}
|
||||
|
||||
/// 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.
|
||||
@@ -148,6 +158,7 @@ impl crate::gen::Operation {
|
||||
CreateText(_) => "CreateText",
|
||||
CreateMText(_) => "CreateMText",
|
||||
SetTextContent { .. } => "SetTextContent",
|
||||
CreateHatch(_) => "CreateHatch",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,8 @@ pub enum QueryResult {
|
||||
Revision(GeometryRevision),
|
||||
/// The text content of a Text/MText annotation.
|
||||
TextContent(String),
|
||||
/// A hatch's boundary loops (outer + islands), each a closed polyline.
|
||||
HatchBoundary(Vec<Vec<[f64; 2]>>),
|
||||
}
|
||||
|
||||
/// Convenience: the query name for diagnostics.
|
||||
@@ -59,6 +61,7 @@ impl crate::gen::Query {
|
||||
GetIntersects { .. } => "GetIntersects",
|
||||
GetGeometryRevision => "GetGeometryRevision",
|
||||
GetTextContent { .. } => "GetTextContent",
|
||||
GetHatchBoundary { .. } => "GetHatchBoundary",
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user