C#ATIA

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

回転プロファイルを考える2

こちらの続きです。
回転プロファイルを考える1 - C#ATIA
年末から忙しく、無理やり時間を確保しました。

チョロチョロ試していたのですが、行列の演算が上手く行かず・・・
諦めCADに仕事をさせる事にしました。

前回の最後のアルゴリズムを進めているのですが、それも
上手く行きません。


テストとして、こんなボディで青い面の軸を元に回転プロファイルを
処理させてます。

元のボディから求めた回転ボディをブーリアンの差を行う事は
何とか出来ているようなのですが、どうしても無限ループと
なってしまう為、結果となるボディの体積を10回出力させると・・

 46.363600447107814
 0.1327936100126632
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732
 0.13274270462853732

3回目までは体積が減っているので順調なのですが、
それ以降は体積が減っていません。無限ループの原因は
分かりましたが、何故?

ん~最大径の求め方が悪いかな・・・。

TriadCommandInput

TriadCommandInputについては昨年もチラッと記載しましたが
こちらの質問に答えようと思い作ったサンプルです。
How to use Triad for for simple user-controlled Scaling - Autodesk Community

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []

CMD_INFO = {
    'id': 'kantoku_test',
    'name': 'test',
    'tooltip': 'test'
}

_triadIpt: adsk.core.TriadCommandInput = None

class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandCreatedEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)
        try:
            global _handlers
            cmd: adsk.core.Command = adsk.core.Command.cast(args.command)
            inputs: adsk.core.CommandInputs = cmd.commandInputs

            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onExecute = MyExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)

            global _triadIpt
            _triadIpt = inputs.addTriadCommandInput(
                '_triadIptId',
                adsk.core.Matrix3D.create()
            )
            _triadIpt.setScaleVisibility(True)

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


class MyExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        global _triadIpt
        dump_matrix3D(_triadIpt.transform)


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: adsk.core.CommandEventArgs):
        adsk.terminate()


def dump_matrix3D(mat: adsk.core.Matrix3D):
    pnt, xVec, yVec, zVec = mat.getAsCoordinateSystem()
    msglist = [
        '*****',
        f'origin:{pnt.asArray()}',
        f'x vecter:{xVec.asArray()}',
        f'y vecter:{yVec.asArray()}',
        f'z vecter:{zVec.asArray()}',
    ]

    global _app
    _app.log('\n'.join(msglist))


def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            CMD_INFO['id']
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                CMD_INFO['id'],
                CMD_INFO['name'],
                CMD_INFO['tooltip']
            )

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

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

え~質問が複数あるような気がする上、意味がわからないのですが、
transformとダイアログ上の値が違うって事じゃないのかな・・・。

GUIのボディの移動等と同じだと思うんだけど、これは確かに
使いにくいと思う。

ダウンタイマー

業務が忙しく、まとまった時間の確保が出来ず宿題に
取り掛かれないです・・。

で、この曲の歌い手さんは匿名になっていますが、
「ダウンタイマー」レトベア(unknown Vo:O2) ××Official Video×× - YouTube
声を聴いても、活動休止中の人だと分かるのですが、
だから匿名なのかな?

2023年の目標

あけましておめでとうございます。
毎年ながらマイペースで頑張りますので、よろしくお願いします。

例年ですと、ブログも仕事始めからにしているのですが、
生憎、始まってしまうと忙しそうなので・・・。

・Autodesk App Storeで何かしら公開する。
  githubで幾ら公開しても、やはり説得力の違いを痛感しています。
  取りあえずはノウハウ構築のためにFreeで何とか公開まで行きたいところ。

・やりかかっている物と完成させる。
  作戦だけでも、やりかかっているものが沢山・・・
  ・回転プロファイルは最優先
   回転プロファイルを考える1 - C#ATIA

  ・"ぶんくろ" の改修。フレームワークが古い事ので大改修したい。
   変形の調査と若干の高速化も。
   解決済み: Re: 大規模アセンブリを動かす方法の一つとして - 3ページ - Autodesk Community

  ・依存関係。かなり行き詰っているのが本音ですが、何とかしたい。
   要素の依存関係5 - C#ATIA

  ・曲線長さと同期させるパラメータ。仕組み自体は一応完成している
   はず。あとはUIだけなんですけどね。
   曲線の長さと同期させる6 - C#ATIA

・three.js を試したい。
  Fusion360と連動する何かを試したい。

Blenderを試したい。
  今までそんな事考えたことも無かったのですが、
  先月のフォーラムのチャレンジに参加してレンダリング
  少しだけ興味が沸きました。でも一番後回しです。
  インストールする事すら疑わしい・・・。


