C#ATIA

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

平面と球体の交差を作る1

気が付いたら、すっかりブログを更新していませんでした。

かなり以前にフォーラムで質問したのですが、Fusion360の場合
平面と球体が接触している場合、交差を作っても何も出来ないんですよね。
CATIAの場合、接触であれば点が作成されます。

ちょっと先の事を考えていて、これを実現したいんです。
こんな感じを想定しています。
f:id:kandennti:20191219182522p:plain
黄色が直方体で緑は球体です。数値的にはこんな感じです。
f:id:kandennti:20191219182506p:plain

ブログを更新を優先した、ずさんなコードです。

#Fusion360API Python script

import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app  :adsk.core.Application = adsk.core.Application.get()
        ui   :adsk.core.UserInterface = app.userInterface
        des  :adsk.fusion.Design = app.activeProduct
        root :adsk.fusion.Component = des.rootComponent

        msg = 'Select Box'
        selFiltter :str = 'Bodies'
        sel :adsk.core.Selection = selectEnt(ui, msg ,selFiltter)
        if not sel: return
        box :adsk.fusion.BRepBody = sel.entity

        msg = 'Select Sphere'
        sel :adsk.core.Selection = selectEnt(ui, msg ,selFiltter)
        if not sel: return
        sp :adsk.fusion.BRepBody = sel.entity

        # 本当は全て平面が条件
        boxSurf = box.faces
        # 本当は1枚で球体が条件
        spSurf = sp.faces

        boxGeos = [adsk.core.Plane.cast(br.geometry) for br in boxSurf]
        spGeo = adsk.core.Sphere.cast(spSurf.item(0).geometry)

        measMgr = app.measureManager
        skt = root.sketches.add(root.xYConstructionPlane)
        for surf in boxSurf:
            ori :adsk.core.Point3D = spGeo.origin
            pln = adsk.core.Plane.cast(surf.geometry)
            eva :adsk.core.SurfaceEvaluator = surf.evaluator
            interLst = pln.intersectWithSurface(spGeo)

            if interLst.count > 0:
                inter = interLst.item(0)
                crvEva = inter.evaluator
                _, startParameter, endParameter = crvEva.getParameterExtents()
                _, pnts = crvEva.getStrokes(startParameter, endParameter, 0.001)

                onPnts = adsk.core.ObjectCollection.create()
                for pnt in pnts:
                    _, prm = eva.getParameterAtPoint(pnt)
                    if eva.isParameterOnFace(prm):
                        onPnts.add(pnt)
                if onPnts.count > 0:
                    skt.sketchCurves.sketchFittedSplines.add(onPnts)
            else:
                minLength = measMgr.measureMinimumDistance(pln, spGeo.origin)
                if abs(minLength.value - spGeo.radius) < 0.001:
                    inf = adsk.core.InfiniteLine3D.create(spGeo.origin, pln.normal)
                    pnt = pln.intersectWithLine(inf)
                    _, prm = eva.getParameterAtPoint(pnt)
                    if eva.isParameterOnFace(prm):
                        skt.sketchPoints.add(pnt)

        ui.messageBox('Done')

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

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

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

後日きれいにします・・・多分。
スクリプト実行後、最初に直方体を選択し、続いて球体を選択します。
(全く選択要素のチェックをしていない為、それ以外の選択ではエラーになるはず)

接触している部分に、点が作成されます。
f:id:kandennti:20191219182535p:plain

球体をめり込むように移動させ、実行すると交差部分に線が出来ます。
f:id:kandennti:20191219182548p:plain
通常、円ですね。処理の都合上、NURBS曲線何ですけど。

角が絡むようにめり込ませて実行するとこんな感じです。
f:id:kandennti:20191219182603p:plain
ボディを消すとわかるのですが、ちょっと正しくないです。
f:id:kandennti:20191219182614p:plain
赤印部分に余計な線が入ってますが、"そこが目的じゃない" と言う
全力の言い訳で、今回は勘弁を。


そもそも手動で作っても正しくないです。
f:id:kandennti:20191219182624p:plain
赤印部分は交差していないです。(これを避けるためにNURBS曲線化してます)


ん~年内には完成しなそう。来年の宿題です。



それ以上に悩むのが、PowerMillの保守。想像以上に高い。
困ったなぁ。