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.
- cad_tools-0.1.0/.gitignore +27 -0
- cad_tools-0.1.0/LICENSE +21 -0
- cad_tools-0.1.0/PKG-INFO +315 -0
- cad_tools-0.1.0/README.md +289 -0
- cad_tools-0.1.0/cad_tools/__init__.py +29 -0
- cad_tools-0.1.0/cad_tools/emitter.py +736 -0
- cad_tools-0.1.0/cad_tools/generate.py +41 -0
- cad_tools-0.1.0/cad_tools/mcp_server.py +204 -0
- cad_tools-0.1.0/cad_tools/references.py +123 -0
- cad_tools-0.1.0/cad_tools/renderer.py +213 -0
- cad_tools-0.1.0/cad_tools/transforms.py +43 -0
- cad_tools-0.1.0/cad_tools/validator.py +219 -0
- cad_tools-0.1.0/examples/__init__.py +0 -0
- cad_tools-0.1.0/examples/__main__.py +31 -0
- cad_tools-0.1.0/examples/_common.py +45 -0
- cad_tools-0.1.0/examples/angle_bracket.py +58 -0
- cad_tools-0.1.0/examples/ball_stud.py +28 -0
- cad_tools-0.1.0/examples/enclosure.py +41 -0
- cad_tools-0.1.0/examples/flange.py +41 -0
- cad_tools-0.1.0/examples/funnel.py +27 -0
- cad_tools-0.1.0/examples/hex_standoff.py +27 -0
- cad_tools-0.1.0/examples/l_bracket.py +44 -0
- cad_tools-0.1.0/examples/o_ring.py +22 -0
- cad_tools-0.1.0/experimental/README.md +23 -0
- cad_tools-0.1.0/pyproject.toml +50 -0
|
@@ -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/
|
cad_tools-0.1.0/LICENSE
ADDED
|
@@ -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.
|
cad_tools-0.1.0/PKG-INFO
ADDED
|
@@ -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
|
+
[](https://www.python.org/)
|
|
30
|
+
[](LICENSE)
|
|
31
|
+
[](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
|
+

|
|
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
|
+
[](https://www.python.org/)
|
|
4
|
+
[](LICENSE)
|
|
5
|
+
[](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
|
+

|
|
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
|
+
]
|