C#ATIA

↑タイトル詐欺 主にCATIA V5 の VBA(最近はPMillマクロとFusion360APIが多い)

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

こちらの続きです。
平面と球体の交差を作る1 - C#ATIA

こちらを合体させてみました。
立方体を判断する - C#ATIA
球体を判断する - C#ATIA

#Fusion360API Python script
#Author-kantoku
#Description-表示された立方体と球体を見つけ、交差作成

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

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

        # 拡張
        adsk.fusion.BRepBody.isCube = isCube
        adsk.fusion.BRepBody.isSphere = isSphere
        adsk.fusion.BRepBody.tryIntersect = tryIntersect

        # 表示された立方体と球体を取得
        showBodies = getShowBody(des)
        cubes = [bd for bd in showBodies if bd.isCube()]
        spheres = [bd for bd in showBodies if bd.isSphere()]

        # 交差を取得
        ints =[]
        for sp in spheres:
            for cb in cubes:
                ints.extend(sp.tryIntersect(cb))

        if len(ints) < 1:
            msg  = '交差はありません!'
            ui.messageBox(msg)
            return
        
        # 拡張
        adsk.core.ObjectCollection.drawSkt = drawSketchCurve
        adsk.core.Point3D.drawSkt = drawSketchPoint

        # 可視化
        skt = initRootSketch()
        skt.arePointsShown = False
        [i.drawSkt(skt) for i in ints]

        # おしまい
        ui.messageBox('Done')

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

def drawSketchCurve(
    self :adsk.core.ObjectCollection,
    skt :adsk.fusion.Sketch):

    skt.sketchCurves.sketchFittedSplines.add(self)

def drawSketchPoint(
    self :adsk.core.Point3D,
    skt :adsk.fusion.Sketch):

    skt.sketchPoints.add(self)

def initRootSketch() -> adsk.fusion.Sketch:
    app  :adsk.core.Application = adsk.core.Application.get()
    des  :adsk.fusion.Design = app.activeProduct
    root :adsk.fusion.Component = des.rootComponent

    return root.sketches.add(root.xYConstructionPlane)

def getShowBody(
    des :adsk.fusion.Design):

    return [bBody
        for comp in des.allComponents if comp.isBodiesFolderLightBulbOn
        for bBody in comp.bRepBodies if bBody.isLightBulbOn & bBody.isVisible]

def isCube(
    self :adsk.fusion.BRepBody) -> bool:

    # 頂点・エッジ・面数正しい?
    if self.faces.count != 6 or self.edges.count != 12 or self.vertices.count != 8:
        return False
    
    # 各面積は同じか?
    if len(set([round(fc.area, 4) for fc in self.faces])) > 1:
        return False
    
    # すべて平面か?
    flat = adsk.core.SurfaceTypes.PlaneSurfaceType
    if len([fc for fc in self.faces if fc.geometry.surfaceType != flat]) > 0:
        return False

    return True

def isSphere(
    self :adsk.fusion.BRepBody) -> bool:

    # すべて球面か?
    sr = adsk.core.SurfaceTypes.SphereSurfaceType
    if len([fc for fc in self.faces if fc.geometry.surfaceType != sr]) > 0:
        return False

    # 半径は一致しているか?
    if len(set([round(fc.geometry.radius, 4) for fc in self.faces])) > 1:
        return False

    # 面積は正しいか?
    r = self.faces.item(0).geometry.radius
    if abs(4 * math.pi * r * r - self.area) > 0.001:
        return False

    return True

def tryIntersect(
    self :adsk.fusion.BRepBody,
    cube :adsk.fusion.BRepBody):

    cbSurfs = cube.faces
    spSurfs = self.faces

    app  :adsk.core.Application = adsk.core.Application.get()
    measMgr = app.measureManager

    ints = []
    for cbSurf in cbSurfs:
        cbGeo = adsk.core.Plane.cast(cbSurf.geometry)
        eva :adsk.core.SurfaceEvaluator = cbSurf.evaluator

        for spSurf in spSurfs:
            spGeo = adsk.core.Sphere.cast(spSurf.geometry)
            interLst = cbGeo.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:
                    ints.append(onPnts)
            else:
                minLength = measMgr.measureMinimumDistance(cbGeo, spGeo.origin)
                if abs(minLength.value - spGeo.radius) < 0.001:
                    inf = adsk.core.InfiniteLine3D.create(spGeo.origin, cbGeo.normal)
                    pnt = cbGeo.intersectWithLine(inf)
                    _, prm = eva.getParameterAtPoint(pnt)
                    if eva.isParameterOnFace(prm):
                        ints.append(pnt)

    return ints

既にブログに記載すべきでは無いサイズに・・・。

表示された立方体と球体を見つけ出し、交差作成します。
f:id:kandennti:20191223194455p:plain
あぁ色付ければ良かった・・・。 上から見た状態で
右:接触
上:接触無し
左:干渉
右下:角部分に干渉
の状態です。

実行すると
f:id:kandennti:20191223194640p:plain
わかりにくいのですが、赤矢印は干渉している部分に線が描かれ
緑矢印部分は接触のため、点を描いてます。

1/3ぐらいは出来たかな?