# ocs_doc_api — API reference (auto-generated) Envelope version: `1` Do NOT edit: regenerated by `build.rs` from `spec/entities.toml`. ## `Solid` (acadrust `Solid3D`, collection `solids`) B-rep solid. Host resolves bodies via the solid_models cache (lift-on-miss from ACIS SAT). ### Constructors (`doc.solids()`) - **create_cuboid**(origin: [f64; 3], size: [f64; 3]) -> `Solid` — `CreateSolid`; fixed primitive="Cuboid" - **create_sphere**(centre: [f64; 3], radius: f64) -> `Solid` — `CreateSolid`; fixed primitive="Sphere" - **create_cylinder**(base: [f64; 3], radius: f64, height: f64) -> `Solid` — `CreateSolid`; fixed primitive="Cylinder" - **create_cone**(base: [f64; 3], radius: f64, height: f64) -> `Solid` — `CreateSolid`; fixed primitive="Cone" - **create_torus**(centre: [f64; 3], major_radius: f64, minor_radius: f64) -> `Solid` — `CreateSolid`; fixed primitive="Torus" - **create_wedge**(origin: [f64; 3], size: [f64; 3]) -> `Solid` — `CreateSolid`; fixed primitive="Wedge" - **extrude**(profile: EntityRef, direction: [f64; 3]) -> `Solid` — `Extrude` - **revolve**(profile: EntityRef, pivot: [f64; 3], axis: [f64; 3], angle: f64) -> `Solid` — `Revolve` - **loft**(profiles: &[EntityRef]) -> `Solid` — `Loft` ### Methods - **intersect**(other: Solid) -> `Solid` — op `SolidBoolean`; fixed erase_sources=true, op="Intersection" - **union**(other: Solid) -> `Solid` — op `SolidBoolean`; fixed erase_sources=true, op="Union" - **subtract**(other: Solid) -> `Solid` — op `SolidBoolean`; fixed erase_sources=true, op="Difference" - **volume**() -> `f64` — query `GetVolume` - **centroid**() -> `[f64; 3]` — query `GetCentroid` - **intersects**(other: Solid) -> `bool` — query `GetIntersects` ## `Line` (acadrust `Line`, collection `curves`) ### Constructors (`doc.curves()`) - **create_line**(start: [f64; 3], end: [f64; 3]) -> `Line` — `CreateCurve`; fixed curve="Line" ## `Circle` (acadrust `Circle`, collection `curves`) ### Constructors (`doc.curves()`) - **create_circle**(centre: [f64; 3], radius: f64) -> `Circle` — `CreateCurve`; fixed curve="Circle" ## `Polyline` (acadrust `LwPolyline`, collection `curves`) ### Constructors (`doc.curves()`) - **create_polyline**(points: &[[f64; 3]], closed: bool) -> `Polyline` — `CreateCurve`; fixed curve="Polyline" ### Methods - **add_vertex**(at: usize, point: [f64; 3]) -> `()` — op `AddVertex` ## `Point` (acadrust `Point`, collection `curves`) ### Constructors (`doc.curves()`) - **create_point**(position: [f64; 3]) -> `Point` — `CreateCurve`; fixed curve="Point" - **create_points**(positions: &[[f64; 3]]) -> `Vec` *(bulk op)* — `CreateMany`; fixed curve="Point" ## `ArcCurve` (acadrust `Arc`, collection `curves`) ### Constructors (`doc.curves()`) - **create_arc**(centre: [f64; 3], radius: f64, start_angle: f64, end_angle: f64) -> `ArcCurve` — `CreateCurve`; fixed curve="Arc" ## `Ellipse` (acadrust `Ellipse`, collection `curves`) ### Constructors (`doc.curves()`) - **create_ellipse**(centre: [f64; 3], major_axis: [f64; 3], ratio: f64, start: f64, end: f64) -> `Ellipse` — `CreateCurve`; fixed curve="Ellipse" ## `Spline` (acadrust `Spline`, collection `curves`) ### Constructors (`doc.curves()`) - **create_spline**(degree: i32, control_points: &[[f64; 3]], knots: &[f64], weights: &[f64]) -> `Spline` — `CreateCurve`; fixed curve="Spline" ## `Ray` (acadrust `Ray`, collection `curves`) ### Constructors (`doc.curves()`) - **create_ray**(origin: [f64; 3], direction: [f64; 3]) -> `Ray` — `CreateCurve`; fixed curve="Ray" ## `XLine` (acadrust `XLine`, collection `curves`) ### Constructors (`doc.curves()`) - **create_xline**(origin: [f64; 3], direction: [f64; 3]) -> `XLine` — `CreateCurve`; fixed curve="XLine" ## `Text` (acadrust `Text`, collection `curves`) Single-line text annotation. content()/set_content() read+replace the value; transform moves insertion point. ### Constructors (`doc.curves()`) - **create_text**(value: &str, insertion_point: [f64; 3], height: f64, rotation: f64) -> `Text` — `CreateText` ### Methods - **content**() -> `String` — query `GetTextContent` - **set_content**(value: &str) -> `()` — op `SetTextContent` ## `MText` (acadrust `MText`, collection `curves`) Multi-line text annotation. content()/set_content() read+replace the value; transform moves insertion point. ### Constructors (`doc.curves()`) - **create_mtext**(value: &str, insertion_point: [f64; 3], height: f64) -> `MText` — `CreateMText` ### Methods - **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` — `CreateHatch` ### Methods - **boundary**() -> `Vec>` — query `GetHatchBoundary` ## `Dimension` (acadrust `Dimension`, collection `curves`) Linear dimension between two measured points. measurement() reads the distance; bounds from the measured + definition points. ### Constructors (`doc.curves()`) - **create_dimension_linear**(first_point: [f64; 3], second_point: [f64; 3], definition_point: [f64; 3]) -> `Dimension` — `CreateDimensionLinear` - **create_dimension_radius**(center: [f64; 3], point: [f64; 3]) -> `Dimension` — `CreateDimensionRadius` - **create_dimension_diameter**(center: [f64; 3], point: [f64; 3]) -> `Dimension` — `CreateDimensionDiameter` - **create_dimension_angular**(vertex: [f64; 3], first_point: [f64; 3], second_point: [f64; 3], arc_location: [f64; 3]) -> `Dimension` — `CreateDimensionAngular` - **create_dimension_angular2ln**(vertex: [f64; 3], first_point: [f64; 3], second_point: [f64; 3], arc_location: [f64; 3]) -> `Dimension` — `CreateDimensionAngular2Ln` ### Methods - **measurement**() -> `f64` — query `GetDimensionMeasurement` ## `Entity` (acadrust `Insert`, collection `entities`) Block reference. Place an existing BlockRecord by name; transform moves its insert point. ### Constructors (`doc.entities()`) - **create_insert**(block_name: &str, insert_point: [f64; 3], scale: f64, rotation: f64) -> `Entity` — `CreateInsert` ### Methods - **attributes**() -> `Vec<(String, String)>` — query `GetAttributes` - **set_attribute**(tag: &str, value: &str) -> `()` — op `SetAttribute` ## `Entity` (acadrust `AttributeDefinition`, collection `entities`) In-block attribute definition (ATTDEF): tag/prompt/default at an insertion point. ### Constructors (`doc.entities()`) - **create_attribute_definition**(tag: &str, prompt: &str, default_value: &str, insertion_point: [f64; 3], height: f64, rotation: f64) -> `Entity` — `CreateAttributeDefinition` ## `Entity` (acadrust `Viewport`, collection `entities`) Paper-space viewport: a width×height window at center looking at view_target with view_height zoom. bounds = center ± w/2,h/2; transform moves center. ### Constructors (`doc.entities()`) - **create_viewport**(center: [f64; 3], width: f64, height: f64, view_target: [f64; 3], view_height: f64) -> `Entity` — `CreateViewport` ### Methods - **viewport_view**() -> `([f64; 3], f64)` — query `GetViewportView` - **set_view**(view_target: [f64; 3], view_height: f64) -> `()` — op `SetViewportView` ## `Entity` (acadrust `RasterImage`, collection `entities`) 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` — `CreateRasterImage` ## `Entity` (acadrust `Table`, collection `entities`) Table: create_table(insertion_point, data[row][col]) builds rows x columns of text cells; non-rectangular grid -> Validation; delete. ### Constructors (`doc.entities()`) - **create_table**(insertion_point: [f64; 3], data: &[Vec]) -> `Entity` — `CreateTable` ## `XRecord` (acadrust `XRecord`, collection `entities`) Extended record (XRecord): arbitrary DXF group-code/value pairs. Roundtripped verbatim as an XRecordSpec payload. ### Constructors (`doc.entities()`) - **create_xrecord**(spec: XRecordSpec) -> `XRecord` — `CreateXRecord` ### Methods - **payload**() -> `XRecordSpec` — query `GetXRecord` - **set_payload**(spec: XRecordSpec) -> `()` — op `SetXRecord` ## `Layer` (acadrust `-`, collection `layers`) Named drawing layer (color, linetype, lineweight, visibility). Not an entity handle; accessed through Document::layers(). ### Methods - **list**() -> `Vec` — query `ListLayers` - **create**(info: LayerInfo) -> `()` — op `CreateLayer` - **update**(name: String, info: LayerInfo) -> `()` — op `UpdateLayer` - **delete**(name: String) -> `()` — op `DeleteLayer` ## Generic methods (every handle) Every typed handle (`Solid`, `Line`, `Circle`, `Polyline`, `Point`, `ArcCurve`, `Ellipse`, `Spline`, `Ray`, `XLine`, `Text`, `MText`, `Dimension`, `Entity`) is a `Clone`, `Send`, `Sync` token `{ ObjectId, session }` and supports: - **`id()` -> `ObjectId`** — the stable entity identity. - **`bounds()` -> `Aabb`** — coarse bounding box (solids lift-on-miss; 2D entities computed; later families may be `Unsupported`). - **`transform(placement)`** — in-place rigid similarity (same `ObjectId`). **v1: solids only.** - **`delete()`** — remove the entity (one undo step). - **`layer()` -> `String`** — the name of the layer the entity is on. - **`set_layer(layer)`** — move the entity to an existing layer (one undo step; blocked if the entity or target layer is locked). `Entity` additionally has `view()` (id + kind + bounds), `as_solid()` (typed downcast when `kind == "Solid3D"`), and XDATA access through `xdata(application_name)` / `set_xdata(application_name, record)`. ## Layer table Layers are a named document table, not an entity family. `Document::layers()` lists all layers as `Vec`. Table-level ops are `CreateLayer(info)`, `UpdateLayer { name, info }` and `DeleteLayer { name }`. `Entity::layer()` returns the layer name and `Entity::set_layer(layer)` moves the entity to an existing layer. The host rejects duplicate names, deletion of layer "0" or the current layer, and removing a layer that still has entities assigned. ## Transports - **`InProcess`** (feature `host`) — drives a `DocApiBackend` directly in the host. - **`OcsPluginApiIpc`** (feature `ipc`) — serializes envelopes over the `ocs_plugin_api` `PluginRequestSender`/`PluginRequest` channel. The host routes `DocApiRequest { tab_id, bytes }` to the same executor. - **`doc_api_for_host(host)`** (feature `doc_api_host`) — convenience helper that builds a `DocApi` from any `ocs_plugin_api::host::HostApi` exposing a `PluginRequestSender` (out-of-process / worker-thread plugins). ## Collections & cross-cutting - **`DocApi`** — root: `document(tab)`, `active_tab()`, `alive()`. - **`Document`** — `solids()` / `curves()` / `entities()` factories + lookup, `revision()`, `assert_revision(rev)` (read-guard), `query_batch(|q| …)` (read-only batch, one round-trip, **no revision bump**). - **`EntityCollection`** — `get(id) -> Entity`, `delete(id)`, `transform_many(&ids, placement)`, `delete_many(&ids)`. - **`OpGroup`** — best-effort client-side failure cleanup (`track` / `commit` / `compensate`). **Not** a transaction: no atomicity, no rollback. ## Bulk ops — single op, all-or-nothing, item-capped `CreateMany` / `TransformMany` / `DeleteMany` are **single** write ops: one undo step, one publish, and **all-or-nothing via upfront validation** (no rollback). Item-capped at `BULK_ITEM_CAP = 100_000` to bound host execution. Use them for bulk data (N ≳ a few hundred); per-op autocommit is the right tool for modeling-scale work. ## Semantics - **Per-op autocommit, no write transactions.** Every write op is ONE atomic host call = one undo step. Multi-op write transactions were removed (security/ integrity review). - **Per-op atomicity.** Validate + compute geometry **before** any mutation; a failed op applies nothing and records no undo step. `erase_sources` booleans run only on success. - **Structured errors.** `ApiError::{Validation, Geometry, UnknownId, Unsupported, Transport}`; bulk validation names the failing index; a stale handle returns `UnknownId` (never a panic). ## Kernel mapping | op | kernel call | returns | |---|---|---| | CreateSolid.Cuboid | `cadkernel::brep::make::cuboid` | Option | | CreateSolid.Sphere | `cadkernel::brep::make::sphere` | Option | | SolidBoolean | `cadkernel::brep::combine` | Result | | Transform | `cadkernel::brep::transform` | Option | | GetBounds | `cadkernel::brep::body_bounds` | Option | | GetVolume | `cadkernel::brep::mesh_body + divergence` | computed | ## Wire vocabulary Every `Operation` is ONE atomic write op (one undo step); every `Query` is read-only (safe to batch). Variants are append-only (bincode discriminant stability). Requests ride `DocApiEnvelope`: `Op(Operation)` for a write, `Queries(Vec)` for a read batch. ### `Operation` - `CreateSolid(SolidPrimitive)` - `CreateCurve(Curve2Spec)` - `Extrude { profile: ObjectId, direction: [f64; 3] }` - `Revolve { profile: ObjectId, axis: ([f64; 3], [f64; 3]), angle: f64 }` - `Transform { id: ObjectId, placement: PlacementSpec }` - `SolidBoolean { op: BoolOp, a: ObjectId, b: ObjectId, erase_sources: bool }` - `AddVertex { id: ObjectId, at: usize, point: [f64; 3] }` - `Delete { id: ObjectId }` - `CreateMany(Vec)` - `TransformMany { ids: Vec, placement: PlacementSpec }` - `DeleteMany(Vec)` - `CreateInsert(InsertSpec)` - `CreateViewport(ViewportSpec)` - `CreateText(TextSpec)` - `CreateMText(MTextSpec)` - `SetTextContent { id: ObjectId, value: String }` - `CreateHatch(HatchSpec)` - `CreateDimensionLinear(DimensionSpec)` - `SetAttribute { id: ObjectId, tag: String, value: String }` - `SetViewportView { id: ObjectId, view_target: [f64; 3], view_height: f64 }` - `CreateRasterImage(RasterImageSpec)` - `Loft { profiles: Vec }` - `CreateDimensionRadius(DimensionRadialSpec)` - `CreateDimensionDiameter(DimensionRadialSpec)` - `CreateDimensionAngular(DimensionAngularSpec)` - `CreateAttributeDefinition(AttributeDefinitionSpec)` - `CreateTable(TableSpec)` - `CreateDimensionAngular2Ln(DimensionAngularSpec)` - `SetXData { id: ObjectId, application_name: String, record: Option }` - `CreateXRecord(XRecordSpec)` - `SetXRecord { id: ObjectId, spec: XRecordSpec }` - `CreateLayer(LayerInfo)` - `UpdateLayer { name: String, info: LayerInfo }` - `DeleteLayer { name: String }` - `SetEntityLayer { id: ObjectId, layer: String }` - `SetXDataMany(Vec<(ObjectId, String, Option)` ### `Query` - `GetEntity { id: ObjectId }` - `GetBounds { id: ObjectId }` - `GetCentroid { id: ObjectId }` - `GetVolume { id: ObjectId }` - `GetIntersects { a: ObjectId, b: ObjectId }` - `GetGeometryRevision` - `GetTextContent { id: ObjectId }` - `GetHatchBoundary { id: ObjectId }` - `GetDimensionMeasurement { id: ObjectId }` - `GetAttributes { id: ObjectId }` - `GetBlockEntities { block_name: String }` - `GetViewportView { id: ObjectId }` - `GetXData { id: ObjectId, application_name: String }` - `GetXRecord { id: ObjectId }` - `ListLayers` - `GetEntityLayer { id: ObjectId }` ## Errors (`ApiError`) | Variant | Meaning | |---|---| | `Validation { op, reason }` | Input rejected before any document mutation. | | `Geometry { kind, msg }` | The kernel failed (boolean refused, invalid input, ACIS lift/lower). | | `UnknownId(ObjectId)` | The handle is stale / deleted / never existed (never a panic). | | `Unsupported(String)` | Capability not supported for this entity or backend. | | `Transport(String)` | The channel failed (disconnected / oversized / timeout). | `ApiError` is serializable, so IPC returns the same structured error the in-process executor produced. ## Envelope & transport `DocApiEnvelope { version, body }` — `body` is `Op(Operation)` (a single write) or `Queries(Vec)` (a read batch). bincode-serialized; `version` is the crate's envelope version (bridges must check it). Transports: `InProcess` (host) and `OcsPluginApiIpc` (plugin over `ocs_plugin_api`), both behind the `Transport: Send + Sync` trait (`apply(envelope) -> Receipt`, `alive()`). `Receipt` carries `outcome` (per-op result), `query_results`, and `new_revision`.