C#ATIA

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

円すい上の2点の最短距離をAPIで2

こちらの続きです。
円すい上の2点の最短距離をAPIで1 - C#ATIA

完成しました。
解決済み: Re: 円すい上の2点の最短距離 - Autodesk Community

#Fusion360API Python script
#Author-kantoku
#Description-円錐上の2点の最短距離

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

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

# 1ステップの角度(deg)
STEP_ANG = 5

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

        # 円錐
        cone :adsk.fusion.BRepFace = root.bRepBodies.item(0).faces.item(1)

        # 展開図スケッチ
        sktDevelop :adsk.fusion.Sketch = root.sketches.itemByName('展開図')

        dims :adsk.fusion.SketchDimensions = sktDevelop.sketchDimensions
        dimAng :adsk.fusion.SketchDimension = getDimensionByName(dims, 'd13')
        dimTgt :adsk.fusion.SketchDimension = getDimensionByName(dims, 'd14')
        dimTmp :adsk.fusion.SketchDimension = getDimensionByName(dims, 'd11')

        # 作業スケッチ
        sktWork :adsk.fusion.Sketch = root.sketches.itemByName('作業')

        dims = sktWork.sketchDimensions
        dimPrt :adsk.fusion.SketchDimension = getDimensionByName(dims, 'd8')
        pntSkt :adsk.fusion.SketchPoint = sktWork.sketchPoints.item(4)

        # カメラ
        vp :adsk.core.Viewport = _app.activeViewport
        cam :adsk.core.Camera = vp.camera
        viewLng = cam.eye.vectorTo(cam.target).length

        # 結果スケッチ
        sktRes :adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane)

        # 円錐上に点作成
        pntRes = adsk.fusion.SketchPoint.cast(None)
        for v in range(0,120 + STEP_ANG,STEP_ANG):
            # 展開スケッチ更新
            dimAng.parameter.value = math.radians(v)
            dimTmp.isDriving = False
            dimTgt.isDriving = True
            dimTgt.isDriving = False
            dimTmp.isDriving = True

            # 作業スケッチ更新
            dimPrt.parameter.value = dimTgt.parameter.value

            # 結果スケッチに取り込み
            includes = sktRes.include(pntSkt)
            pntRes :adsk.fusion.SketchPoint = includes.item(0)
            pntRes.isReference = False

            # 画面更新
            updateCam(cone, pntRes.geometry, viewLng)

            # 画面が固まるのを防ぐ
            adsk.doEvents()

        # 曲線作成
        pnts = adsk.core.ObjectCollection.create()
        [pnts.add(p) for p in sktRes.sketchPoints]
        pnts.removeByIndex(0)
        sktRes.sketchCurves.sketchFittedSplines.add(pnts)

        # 邪魔な点非表示
        sktRes.arePointsShown = False

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

# カメラの更新
def updateCam(
    brep :adsk.fusion.BRepFace,
    tgt :adsk.core.Point3D,
    viLng :float):

    vec :adsk.core.Vector3D = getViewVec(brep, tgt)
    vec.scaleBy(viLng)

    eye :adsk.core.Point3D = tgt.copy()
    eye.translateBy(vec)

    vp :adsk.core.Viewport = _app.activeViewport
    cam :adsk.core.Camera = vp.camera

    cam.eye = eye
    cam.target = tgt
    cam.upVector = adsk.core.Vector3D.create(0, 0, 1)
    vp.camera = cam

    _app.activeViewport.refresh()

# サーフェス上の点位置の法線取得
def getViewVec(
    brep :adsk.fusion.BRepFace,
    pnt :adsk.core.Point3D) -> adsk.core.Vector3D:

    eva :adsk.core.SurfaceEvaluator = brep.evaluator
    vec = adsk.core.Vector3D.cast(None)
    _,vec = eva.getNormalAtPoint(pnt)
    vec.normalize()

    return vec

# モデリングパラメータ名から寸法取得
def getDimensionByName(
    dims :adsk.fusion.SketchDimensions,
    name :str) -> adsk.fusion.SketchDimension:

    lst =[d for d in dims if d.parameter.name == name]
    if len(lst) < 1:
        return None
    
    return adsk.fusion.SketchDimension.cast(lst[0])

全く使いまわしのきかないものです・・・。

普段はループ内で複数の処理するの嫌なのですが、動画にしたかったので
あえて遅くなるようにしています。
画面も一緒に追いかけるようにしたのですが、

    cam.upVector = adsk.core.Vector3D.create(0, 0, 1)

最初にこの処理を入れ忘れ、結構酔いそうになりました。