Fusion360APIで押し出し三昧

## 背景
今年も「Fusion360押し出しコンペ」（詳細は別ブログ記事()にて）が始まるらしいとの
噂が流れてきました。
Fusion360にはスクリプトというマクロみたいな機能があります。
こいつを使えば優勝間違いない！？という訳で挑戦してみました。

## 準備
スクリプトを新規作成する、または既にあるスクリプトを編集する方法は
次の記事を参考ください。公式ヘルプを日本語訳して下さってます。

[Fusion360のスクリプトやアドインを作成する](https://cad.vdlz.xyz/3dCad/Fusion360/Documents/API/CreatingAScriptOrAdd-In.html)

最初から入っているサンプルスクリプトを「編集」して（上書き保存しないよう注意！）
中身を確認する事もできます。
また（英語しかないのが辛いですが）公式ヘルプのスクリプトのページにも
色んなサンプルがあったので、大変参考になりました。
下記リンクは色んな押し出しを実行するやつ。

[Extrude Feature API Sample API Sample](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-CB1A2357-C8CD-474D-921E-992CA3621D04)


## スクリプト内容
スケッチで丸を描いて押し出し、その上に違う丸を書いて押し出し、を繰り返します。
積み上げるピッチ高さ（＝各押し出し高さ）、丸の位置と直径のデータを
CSVファイルにして読み込ませると、自動で押し出しまくります。

色んなサンプルを組み合わせて何とか動くようになりました。
以下、コードを少し区切って説明します。
順番に全てを繋げれば動くはずですが、必要に応じて適時修正お願いします。

```python
import adsk.core, adsk.fusion, traceback, math, io

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        # Get all components in the active design.
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        # Get the root component of the active design
        rootComp = design.rootComponent
        # Get extrude features
        extrudes = rootComp.features.extrudeFeatures

        title = 'Import csv file'
        if not design:
            ui.messageBox('No active Fusion design', title)
            return
        
        dlg = ui.createFileDialog()
        dlg.title = 'Open CSV File'
        dlg.filter = 'Comma Separated Values (*.csv);;All Files (*.*)'
        if dlg.showOpen() != adsk.core.DialogResults.DialogOK :
            return
        filename = dlg.filename
```
ここまで、初期設定とCSVファイルを選択させる画面を実行。
ほぼサンプルスクリプトそのままです。

```python
        # Set 1st-sketch plane
        sketches = rootComp.sketches   
        sketch = sketches.add(rootComp.xZConstructionPlane)
        
        cnt = 0
        # Read the csv file.
        with io.open(filename, 'r', encoding='utf-8-sig') as f:
            line = f.readline()
            data = []
            while line:
                pntStrArr = line.split(',')
                for pntStr in pntStrArr:
                    try:
                        data.append(float(pntStr))
                    except:
                        break
                # csv file line 1 is pitch of extrude
                if cnt == 0:
                    distance = adsk.core.ValueInput.createByReal(data[0]/10)
```
XZ平面にスケッチを書いてY方向に押し出すように設定。
CSVファイルを一行づつ読み込み。
1行目のデータである、積み上げるピッチ高さ（＝各押し出し高さ）を設定。

```python
                # csv file after line 2 are sketch of extrude
                elif cnt == 1:
                    sketchCircles = sketch.sketchCurves.sketchCircles
                    centerPoint = adsk.core.Point3D.create(data[0]/10, data[1]/10, 0)
                    circle = sketchCircles.addByCenterRadius(centerPoint, data[2]/10)
                    prof = sketch.profiles.item(0)
                    extrude = extrudes.addSimple(prof, distance, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
                else:
                    sketch = sketches.addWithoutEdges(extrude.endFaces.item(0) )
                    sketchCircles = sketch.sketchCurves.sketchCircles
                    centerPoint = adsk.core.Point3D.create(data[0]/10, data[1]/10, 0)
                    circle = sketchCircles.addByCenterRadius(centerPoint, data[2]/10)
                    prof = sketch.profiles.item(0)
                    extrude = extrudes.addSimple(prof, distance, adsk.fusion.FeatureOperations.JoinFeatureOperation)
                
                line = f.readline()
                data.clear()
                cnt += 1

        ui.messageBox('Finished')
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
```
CSVファイル2行目以降のデータである、丸の中心位置X,Yと直径を読み取り
スケッチに描いて、設定したピッチで押し出します。
一段目はXY平面にスケッチを描いて、新規ボディで押し出し実行。
二段目以降はボディの平面上にスケッチを描いて、結合で押し出し実行。
CSVファイルの末行まで繰り返します。

## 最後に
エクセルのマクロのように「記録」ボタンがあれば、API解析も捗るのですが
日本語の情報が少なく、分かっていない事も多々あります。
乱雑なコードかもしれませんが、御容赦ください。

正円以外に、楕円(SketchEllipses)も描けそうでした。
四角は直線を組み合わせて描く方法しかググっても見つからず、分かっていません。

本当はXY平面ではなく、任意の平面を選んで開始させたかったのですが
これも分からなかったので、御存知でしたら教えていただけると幸いです。

記事で紹介した以外に、次のQiita記事も参考にさせていただきました。
シリーズで連載されており、丁寧に解説されてたので分かりやすかったです。感謝！

[Fusion 360 を Pythonで動かそう その１　スクリプトの新規作成](https://qiita.com/reisyu/items/84aa97117439e4962bbf)

ちなみに今回、2020年の押し出しコンペでは「スクリプトなど使用不可」と明記されてました。
使うと反則になってしまうのでご注意ください(笑)