C#ATIA

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

pythonのプロパティ

pythonの自作クラスでプロパティをほぼ使ったことが無かったのですが、
調べてみると結構面倒・・・。
C#は度重なるバージョンアップで、かなり簡素に書けるのに。

清楚に書く方法が無いものか探したところ、こちらを発見しました。
Python におけるプロパティ定義を短く書く - Qiita
使い方を含めて理解しきれていないのですが、確かに清楚になります。

但し、インテリセンスが効かなかったり、pyrightで引っかかったり(無視してる)
するので悩んでます。全て読み書き可のプロパティが欲しいだけなんだけどなぁ

奇妙な歯車3

こちらの続きです。
奇妙な歯車2 - C#ATIA

昨日の後半の失速感でモチベーションダダ下がりだったのですが、
CustomGraphicsの表示方法を変更したところ、処理速度が劇的に改善しました。
CustomGraphicsの処理は結構重いんだな。(以前にもそんな経験してたなぁ・・・)

動作的には満足しているのですが、色々なチェックを省いている為、
モチベーションが維持できているうちに、地味な作業を済ませて
公開まで持ち込みたい。

奇妙な歯車2

こちらの続きです。
奇妙な歯車1 - C#ATIA

結局、チマチマ回転させる方法しか思いつかない為、そうしてみました。
半端じゃなくコードが汚いのですが、動作確認出来る程度まで行きました。

f:id:kandennti:20201111154733p:plain
赤矢印:ベースサークル
緑矢印:ターゲットサークル
青矢印:ベース形状

赤・緑がピッチ円を想定していて、比率は1:2です。
ベース形状が2回転して、相手側の形状を作ります。

色々試しましたが、ベースサークルを2度単位で回転させました。
後半の失速感が半端じゃない。
35秒ほどですが、自宅だと何分かかるのだろう?恐ろしい。

もうちょっと何とかならないのかなぁ・・・。

パラメータ範囲外の点(座標)を取得

タイトルがあやふやなのですが、要はこちらの内容に関連してます。
Quantum effect - getParameterAtLength() - Autodesk Community

f:id:kandennti:20201111111638p:plain
黒い線が3D的な1本の曲線として、赤矢印が始点で青矢印が終点とします。
曲線上に点を描いて、その位置は3Dな座標値として知ることは出来ますが、
点と曲線との相対的な位置関係はパラメータ(1つの実数)で表現できます。
Fusion360で作成したNURBS曲線は始点が0.0で終点は1.0になるようです。
・・・CATIAと違う。

質問者さんの内容を簡単に書くと、終点より先(緑ライン)の紫の座標を取得したいけど
終点より先はパラメータ0.0(始点のパラメータ)を返してくる。おかしくないかな?
との事の様です。
確かにそうでした。

サーフェスにも類似したオブジェクトが有り、そちらでは範囲外のパラメータを
使用しても正しい結果が返ってくることを知っていました。
この辺で試しています。
https://kantoku.hatenablog.com/entry/2019/11/11/160818

サーフェスの場合、範囲外のパラメータを使用しても正しい結果が得られますよ
と言う意味でサンプルを作ったのですが、結果的にバグですとのレスが付きました。


と、ここまでが前置きで、行き場の無くなったサンプルをここに残しておきます。

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

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        des  :adsk.fusion.Design = _app.activeProduct
        root :adsk.fusion.Component = des.rootComponent

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

        # RepFace.evaluator
        surf :adsk.fusion.BRepFace = sel.entity
        surfEva :adsk.core.SurfaceEvaluator = surf.evaluator
        surfBound :adsk.core.BoundingBox2D = surfEva.parametricRange()
        surfPnts = PointAtParameterTest(surfEva, surfBound)

        dumpSkt(root, surfPnts, 'surfEva')


        # RepFace.geometry.evaluator
        geo :adsk.core.Surface = surf.geometry
        geoEva :adsk.core.SurfaceEvaluator = geo.evaluator
        geoBound :adsk.core.BoundingBox2D = geoEva.parametricRange() # 平らな面の場合 None
        geoPnts = PointAtParameterTest(geoEva, surfBound)

        dumpSkt(root, geoPnts, 'geoEva')

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

