cad-tools 0.1.0__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.
@@ -0,0 +1,27 @@
1
+ #
2
+ .DS_Store
3
+ *.json
4
+ *.png
5
+ *.stl
6
+ *.step
7
+
8
+ # MCP 設定はコミットする(生成物の *.json 除外の例外)
9
+ !.mcp.json
10
+ !**/mcp.json
11
+
12
+ # README 用の画像はコミットする(*.png 除外の例外)
13
+ !docs/images/*.png
14
+
15
+ # Python-generated files
16
+ __pycache__/
17
+ *.py[oc]
18
+ build/
19
+ dist/
20
+ wheels/
21
+ *.egg-info
22
+
23
+ # Virtual environments
24
+ .venv
25
+
26
+ # 生成物の出力先
27
+ workspace/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 ToPo
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,315 @@
1
+ Metadata-Version: 2.4
2
+ Name: cad-tools
3
+ Version: 0.1.0
4
+ Summary: Generate 3D CAD models (STEP/STL) and multi-view renders from a declarative JSON intermediate representation, built on build123d.
5
+ Project-URL: Homepage, https://github.com/ToPo-ToPo-ToPo/cad-tools
6
+ Project-URL: Repository, https://github.com/ToPo-ToPo-ToPo/cad-tools
7
+ Author: ToPo
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Keywords: 3d,build123d,cad,mcp,parametric,step,stl
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: Manufacturing
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Topic :: Multimedia :: Graphics :: 3D Modeling
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Requires-Python: <3.13,>=3.12
20
+ Requires-Dist: build123d>=0.10.0
21
+ Requires-Dist: mcp[cli]>=1.2
22
+ Requires-Dist: numpy>=2.1
23
+ Requires-Dist: pillow>=11.0
24
+ Requires-Dist: pyvista>=0.45
25
+ Description-Content-Type: text/markdown
26
+
27
+ # cad-tools
28
+
29
+ [![Python](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/)
30
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
31
+ [![Built on build123d](https://img.shields.io/badge/built%20on-build123d-orange.svg)](https://build123d.readthedocs.io/)
32
+
33
+ 宣言的な JSON(semantic IR)から [build123d](https://build123d.readthedocs.io/) で
34
+ 3D CAD モデルを生成し、**STEP / STL 出力**と **4 ビュー PNG レンダリング**を行う Python ライブラリ。
35
+
36
+ 命令的な CAD コードではなく「どんな形状か」を JSON で記述するだけでモデルが組み上がる。
37
+ **AI エージェントが MCP 経由で形状を反復設計する**ことを主眼に設計している。
38
+
39
+ ![L字ブラケットの 4 ビューレンダリング](https://raw.githubusercontent.com/ToPo-ToPo-ToPo/cad-tools/main/docs/images/l_bracket.png)
40
+
41
+ > 上図はサンプル `examples/l_bracket.py` の出力。ISO / 正面 / 上面 / 右側面の 4 ビュー。
42
+
43
+ ---
44
+
45
+ ## 特長
46
+
47
+ - **宣言的な IR** — プリミティブ・穴・面取り・中空などを JSON で組み合わせるだけ
48
+ - **相対配置** — 既存形状の面中心・角・中心(アンカー)を基準に部品を置ける
49
+ - **headless レンダリング** — VTK / PyVista による GUI 不要の 4 ビュー描画(CAD 風の輪郭付き)
50
+ - **MCP サーバ** — エージェントが「IR を渡す → 画像が返る」ループで設計を反復できる
51
+ - **標準フォーマット出力** — STEP(CAD)/ STL(メッシュ)/ PNG(確認用)
52
+
53
+ ---
54
+
55
+ ## インストール
56
+
57
+ Python 3.12 が必要。[uv](https://docs.astral.sh/uv/) を推奨する。
58
+
59
+ ```bash
60
+ uv add cad-tools
61
+ ```
62
+
63
+ pip の場合:
64
+
65
+ ```bash
66
+ pip install cad-tools
67
+ ```
68
+
69
+ > GUI / GPU の無い環境(コンテナ・CI)では、描画時に Xvfb 仮想ディスプレイを自動起動する。
70
+ > Linux では `Xvfb` がインストールされていること(例: `apt-get install xvfb`)。
71
+
72
+ ---
73
+
74
+ ## クイックスタート
75
+
76
+ ```python
77
+ from cad_tools import Build123dEmitter, render_part
78
+
79
+ ir = {
80
+ "features": [
81
+ {"id": "base", "type": "box", "size": [40, 30, 10]},
82
+ {"id": "post", "type": "cylinder", "radius": 5, "height": 20,
83
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
84
+ {"id": "hole", "type": "hole", "target": "base", "diameter": 6, "depth": 10,
85
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
86
+ ]
87
+ }
88
+
89
+ part = Build123dEmitter(ir).build() # build123d の Solid を返す
90
+ render_part(part, "render.png") # 4 ビュー PNG を書き出す
91
+ ```
92
+
93
+ STEP / STL に出力するには build123d の関数をそのまま使える:
94
+
95
+ ```python
96
+ from build123d import export_step, export_stl
97
+
98
+ export_step(part, "part.step")
99
+ export_stl(part, "part.stl")
100
+ ```
101
+
102
+ ---
103
+
104
+ ## 公開 API
105
+
106
+ ```python
107
+ from cad_tools import (
108
+ Build123dEmitter, # IR から build123d パーツを構築するメインクラス
109
+ load_ir, # JSON ファイルから IR を読み込む
110
+ validate_ir, # IR の構造を検証する(不正なら ValueError)
111
+ render_part, # パーツを 4 ビュー PNG に描画
112
+ render_step, # STEP ファイルを読み込んで 4 ビュー PNG に描画
113
+ get_anchor_position, # ソリッドのアンカー座標を取得
114
+ apply_transform, # 回転・平行移動を適用
115
+ )
116
+ ```
117
+
118
+ | 名前 | シグネチャ | 説明 |
119
+ |---|---|---|
120
+ | `Build123dEmitter(ir)` | `.build() -> Solid` | IR を検証・構築して build123d の Solid を返す |
121
+ | `render_part(part, png_path)` | `-> Path` | パーツを 2x2 マルチビュー PNG に描画 |
122
+ | `render_step(step_path, png_path)` | `-> Path` | STEP を読み込んで同様に描画 |
123
+ | `validate_ir(ir)` | `-> None` | 構造を検証(問題があれば `ValueError`) |
124
+ | `load_ir(path)` | `-> dict` | JSON ファイルから IR を読む |
125
+
126
+ ---
127
+
128
+ ## サンプル
129
+
130
+ リポジトリの `examples/` に IR の書き方を示すサンプルがある。各サンプルは
131
+ STEP / STL / 4 ビュー PNG を `workspace/<サンプル名>/` に書き出す(フォルダは自動作成)。
132
+
133
+ ```bash
134
+ uv run python -m examples # 全サンプルを生成
135
+ uv run python -m examples.l_bracket # 個別に生成
136
+ ```
137
+
138
+ | サンプル | 内容 | 使う機能 |
139
+ |---|---|---|
140
+ | `l_bracket` | L 字ブラケット(底板+垂直板+取り付け穴) | box, reference, linear 穴 |
141
+ | `flange` | 円形フランジ(中央穴+ボルト円+面取り) | cylinder, circular 穴, chamfer |
142
+ | `enclosure` | 角丸の中空ケース(上面開口+4 隅穴) | fillet, shell, grid 穴 |
143
+ | `hex_standoff` | 六角スペーサ(貫通穴) | prism, hole |
144
+ | `o_ring` | O リング(ガスケット) | torus |
145
+ | `funnel` | 漏斗(上下開口の円錐台) | cone(テーパ), shell |
146
+ | `ball_stud` | ボールスタッド(軸+先端球) | cylinder, sphere, reference offset |
147
+ | `angle_bracket` | 補強リブ付き L 字ブラケット(曲げラウンド+ボルト穴+リブ) | extrude(L 断面+角丸), hole, transform |
148
+
149
+ ---
150
+
151
+ ## semantic IR リファレンス
152
+
153
+ IR は `features` のリスト。各 feature は `id`(一意)と `type` を持ち、`type` ごとの
154
+ フィールドを足す。feature はリスト順に処理され、`hole` / `fillet` / `chamfer` / `shell`
155
+ は `target` に指定した既存 feature を変更する。
156
+
157
+ ```json
158
+ {
159
+ "features": [
160
+ {"id": "base", "type": "box", "size": [40, 30, 10]},
161
+ {"id": "post", "type": "cylinder", "radius": 5, "height": 20,
162
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
163
+ {"id": "h1", "type": "hole", "target": "base", "diameter": 6, "depth": 10,
164
+ "reference": {"feature": "base", "anchor": "top_face_center"}}
165
+ ]
166
+ }
167
+ ```
168
+
169
+ ### feature.type
170
+
171
+ | type | 種別 | 必須フィールド | 任意フィールド |
172
+ |---|---|---|---|
173
+ | `box` | 加算 | `size:[x,y,z]` | |
174
+ | `cylinder` | 加算 | `radius`, `height` | |
175
+ | `sphere` | 加算 | `radius` | |
176
+ | `cone` | 加算 | `radius`, `height` | `top_radius`(既定 0 = 尖り) |
177
+ | `torus` | 加算 | `major_radius`, `minor_radius` | |
178
+ | `prism` | 加算 | `radius`, `sides`, `height` | 正多角柱 |
179
+ | `extrude` | 加算 | `profile:[[x,y],...]`, `height` | `fillet_corners`(断面の角丸) |
180
+ | `hole` | 減算 | `target`, `diameter`, `depth` | `count`, `pattern` |
181
+ | `fillet` | 変更 | `target`, `radius` | `edges` |
182
+ | `chamfer` | 変更 | `target`, `length` | `edges` |
183
+ | `shell` | 変更 | `target`, `thickness` | `openings` |
184
+
185
+ ### 配置(加算プリミティブ共通)
186
+
187
+ | キー | 説明 |
188
+ |---|---|
189
+ | `reference` | `{feature, anchor, offset?}` — 既存 feature のアンカーを基準に配置 |
190
+ | `position` | `[x, y, z]` — 絶対座標に配置(reference が無い場合) |
191
+ | `transform` | `{rotate:[rx,ry,rz], translate:[x,y,z]}` — 回転・平行移動(度) |
192
+
193
+ **anchor** に使える値:
194
+
195
+ - `center`
196
+ - `top_face_center` / `bottom_face_center` / `left_face_center` /
197
+ `right_face_center` / `front_face_center` / `back_face_center`
198
+ - 角(8 種): `top_left_front` / `top_right_front` / `top_left_back` /
199
+ `top_right_back` / `bottom_left_front` / `bottom_right_front` /
200
+ `bottom_left_back` / `bottom_right_back`
201
+
202
+ ### hole の複数穴
203
+
204
+ `pattern` を付けると複数の穴を一括で開ける(`count` は linear / circular で使用)。
205
+
206
+ | pattern.kind | 指定 | 説明 |
207
+ |---|---|---|
208
+ | `linear` | `spacing:[dx,dy,dz]` | 基準位置から等間隔に `count` 個 |
209
+ | `grid` | `counts:[nx,ny]`, `spacing:[dx,dy]` | +x / +y に nx × ny 個の格子 |
210
+ | `circular` | `radius:R`(任意で `axis`, `start_angle`, `center`) | 円周上に `count` 個(ボルト円) |
211
+
212
+ ### extrude の `fillet_corners`(断面の角丸)
213
+
214
+ 押し出し前に 2D 断面の指定頂点をラウンドにする。L 字の内隅などに使う。
215
+ `corners` は `profile` の頂点インデックス(0 始まり、入力順)のリスト。
216
+
217
+ ```json
218
+ {"id": "body", "type": "extrude", "height": 40,
219
+ "profile": [[0,0],[50,0],[50,6],[6,6],[6,40],[0,40]],
220
+ "fillet_corners": {"corners": [3], "radius": 6}}
221
+ ```
222
+
223
+ ### fillet / chamfer の `edges`
224
+
225
+ `all`(既定)/ `vertical` / `horizontal` / `top` / `bottom`
226
+
227
+ ### shell の `openings`
228
+
229
+ 開口する面の名前リスト。例 `["top"]`。省略すると全閉の中空になる。
230
+ 使える面: `top` / `bottom` / `left` / `right` / `front` / `back`
231
+
232
+ ### 例(円周ボルト穴+面取り)
233
+
234
+ ```json
235
+ {
236
+ "features": [
237
+ {"id": "flange", "type": "cylinder", "radius": 25, "height": 10},
238
+ {"id": "bolts", "type": "hole", "target": "flange", "diameter": 4, "depth": 10,
239
+ "reference": {"feature": "flange", "anchor": "top_face_center"},
240
+ "count": 8, "pattern": {"kind": "circular", "radius": 18}},
241
+ {"id": "edge", "type": "chamfer", "target": "flange", "length": 1, "edges": "top"}
242
+ ]
243
+ }
244
+ ```
245
+
246
+ ---
247
+
248
+ ## MCP サーバ
249
+
250
+ AI エージェントが「IR を渡す → 4 ビュー画像が返る」ループで形状を反復設計できる。
251
+
252
+ ```bash
253
+ cad-tools-mcp # インストール後のコンソールスクリプト
254
+ # または
255
+ python -m cad_tools.mcp_server # モジュールとして起動(stdio)
256
+ ```
257
+
258
+ リポジトリ直下の `.mcp.json` により Claude Code では自動検出される。
259
+
260
+ | ツール | 入力 | 出力 |
261
+ |---|---|---|
262
+ | `validate_cad` | `ir` | 妥当性(`valid` / エラー文)。モデル構築なしの軽量チェック |
263
+ | `render_cad` | `ir`, `save_dir?` | **4 ビュー PNG 画像** + サマリ。`save_dir` 指定で STEP/STL/PNG も保存 |
264
+ | `export_cad` | `ir`, `output_dir`, `basename?` | STEP/STL/PNG をディスクに保存しパスを返す |
265
+
266
+ `render_cad` は画像をインライン返却するため、エージェントが生成形状を直接「見て」
267
+ 確認できる。構築に失敗した場合は例外ではなくエラー文を返すので、IR を自己修正しやすい。
268
+
269
+ ---
270
+
271
+ ## 開発
272
+
273
+ ```bash
274
+ git clone https://github.com/ToPo-ToPo-ToPo/cad-tools
275
+ cd cad-tools
276
+ uv sync # 依存と本パッケージを editable install
277
+
278
+ uv run python test.py # 複合アセンブリ
279
+ uv run python test_ring.py # リング
280
+ uv run python test_schema_extensions.py # IR 拡張機能(全 12 ケース)
281
+
282
+ uv build # wheel / sdist を dist/ に生成
283
+ ```
284
+
285
+ ### プロジェクト構成
286
+
287
+ ```
288
+ cad_tools/ ライブラリ本体(配布パッケージ)
289
+ ├── __init__.py 公開 API
290
+ ├── emitter.py semantic IR → build123d ジオメトリ
291
+ ├── validator.py IR の構造検証
292
+ ├── references.py アンカー(面中心・角・中心)による相対配置
293
+ ├── transforms.py 回転・平行移動
294
+ ├── renderer.py VTK/PyVista による headless マルチビュー描画
295
+ ├── generate.py ファイル入出力の CLI
296
+ └── mcp_server.py MCP サーバ(validate_cad / render_cad / export_cad)
297
+ examples/ サンプル(l_bracket / flange / ...)
298
+ experimental/ 退避した試作レンダラ(Blender / FreeCAD)
299
+ docs/images/ README 用の画像
300
+ ```
301
+
302
+ ---
303
+
304
+ ## レンダラについて
305
+
306
+ default は **VTK / PyVista** ベースの headless 実装(`cad_tools/renderer.py`)。
307
+ 特徴エッジ抽出で CAD 風の輪郭を出し、STL 三角分割のノイズを除く。
308
+ 過去に試した Blender / FreeCAD 版は headless 運用が不安定なため
309
+ `experimental/` に退避している(経緯は `experimental/README.md`)。
310
+
311
+ ---
312
+
313
+ ## ライセンス
314
+
315
+ [MIT](LICENSE)
@@ -0,0 +1,289 @@
1
+ # cad-tools
2
+
3
+ [![Python](https://img.shields.io/badge/python-3.12-blue.svg)](https://www.python.org/)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5
+ [![Built on build123d](https://img.shields.io/badge/built%20on-build123d-orange.svg)](https://build123d.readthedocs.io/)
6
+
7
+ 宣言的な JSON(semantic IR)から [build123d](https://build123d.readthedocs.io/) で
8
+ 3D CAD モデルを生成し、**STEP / STL 出力**と **4 ビュー PNG レンダリング**を行う Python ライブラリ。
9
+
10
+ 命令的な CAD コードではなく「どんな形状か」を JSON で記述するだけでモデルが組み上がる。
11
+ **AI エージェントが MCP 経由で形状を反復設計する**ことを主眼に設計している。
12
+
13
+ ![L字ブラケットの 4 ビューレンダリング](https://raw.githubusercontent.com/ToPo-ToPo-ToPo/cad-tools/main/docs/images/l_bracket.png)
14
+
15
+ > 上図はサンプル `examples/l_bracket.py` の出力。ISO / 正面 / 上面 / 右側面の 4 ビュー。
16
+
17
+ ---
18
+
19
+ ## 特長
20
+
21
+ - **宣言的な IR** — プリミティブ・穴・面取り・中空などを JSON で組み合わせるだけ
22
+ - **相対配置** — 既存形状の面中心・角・中心(アンカー)を基準に部品を置ける
23
+ - **headless レンダリング** — VTK / PyVista による GUI 不要の 4 ビュー描画(CAD 風の輪郭付き)
24
+ - **MCP サーバ** — エージェントが「IR を渡す → 画像が返る」ループで設計を反復できる
25
+ - **標準フォーマット出力** — STEP(CAD)/ STL(メッシュ)/ PNG(確認用)
26
+
27
+ ---
28
+
29
+ ## インストール
30
+
31
+ Python 3.12 が必要。[uv](https://docs.astral.sh/uv/) を推奨する。
32
+
33
+ ```bash
34
+ uv add cad-tools
35
+ ```
36
+
37
+ pip の場合:
38
+
39
+ ```bash
40
+ pip install cad-tools
41
+ ```
42
+
43
+ > GUI / GPU の無い環境(コンテナ・CI)では、描画時に Xvfb 仮想ディスプレイを自動起動する。
44
+ > Linux では `Xvfb` がインストールされていること(例: `apt-get install xvfb`)。
45
+
46
+ ---
47
+
48
+ ## クイックスタート
49
+
50
+ ```python
51
+ from cad_tools import Build123dEmitter, render_part
52
+
53
+ ir = {
54
+ "features": [
55
+ {"id": "base", "type": "box", "size": [40, 30, 10]},
56
+ {"id": "post", "type": "cylinder", "radius": 5, "height": 20,
57
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
58
+ {"id": "hole", "type": "hole", "target": "base", "diameter": 6, "depth": 10,
59
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
60
+ ]
61
+ }
62
+
63
+ part = Build123dEmitter(ir).build() # build123d の Solid を返す
64
+ render_part(part, "render.png") # 4 ビュー PNG を書き出す
65
+ ```
66
+
67
+ STEP / STL に出力するには build123d の関数をそのまま使える:
68
+
69
+ ```python
70
+ from build123d import export_step, export_stl
71
+
72
+ export_step(part, "part.step")
73
+ export_stl(part, "part.stl")
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 公開 API
79
+
80
+ ```python
81
+ from cad_tools import (
82
+ Build123dEmitter, # IR から build123d パーツを構築するメインクラス
83
+ load_ir, # JSON ファイルから IR を読み込む
84
+ validate_ir, # IR の構造を検証する(不正なら ValueError)
85
+ render_part, # パーツを 4 ビュー PNG に描画
86
+ render_step, # STEP ファイルを読み込んで 4 ビュー PNG に描画
87
+ get_anchor_position, # ソリッドのアンカー座標を取得
88
+ apply_transform, # 回転・平行移動を適用
89
+ )
90
+ ```
91
+
92
+ | 名前 | シグネチャ | 説明 |
93
+ |---|---|---|
94
+ | `Build123dEmitter(ir)` | `.build() -> Solid` | IR を検証・構築して build123d の Solid を返す |
95
+ | `render_part(part, png_path)` | `-> Path` | パーツを 2x2 マルチビュー PNG に描画 |
96
+ | `render_step(step_path, png_path)` | `-> Path` | STEP を読み込んで同様に描画 |
97
+ | `validate_ir(ir)` | `-> None` | 構造を検証(問題があれば `ValueError`) |
98
+ | `load_ir(path)` | `-> dict` | JSON ファイルから IR を読む |
99
+
100
+ ---
101
+
102
+ ## サンプル
103
+
104
+ リポジトリの `examples/` に IR の書き方を示すサンプルがある。各サンプルは
105
+ STEP / STL / 4 ビュー PNG を `workspace/<サンプル名>/` に書き出す(フォルダは自動作成)。
106
+
107
+ ```bash
108
+ uv run python -m examples # 全サンプルを生成
109
+ uv run python -m examples.l_bracket # 個別に生成
110
+ ```
111
+
112
+ | サンプル | 内容 | 使う機能 |
113
+ |---|---|---|
114
+ | `l_bracket` | L 字ブラケット(底板+垂直板+取り付け穴) | box, reference, linear 穴 |
115
+ | `flange` | 円形フランジ(中央穴+ボルト円+面取り) | cylinder, circular 穴, chamfer |
116
+ | `enclosure` | 角丸の中空ケース(上面開口+4 隅穴) | fillet, shell, grid 穴 |
117
+ | `hex_standoff` | 六角スペーサ(貫通穴) | prism, hole |
118
+ | `o_ring` | O リング(ガスケット) | torus |
119
+ | `funnel` | 漏斗(上下開口の円錐台) | cone(テーパ), shell |
120
+ | `ball_stud` | ボールスタッド(軸+先端球) | cylinder, sphere, reference offset |
121
+ | `angle_bracket` | 補強リブ付き L 字ブラケット(曲げラウンド+ボルト穴+リブ) | extrude(L 断面+角丸), hole, transform |
122
+
123
+ ---
124
+
125
+ ## semantic IR リファレンス
126
+
127
+ IR は `features` のリスト。各 feature は `id`(一意)と `type` を持ち、`type` ごとの
128
+ フィールドを足す。feature はリスト順に処理され、`hole` / `fillet` / `chamfer` / `shell`
129
+ は `target` に指定した既存 feature を変更する。
130
+
131
+ ```json
132
+ {
133
+ "features": [
134
+ {"id": "base", "type": "box", "size": [40, 30, 10]},
135
+ {"id": "post", "type": "cylinder", "radius": 5, "height": 20,
136
+ "reference": {"feature": "base", "anchor": "top_face_center"}},
137
+ {"id": "h1", "type": "hole", "target": "base", "diameter": 6, "depth": 10,
138
+ "reference": {"feature": "base", "anchor": "top_face_center"}}
139
+ ]
140
+ }
141
+ ```
142
+
143
+ ### feature.type
144
+
145
+ | type | 種別 | 必須フィールド | 任意フィールド |
146
+ |---|---|---|---|
147
+ | `box` | 加算 | `size:[x,y,z]` | |
148
+ | `cylinder` | 加算 | `radius`, `height` | |
149
+ | `sphere` | 加算 | `radius` | |
150
+ | `cone` | 加算 | `radius`, `height` | `top_radius`(既定 0 = 尖り) |
151
+ | `torus` | 加算 | `major_radius`, `minor_radius` | |
152
+ | `prism` | 加算 | `radius`, `sides`, `height` | 正多角柱 |
153
+ | `extrude` | 加算 | `profile:[[x,y],...]`, `height` | `fillet_corners`(断面の角丸) |
154
+ | `hole` | 減算 | `target`, `diameter`, `depth` | `count`, `pattern` |
155
+ | `fillet` | 変更 | `target`, `radius` | `edges` |
156
+ | `chamfer` | 変更 | `target`, `length` | `edges` |
157
+ | `shell` | 変更 | `target`, `thickness` | `openings` |
158
+
159
+ ### 配置(加算プリミティブ共通)
160
+
161
+ | キー | 説明 |
162
+ |---|---|
163
+ | `reference` | `{feature, anchor, offset?}` — 既存 feature のアンカーを基準に配置 |
164
+ | `position` | `[x, y, z]` — 絶対座標に配置(reference が無い場合) |
165
+ | `transform` | `{rotate:[rx,ry,rz], translate:[x,y,z]}` — 回転・平行移動(度) |
166
+
167
+ **anchor** に使える値:
168
+
169
+ - `center`
170
+ - `top_face_center` / `bottom_face_center` / `left_face_center` /
171
+ `right_face_center` / `front_face_center` / `back_face_center`
172
+ - 角(8 種): `top_left_front` / `top_right_front` / `top_left_back` /
173
+ `top_right_back` / `bottom_left_front` / `bottom_right_front` /
174
+ `bottom_left_back` / `bottom_right_back`
175
+
176
+ ### hole の複数穴
177
+
178
+ `pattern` を付けると複数の穴を一括で開ける(`count` は linear / circular で使用)。
179
+
180
+ | pattern.kind | 指定 | 説明 |
181
+ |---|---|---|
182
+ | `linear` | `spacing:[dx,dy,dz]` | 基準位置から等間隔に `count` 個 |
183
+ | `grid` | `counts:[nx,ny]`, `spacing:[dx,dy]` | +x / +y に nx × ny 個の格子 |
184
+ | `circular` | `radius:R`(任意で `axis`, `start_angle`, `center`) | 円周上に `count` 個(ボルト円) |
185
+
186
+ ### extrude の `fillet_corners`(断面の角丸)
187
+
188
+ 押し出し前に 2D 断面の指定頂点をラウンドにする。L 字の内隅などに使う。
189
+ `corners` は `profile` の頂点インデックス(0 始まり、入力順)のリスト。
190
+
191
+ ```json
192
+ {"id": "body", "type": "extrude", "height": 40,
193
+ "profile": [[0,0],[50,0],[50,6],[6,6],[6,40],[0,40]],
194
+ "fillet_corners": {"corners": [3], "radius": 6}}
195
+ ```
196
+
197
+ ### fillet / chamfer の `edges`
198
+
199
+ `all`(既定)/ `vertical` / `horizontal` / `top` / `bottom`
200
+
201
+ ### shell の `openings`
202
+
203
+ 開口する面の名前リスト。例 `["top"]`。省略すると全閉の中空になる。
204
+ 使える面: `top` / `bottom` / `left` / `right` / `front` / `back`
205
+
206
+ ### 例(円周ボルト穴+面取り)
207
+
208
+ ```json
209
+ {
210
+ "features": [
211
+ {"id": "flange", "type": "cylinder", "radius": 25, "height": 10},
212
+ {"id": "bolts", "type": "hole", "target": "flange", "diameter": 4, "depth": 10,
213
+ "reference": {"feature": "flange", "anchor": "top_face_center"},
214
+ "count": 8, "pattern": {"kind": "circular", "radius": 18}},
215
+ {"id": "edge", "type": "chamfer", "target": "flange", "length": 1, "edges": "top"}
216
+ ]
217
+ }
218
+ ```
219
+
220
+ ---
221
+
222
+ ## MCP サーバ
223
+
224
+ AI エージェントが「IR を渡す → 4 ビュー画像が返る」ループで形状を反復設計できる。
225
+
226
+ ```bash
227
+ cad-tools-mcp # インストール後のコンソールスクリプト
228
+ # または
229
+ python -m cad_tools.mcp_server # モジュールとして起動(stdio)
230
+ ```
231
+
232
+ リポジトリ直下の `.mcp.json` により Claude Code では自動検出される。
233
+
234
+ | ツール | 入力 | 出力 |
235
+ |---|---|---|
236
+ | `validate_cad` | `ir` | 妥当性(`valid` / エラー文)。モデル構築なしの軽量チェック |
237
+ | `render_cad` | `ir`, `save_dir?` | **4 ビュー PNG 画像** + サマリ。`save_dir` 指定で STEP/STL/PNG も保存 |
238
+ | `export_cad` | `ir`, `output_dir`, `basename?` | STEP/STL/PNG をディスクに保存しパスを返す |
239
+
240
+ `render_cad` は画像をインライン返却するため、エージェントが生成形状を直接「見て」
241
+ 確認できる。構築に失敗した場合は例外ではなくエラー文を返すので、IR を自己修正しやすい。
242
+
243
+ ---
244
+
245
+ ## 開発
246
+
247
+ ```bash
248
+ git clone https://github.com/ToPo-ToPo-ToPo/cad-tools
249
+ cd cad-tools
250
+ uv sync # 依存と本パッケージを editable install
251
+
252
+ uv run python test.py # 複合アセンブリ
253
+ uv run python test_ring.py # リング
254
+ uv run python test_schema_extensions.py # IR 拡張機能(全 12 ケース)
255
+
256
+ uv build # wheel / sdist を dist/ に生成
257
+ ```
258
+
259
+ ### プロジェクト構成
260
+
261
+ ```
262
+ cad_tools/ ライブラリ本体(配布パッケージ)
263
+ ├── __init__.py 公開 API
264
+ ├── emitter.py semantic IR → build123d ジオメトリ
265
+ ├── validator.py IR の構造検証
266
+ ├── references.py アンカー(面中心・角・中心)による相対配置
267
+ ├── transforms.py 回転・平行移動
268
+ ├── renderer.py VTK/PyVista による headless マルチビュー描画
269
+ ├── generate.py ファイル入出力の CLI
270
+ └── mcp_server.py MCP サーバ(validate_cad / render_cad / export_cad)
271
+ examples/ サンプル(l_bracket / flange / ...)
272
+ experimental/ 退避した試作レンダラ(Blender / FreeCAD)
273
+ docs/images/ README 用の画像
274
+ ```
275
+
276
+ ---
277
+
278
+ ## レンダラについて
279
+
280
+ default は **VTK / PyVista** ベースの headless 実装(`cad_tools/renderer.py`)。
281
+ 特徴エッジ抽出で CAD 風の輪郭を出し、STL 三角分割のノイズを除く。
282
+ 過去に試した Blender / FreeCAD 版は headless 運用が不安定なため
283
+ `experimental/` に退避している(経緯は `experimental/README.md`)。
284
+
285
+ ---
286
+
287
+ ## ライセンス
288
+
289
+ [MIT](LICENSE)
@@ -0,0 +1,29 @@
1
+ """cad_tools — semantic IR (JSON) から 3D CAD モデルを生成するツール。
2
+
3
+ 主な公開 API:
4
+
5
+ from cad_tools import Build123dEmitter, render_part, render_step, validate_ir
6
+
7
+ ir = {"features": [{"id": "b", "type": "box", "size": [40, 30, 10]}]}
8
+ part = Build123dEmitter(ir).build() # build123d の Solid を返す
9
+ render_part(part, "render.png") # 4 ビュー PNG を書き出す
10
+ """
11
+
12
+ from .emitter import Build123dEmitter, load_ir
13
+ from .validator import validate_ir
14
+ from .renderer import render_part, render_step
15
+ from .references import get_anchor_position
16
+ from .transforms import apply_transform
17
+
18
+ __version__ = "0.1.0"
19
+
20
+ __all__ = [
21
+ "Build123dEmitter",
22
+ "load_ir",
23
+ "validate_ir",
24
+ "render_part",
25
+ "render_step",
26
+ "get_anchor_position",
27
+ "apply_transform",
28
+ "__version__",
29
+ ]