icadkit 0.2.0__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (146) hide show
  1. {icadkit-0.2.0 → icadkit-0.3.5}/Cargo.lock +4 -4
  2. {icadkit-0.2.0 → icadkit-0.3.5}/Cargo.toml +2 -2
  3. {icadkit-0.2.0 → icadkit-0.3.5}/LICENSES/rust-dependencies.txt +1 -1
  4. {icadkit-0.2.0 → icadkit-0.3.5}/PKG-INFO +62 -20
  5. {icadkit-0.2.0 → icadkit-0.3.5}/README.md +61 -19
  6. {icadkit-0.2.0 → icadkit-0.3.5}/THIRD_PARTY_NOTICES.md +1 -1
  7. icadkit-0.3.5/corpus/README.md +57 -0
  8. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/LICENSE +2 -2
  9. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/document.rs +32 -1
  10. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/lib.rs +15 -4
  11. icadkit-0.3.5/crates/icad-core/src/native.rs +625 -0
  12. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/parasolid.rs +2 -3
  13. icadkit-0.3.5/crates/icad-core/src/parts.rs +1290 -0
  14. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/reader.rs +14 -0
  15. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/resource.rs +10 -0
  16. icadkit-0.3.5/crates/icad-core/src/trailer.rs +703 -0
  17. icadkit-0.3.5/crates/icad-core/src/views.rs +410 -0
  18. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/tests/resources.rs +90 -1
  19. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/LICENSE +2 -2
  20. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/src/document.rs +241 -0
  21. {icadkit-0.2.0 → icadkit-0.3.5}/docs/api.md +41 -2
  22. icadkit-0.3.5/docs/changelog.md +233 -0
  23. icadkit-0.3.5/docs/csg.md +106 -0
  24. icadkit-0.3.5/docs/drawing.md +131 -0
  25. icadkit-0.3.5/docs/native.md +248 -0
  26. icadkit-0.3.5/docs/parameters.md +74 -0
  27. icadkit-0.3.5/docs/parts.md +312 -0
  28. {icadkit-0.2.0 → icadkit-0.3.5}/docs/preview.md +8 -4
  29. icadkit-0.3.5/docs/references.md +173 -0
  30. icadkit-0.3.5/docs/roadmap.md +325 -0
  31. icadkit-0.3.5/docs/saved-bodies.md +213 -0
  32. icadkit-0.3.5/docs/support.md +208 -0
  33. icadkit-0.3.5/docs/trailer.md +155 -0
  34. icadkit-0.3.5/docs/viewer.md +153 -0
  35. {icadkit-0.2.0 → icadkit-0.3.5}/pyproject.toml +2 -0
  36. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/check_license.py +1 -2
  37. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/verify_artifacts.py +41 -4
  38. icadkit-0.3.5/scripts/verify_native_corpus.py +424 -0
  39. icadkit-0.3.5/src/icadkit/__init__.py +227 -0
  40. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/_core.pyi +105 -1
  41. icadkit-0.3.5/src/icadkit/_csg_occt.py +288 -0
  42. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/_preview_bridge.py +27 -4
  43. icadkit-0.3.5/src/icadkit/_saved_occt.py +265 -0
  44. icadkit-0.3.5/src/icadkit/_viewer/index.html +34 -0
  45. icadkit-0.3.5/src/icadkit/_viewer/viewer.css +51 -0
  46. icadkit-0.3.5/src/icadkit/_viewer/viewer.js +363 -0
  47. icadkit-0.3.5/src/icadkit/_viewer_io.py +121 -0
  48. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/cli.py +490 -6
  49. icadkit-0.3.5/src/icadkit/csg.py +632 -0
  50. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/document.py +82 -1
  51. icadkit-0.3.5/src/icadkit/drawing.py +304 -0
  52. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/models.py +15 -0
  53. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/native.py +97 -10
  54. icadkit-0.3.5/src/icadkit/parameters.py +446 -0
  55. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/parts.py +301 -11
  56. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/preview.py +1 -22
  57. icadkit-0.3.5/src/icadkit/references.py +713 -0
  58. icadkit-0.3.5/src/icadkit/saved.py +492 -0
  59. icadkit-0.3.5/src/icadkit/trailer.py +253 -0
  60. icadkit-0.3.5/src/icadkit/viewer.py +1129 -0
  61. icadkit-0.3.5/src/icadkit/views.py +114 -0
  62. icadkit-0.3.5/tests/drawing_fixtures.py +94 -0
  63. {icadkit-0.2.0 → icadkit-0.3.5}/tests/fixture_builders.py +13 -0
  64. {icadkit-0.2.0 → icadkit-0.3.5}/tests/geometry_fixtures.py +47 -5
  65. icadkit-0.3.5/tests/parameter_fixtures.py +82 -0
  66. {icadkit-0.2.0 → icadkit-0.3.5}/tests/part_fixtures.py +25 -3
  67. icadkit-0.3.5/tests/saved_fixtures.py +356 -0
  68. icadkit-0.3.5/tests/test_api.py +49 -0
  69. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_cli.py +1 -1
  70. icadkit-0.3.5/tests/test_csg.py +548 -0
  71. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_distribution.py +2 -0
  72. icadkit-0.3.5/tests/test_drawing.py +391 -0
  73. icadkit-0.3.5/tests/test_extrusion.py +162 -0
  74. icadkit-0.3.5/tests/test_followup_parts.py +260 -0
  75. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_geometry.py +158 -7
  76. icadkit-0.3.5/tests/test_legacy_parts.py +139 -0
  77. icadkit-0.3.5/tests/test_mirrors.py +192 -0
  78. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_native.py +61 -14
  79. icadkit-0.3.5/tests/test_native_corpus.py +257 -0
  80. icadkit-0.3.5/tests/test_native_round.py +95 -0
  81. icadkit-0.3.5/tests/test_parameters.py +222 -0
  82. icadkit-0.3.5/tests/test_part_profiles.py +131 -0
  83. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_part_semantics.py +16 -11
  84. icadkit-0.3.5/tests/test_profile_shapes.py +296 -0
  85. icadkit-0.3.5/tests/test_references.py +407 -0
  86. icadkit-0.3.5/tests/test_saved.py +709 -0
  87. icadkit-0.3.5/tests/test_trailer.py +342 -0
  88. icadkit-0.3.5/tests/test_v7_parts.py +366 -0
  89. icadkit-0.3.5/tests/test_v8l4_boundary.py +139 -0
  90. icadkit-0.3.5/tests/test_version_geometry.py +180 -0
  91. icadkit-0.3.5/tests/test_viewer.py +347 -0
  92. icadkit-0.3.5/tests/trailer_fixtures.py +90 -0
  93. icadkit-0.3.5/tests/viewer_assembly_browser.mjs +102 -0
  94. icadkit-0.3.5/tests/viewer_browser.mjs +167 -0
  95. icadkit-0.3.5/tests/viewer_mirror_browser.mjs +83 -0
  96. icadkit-0.2.0/corpus/README.md +0 -26
  97. icadkit-0.2.0/crates/icad-core/src/native.rs +0 -159
  98. icadkit-0.2.0/crates/icad-core/src/parts.rs +0 -594
  99. icadkit-0.2.0/docs/changelog.md +0 -54
  100. icadkit-0.2.0/docs/native.md +0 -126
  101. icadkit-0.2.0/docs/parts.md +0 -181
  102. icadkit-0.2.0/docs/roadmap.md +0 -132
  103. icadkit-0.2.0/docs/support.md +0 -87
  104. icadkit-0.2.0/src/icadkit/__init__.py +0 -110
  105. icadkit-0.2.0/tests/test_api.py +0 -20
  106. {icadkit-0.2.0 → icadkit-0.3.5}/COMMERCIAL-LICENSE.md +0 -0
  107. {icadkit-0.2.0 → icadkit-0.3.5}/LICENSE +0 -0
  108. {icadkit-0.2.0 → icadkit-0.3.5}/LICENSES/Apache-2.0.txt +0 -0
  109. {icadkit-0.2.0 → icadkit-0.3.5}/LICENSES/PolyForm-Noncommercial-1.0.0.md +0 -0
  110. {icadkit-0.2.0 → icadkit-0.3.5}/LICENSES/parasolid-core-MIT.txt +0 -0
  111. {icadkit-0.2.0 → icadkit-0.3.5}/corpus/generate.py +0 -0
  112. {icadkit-0.2.0 → icadkit-0.3.5}/corpus/public.jsonl +0 -0
  113. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/Cargo.toml +0 -0
  114. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/compression.rs +0 -0
  115. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/error.rs +0 -0
  116. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/header.rs +0 -0
  117. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/limits.rs +0 -0
  118. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/provenance.rs +0 -0
  119. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/record.rs +0 -0
  120. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/src/schema.rs +0 -0
  121. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-core/tests/header.rs +0 -0
  122. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/Cargo.toml +0 -0
  123. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/src/brep.rs +0 -0
  124. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/src/geometry.rs +0 -0
  125. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/src/lib.rs +0 -0
  126. {icadkit-0.2.0 → icadkit-0.3.5}/crates/icad-python/src/schema.rs +0 -0
  127. {icadkit-0.2.0 → icadkit-0.3.5}/docs/license.md +0 -0
  128. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/check_public_tree.py +0 -0
  129. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/test_publication.py +0 -0
  130. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/verify_corpus.py +0 -0
  131. {icadkit-0.2.0 → icadkit-0.3.5}/scripts/verify_install.py +0 -0
  132. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/__main__.py +0 -0
  133. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/api.py +0 -0
  134. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/errors.py +0 -0
  135. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/geometry.py +0 -0
  136. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/py.typed +0 -0
  137. {icadkit-0.2.0 → icadkit-0.3.5}/src/icadkit/schema.py +0 -0
  138. {icadkit-0.2.0 → icadkit-0.3.5}/tests/conftest.py +0 -0
  139. {icadkit-0.2.0 → icadkit-0.3.5}/tests/preview_fixtures.py +0 -0
  140. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_corpus.py +0 -0
  141. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_inspect.py +0 -0
  142. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_parts.py +0 -0
  143. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_preview.py +0 -0
  144. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_resource_cli.py +0 -0
  145. {icadkit-0.2.0 → icadkit-0.3.5}/tests/test_resources.py +0 -0
  146. {icadkit-0.2.0 → icadkit-0.3.5}/uv.lock +0 -0
