同一半径限定で、表示された球体同士の交差を作ります。
・・・同一半径のみ欲しいので、同一半径のみなんです。
#Fusion360API Python script #Author-kantoku #Description-表示された球体を見つけ、交差作成(同一半径のみ) import adsk.core, adsk.fusion, traceback import math, itertools _tolerance = 0 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 global _tolerance um = des.unitsManager um.defaultLengthUnits _tolerance = um.convert(0.01, um.defaultLengthUnits, um.internalUnits) # 拡張 adsk.fusion.BRepBody.isSphere = isSphere adsk.fusion.BRepBody.tryIntersect = tryIntersect adsk.core.Point3D.midPoint = midPoint3D adsk.core.Point3D.drawSkt = drawSketchPoint adsk.core.Circle3D.drawSkt = drawSketchCircle # 表示された球体を取得 showBodies = getShowBody(des) spheres = [bd for bd in showBodies if bd.isSphere()] # 交差を取得 ints = [] for idx, sp1 in enumerate(spheres): for sp2 in spheres[idx + 1:]: ints.append(sp1.tryIntersect(sp2)) if len(ints) < 1: msg = '交差はありません!' ui.messageBox(msg) return # 可視化 skt = initRootSketch() skt.arePointsShown = False skt.isComputeDeferred = True [i[0].drawSkt(skt) for i in ints if len(i) > 0] skt.isComputeDeferred = False # おしまい app.activeViewport.refresh() ui.messageBox('Done') except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def drawSketchCircle( self :adsk.core.ObjectCollection, skt :adsk.fusion.Sketch): skt.sketchCurves.sketchFittedSplines.addByNurbsCurve(self.asNurbsCurve) 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 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, tgt :adsk.fusion.BRepBody): tgtSurfs = tgt.faces spSurfs = self.faces app :adsk.core.Application = adsk.core.Application.get() ints = [] for tgtSurf in tgtSurfs: tgtGeo = adsk.core.Sphere.cast(tgtSurf.geometry) tgtOri :adsk.core.Point3D = tgtGeo.origin tgtRad = tgtGeo.radius for spSurf in spSurfs: spGeo = adsk.core.Sphere.cast(spSurf.geometry) if abs(spGeo.radius - tgtRad) > _tolerance: return None spOri = spGeo.origin minLength = tgtOri.distanceTo(spOri) if minLength > tgtRad * 2: # 干渉なし continue if minLength < _tolerance: # 同一 continue if abs(minLength - tgtRad * 2) < _tolerance: # 接触 ints.append(spOri.midPoint(tgtOri)) else: # 干渉 vec = spOri.asVector() vec.subtract(tgtOri.asVector()) ori = spOri.midPoint(tgtOri) pln = adsk.core.Plane.create(ori, vec) interLst = pln.intersectWithSurface(spGeo) [ints.append(c) for c in interLst] return ints def midPoint3D( self :adsk.core.Point3D, pnt :adsk.core.Point3D) -> adsk.core.Point3D: p = self.copy() p.setWithArray([(x + y) * 0.5 for (x, y) in zip(self.asArray(), pnt.asArray())]) return p
イマイチな部分が多々有り。
こんなデータで実行すると
こんな感じで