chore: take the stack with its solid layer and ACIS bridge

The kernel gained a B-rep layer — topology, analytic surfaces, surface
intersection, face splitting, point classification, booleans — and
acadifc gained the bridge that lifts an ACIS document into it and lowers
it back, provenance-driven so an untouched body saves byte for byte.

The reachability test is a compile-time one on purpose. A dependency
chain that stops resolving is caught where it breaks rather than the
next time somebody reaches for the far end of it.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-08-09 11:26:57 +03:00
commit 1a37562a28
3 changed files with 35 additions and 6 deletions

24
Cargo.lock generated
View file

@ -16,7 +16,7 @@ dependencies = [
name = "OpenCADStudio"
version = "0.9.4"
dependencies = [
"acadifc",
"acadifc 0.5.0 (git+https://github.com/OpenAEC-Foundation/acadifc.git?rev=fe98e42)",
"ashpd",
"bincode",
"bytemuck",
@ -96,6 +96,20 @@ dependencies = [
"thiserror 1.0.69",
]
[[package]]
name = "acadifc"
version = "0.5.0"
source = "git+https://github.com/OpenAEC-Foundation/acadifc.git?rev=fe98e42#fe98e425578c54facd021d8df74d86052b2f848b"
dependencies = [
"acadrust",
"base64 0.22.1",
"cadkernel",
"serde",
"serde_json",
"sha2 0.10.9",
"thiserror 1.0.69",
]
[[package]]
name = "acadrust"
version = "0.4.1"
@ -935,7 +949,7 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04"
[[package]]
name = "cadkernel"
version = "0.1.0"
source = "git+https://github.com/HakanSeven12/cadkernel.git#47655b21de5e2678fb12ec5f093d7e338d68409d"
source = "git+https://github.com/HakanSeven12/cadkernel.git#c9e104b99e8901c4804e7cece67f038f249a33f5"
dependencies = [
"cavalier_contours",
]
@ -3462,7 +3476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d"
dependencies = [
"bytecount",
"memchr 2.8.3",
"memchr 1.0.2",
"nom 8.0.0",
]
@ -3939,7 +3953,7 @@ dependencies = [
name = "ocs_plugin_api"
version = "0.1.0"
dependencies = [
"acadifc",
"acadifc 0.5.0 (git+https://github.com/OpenAEC-Foundation/acadifc.git?rev=c65d396)",
"bincode",
"getrandom 0.2.17",
"interprocess",
@ -3954,7 +3968,7 @@ dependencies = [
name = "ocs_web_worker"
version = "0.1.0"
dependencies = [
"acadifc",
"acadifc 0.5.0 (git+https://github.com/OpenAEC-Foundation/acadifc.git?rev=c65d396)",
"bincode",
"console_error_panic_hook",
"getrandom 0.3.4",

View file

@ -38,7 +38,7 @@ env_logger = "0.11"
# The CAD stack is reached through acadifc, which re-exports the codec and
# the geometry kernel. Aliased to `acadrust` so existing `use acadrust::…`
# paths keep resolving.
acadrust = { package = "acadifc", git = "https://github.com/OpenAEC-Foundation/acadifc.git", rev = "c65d396", features = ["serde", "offset"] }
acadrust = { package = "acadifc", git = "https://github.com/OpenAEC-Foundation/acadifc.git", rev = "fe98e42", features = ["serde", "offset"] }
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
flate2 = "1"
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }

View file

@ -710,6 +710,21 @@ mod tests {
assert!(curve.is_closed());
}
/// The whole stack resolves from here: OCS reaches the B-rep layer and
/// the ACIS bridge through the same alias every other CAD type comes in
/// by. A compile-time check, so a chain that stops resolving is caught
/// where it happens rather than the next time somebody reaches for it.
#[test]
fn the_solid_layer_and_the_acis_bridge_are_reachable() {
let solid = acadrust::kernel::brep::make::cuboid([0.0; 3], [1.0; 3])
.expect("the kernel builds its own primitives");
assert!(solid.validate().is_empty());
assert_eq!(solid.euler_characteristic(), 2);
let document = acadrust::entities::acis::types::SatDocument::new();
let (bodies, loss) = acadrust::acis::lift(&document);
assert!(bodies.is_empty() && loss.is_empty(), "an empty document lifts to nothing");
}
#[test]
fn entities_that_are_not_curves_say_so() {
assert!(entity_curve(&EntityType::Point(Default::default())).is_none());