feat(model): 3D solid modelling tab — primitives + boolean ops

Rename the Home tab to "Draw" and add a Model tab beside it with two
groups:

- Model: BOX / CYLINDER / CONE / SPHERE / WEDGE / TORUS, placed with a
  footprint + height. Each is built as a real ACIS Solid3D (acadrust
  primitive builders) plus a truck B-rep, tessellated into the shaded
  mesh pipeline, with edge wires for picking + wireframe.
- Design: UNION / SUBTRACT / INTERSECT via truck-shapeops.

A session-only Scene.model_solids cache holds each solid's truck B-rep
so the boolean tools can combine and chain them. Supersedes the old
command-line BOX/SPHERE/CYLINDER (insert::solid3d_cmds keeps EXTRUDE/
REVOLVE/SWEEP/LOFT).

Known limitations: booleans need solids created this session; curved
ACIS primitives render in-session but not after reload (the SAT
tessellator handles only planar caps); geometry assumes world_offset 0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-05-31 19:27:06 +03:00
commit 7bf9ce31ae
17 changed files with 1095 additions and 397 deletions

337
Cargo.lock generated
View file

@ -2,6 +2,16 @@
# It is not intended for manual editing.
version = 4
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]]
name = "OpenCADStudio"
version = "0.4.6"
@ -20,6 +30,7 @@ dependencies = [
"truck-meshalgo",
"truck-modeling",
"truck-polymesh",
"truck-shapeops",
"ureq",
"windows-sys 0.61.2",
]
@ -90,6 +101,15 @@ dependencies = [
"zerocopy",
]
[[package]]
name = "aho-corasick"
version = "1.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301"
dependencies = [
"memchr 2.8.0",
]
[[package]]
name = "aliasable"
version = "0.1.3"
@ -533,7 +553,7 @@ dependencies = [
"allsorts",
"azul-core",
"azul-css",
"base64",
"base64 0.22.1",
"hyphenation",
"lru",
"roxmltree 0.21.1",
@ -555,6 +575,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8259ebd5ee48a37fd8931116405456fd67efbb5435b4789e45bdbccf5d7dea7e"
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.22.1"
@ -852,6 +878,19 @@ dependencies = [
"serde",
]
[[package]]
name = "chrono"
version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [
"iana-time-zone",
"js-sys",
"num-traits",
"wasm-bindgen",
"windows-link",
]
[[package]]
name = "cipher"
version = "0.4.4"
@ -925,7 +964,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
dependencies = [
"bytes",
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -1010,7 +1049,7 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -1173,6 +1212,17 @@ dependencies = [
"serde_core",
]
[[package]]
name = "derive-new"
version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3418329ca0ad70234b9735dc4ceed10af4df60eff9c8e7b06cb5e520d92c3535"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "derive_more"
version = "0.99.20"
@ -1662,7 +1712,7 @@ dependencies = [
"futures-macro",
"futures-sink",
"futures-task",
"memchr",
"memchr 2.8.0",
"pin-project-lite",
"slab",
]
@ -2027,6 +2077,30 @@ dependencies = [
"serde",
]
[[package]]
name = "iana-time-zone"
version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"iana-time-zone-haiku",
"js-sys",
"log",
"wasm-bindgen",
"windows-core 0.62.2",
]
[[package]]
name = "iana-time-zone-haiku"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
dependencies = [
"cc",
]
[[package]]
name = "iced"
version = "0.14.0"
@ -2774,6 +2848,23 @@ dependencies = [
"num-traits",
]
[[package]]
name = "lz4_flex"
version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05304f8e67dfc93d1b4b990137fd1a7a4c6ad44b60a9c486c8c4486f9d2027ae"
[[package]]
name = "lzma-sys"
version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fda04ab3764e6cde78b9974eec4f779acaba7c4e84b36eca3cf77c581b85d27"
dependencies = [
"cc",
"libc",
"pkg-config",
]
[[package]]
name = "mac"
version = "0.1.1"
@ -2850,6 +2941,15 @@ dependencies = [
"digest",
]
[[package]]
name = "memchr"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a"
dependencies = [
"libc",
]
[[package]]
name = "memchr"
version = "2.8.0"
@ -3062,13 +3162,22 @@ version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
[[package]]
name = "nom"
version = "3.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b"
dependencies = [
"memchr 1.0.2",
]
[[package]]
name = "nom"
version = "7.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
dependencies = [
"memchr",
"memchr 2.8.0",
"minimal-lexical",
]
@ -3078,7 +3187,7 @@ version = "8.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -3088,7 +3197,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b577e2d69827c4740cba2b52efaad1c4cc7c73042860b199710b3575c68438d"
dependencies = [
"bytecount",
"memchr",
"memchr 2.8.0",
"nom 8.0.0",
]
@ -3123,6 +3232,17 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6673768db2d862beb9b39a78fdcb1a69439615d5794a1be50caa9bc92c81967"
[[package]]
name = "num-derive"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "876a53fff98e03a936a674b29568b0e605f06b29372c2489ff4de23f1949743d"
dependencies = [
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "num-derive"
version = "0.4.2"
@ -3180,7 +3300,7 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
dependencies = [
"proc-macro-crate",
"proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@ -3944,7 +4064,7 @@ dependencies = [
"azul-core",
"azul-css",
"azul-layout",
"base64",
"base64 0.22.1",
"flate2",
"getrandom 0.3.4",
"kuchiki",
@ -3960,13 +4080,23 @@ dependencies = [
"xmlparser",
]
[[package]]
name = "proc-macro-crate"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919"
dependencies = [
"once_cell",
"toml_edit 0.19.15",
]
[[package]]
name = "proc-macro-crate"
version = "3.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
dependencies = [
"toml_edit",
"toml_edit 0.25.10+spec-1.1.0",
]
[[package]]
@ -4048,13 +4178,23 @@ version = "2.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
[[package]]
name = "quick-xml"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8533f14c8382aaad0d592c812ac3b826162128b65662331e1127b45c3d18536b"
dependencies = [
"memchr 2.8.0",
"serde",
]
[[package]]
name = "quick-xml"
version = "0.39.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "958f21e8e7ceb5a1aa7fa87fab28e7c75976e0bfe7e23ff069e0a260f894067d"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -4223,7 +4363,7 @@ dependencies = [
"maybe-rayon",
"new_debug_unreachable",
"noop_proc_macro",
"num-derive",
"num-derive 0.4.2",
"num-traits",
"paste",
"profiling",
@ -4339,6 +4479,35 @@ dependencies = [
"bitflags 2.11.0",
]
[[package]]
name = "regex"
version = "1.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e10754a14b9137dd7b1e3e5b0493cc9171fdd105e0ab477f51b72e7f3ac0e276"
dependencies = [
"aho-corasick",
"memchr 2.8.0",
"regex-automata",
"regex-syntax",
]
[[package]]
name = "regex-automata"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f"
dependencies = [
"aho-corasick",
"memchr 2.8.0",
"regex-syntax",
]
[[package]]
name = "regex-syntax"
version = "0.8.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a"
[[package]]
name = "renderdoc-sys"
version = "1.1.0"
@ -4430,7 +4599,7 @@ version = "0.21.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -4440,7 +4609,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ba4f18e13793c89413ba7e7c991db5f56527803d4706df6a14291d045cd67db2"
dependencies = [
"allsorts",
"base64",
"base64 0.22.1",
"mmapio",
"xmlparser",
]
@ -4527,6 +4696,36 @@ dependencies = [
"untrusted",
]
[[package]]
name = "ruststep"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5df866eb24b48dd4bb8a3cb0dfeb3a25ff2c251ed93aae1cbfc03eb8ee3c7dcc"
dependencies = [
"Inflector",
"derive-new",
"derive_more",
"itertools 0.10.5",
"nom 7.1.3",
"ruststep-derive",
"serde",
"thiserror 1.0.69",
]
[[package]]
name = "ruststep-derive"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81bfdd035ae42e977d18e3197065392784566ef230eda4241d15799ea2154e84"
dependencies = [
"Inflector",
"proc-macro-crate 1.3.1",
"proc-macro-error",
"proc-macro2",
"quote",
"syn 2.0.117",
]
[[package]]
name = "rustversion"
version = "1.0.22"
@ -4673,7 +4872,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86"
dependencies = [
"itoa 1.0.18",
"memchr",
"memchr 2.8.0",
"serde",
"serde_core",
"zmij",
@ -5343,6 +5542,12 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "toml_datetime"
version = "0.6.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
[[package]]
name = "toml_datetime"
version = "1.1.1+spec-1.1.0"
@ -5352,6 +5557,17 @@ dependencies = [
"serde_core",
]
[[package]]
name = "toml_edit"
version = "0.19.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421"
dependencies = [
"indexmap",
"toml_datetime 0.6.11",
"winnow 0.5.40",
]
[[package]]
name = "toml_edit"
version = "0.25.10+spec-1.1.0"
@ -5359,7 +5575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a82418ca169e235e6c399a84e395ab6debeb3bc90edc959bf0f48647c6a32d1b"
dependencies = [
"indexmap",
"toml_datetime",
"toml_datetime 1.1.1+spec-1.1.0",
"toml_parser",
"winnow 1.0.1",
]
@ -5470,6 +5686,7 @@ dependencies = [
"truck-geometry",
"truck-polymesh",
"truck-topology",
"vtkio",
]
[[package]]
@ -5505,6 +5722,41 @@ dependencies = [
"truck-geotrait",
]
[[package]]
name = "truck-shapeops"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fd6e83ea4d36d00229d38ab985a991e32f58c3ed2971083011ac66fb57e26d5c"
dependencies = [
"derive_more",
"itertools 0.13.0",
"rustc-hash 2.1.2",
"truck-base",
"truck-geometry",
"truck-geotrait",
"truck-meshalgo",
"truck-stepio",
"truck-topology",
]
[[package]]
name = "truck-stepio"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d29cf5b0dec4b927e80b5dca26ce3ca69601c77ea5b9c953e30bfc3e123d189"
dependencies = [
"chrono",
"derive_more",
"ruststep",
"serde",
"truck-derivers",
"truck-geometry",
"truck-geotrait",
"truck-modeling",
"truck-polymesh",
"truck-topology",
]
[[package]]
name = "truck-topology"
version = "0.6.0"
@ -5658,7 +5910,7 @@ version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dea7109cdcd5864d4eeb1b58a1648dc9bf520360d7af16ec26d0a9354bafcfc0"
dependencies = [
"base64",
"base64 0.22.1",
"log",
"percent-encoding",
"rustls",
@ -5674,7 +5926,7 @@ version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e994ba84b0bd1b1b0cf92878b7ef898a5c1760108fe7b6010327e274917a808c"
dependencies = [
"base64",
"base64 0.22.1",
"http",
"httparse",
"log",
@ -5686,7 +5938,7 @@ version = "0.45.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80be9b06fbae3b8b303400ab20778c80bbaf338f563afe567cf3c9eea17b47ef"
dependencies = [
"base64",
"base64 0.22.1",
"data-url",
"flate2",
"fontdb",
@ -5747,6 +5999,25 @@ version = "0.9.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
[[package]]
name = "vtkio"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "abbe89e5b97b472d57abeb02755a06d75b28d2df7d1fe3df5baf032281a65c16"
dependencies = [
"base64 0.13.1",
"bytemuck",
"byteorder",
"flate2",
"lz4_flex",
"nom 3.2.1",
"num-derive 0.3.3",
"num-traits",
"quick-xml 0.22.0",
"serde",
"xz2",
]
[[package]]
name = "walkdir"
version = "2.5.0"
@ -6009,7 +6280,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c324a910fd86ebdc364a3e61ec1f11737d3b1d6c273c0239ee8ff4bc0d24b4a"
dependencies = [
"proc-macro2",
"quick-xml",
"quick-xml 0.39.2",
"quote",
]
@ -6649,13 +6920,22 @@ dependencies = [
"xkbcommon-dl",
]
[[package]]
name = "winnow"
version = "0.5.40"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876"
dependencies = [
"memchr 2.8.0",
]
[[package]]
name = "winnow"
version = "0.7.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -6664,7 +6944,7 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09dac053f1cd375980747450bfc7250c264eaae0583872e845c0c7cd578872b5"
dependencies = [
"memchr",
"memchr 2.8.0",
]
[[package]]
@ -6830,6 +7110,15 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec7a2a501ed189703dba8b08142f057e887dfc4b2cc4db2d343ac6376ba3e0b9"
[[package]]
name = "xz2"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "388c44dc09d76f1536602ead6d325eb532f5c122f17782bd57fb47baeeb767e2"
dependencies = [
"lzma-sys",
]
[[package]]
name = "y4m"
version = "0.8.0"
@ -6883,7 +7172,7 @@ version = "5.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897e79616e84aac4b2c46e9132a4f63b93105d54fe8c0e8f6bffc21fa8d49222"
dependencies = [
"proc-macro-crate",
"proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
"syn 2.0.117",
@ -7000,7 +7289,7 @@ version = "5.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b59b012ebe9c46656f9cc08d8da8b4c726510aef12559da3e5f1bf72780752c"
dependencies = [
"proc-macro-crate",
"proc-macro-crate 3.5.0",
"proc-macro2",
"quote",
"syn 2.0.117",