年末には答え合わせするつもりもないです。
恐らく、半分も達成していない予感しかしないので。

2022年を振り返る

終盤は仕事が忙しくかなり中途半端な状態なのですが、
今年の更新はしないだろうと思います。

今年は色々と不安な一年でしたが、昨年の最後を見返すと
”去年よりマシか” と思いましたね。人間、前向きが良さそうです。


〇CATIA
CATIAに関しては、今年はこれが一番です。
CATIA V5のマクロを残すのは難しい - C#ATIA

来年は他に頼るところが無いので、何かあればもう少し
取り組みたいなとは思っています。


Fusion360
やり残した事だらけですが、比較的成果物は、
こちら
GitHub - kantoku-code/Fusion360_GOKOTAI: 短刀のような小さな機能を集めたFusion360用アドインです。
と、こちら
GitHub - kantoku-code/Fusion360_NEKONOTE: A little help with show/hide
です。
来年も引き続き、APIは頑張ろう。



あと、今年もAutodesk Expert Elite Award 2022を頂きました。

こうして、他人に評価して頂けることは非常にありがたいです。

では、皆様良いお年を!!

回転プロファイルを考える1

連日、チョロチョロ進めているのは、未だ完成に辿り着けないでいますし、
恐らく年内は無理かな・・・。

取りあえず、作戦です。
最初は、軸を通過する断面を作って、断面積が最大になる角度を
探してグルっと回転させれば良いのかな? と思っていたのですが
全然ダメな事に気が付きました。

例えば、こんな形状で赤い面を軸とした場合は、青い平面ぐらいが
断面積で最大になると思います。

実際に断面のプロファイルを作り、回転させたのが緑の面なのですが
黄矢印部分が不足しているのは明らかです。

あぁ、安易に考えたらダメなのね。


次に思い付いたのが、軸に沿って断面を複数作り
各断面の軸からの最大位置を調べ、一つの断面を作り出す方法です。

やるのであれば、もっと大量の平面が必要でしょう。
しかし、
・どのくらいの間隔で平面を作る事が適切か?
・得られた最大位置は結果的に点群となり、直線や曲線を
 どの様に判断し作れば良いのか?
と言う疑問もあり、取り組むこと無く断念しました。


結局、最初に考えた通り軸を通過する断面を利用するしか
思い付きませんでした。つまり、この様な感じで多くの角度で
大量の断面を取得し、断面自体を合成すれば形になるような
気がしています。

もう、ボディ見えないですね・・・。

但し、この方法で問題となりそうなのは、
・何度毎に断面を取得すれば良いのか?(5度?1度?0.1度?)
 → 細かければ精度が上がる反面、処理時間がかかる。
です。そもそも "数撃ちゃ当たる" 的な方法でセンス無いですようね。

そこで、断面を取得する角度を効率良くする方法を考えました。
まず、軸から最大距離となる位置を求め、その位置と軸が
通過する平面の断面を取得します。

”軸から最大距離となる位置” は、こちらの方法です。
軸に対して最大距離になるポイントを取得する - C#ATIA

取得した断面を回転させます。

これです。
サーフェスをプロファイルとした回転を作る - C#ATIA

元の形状を、回転させたボディで引きます。

この残った形状を利用し、再度軸から最大位置となる角度を
求め、断面を取得し・・・を、体積0になるまで繰り返す事で
比較的効率良く、回転プロファイルが作れるのでは?
と思っています。

但し、元の形状を回転させたボディで引く処理(ブーリアン)が
エラーにならないのか?が、やってみないと分かりません。

サーフェスをプロファイルとした回転を作る

悩みました。
こんな感じのデータで、サーフェスをプロファイルとして
Z軸を軸として回転のボディ(ソリッド)を作ります。

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import math

def run(context):
    ui = adsk.core.UserInterface.cast(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

        face: adsk.fusion.BRepFace = root.bRepBodies[0].faces[0]


        revolveFeats: adsk.fusion.RevolveFeatures = root.features.revolveFeatures
        revolveIpt: adsk.fusion.RevolveFeatureInput = revolveFeats.createInput(
            face,
            root.zConstructionAxis,
            adsk.fusion.FeatureOperations.NewBodyFeatureOperation
        )

        revolveIpt.setAngleExtent(
            False,
            adsk.core.ValueInput.createByReal(math.pi*2)
        )

        revolveFeats.add(revolveIpt)


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

・プロファイルはサーフェスそのもので大丈夫。
・軸は実在するものにする。

上手く行かなかったのは、軸だ・・・。


追記。
Fusion360は軸は線などの要素では無く、円筒や円錐等の中心軸が
直線になるものの場合は、回転の軸として指定できるみたい。
凄いなこれ。(API的にはちょっと迷惑・・・)