Files
OneCAD-Draft/crates/ocs_doc_api/examples/e2_intersect_two_solids.rs
T
Sebastian e41086b058 Add ocs_doc_api: object-oriented CAD entity API (v2)
New crate crates/ocs_doc_api: object-centric facade (DocApi -> Document ->
collections -> typed handles), transport-agnostic wire layer (DocApiEnvelope =
single op | read-only query batch), per-op autocommit (no write transactions),
bulk ops with upfront-validation all-or-nothing, structured ApiError, and
build-time codegen (spec/entities.toml -> ops/query enums, api_reference.md,
binding_schema.json).

ocs_plugin_api: append-only PluginRequest::DocApiRequest / PluginResponse::
DocApiResponse (serde_bytes payload) + defaulted HostApi::doc_api_dispatch.

Host: DocApiBackend impl for HostSession (src/app/doc_api.rs) mapping to scene
primitives (solid_models lift-on-miss, register_prepared_solid_model, meshes
metrics), entity conversions (doc_api_convert.rs), HostSession accessors +
doc_api_dispatch override.

Tests: 592 host lib (incl. 7 DocApi integration tests: create/boolean/query,
unknown-id, transform-many all-or-nothing, query-batch cap, 2D/geometric/DWG
roundtrips), 8 crate unit tests. Examples + README/ARCHITECTURE/IMPLEMENTATION docs.
2026-09-06 00:15:27 +02:00

54 lines
2.1 KiB
Rust

//! Example 2 — Construct two solids and intersect them (the canonical boolean).
//!
//! Run: `cargo run --example e2_intersect_two_solids --features host`
//!
//! Shows: `intersect` / `union` / `subtract` on `Solid`, `erase_sources`
//! semantics (the result lives at the first input's id, the second is erased),
//! and `OpGroup` cleanup on failure.
mod common;
use ocs_doc_api::{DocApi, HasId, OpGroup};
fn main() -> ocs_doc_api::ApiResult<()> {
let api = DocApi::in_process(common::MockBackend::default(), 0);
let doc = api.document(api.active_tab());
let mut grp = OpGroup::new();
// Two overlapping boxes: [0,10]^3 and [5,15]^3.
let a = grp.track(doc.solids().create_cuboid([0.0, 0.0, 0.0], [10.0; 3]))?;
let b = grp.track(doc.solids().create_cuboid([5.0, 5.0, 5.0], [10.0; 3]))?;
// intersect -> SolidBoolean{Intersection, erase_sources:true}. The result is
// returned AT `a`'s id; `b` is erased. [5,10]^3 = volume 125.
let lens = match a.intersect(&b) {
Ok(l) => {
grp.commit(); // keep everything
l
}
Err(e) => {
grp.compensate(&doc)?; // best-effort: delete the two boxes
return Err(e);
}
};
assert_eq!(lens.id(), a.id(), "result lives at the first input's id");
let vol = lens.volume()?;
let bb = lens.bounds()?;
println!("intersection volume = {vol:.2} (expected 125)");
println!("intersection bounds = {bb:?}");
// union / subtract follow the same shape. Fresh inputs (b was erased above).
let c = doc.solids().create_cuboid([0.0, 0.0, 0.0], [10.0; 3])?;
let d = doc.solids().create_cuboid([5.0, 5.0, 5.0], [10.0; 3])?;
let uni = c.union(&d)?;
// union volume = 1000 + 1000 - 125 (overlap) = 1875.
println!("union volume = {:.2} (expected 1875)", uni.volume()?);
let e = doc.solids().create_cuboid([0.0, 0.0, 0.0], [10.0; 3])?;
let f = doc.solids().create_cuboid([5.0, 5.0, 5.0], [10.0; 3])?;
let diff = e.subtract(&f)?;
println!("difference volume = {:.2} (expected 875)", diff.volume()?);
Ok(())
}