C#ATIA

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

Fusion360APIのVecter3Dの外積を確認2

こちらの続きです。
Fusion360APIのVecter3Dの外積を確認1 - C#ATIA
もう一つ違う方法で確認する事にしました。

適当なボディをクリックすると慣性モーメントを利用して、
重心やら軸やらを取得して、そこからマトリックスを作成し
可視化しました。
f:id:kandennti:20211008143450p:plain

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

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

        msg: str = 'Select'
        selFiltter: str = 'Bodies'
        sel: adsk.core.Selection = selectEnt(msg, selFiltter)
        if not sel:
            return

        # BRepBody
        body: adsk.fusion.BRepBody = sel.entity

        # Principal cog Axes
        physicalProp: adsk.fusion.PhysicalProperties = body.getPhysicalProperties()
        cog: adsk.core.Point3D = physicalProp.centerOfMass
        _, xAxis, yAxis, zAxis = physicalProp.getPrincipalAxes()

        mat1: adsk.core.Matrix3D = initMatrix3D_fromXZ(xAxis, zAxis, cog)
        dumpMatrix(root, mat1, 'mat1')

        mat2: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
        mat2.setWithCoordinateSystem(cog, xAxis, yAxis, zAxis)
        dumpMatrix(root, mat2, 'mat2')

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

# 長さ X10Cm Y15Cm Z20Cm
def dumpMatrix(
    comp: adsk.fusion.Component,
    mat: adsk.core.Matrix3D,
    name: str = ''):

    skt: adsk.fusion.Sketch = comp.sketches.add(comp.xYConstructionPlane)
    if name != '':
        skt.name = name

    pnt, vx, vy, vz = mat.getAsCoordinateSystem()
    vy.scaleBy(1.5)
    vz.scaleBy(2)
    for v in [vx, vy, vz]:
        p = pnt.copy()
        p.translateBy(v)
        skt.sketchCurves.sketchLines.addByTwoPoints(
            pnt, p
        )

def initMatrix3D_fromXZ(
    vecX: adsk.core.Vector3D,
    vecZ: adsk.core.Vector3D,
    cog: adsk.core.Point3D = None) -> adsk.core.Matrix3D:

    vecY: adsk.core.Vector3D = vecZ.crossProduct(vecX)
    vecX = vecZ.crossProduct(vecY)

    vecX.normalize()
    vecY.normalize()
    vecZ.normalize()

    if not cog:
        cog = adsk.core.Point3D.create(0, 0, 0)

    mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
    mat.setWithCoordinateSystem(
        cog,
        vecX,
        vecY,
        vecZ
    )

    return mat

def selectEnt(
        msg: str,
        filtterStr: str) -> adsk.core.Selection:

    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        sel = ui.selectEntity(msg, filtterStr)
        return sel
    except:
        return None

こちらを実行すると、
f:id:kandennti:20211008143622p:plain
mat1側は僕が作った関数から作ったマトリックス
mat2側は慣性モーメントから素直に作ったマトリックスです。

mat1側が左手系です。・・・犯人は僕です。


仕方が無いので、関数を修正しました。

def initMatrix3D_fromXZ(
    vecX: adsk.core.Vector3D,
    vecZ: adsk.core.Vector3D,
    cog: adsk.core.Point3D = None) -> adsk.core.Matrix3D:

    vecY: adsk.core.Vector3D = vecZ.crossProduct(vecX)
    vecX = vecZ.crossProduct(vecY)
    if vecX.crossProduct(vecY).dotProduct(vecZ) < 0:
        vecX.scaleBy(-1)

    vecX.normalize()
    vecY.normalize()
    vecZ.normalize()

    if not cog:
        cog = adsk.core.Point3D.create(0, 0, 0)

    mat: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
    mat.setWithCoordinateSystem(
        cog,
        vecX,
        vecY,
        vecZ
    )

    return mat

内積を利用して、1軸(X軸)だけ逆にしました。
恐らくこれでOKでしょう。
本題に戻れそう。