Fusion360 でフィボナッチ数列に従う二股分岐ツリーを自動生成するには、Python スクリプト(Add-in)を使うのが手早く確実です。以下の手順で進めてみてください。
1. ユーザーパラメータを登録する
- 「修正」→「パラメータ」を開く
- 新規パラメータを追加
- phi:
(1+√5)/2
- goldenAngle:
360*(1 - 1/phi)
(約137.5°) - scaleFactor:
1/phi
(約0.618) - initialLength:枝長(例:100 mm)
- maxDepth:分岐深さ(ツリーの階層数。出口数をF(n)に合わせたい場合は n)
- phi:
これでスクリプトから design.userParameters
経由で呼び出せます。
2. スクリプトを作成する
- メニューから「ツール」→「スクリプトとアドイン」を開く
- 「Python」タブ → +Create で新規スクリプトを作成
- 生成されたスクリプトフォルダ内の
run
関数に、以下のコードを貼り付け
import adsk.core, adsk.fusion, traceback, math
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
design = adsk.fusion.Design.cast(app.activeProduct)
root = design.rootComponent
# パラメータ取得
params = design.userParameters
phi = params.itemByName('phi').value
goldenAngle = params.itemByName('goldenAngle').value
scaleFactor = params.itemByName('scaleFactor').value
initLen = params.itemByName('initialLength').value
maxDepth = int(params.itemByName('maxDepth').value)
# 再帰で分岐を作成
def createBranch(startPt, dirVec, length, depth):
if depth == 0:
return
# 終点
endPt = adsk.core.Point3D.create(
startPt.x + dirVec.x*length,
startPt.y + dirVec.y*length,
startPt.z + dirVec.z*length
)
# スケッチ&線分を追加
sketch = root.sketches.add(root.xYConstructionPlane)
sketch.sketchCurves.sketchLines.addByTwoPoints(startPt, endPt)
# (必要ならここでパイプ用の円断面スケッチ→Sweepを追加)
# 左右2方向に再帰
for angle in ( goldenAngle, -goldenAngle ):
mat = adsk.core.Matrix3D.create()
mat.setToRotation(math.radians(angle),
adsk.core.Vector3D.create(0,0,1),
startPt)
newDir = dirVec.copy(); newDir.transformBy(mat)
createBranch(endPt, newDir, length*scaleFactor, depth-1)
# 初回呼び出し:原点から +Y 方向
createBranch(adsk.core.Point3D.create(0,0,0),
adsk.core.Vector3D.create(0,1,0),
initLen, maxDepth)
except:
if ui:
ui.messageBox(f'Error:\n{traceback.format_exc()}')
- スクリプトを保存し、リストから選んで「実行」
3. モデルを肉付けして仕上げる
- スケッチされた枝線を選び、円断面スケッチを作成
- 「作成」→「スイープ」で枝線に沿ってパイプ化
- すべてのボディを結合(「結合」コマンド)
- STEP や STL でエクスポート
ポイント
- maxDepth を変えるだけで F(2)=2 枝〜F(377)=377 枝まで自動生成できます。
- goldenAngle+scaleFactor で自然界の黄金比的配置を再現。
- スクリプト内の「パイプ化処理」は用途に合わせて円径や断面形状をカスタマイズしてください。
不明点や細かな調整が必要でしたら、またお知らせください!
1. ユーザーパラメータを登録するをもっと詳しく教えてください
Fusion360 でユーザーパラメータを登録する手順を、より細かく説明します。
1. 「パラメータ」ダイアログを開く
- Fusion360 の上部メニューから 「修正」→「パラメータ」 を選択
- すると「ユーザーパラメータ/モデルパラメータ」の一覧が表示されるウィンドウがポップアップします
2. ユーザーパラメータの追加方法
- ウィンドウ左上の 「+ ユーザーパラメータの追加」 ボタンをクリック
- 新しい行が追加されるので、以下項目を順に入力します:
項目 説明例 名前 phi
単位 (通常は「なし」か「自動検出」) 式(数式) (1+sqrt(5))/2
コメント 「黄金比 φ」など、意味がわかる補足を入れておくと親切です - 右側のチェックマーク(
)を押して確定
3. 他のパラメータも同様に追加
以下の5つを、同じ手順で登録してください。
- phi
- 単位:なし
- 式:
(1+sqrt(5))/2
- コメント:黄金比 φ
- goldenAngle
- 単位:°(度)
- 式:
360*(1 - 1/phi)
- コメント:黄金角 ≈137.5°
- scaleFactor
- 単位:なし
- 式:
1/phi
- コメント:枝長縮小率 ≈0.618
- initialLength
- 単位:mm(ご希望の長さ単位)
- 式:
100 mm
(例として初期枝長 100 mm を設定) - コメント:初期の枝長
- maxDepth
- 単位:なし
- 式:
6
(深さ6階層で最終枝数が F(6)=8 本になります。F(n) 本にしたい場合は n を入力) - コメント:分岐の最大階層数
4. 登録後の確認・編集
- パラメータ一覧に名前・値・式が反映されていれば登録完了です。
- 数式に誤りがあると赤字でエラーが表示されますので、正しい形になるよう修正してください。
- 既存のユーザーパラメータをダブルクリックすると、いつでも式やコメントを変更できます。
5. スクリプトからの参照
登録したパラメータは Python スクリプト内で以下のように取得できます。
params = design.userParameters
phi = params.itemByName('phi').value
goldenAng = params.itemByName('goldenAngle').value
scaleFactor = params.itemByName('scaleFactor').value
initLen = params.itemByName('initialLength').value
maxDepth = int(params.itemByName('maxDepth').value)
以上の手順で、Fusion360 のモデルパラメータとしてフィボナッチ分岐に必要な定数や設定値を一元管理できます。
この状態でスクリプトを実行すれば、パラメータを変えるだけでモデルを簡単に再生成できますので、ぜひお試しください。
パラメータの式にphiをいれるとエラーになるので、1.618の数値をいれました
Fusion360 のパラメータ同士を参照する際は、以下のポイントに気をつけるとエラーなく設定できます。
1. 先に phi
を正しく登録する
- 単位:なし
- 名前:
phi
(※大文字・小文字を正確に) - 式:
(1+sqrt(5))/2
- 確定ボタンを押して登録を完了させる
Tip:―式入力欄の右端にある「パラメータ挿入ボタン(fx アイコン)」を使うと、登録済みの
phi
を確実に参照できます。
2. goldenAngle
では単位を「度 (deg)」に
- 「ユーザーパラメータの追加」ボタン
- 名前:
goldenAngle
- 単位:
deg
(プルダウンで「度」を選択) - 式:
360 deg * (1 - 1/phi)
- 単位を明示的に書くことで Fusion が「360 度 × (… )」と解釈します
- 式中の
phi
は先ほど登録した名前を挿入してください
で確定
なぜ「deg」を入れるのか?
- Fusion360 は 式の単位が食い違う とエラーを出します。
phi
は「無次元」、360 に「deg」を付けないと「deg」と「無次元」を掛け合わせた結果の単位が分からずエラーになります。
3. 他のパラメータも同様に登録
scaleFactor
(単位:なし、式:1/phi
)initialLength
(単位:mm、式:例100 mm
)maxDepth
(単位:なし、式:例6
)
これで、ほかの式でもすべて phi
を参照できるようになります。
動作確認
- パラメータ一覧で値が自動計算されているかチェック
- 式にエラー(赤文字)が出ていなければ OK
以上を試していただければ、phi
を固定値に置き換えることなく、パラメトリックにモデルを作り込めるようになります。ご参考になれば幸いです!
B. Python APIで一括Sweep+Combineスクリプト化ですすめます。詳しく教えてください
以下のサンプルでは、先にご自身で「線だけ」のスケッチを用意した後に、それらを一括でパイプ化→結合する流れを Python API で自動化します。
1. 前提
- ツリー状に枝線(SketchLine)がすべて rootComponent.sketches のいずれかのスケッチ上に描かれていること
- ユーザーパラメータとして
branchDiameter
(枝の直径, mm 単位)が登録されていること
2. 大まかな流れ
- 全スケッチから線分を収集
- 各線分の始点に「法線平面」を作成
- その平面上で円断面スケッチを描き、Profile を取得
- Profile+線分を SweepFeatures でパイプ化
- 生成されたすべてのボディを CombineFeatures で一体化
3. 完全サンプルコード
import adsk.core, adsk.fusion, traceback, math
def run(context):
ui = None
try:
# アプリケーション・UI・デザイン取得
app = adsk.core.Application.get()
ui = app.userInterface
design = adsk.fusion.Design.cast(app.activeProduct)
root = design.rootComponent
feats = root.features
# ユーザーパラメータ取得
params = design.userParameters
branchDiameter = params.itemByName('branchDiameter').value # mm
radius = branchDiameter / 2.0
# 全スケッチ線を集める
sketchLines = []
for sk in root.sketches:
for ln in sk.sketchCurves.sketchLines:
sketchLines.append(ln)
# Pipe化用のPlane/Sketch作成 API
def makeProfileSketch(line):
# 1) 分岐線の始点と方向ベクトル
startPt = line.startSketchPoint.worldGeometry
endPt = line.endSketchPoint.worldGeometry
dirVec = endPt.vectorTo(startPt)
dirVec.normalize()
# 2) 始点を通り dirVec を法線とする ConstructionPlane を追加
planes = root.constructionPlanes
planeInput = planes.createInput()
planeInput.setByAngle(
adsk.core.ValueInput.createByReal(math.pi/2), # 90°
adsk.core.Plane.create(adsk.core.Point3D.create(0,0,0),
adsk.core.Vector3D.create(0,0,1))
)
# → 一旦 XY 平面から 90°回転してから、後で移動・回転する方法よりも
# direct createByPointNormal が使える場合はそちらを。
plane = planes.add(adsk.core.ConstructionPlaneInput.cast(planeInput)) # 調整要
# 3) Plane を移動/回転して startPt + dirVec 法線に合わせる
# (ここは API のバージョンに合わせて createByPointNormal を使ってください)
# 4) Sketch を作成し、円描画
sk = root.sketches.add(plane)
sk.isComputeDeferred = True
sk.sketchCurves.sketchCircles.addByCenterRadius(
startPt, radius
)
sk.isComputeDeferred = False
return sk.profiles.item(0)
# 4) 各線分ごとに Sweep
sweepFeats = feats.sweepFeatures
sweptBodies = []
for line in sketchLines:
prof = makeProfileSketch(line)
path = adsk.core.ObjectCollection.create()
path.add(line)
sweepInput = sweepFeats.createInput(
prof,
path,
adsk.fusion.FeatureOperations.NewBodyFeatureOperation
)
sweepInput.orientation = adsk.fusion.SweepOrientationTypes.PathOrientationType
sweep = sweepFeats.add(sweepInput)
sweptBodies.append(sweep.bodies.item(0))
# 5) すべてのボディを結合
if sweptBodies:
mainBody = sweptBodies[0]
others = adsk.core.ObjectCollection.create()
for b in sweptBodies[1:]:
others.add(b)
combineFeats = feats.combineFeatures
combineInput = combineFeats.createInput(
mainBody, others
)
combineInput.operation = adsk.fusion.FeatureOperations.JoinFeatureOperation
combineFeats.add(combineInput)
except:
if ui:
ui.messageBox('Error:\n{}'.format(traceback.format_exc()))
ポイント解説
- ConstructionPlane の作り方は API バージョンにより数種あるので、
root.constructionPlanes.addByPointNormal( startPt, dirVec )
が使えるならそちらを推奨します。 - 各
sweepFeatures
の出力ボディをリストに保持し、最後に一括でcombineFeatures
しています。 - エラーが出やすい箇所は「Plane の定義」「Profile のスケッチ面の向き」なので、都度
messageBox
やログで確認してください。
このサンプルをベースに、
- Plane の作成ロジックをご自身の環境に合わせて(諸バージョン差対応)書き換え
- Profile を矩形にしたり、スクリプト内で ConstructionPlane を削除してクリーンアップ
- maxDepth を超えた深さ判定で線をフィルタリング
などを追加・最適化していただくと、12 種類のモデルをワンクリックで自動生成→一体化できるようになります。
ぜひお試しください。