Fusion 360 を Pythonで動かそう その11　パスに沿った点がAPIにないので代替案を考えた

#はじめに
Fusion 360 に [**パスに沿った点**](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-ACF6CB62-2977-46EB-A72D-803B26C117AD) というコマンドがあります。これを Fusion 360 API で実現しようと紆余曲折した記録です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/6cda6282-9a29-2e22-48d0-cc05f7724eb8.png)

#リファレンスマニュアルを調べてみる
Fusion 360 API で構築の点を作成する方法の指定は [**ConstructionPointInput Object**](http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-b3ffae9a-d7d7-48ee-bd66-b1138536767f) を使います。リファレンスマニュアルのメソッドの中にある **setBy** で始まるものが UI での各コマンドに対応しているのでこの中から「パスに沿った点」を探します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/c2e83c6b-992c-4a7a-dc80-2729ef56a0b5.png)
[**setByCenter**](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-c2249d0d-65fe-4755-a1b4-b12ccfe5cdb2) > [円/球/トーラスの中心点](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-064F72C2-64DC-4BA0-B4B9-0F8335B3D9C8)
[**setByEdgePlane**](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-b5124c86-74ed-46bb-a47c-fd32f01b23a4) > [エッジおよび平面にある点](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-BF8B03C7-6E09-44E3-A641-E310E3E53FF1)
[**setByPoint**](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-2f8b1097-3882-4100-a9dd-e2524b72ce05) > [頂点の点](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-0513EE5B-3A28-425E-AE34-E9E0BFF7D8D1)
[**setByThreePlanes**](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-7e942510-c141-46ea-8112-7ea44ccb9265) > [3つの平面が通過する点](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-541E71D4-55A4-434C-983B-EA19D95A0FB4)
[**setByTwoEdges**](https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-1f1e9330-5e25-4641-9550-a314851afeaa) > [2つのエッジの通過点](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-C0483AF3-AD6E-48C5-8BA7-0443C8AB4D65)
あれ・・・？？？パスに沿った線に対応するメソッドがない？？？

#「パスに沿った点」はないけど「パスに沿った平面」はあった！
パスに沿った点によく似たコマンドで [**パスに沿った平面**](https://help.autodesk.com/view/NINVFUS/JPN/?guid=GUID-4ED5A7DB-8EAE-466E-A860-8A8968BDD3F8) というのがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/c5a14f98-73cf-368e-2579-d078f50826f2.png)
なぜかこちらはちゃんと [**ConstructionPlaneInput.setByDistanceOnPath メソッド**](http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-46dd5f0a-e384-4707-b431-37c0e596f328)があるようです。平面は有るのに点は無いのはなぜだー!といっても無いものは無いので開き直って代替案を考えることにしました。

パスに沿った平面をつくる > その平面とパスとの交点をつくる という手順を Fusion 360 API でやってみます

#手順
スケッチ内の曲線状に点を作成する手順です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/095fe91d-34f5-3db7-e52b-5f79b712ee7a.png)

##最初と最後のおまじないから途中まで
```Python
import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = app.activeProduct

        # Get the root component of the active design.
        rootComp = design.rootComponent

        # 
        # ここにコードを追加していく 
        # 
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
```

##スケッチの中のスプラインを取得する
スケッチ1のなかのスプラインを取得して crvPath に代入しています

```Python
        # スケッチの中のスケッチ1を取得 > スケッチ1の中のスプラインカーブを取得
        sketch1 = rootComp.sketches.item(0)
        crvPath = sketch1.sketchCurves.sketchFittedSplines.item(0)
```

##パスに沿った平面を作成する
setByDistanceOnPath を使ってパスに沿った面を作成します。始点を0、終点を1として0～1の値を指定するのですが、直接数値を入力するのではなく、[**ValueInput**](http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-bdeb52e0-a6af-4909-93e8-3b13acd0e39c) オブジェクトで指定する必要があります。

```Python
        # constructionPlanes オブジェクトを取得
        planes = rootComp.constructionPlanes
        
        # ConstructionPlaneInput オブジェクトを取得
        planeInput = planes.createInput()

        # パスに沿った平面を作成
        distance = adsk.core.ValueInput.createByReal(0.4)
        planeInput.setByDistanceOnPath(crvPath, distance)
        plane = planes.add(planeInput)
```

##平面とパスの交点を作る
Fusion 360 には平面とパスとの交点を作るコマンドはありませんが、[**Sketch.intersectWithSketchPlane メソッド**](http://help.autodesk.com/view/fusion360/ENU/?guid=GUID-1EB28A55-7250-4694-A253-582B395AB234) でスケッチ平面と曲線との交点を作ることができます。指定するパスは曲線一本だとしても配列にしないといけないようです。ここでは `entities` という配列に `crvPath` を追加して intersectWithSketchPlane  メソッドの引数に入れています。

```Python
        # 新しいスケッチを追加
        sketch2 = rootComp.sketches.add(plane)

        # スケッチ平面とパスとの交点を作成
        entities = []
        entities.append(crvPath)
        skPoints = sketch2.intersectWithSketchPlane(entities)
```
このスクリプトを実行するとこうなります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433170/2b671388-4969-7620-1fa2-546af1bd76fe.png)

#まとめ
できたのはいいけど手数が多くて結構面倒でしたね。 pointInput.setByDistanceOnPath はリファレンスに載っていないだけで実は使えるのではと淡い期待を抱いてこんなコードを描いて実行してみた・・・けどエラーが出てしまってだめでした！

```Python
        # Get construction points
        points = rootComp.constructionPoints
        
        # Create construction point input
        pointInput = points.createInput()

        # Add construction point by distance on path
        distance = adsk.core.ValueInput.createByReal(0.4)
        pointInput.setByDistanceOnPath(crvPath, distance)
        point = points.add(pointInput)
```

早く API に実装されてほしいー！