@@ -89,7 +89,7 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
89
89
 
90
90
  [[package]]
91
91
  name = "icad-core"
92
- version = "0.2.0"
92
+ version = "0.3.5"
93
93
  dependencies = [
94
94
  "flate2",
95
95
  "parasolid-core",
@@ -99,7 +99,7 @@ dependencies = [
99
99
 
100
100
  [[package]]
101
101
  name = "icad-python"
102
- version = "0.2.0"
102
+ version = "0.3.5"
103
103
  dependencies = [
104
104
  "icad-core",
105
105
  "parasolid-core",
@@ -142,9 +142,9 @@ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
142
142
 
143
143
  [[package]]
144
144
  name = "parasolid-core"
145
- version = "0.3.0"
145
+ version = "0.3.5"
146
146
  source = "registry+https://github.com/rust-lang/crates.io-index"
147
- checksum = "5de85a20a5b7dc7afb453f1114c1c44f27236c6447e1bd26e12227d87333adef"
147
+ checksum = "ea19ba26c4ea0217f3f81dc5a5479239f92d43fc08bd6754d9f9f5ad74cf2c0a"
148
148
 
149
149
  [[package]]
150
150
  name = "portable-atomic"
@@ -3,13 +3,13 @@ members = ["crates/icad-core", "crates/icad-python"]
3
3
  resolver = "3"
4
4
 
5
5
  [workspace.package]
6
- version = "0.2.0"
6
+ version = "0.3.5"
7
7
  edition = "2024"
8
8
  rust-version = "1.88"
9
9
  license = "PolyForm-Noncommercial-1.0.0"
10
10
 
11
11
  [workspace.dependencies]
12
- parasolid-core = "=0.3.0"
12
+ parasolid-core = "=0.3.5"
13
13
  pyo3 = { version = "=0.29.2", features = ["abi3-py310"] }
14
14
  flate2 = { version = "1", default-features = false, features = ["rust_backend"] }
15
15
  sha2 = "0.10"
@@ -134,7 +134,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
134
134
  DEALINGS IN THE SOFTWARE.
135
135
 
136
136
 
137
- === parasolid-core 0.3.0 (MIT AND Apache-2.0) ===
137
+ === parasolid-core 0.3.5 (MIT AND Apache-2.0) ===
138
138
  MIT License
139
139
 
140
140
  Copyright (c) 2026 parasolid-kit contributors
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: icadkit
3
- Version: 0.2.0
3
+ Version: 0.3.5
4
4
  Classifier: Development Status :: 2 - Pre-Alpha
5
5
  Classifier: Programming Language :: Python :: 3 :: Only
6
6
  Classifier: Programming Language :: Python :: Implementation :: CPython
@@ -32,23 +32,40 @@ A Rust-based Python reader for **iCAD SX `.icd` files**. Read saved part
32
32
  structure, coordinate frames, names and selected attributes; inspect native
33
33
  box/cylinder parameters; and extract embedded Parasolid geometry.
34
34
 
35
- Version **0.2.0** adds:
36
-
37
- - [Native part access](docs/parts.md): hierarchy, internal snapshot definitions,
38
- unresolved external references, millimetre local/world part frames, comments
39
- and extended text, with per-part Python rows.
40
- - [Native parameters and appearance](docs/native.md): qualified box/cylinder
41
- dimensions and global frames, saved entity palette indices, visibility and layers.
42
- - The exact iCAD V34 `SCH_3401212_34101_13006` Parasolid profile through
43
- `parasolid-core 0.3.0`, without an external catalog for qualified resources.
44
- - Optional [resource preview and GLB export](docs/preview.md), with explicit
45
- source units and a local browser viewer.
35
+ Version **0.3.5** adds:
36
+
37
+ - [View inventories and saved 2D geometry](docs/drawing.md) through
38
+ `read_views()` / `read_drawing()` and the `views` / `drawing` CLI commands.
39
+ Old originals and registered parts are read directly. Qualified 2D primitives
40
+ use view-local coordinates; text content is separate from unsupported layout.
41
+ - Catalog-free raw parsing and source B-Rep mapping of
42
+ [twenty-six further exact iCAD schema keys](docs/support.md#schemas) through
43
+ `parasolid-core 0.3.5`. SPUN_SURF geometry remains partial; saved-body
44
+ conversion has separate limits.
45
+ - The [trailing container](docs/trailer.md): per-entity blocks with stored
46
+ local bounds and the identity of their faces and edges (`read_trailer()`,
47
+ `icadkit trailer`).
48
+ - [Saved final bodies](docs/saved-bodies.md) bound through saved association
49
+ records in V8 and by source ID in V7L2–V7L5, and converted with elliptical
50
+ edges, intersection curves and cone apexes.
51
+ - More [native primitives](docs/native.md): polygon extrusions, extrusions with
52
+ arc profiles, revolved profiles and signed heights, in V7L6/V7L7 and
53
+ V8L1/V8L2/V8L3, including internal mirrors.
54
+ - [Saved 3D parameter tables](docs/parameters.md) and explicit
55
+ [external-reference resolution](docs/references.md).
56
+
57
+ Version 0.3.0 added the [native file viewer](docs/viewer.md), broader
58
+ [part access](docs/parts.md), optional [V7L7 boolean evaluation](docs/csg.md)
59
+ and [saved final body display](docs/saved-bodies.md).
46
60
 
47
61
  icadkit is experimental. Unsupported geometry remains in the part inventory;
48
62
  unknown values and source ranges are preserved. Part frames, native primitive
49
63
  frames and embedded resource coordinates have separate contracts. Complete
50
- assembly geometry, inherited attributes and drawings remain unsupported.
51
- Read the [support boundaries](docs/support.md) and [changes since 0.1.0](docs/changelog.md).
64
+ assembly geometry, inherited attributes and complete drawing reconstruction remain unsupported.
65
+ Read the [support boundaries](docs/support.md) and [release notes](docs/changelog.md).
66
+
67
+ Run `icadkit view model.icd` to open qualified native primitives and their
68
+ part properties. The base viewer works without the preview extra.
52
69
 
53
70
  ## Installation
54
71
 
@@ -56,7 +73,7 @@ The base reader supports standard GIL-enabled CPython 3.10–3.14. Wheel targets
56
73
  are Linux x86_64 (glibc 2.28+), Windows x86_64 and macOS ARM64 (11+):
57
74
 
58
75
  ```sh
59
- python -m pip install icadkit==0.2.0
76
+ python -m pip install icadkit==0.3.5
60
77
  ```
61
78
 
62
79
  The native extension bundles `parasolid-core` and has no mandatory Python
@@ -65,7 +82,7 @@ explicit compatible catalog is needed only for schemas absent from the built-in
65
82
  profiles. Release files are available on the
66
83
  [GitHub releases page](https://github.com/monozukuri-ai/icadkit/releases).
67
84
 
68
- For preview/GLB, install `python -m pip install 'icadkit[preview]==0.2.0'`.
85
+ For preview/GLB, install `python -m pip install 'icadkit[preview]==0.3.5'`.
69
86
  The optional OCCT dependency requires glibc 2.31+ on Linux; see
70
87
  [preview requirements](docs/preview.md#dependencies-and-validation).
71
88
  To build from a source checkout or sdist, install Rust 1.88+ and a C linker,
@@ -88,10 +105,35 @@ for part in parts.walk(include_root=False):
88
105
  rows = parts.to_rows() # JSON-compatible rows; not certified BOM quantities.
89
106
  ```
90
107
 
91
- The qualified native profile is the observed little-endian V8L3 `3DGLOBAL`
92
- layout. Part frames use millimetres. Mirrored frames and external-file loading
93
- remain unsupported. Extended information is stored text, not interpreted typed
94
- engineering properties. Check each scope's status before relying on its values.
108
+ The reader supports the observed little-endian V7L7 part layout:
109
+ hierarchy, names, comments, extended text and saved external reference names.
110
+ Qualified V7L7 part frames use millimetres and are evaluated relative to the
111
+ saved root frame. Qualified standalone primitive owners also expose geometry and saved
112
+ entity appearance. The separate [CSG API](docs/csg.md) and
113
+ `uv run --extra preview icadkit view model.icd --csg` evaluate qualified
114
+ box/cylinder unions, differences and intersections. Unknown programs retain
115
+ diagnostics without substitute geometry.
116
+ The [saved final body mode](docs/saved-bodies.md), `view --saved-brep`, also
117
+ displays qualified V7L7/V8L3 final bodies and imported solids, including bounded
118
+ spherical, conical and toroidal surfaces. V8L3 resource sharing preserves each
119
+ occurrence's saved placement. An explicit schema catalog is needed when the
120
+ exact built-in profile lacks a required type. Counted metadata framing also
121
+ extends part inventories while preserving unknown records and diagnostics.
122
+ Version 0.3.0 also preserves bounded binary attributes as raw owned records,
123
+ reads V8L1/V8L2 part inventories without assigning units or geometry, and displays
124
+ native cones/frusta and full ring tori. The updated exact V34 profile in
125
+ `parasolid-core 0.3.1` removes the catalog requirement for qualified toroidal
126
+ resources.
127
+
128
+ Version 0.3.5 extends qualified millimetre frames and bounded
129
+ native/saved geometry to V7L6/V7L7 and V8L1/V8L2/V8L3, including internal mirrors.
130
+ Signed occurrence orientation is separate from already placed geometry; see
131
+ [mirror semantics](docs/parts.md#coordinate-frames-and-units). Explicit
132
+ [external-reference resolution](docs/references.md) now composes qualified child
133
+ and grandchild placements, including mirrors, through `read_assembly()` or
134
+ `icadkit view model.icd --reference-root /path/to/bundle`. Saved names, resolved
135
+ paths, hashes and missing/ambiguous references remain separate. Extended information is stored text, not interpreted
136
+ typed engineering properties. Check each scope's status before relying on its values.
95
137
 
96
138
  ## Embedded geometry
97
139
 
@@ -4,23 +4,40 @@ A Rust-based Python reader for **iCAD SX `.icd` files**. Read saved part
4
4
  structure, coordinate frames, names and selected attributes; inspect native
5
5
  box/cylinder parameters; and extract embedded Parasolid geometry.
6
6
 
7
- Version **0.2.0** adds:
8
-
9
- - [Native part access](docs/parts.md): hierarchy, internal snapshot definitions,
10
- unresolved external references, millimetre local/world part frames, comments
11
- and extended text, with per-part Python rows.
12
- - [Native parameters and appearance](docs/native.md): qualified box/cylinder
13
- dimensions and global frames, saved entity palette indices, visibility and layers.
14
- - The exact iCAD V34 `SCH_3401212_34101_13006` Parasolid profile through
15
- `parasolid-core 0.3.0`, without an external catalog for qualified resources.
16
- - Optional [resource preview and GLB export](docs/preview.md), with explicit
17
- source units and a local browser viewer.
7
+ Version **0.3.5** adds:
8
+
9
+ - [View inventories and saved 2D geometry](docs/drawing.md) through
10
+ `read_views()` / `read_drawing()` and the `views` / `drawing` CLI commands.
11
+ Old originals and registered parts are read directly. Qualified 2D primitives
12
+ use view-local coordinates; text content is separate from unsupported layout.
13
+ - Catalog-free raw parsing and source B-Rep mapping of
14
+ [twenty-six further exact iCAD schema keys](docs/support.md#schemas) through
15
+ `parasolid-core 0.3.5`. SPUN_SURF geometry remains partial; saved-body
16
+ conversion has separate limits.
17
+ - The [trailing container](docs/trailer.md): per-entity blocks with stored
18
+ local bounds and the identity of their faces and edges (`read_trailer()`,
19
+ `icadkit trailer`).
20
+ - [Saved final bodies](docs/saved-bodies.md) bound through saved association
21
+ records in V8 and by source ID in V7L2–V7L5, and converted with elliptical
22
+ edges, intersection curves and cone apexes.
23
+ - More [native primitives](docs/native.md): polygon extrusions, extrusions with
24
+ arc profiles, revolved profiles and signed heights, in V7L6/V7L7 and
25
+ V8L1/V8L2/V8L3, including internal mirrors.
26
+ - [Saved 3D parameter tables](docs/parameters.md) and explicit
27
+ [external-reference resolution](docs/references.md).
28
+
29
+ Version 0.3.0 added the [native file viewer](docs/viewer.md), broader
30
+ [part access](docs/parts.md), optional [V7L7 boolean evaluation](docs/csg.md)
31
+ and [saved final body display](docs/saved-bodies.md).
18
32
 
19
33
  icadkit is experimental. Unsupported geometry remains in the part inventory;
20
34
  unknown values and source ranges are preserved. Part frames, native primitive
21
35
  frames and embedded resource coordinates have separate contracts. Complete
22
- assembly geometry, inherited attributes and drawings remain unsupported.
23
- Read the [support boundaries](docs/support.md) and [changes since 0.1.0](docs/changelog.md).
36
+ assembly geometry, inherited attributes and complete drawing reconstruction remain unsupported.
37
+ Read the [support boundaries](docs/support.md) and [release notes](docs/changelog.md).
38
+
39
+ Run `icadkit view model.icd` to open qualified native primitives and their
40
+ part properties. The base viewer works without the preview extra.
24
41
 
25
42
  ## Installation
26
43
 
@@ -28,7 +45,7 @@ The base reader supports standard GIL-enabled CPython 3.10–3.14. Wheel targets
28
45
  are Linux x86_64 (glibc 2.28+), Windows x86_64 and macOS ARM64 (11+):
29
46
 
30
47
  ```sh
31
- python -m pip install icadkit==0.2.0
48
+ python -m pip install icadkit==0.3.5
32
49
  ```
33
50
 
34
51
  The native extension bundles `parasolid-core` and has no mandatory Python
@@ -37,7 +54,7 @@ explicit compatible catalog is needed only for schemas absent from the built-in
37
54
  profiles. Release files are available on the
38
55
  [GitHub releases page](https://github.com/monozukuri-ai/icadkit/releases).
39
56
 
40
- For preview/GLB, install `python -m pip install 'icadkit[preview]==0.2.0'`.
57
+ For preview/GLB, install `python -m pip install 'icadkit[preview]==0.3.5'`.
41
58
  The optional OCCT dependency requires glibc 2.31+ on Linux; see
42
59
  [preview requirements](docs/preview.md#dependencies-and-validation).
43
60
  To build from a source checkout or sdist, install Rust 1.88+ and a C linker,
@@ -60,10 +77,35 @@ for part in parts.walk(include_root=False):
60
77
  rows = parts.to_rows() # JSON-compatible rows; not certified BOM quantities.
61
78
  ```
62
79
 
63
- The qualified native profile is the observed little-endian V8L3 `3DGLOBAL`
64
- layout. Part frames use millimetres. Mirrored frames and external-file loading
65
- remain unsupported. Extended information is stored text, not interpreted typed
66
- engineering properties. Check each scope's status before relying on its values.
80
+ The reader supports the observed little-endian V7L7 part layout:
81
+ hierarchy, names, comments, extended text and saved external reference names.
82
+ Qualified V7L7 part frames use millimetres and are evaluated relative to the
83
+ saved root frame. Qualified standalone primitive owners also expose geometry and saved
84
+ entity appearance. The separate [CSG API](docs/csg.md) and
85
+ `uv run --extra preview icadkit view model.icd --csg` evaluate qualified
86
+ box/cylinder unions, differences and intersections. Unknown programs retain
87
+ diagnostics without substitute geometry.
88
+ The [saved final body mode](docs/saved-bodies.md), `view --saved-brep`, also
89
+ displays qualified V7L7/V8L3 final bodies and imported solids, including bounded
90
+ spherical, conical and toroidal surfaces. V8L3 resource sharing preserves each
91
+ occurrence's saved placement. An explicit schema catalog is needed when the
92
+ exact built-in profile lacks a required type. Counted metadata framing also
93
+ extends part inventories while preserving unknown records and diagnostics.
94
+ Version 0.3.0 also preserves bounded binary attributes as raw owned records,
95
+ reads V8L1/V8L2 part inventories without assigning units or geometry, and displays
96
+ native cones/frusta and full ring tori. The updated exact V34 profile in
97
+ `parasolid-core 0.3.1` removes the catalog requirement for qualified toroidal
98
+ resources.
99
+
100
+ Version 0.3.5 extends qualified millimetre frames and bounded
101
+ native/saved geometry to V7L6/V7L7 and V8L1/V8L2/V8L3, including internal mirrors.
102
+ Signed occurrence orientation is separate from already placed geometry; see
103
+ [mirror semantics](docs/parts.md#coordinate-frames-and-units). Explicit
104
+ [external-reference resolution](docs/references.md) now composes qualified child
105
+ and grandchild placements, including mirrors, through `read_assembly()` or
106
+ `icadkit view model.icd --reference-root /path/to/bundle`. Saved names, resolved
107
+ paths, hashes and missing/ambiguous references remain separate. Extended information is stored text, not interpreted
108
+ typed engineering properties. Check each scope's status before relying on its values.
67
109
 
68
110
  ## Embedded geometry
69
111
 
@@ -4,7 +4,7 @@ icadkit project material is offered under PolyForm Noncommercial 1.0.0, with sep
4
4
  commercial licensing available from UnRobotics Inc.
5
5
  See `LICENSE` and `COMMERCIAL-LICENSE.md`.
6
6
 
7
- Binary distributions also contain `parasolid-core 0.3.0` (MIT AND Apache-2.0)
7
+ Binary distributions also contain `parasolid-core 0.3.5` (MIT AND Apache-2.0)
8
8
  and PyO3 (MIT OR Apache-2.0, MIT selected). The source metadata declares
9
9
  `PolyForm-Noncommercial-1.0.0`; the combined Python distribution declares
10
10
  `PolyForm-Noncommercial-1.0.0 AND MIT AND Apache-2.0`. These expressions describe
@@ -0,0 +1,57 @@
1
+ # Public regression corpus
2
+
3
+ These eight cases are authored synthetic framing/topology, not iCAD-produced
4
+ models. No vendor CAD payload, proprietary catalog or SDK is used. Project-authored
5
+ material is offered under PolyForm Noncommercial 1.0.0; see [LICENSE](../LICENSE).
6
+ The V30 scalar layouts come from the MIT/Apache-2.0 parasolid-core profile,
7
+ as documented in tests/geometry_fixtures.py.
8
+
9
+ The four wire cases describe endpoints (2, -1, 3) and (5, 3, 3), independently
10
+ giving length 5 in unspecified source units. They cover both byte orders and
11
+ raw/zlib owners. Other cases cover uninterpreted content, an unknown schema,
12
+ an invalid reference, and a bad zlib checksum. None is a geometric holdout.
13
+
14
+ public.jsonl pins generated bytes, provenance, expected scope and diagnostics.
15
+ The generator uses a stored DEFLATE block so hashes do not depend on zlib's
16
+ compression heuristics. The checker never rewrites expectations or skips inputs.
17
+
18
+ ```sh
19
+ python corpus/generate.py --output .local/public-corpus
20
+ uv run python scripts/verify_corpus.py --manifest corpus/public.jsonl \
21
+ --root .local/public-corpus --required
22
+ ```
23
+
24
+ The generators, manifest and tests are in the sdist. Generated ICD files are
25
+ excluded from both wheel and sdist. These synthetic cases verify specific
26
+ behaviors and do not establish general compatibility with vendor-produced files.
27
+
28
+ ## Caller-owned native regression data
29
+
30
+ `scripts/verify_native_corpus.py` checks an explicit JSON manifest without
31
+ starting iCAD. Each row pins an input SHA-256, its existing API snapshot,
32
+ `family_id` and `development`/`validation` partition. Optional SDK observations,
33
+ required companion files and intentionally absent dependencies have separate
34
+ entries. Supply each named input root explicitly with `--root NAME=PATH` and
35
+ pin the manifest itself with `--manifest-sha256` when recording a baseline.
36
+
37
+ The runner rejects missing/changed evidence and split families or shared CAD
38
+ payloads across different families. It reports unchanged reader behavior
39
+ separately from SDK comparison. Current SDK checks cover host child-part
40
+ hierarchy, saved names/properties and available world frames, not full geometry.
41
+ Resolved external descendants belong to their own document. An unloaded SDK
42
+ placeholder cannot certify saved comment/reference properties. A library-part
43
+ insertion oracle cannot certify the original file's raw document coordinates.
44
+ These fields remain explicitly partial or not comparable.
45
+ Repeated same-name parent paths remain partial where occurrence ownership cannot
46
+ be independently matched; equal counts and list ordering are not proof.
47
+
48
+ The manifest and actual CAD/SDK data are not included. Tests construct independent
49
+ synthetic evidence. An unchanged unsupported result passes the regression check
50
+ but does not qualify that file as newly supported.
51
+
52
+ The explicit [assembly resolver](../docs/references.md) has separate synthetic
53
+ tests in `tests/test_references.py` and optional browser checks in
54
+ `tests/viewer_assembly_browser.mjs`. The single-file corpus snapshot is unchanged
55
+ by resolution. Private P5 SDK bundles additionally check child/grandchild frames,
56
+ dependency updates, missing targets, mirrors and placed geometry; these bundles
57
+ and their proprietary catalogs are not distributed.
@@ -108,7 +108,7 @@ icadkit project material is offered under PolyForm Noncommercial 1.0.0, with sep
108
108
  commercial licensing available from UnRobotics Inc.
109
109
  See `LICENSE` and `COMMERCIAL-LICENSE.md`.
110
110
 
111
- Binary distributions also contain `parasolid-core 0.3.0` (MIT AND Apache-2.0)
111
+ Binary distributions also contain `parasolid-core 0.3.5` (MIT AND Apache-2.0)
112
112
  and PyO3 (MIT OR Apache-2.0, MIT selected). The source metadata declares
113
113
  `PolyForm-Noncommercial-1.0.0`; the combined Python distribution declares
114
114
  `PolyForm-Noncommercial-1.0.0 AND MIT AND Apache-2.0`. These expressions describe
@@ -582,7 +582,7 @@ IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
582
582
  DEALINGS IN THE SOFTWARE.
583
583
 
584
584
 
585
- === parasolid-core 0.3.0 (MIT AND Apache-2.0) ===
585
+ === parasolid-core 0.3.5 (MIT AND Apache-2.0) ===
586
586
  MIT License
587
587
 
588
588
  Copyright (c) 2026 parasolid-kit contributors
@@ -7,7 +7,8 @@ use crate::provenance::sha256;
7
7
  use crate::record::record_info;
8
8
  use crate::{
9
9
  ByteOrder, ByteRange, Diagnostic, Encoding, ErrorKind, Extraction, InspectError, Inspection,
10
- ReadLimits, RecordInfo, ResourceRef, SourceRef, UnparsedRange, inspect_bytes,
10
+ ReadLimits, RecordInfo, ResourceAssociation, ResourceRef, SourceRef, UnparsedRange,
11
+ inspect_bytes,
11
12
  };
12
13
 
13
14
  /// Immutable owned input and a structural resource index. Construction never
@@ -21,6 +22,7 @@ pub struct Document {
21
22
  source_sha256: String,
22
23
  records: Vec<RecordInfo>,
23
24
  resources: Vec<ResourceRef>,
25
+ associations: Vec<ResourceAssociation>,
24
26
  unparsed_ranges: Vec<UnparsedRange>,
25
27
  diagnostics: Vec<Diagnostic>,
26
28
  resource_index_complete: bool,
@@ -43,6 +45,14 @@ impl Document {
43
45
  pub fn resources(&self) -> &[ResourceRef] {
44
46
  &self.resources
45
47
  }
48
+ /// Saved entity-to-resource records, in source order. Presence does not
49
+ /// establish that the entity or the resource is otherwise qualified.
50
+ pub fn associations(&self) -> &[ResourceAssociation] {
51
+ &self.associations
52
+ }
53
+ pub(crate) fn all_bytes(&self) -> &[u8] {
54
+ &self.data
55
+ }
46
56
  pub fn unparsed_ranges(&self) -> &[UnparsedRange] {
47
57
  &self.unparsed_ranges
48
58
  }
@@ -122,6 +132,7 @@ impl Document {
122
132
  source_sha256,
123
133
  records: Vec::new(),
124
134
  resources: Vec::new(),
135
+ associations: Vec::new(),
125
136
  unparsed_ranges: Vec::new(),
126
137
  diagnostics: Vec::new(),
127
138
  resource_index_complete: true,
@@ -419,6 +430,26 @@ impl Document {
419
430
  "view entity has an unobserved length",
420
431
  ))?;
421
432
  }
433
+ if kind == 0x88 {
434
+ // The fixed record names one saved entity, one resource
435
+ // number and that entity's frame. Its other words stay opaque.
436
+ let mut frame = [0.0; 9];
437
+ for (i, value) in frame.iter_mut().enumerate() {
438
+ let at = position + 24 + 8 * i;
439
+ let mut raw = [0; 8];
440
+ raw.copy_from_slice(&self.data[at..at + 8]);
441
+ *value = order.f64(raw);
442
+ }
443
+ self.associations.push(ResourceAssociation {
444
+ byte_range: ByteRange {
445
+ start: position as u64,
446
+ end: next as u64,
447
+ },
448
+ entity_source_id: self.word(position + 4)?,
449
+ resource_source_id: self.word(position + 8)?,
450
+ frame,
451
+ });
452
+ }
422
453
  self.opaque(position, next, "entity_metadata", "USR");
423
454
  }
424
455
  position = next;
@@ -13,6 +13,8 @@ mod reader;
13
13
  mod record;
14
14
  mod resource;
15
15
  mod schema;
16
+ mod trailer;
17
+ mod views;
16
18
 
17
19
  pub use document::Document;
18
20
  pub use error::{Diagnostic, ErrorKind, InspectError};
@@ -25,12 +27,20 @@ pub use native::{NativeEntityRecord, NativePrimitiveRecord};
25
27
  pub use parasolid::{
26
28
  GeometryDiagnostic, GeometryError, GeometryResult, GeometryStatus, SchemaSelection,
27
29
  };
28
- pub use parts::{PartIndex, PartLimits, PartOpaqueRange, PartRecord};
30
+ pub use parts::{
31
+ PartAttributeRecord, PartIndex, PartLimits, PartOpaqueRange, PartProfileInfo, PartRecord,
32
+ PartViewRecord,
33
+ };
29
34
  pub use provenance::{Extraction, SourceRef};
30
35
  pub use reader::ByteOrder;
31
36
  pub use record::{ByteRange, RecordInfo};
32
- pub use resource::{Encoding, ResourceRef};
37
+ pub use resource::{Encoding, ResourceAssociation, ResourceRef};
33
38
  pub use schema::SchemaCatalog;
39
+ pub use trailer::{
40
+ TrailerBlock, TrailerBlockData, TrailerEdge, TrailerFace, TrailerIndex, TrailerLimits,
41
+ TrailerTable, TrailerView,
42
+ };
43
+ pub use views::{ViewEntry, ViewIndex, ViewLimits, ViewRecord};
34
44
 
35
45
  use parasolid_core::{BuiltinProfileRegistry, ParseError};
36
46
 
@@ -38,7 +48,7 @@ use parasolid_core::{BuiltinProfileRegistry, ParseError};
38
48
  pub const VERSION: &str = env!("CARGO_PKG_VERSION");
39
49
 
40
50
  /// Exact registry dependency; checked against the manifest and lock in CI.
41
- pub const PARASOLID_CORE_VERSION: &str = "0.3.0";
51
+ pub const PARASOLID_CORE_VERSION: &str = "0.3.5";
42
52
 
43
53
  /// Metadata of the compiled Parasolid backend, not ICD format coverage.
44
54
  #[derive(Debug, Clone, PartialEq, Eq)]
@@ -75,7 +85,8 @@ mod tests {
75
85
  assert!(!info.builtin_profile_ids.is_empty());
76
86
  let registry = BuiltinProfileRegistry::compiled()?;
77
87
  let covered = SchemaKey::parse("SCH_3000310_30000_13006")?;
78
- let uncovered = SchemaKey::parse("SCH_2601246_26105_13006")?;
88
+ // A neighbouring modeller build is a different key, never a fallback.
89
+ let uncovered = SchemaKey::parse("SCH_3000311_30000_13006")?;
79
90
  assert!(registry.provider_for_key(&covered).is_some());
80
91
  assert!(registry.provider_for_key(&uncovered).is_none());
81
92
  Ok(())