C#ATIA

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

スケッチの点を元にボディを複製したい1

先日のアップデートで、明らかにCustom Featuresの改善に
取り組まれている事をヒシヒシと感じているので、しんどいのですが
再挑戦しようかと考えています。

・・・こちらに嫌味を書いたので後ろめたい思いも有ってです。
Re: Custom Feature API Preview - Feedback Thread - Autodesk Community



Custom Features目的で作り始めた2回転メビウスの帯での再挑戦は
止めておきます。
GitHub - kantoku-code/Fusion360_Two-turn_Mobius_strip: Create a two-turn Möbius strip.
あれはあまりに処理が重すぎます。


そこで、以前からCATIAに比べて不足していると感じている、
ユーザーパターンを取り組みたいと思っています。(結構前から・・・)

かなり以前に小原さんもアイデアに書いています。
スケッチ点に形状をパターンコピーできるようにしてほしい - Autodesk Community


いきなりCustom Featuresのアドインを作るのは、辛すぎるので
機能する部分から作っていくことにします。


この様なデータを用意しました。
f:id:kandennti:20210708190553p:plain

円柱のボディと点を配置したスケッチです。
但しスケッチはボディとはZ方向的には一致していない状態です。
(言葉での表現が難しい)
CATIAのユーザーパターンは、参照したスケッチ上に出来るのではなく
点のXY座標を移動させる様に配置します。
(ここも言葉では難しい)

要はCATIAのユーザーパターンを視野に入れて作りたいのです。
で、スクリプトを作ってみました。

# Fusion360API Python script
import adsk.core, adsk.fusion, adsk.cam, traceback

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

        # msg :str = 'Select Body'
        # selFiltter :str = 'Bodies'
        # sel :adsk.core.Selection = selectEnt(msg ,selFiltter)
        # if not sel: return
        # body :adsk.fusion.BRepBody = sel.entity

        # msg = 'Select Sketch'
        # selFiltter :str = 'Sketches'
        # sel :adsk.core.Selection = selectEnt(msg ,selFiltter)
        # if not sel: return
        # skt :adsk.fusion.Sketch = sel.entity

        execUserPattern(
            root.bRepBodies[0],
            root.sketches[0])

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


# 将来的に body skt は同一コンポーネントの制限を行いたい
def execUserPattern(
    body :adsk.fusion.BRepBody,
    skt :adsk.fusion.Sketch):

    # body cog
    VERYHI = adsk.fusion.CalculationAccuracy.VeryHighCalculationAccuracy
    prop :adsk.fusion.PhysicalProperties = body.getPhysicalProperties(VERYHI)
    bodyCenter :adsk.core.Point3D = prop.centerOfMass

    # get points
    origin :adsk.fusion.SketchPoint = skt.originPoint
    p :adsk.fusion.SketchPoint
    pnts = [p.worldGeometry for p in skt.sketchPoints
        if p != origin]

    # get sketch axis
    _, _, _, zAxis = skt.transform.getAsCoordinateSystem()

    tmpMgr :adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get()
    cloneMat :adsk.core.Matrix3D = adsk.core.Matrix3D.create()
    clones = []
    for p in pnts:
        plane :adsk.core.Plane = adsk.core.Plane.create(
            bodyCenter, zAxis)

        infinite :adsk.core.InfiniteLine3D = adsk.core.InfiniteLine3D.create(
            p, zAxis)

        targetPnt :adsk.core.Point3D = plane.intersectWithLine(infinite)

        vec :adsk.core.Vector3D = bodyCenter.vectorTo(targetPnt)
        cloneMat = adsk.core.Matrix3D.create()
        cloneMat.translation = vec

        clone :adsk.fusion.BRepBody = tmpMgr.copy(body)
        tmpMgr.transform(clone, cloneMat)
        clones.append(clone)

    comp :adsk.fusion.Component = body.parentComponent
    bodies :adsk.fusion.BRepBodies = comp.bRepBodies
    baseFeat : adsk.fusion.BaseFeature = comp.features.baseFeatures.add()
    baseFeat.startEdit()
    for clone in clones:
        bodies.add(clone, baseFeat)
    baseFeat.finishEdit()


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:20210708191359p:plain

スケッチの点上では無く、水平に移動して配置される感じです。
Point3DやPlaneのオブジェクトに射影処理のようなものが無いんですよね。
自分が気が付いていない可能性もあるのですが。
結果的に少し遠回りな処理になっちゃってます。

又、移動させるベクトルをボディの重心上に平面を作ってゴニョゴニョ
処理したのですが、よく考えたら逆ですね。
スケッチ平面上に作らないと、後々の処理に間違いなく悪影響が出そう。

出だしから、直すべき部分が多すぎる。