def PointAtParameterTest(
    eva :adsk.core.SurfaceEvaluator,
    bound :adsk.core.BoundingBox2D
    ) -> list:

    try:
        maxPrm :adsk.core.Point2D = bound.maxPoint
        minPrm :adsk.core.Point2D = bound.minPoint

        newPrm :adsk.core.Point2D = maxPrm.copy()
        newPrm.x += 1.0
        newPrm.y += 1.0

        _, maxPnt = eva.getPointAtParameter(newPrm)

        newPrm = minPrm.copy()
        newPrm.x -= 1.0
        newPrm.y -= 1.0

        _, minPnt = eva.getPointAtParameter(newPrm)

        return [maxPnt, minPnt]

    except:
        return []

def dumpSkt(
    comp :adsk.fusion.Component,
    pnts :list,
    name :str):

    skt :adsk.fusion.Sketch = comp.sketches.add(comp.xYConstructionPlane)
    skt.name = name
    [skt.sketchPoints.add(p) for p in pnts]


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

    try:
        sel = _ui.selectEntity(msg, filtterStr)
        return sel
    except:
        return None

スクリプト実行後、面を指定すると面の外(最大・最小値の外)に2個点を作成します。
面上ならともかく、面の外側と言うところが全く役立たないです。

手元に残しておくと、間違いなくコードを無くすので覚書です。

Bodyの制限数

Fusion360の1個のドキュメントのBodyの制限数は5000個なのかな?
How to load more (or the next items) after 5,000 limit? - Autodesk Community
検索すると10000個と記載があったものも見かけたのですが、謎です。

リンク先の記載では、”5000個の制限を超えてどうやって読み込めばよいの?” と・・・。
制限なんだから無理でしょ、恐らく。

ちょっと確認したくなったので、大量のボディをひたすらBodyを作る無駄スクリプト
作りました。

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

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        bodyCount = 500

        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        des  :adsk.fusion.Design = _app.activeProduct
        root :adsk.fusion.Component = des.rootComponent

        dumpMsg('start')
        adsk.doEvents()

        bodies = initBoxes(bodyCount)

        dumpMsg('finish_initBoxes')
        adsk.doEvents()

        baseFeatures = root.features.baseFeatures
        baseFeature = baseFeatures.add()
        
        
        rootBodies = root.bRepBodies
        for body in bodies:
            baseFeature.startEdit()
            rootBodies.add(body, baseFeature)
            baseFeature.finishEdit()
            dumpMsg('body count:{}'.format(rootBodies.count))
            adsk.doEvents()

        dumpMsg('Done')

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

def initBoxes(
    count) -> list:

    unitBox = 1

    pnt3D = adsk.core.Point3D
    vec3D = adsk.core.Vector3D
    pnt = pnt3D.create(0.0, 0.0, 0.0)
    lVec = vec3D.create(1.0, 0.0, 0.0)
    wVec= vec3D.create(0.0, 1.0, 0.0)

    bouBox3D = adsk.core.OrientedBoundingBox3D
    box = bouBox3D.create(pnt, lVec, wVec, unitBox, unitBox, unitBox)

    tmpBrMgr = adsk.fusion.TemporaryBRepManager.get()
    bodies = [tmpBrMgr.createBox(box) for idx in range(count)]

    return bodies


def dumpMsg(msg :str):
    global _ui
    _ui.palettes.itemById('TextCommands').writeText(str(msg))

現状一度の実行で500個Bodyを作成します。bodyCount部分変更すればお好きな数
作成できます。
又、テキストコマンドを開いておけば実行中のボディ数のログを垂れ流しています。

肝心な実行結果ですが、1400個で断念・・・。途中から数秒に1個しか作成されなく
なりました。
恐らく、これを書いた事すら忘れると思う。

奇妙な歯車1

こちらちょっと面白そう。
Weird Gears | help in scripting - Autodesk Community
さらにリンク先のYoutubeの動画見ると、AutoCADかな?

直感的な思い付きで
f:id:kandennti:20201104173824p:plain
こんな状態だとして、回転中心から一周分等間隔の線を描いて
交差する座標値を求めてみます。こんな感じ
f:id:kandennti:20201104172940p:plain

この座標を相手側のピッチ円上に角度とか比率とか考慮しながら
配置してスプライン作れば良いのかな? と思ったのですが、
違うんですね。

左が3:11で右が3:12付近。
f:id:kandennti:20201104173532p:plain
左の緑印部分は直線的にカットしているけど、右ではさらに削り落とされている。
そりゃそうですね、干渉しちゃうので。

そうか、やっぱりチマチマ角度変えながら削り落とすしかないんだな。