C#ATIA

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

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

タイトルがあやふやなのですが、要はこちらの内容に関連してます。
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個点を作成します。
面上ならともかく、面の外側と言うところが全く役立たないです。

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