C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

ボディを回転移動させる

こちらが上手く行かないので、色々模索中です。
回転プロファイルを考える2 - C#ATIA

年末に諦めた処理を改めて見直す事にしました。

左図のような状態のボディを、軸を中心として垂直に回転させた
ボディを作り出したいのですが、ちょっとだけ条件があります。

単に回転コマンドで処理するのは簡単なのですが、処理を早めたいので
TemporaryBRepManagerを使って行いたい。


TemporaryBRepManager.transformメソッドで"回転"を"変換"で
行えば良いので、回転させるためのMatrix3Dを求める必要があります。
Fusion 360 Help

回転の為のMatrix3D.setToRotateToメソッドがあるので、これを
利用します。
Fusion 360 Help
二つのVector3Dが必要ですね。
setToRotationメソッドもありますが、2つのベクトルの角度を測定する際
どうしても近い方の角度を取得してしまい、場合によっては意図した方向の
逆の場合もあったため、諦めました。(上手く行けば楽だったのに・・・)
Fusion 360 Help

最初は気が付かなかったのですが、setToRotateToメソッドは常に原点中心で
回転するマトリックスになります。考えてみれば、ベクトルには位置情報が
無いため当然ですね。

最初の画像の状態の場合、原点と回転軸が一致しないため当然不都合です。

その為、
・軸上の位置から原点に移動
・回転
・元の位置に移動
を行う必要があります・・よね?(以前、何処かの数学のサイトで観た記憶があるのですが)


テストコードの為、全く使い道が無いのですがこんな感じです。

# Fusion360API Python script

import traceback
import adsk
import adsk.core as core
import adsk.fusion as fusion

def run(context):
    ui = core.UserInterface.cast(None)
    try:
        app: core.Application = core.Application.get()
        ui = app.userInterface
        des: fusion.Design = app.activeProduct
        root: fusion.Component = des.rootComponent

        # 各種データの取得
        body: fusion.BRepBody = root.bRepBodies[0]
        axis: fusion.ConstructionAxis = root.constructionAxes[0]
        point: core.Point3D = root.constructionPoints[0].geometry

        # クローン作成
        tmpMgr: fusion.TemporaryBRepManager = fusion.TemporaryBRepManager.get()
        clone: fusion.BRepBody = tmpMgr.copy(body)

        # 軸上の点から原点へのマトリックス
        vecToOrigin: core.Vector3D = point.vectorTo(root.originConstructionPoint.geometry)
        matToOrigin: core.Matrix3D = core.Matrix3D.create()
        matToOrigin.translation = vecToOrigin

        # 回転マトリックス
        cloneFace: fusion.BRepFace = clone.faces[0]
        normal: core.Vector3D = cloneFace.geometry.normal
        vecRotate: core.Vector3D = normal.crossProduct(axis.geometry.direction)
        matRotate: core.Matrix3D = core.Matrix3D.create()
        matRotate.setToRotateTo(
            vecRotate,
            core.Vector3D.create(0,0,1),
        )

        # 原点から軸上の点へのマトリックス
        vecFromOrigin: core.Vector3D = root.originConstructionPoint.geometry.vectorTo(point)
        matFromOrigin: core.Matrix3D = core.Matrix3D.create()
        matFromOrigin.translation = vecFromOrigin

        # 変換
        tmpMgr.transform(clone, matToOrigin)
        tmpMgr.transform(clone, matRotate)
        tmpMgr.transform(clone, matFromOrigin)

        # NG
        # matToOrigin.transformBy(matRotate)
        # matToOrigin.transformBy(matFromOrigin)

        # ダンプ
        dump_bodies([clone])


    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def dump_bodies(bodyLst: list):
    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct
    root: fusion.Component = des.rootComponent

    baseFeat: fusion.BaseFeature = None
    if des.designType == fusion.DesignTypes.ParametricDesignType:
        baseFeat = root.features.baseFeatures.add()

    bodies: fusion.BRepBodies = root.bRepBodies
    if baseFeat:
        try:
            baseFeat.startEdit()
            [bodies.add(body, baseFeat) for body in bodyLst]
        except:
            pass
        finally:
            baseFeat.finishEdit()
    else:
        [bodies.add(body) for body in bodyLst]

説明書きの通り、3個のマトリックスを作成してボディを3回変換しています。
年末に上手く行かなかった原因の一つは、コメント化している部分のやり方です。

        # NG
        # matToOrigin.transformBy(matRotate)
        # matToOrigin.transformBy(matFromOrigin)

3個のマトリックスを先に変換してしまい、ボディの変換自体は1回に
してしまっていた事が原因でした。

もう一つの原因が、Matrix3D.translationプロパティです。
"transformBy”はメソッドで破壊的です。 しかしtranslationは
プロパティなので扱いの違いに気が付きませんでした。

と、これが解決しても、完成には程遠い。(正直、諦めたい)