C#ATIA

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

複数面に線を描きたい6

こちらの続きです。
複数面に線を描きたい5 - C#ATIA

良い方法が思い付かない為、素直に平面で交差を作り
その線を使うことにしました。・・・情けない。
f:id:kandennti:20200513134621p:plain
一本は2点間を繋ぐ3D直線で、もう一本は3D直線と共有している
エッジの最短距離となる部分のベクトルです。

#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

        # get body
        body :adsk.fusion.BRepBody = root.bRepBodies.item(0)

        # get face
        face1 :adsk.fusion.BRepFace = body.faces.item(0)
        face2 :adsk.fusion.BRepFace = body.faces.item(1)

        # 共有エッジ取得
        shareEdges = getShareEdges(face1, face2)

        # get point
        pnt1 :adsk.fusion.ConstructionPoint = root.constructionPoints.item(1)
        pnt2 :adsk.fusion.ConstructionPoint = root.constructionPoints.item(0)

        # 直線
        line :adsk.core.Line3D = adsk.core.Line3D.create(pnt1.geometry, pnt2.geometry)
        lineVec :adsk.core.Vector3D = pnt1.geometry.vectorTo(pnt2.geometry)

        # 共有エッジと直線の最短取得 - 本当は1本とは限らない
        mersRes :adsk.core.MeasureResults = getMinDist(line, shareEdges[0])
        mersVec :adsk.core.Vector3D = mersRes.positionOne.vectorTo(mersRes.positionTwo)

        # 平面
        plane :adsk.core.Plane = initPlane(mersRes.positionOne, mersVec, lineVec)

        # 交差取得
        crv1 = getCurve(pnt1.geometry, shareEdges[0], plane, face1)
        crv2 = getCurve(pnt2.geometry, shareEdges[0], plane, face2)

        # add sketch
        skt :adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane)
        skt.arePointsShown = False

        # 面上に線を描く
        drawSketch(skt, [crv1, crv2])

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

def drawSketch(
    skt :adsk.fusion.Sketch,
    crvs :list):

    skt.isComputeDeferred = True
    sktCrvs :adsk.fusion.SketchCurves = skt.sketchCurves

    for crv in crvs:
        if hasattr(crv,'asNurbsCurve'):
            crv = crv.asNurbsCurve

        if crv.objectType == 'adsk::core::NurbsCurve3D':
            sktElm = sktCrvs.sketchFittedSplines.addByNurbsCurve(crv)

        else:
            s = crv.startPoint
            e = crv.endPoint
            sktElm = sktCrvs.sketchLines.addByTwoPoints(s,e)

    skt.isComputeDeferred = False

def getCurve(
    pnt :adsk.core.Point3D,
    edge :adsk.fusion.BRepEdge,
    pln :adsk.core.Plane,
    face :adsk.fusion.BRepFace):

    crvs :adsk.core.ObjectCollection = getSection(pln, face)
    sect :adsk.core.Curve3D = crvs[0]

    sectEva :adsk.core.CurveEvaluator3D = sect.evaluator
    _, sPnt, ePnt = sectEva.getEndPoints()

    tgtPnts = [pnt]
    tgtPnts.append(sPnt if isOnCurve(edge,sPnt) else ePnt)

    _, prms = sectEva.getParametersAtPoints(tgtPnts)
    list(prms).sort()

    # return sect.extract(prms[0], prms[1]) # err!
    return sect

def isOnCurve(
    crv :adsk.fusion.BRepEdge,
    pnt :adsk.core.Point3D) -> bool:

        eva :adsk.core.CurveEvaluator3D = crv.evaluator
        _, sPrm, ePrm = eva.getParameterExtents()

        _, prm = eva.getParameterAtPoint(pnt)

        return True if sPrm <= prm <= ePrm else False

def getSection(
    pln :adsk.core.Plane,
    face :adsk.fusion.BRepFace) -> adsk.core.ObjectCollection:

    return pln.intersectWithSurface(face.geometry)

def initPlane(
    ori :adsk.core.Point3D,
    vec1 :adsk.core.Vector3D,
    vec2 :adsk.core.Vector3D) -> adsk.core.Plane:

    if vec1.isParallelTo(vec2):
        return None
    
    return adsk.core.Plane.createUsingDirections(ori,vec1,vec2)

def getMinDist(
    crv1 ,
    crv2) -> adsk.core.MeasureResults:

    meas = _app.measureManager
    return meas.measureMinimumDistance(crv1, crv2)

def getShareEdges(
    face1 :adsk.fusion.BRepFace,
    face2 :adsk.fusion.BRepFace) -> list:

    lps1 :adsk.fusion.BRepLoops = face1.loops
    lp1 :adsk.fusion.BRepLoop = lps1[0]
    cos1 = [co for co in lp1.coEdges if hasPartner(co)]

    lps2 :adsk.fusion.BRepLoops = face2.loops
    lp2 :adsk.fusion.BRepLoop = lps2[0]
    cos2 = [co.partner for co in lp2.coEdges if hasPartner(co)]

    # 共有エッジ取得
    rap = []
    for co1 in cos1:
        for co2 in cos2:
            if co1 == co2:
                rap.append(co1.edge)

    return rap

def hasPartner(
    coEdge :adsk.fusion.BRepCoEdge) -> bool:

    try:
        coEdge.partner
        return True
    except:
        return False

段々肥大化してきた・・・。

当然、手動で作ったのと一致しますが、2点間だけで欲しいので
外側が要らないんです。
f:id:kandennti:20200513134636p:plain

この辺にその処理を入れているのですが、エラーになっちゃいます。

     return sect.extract(prms[0], prms[1]) # err!

Nurbs曲線を指定したパラメータ間のみにしている部分なのですが
どうしてもエラーになる・・・。

スケッチに入れてからトリムするの嫌だなぁ。