こんなスケッチを描き、フィレット部分をクリック
そうするとこんなボディを作ります。
頑張れば比較的少ない手数で、こんなのが作れます。
# Fusion360API Python script import traceback import adsk.fusion import adsk.core def run(context): ui = adsk.core.UserInterface.cast(None) try: app: adsk.core.Application = adsk.core.Application.get() ui = app.userInterface des: adsk.fusion.Design = app.activeProduct root: adsk.fusion.Component = des.rootComponent msg: str = 'Select' selFilter: str = 'SketchCurves' while True: sel: adsk.core.Selection = selectEnt(msg, selFilter) if not sel: return body: adsk.fusion.BRepBody = initJoint(sel, 0.2, 0.05, 0.2) if body: root.bRepBodies.add(body) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def initJoint( sel: adsk.core.Selection, radius: float, offset: float = 0.05, offsetLength: float = 0.1) -> adsk.fusion.BRepBody: app: adsk.core.Application = adsk.core.Application.get() # dustBox = [] tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get() sktCrv: adsk.fusion.SketchCurve = sel.entity parentSkt: adsk.fusion.Sketch = sktCrv.parentSketch comp: adsk.fusion.Component = sktCrv.parentSketch.parentComponent def initCylinderByVecter( pnt: adsk.core.Point3D, vec: adsk.core.Vector3D, radius: float, offsetLength: float) -> adsk.fusion.BRepBody: vec.normalize() vec.scaleBy(offsetLength) target: adsk.core.Point3D = pnt.copy() target.translateBy(vec) body: adsk.fusion.BRepBody = tmpMgr.createCylinderOrCone( pnt, radius, target, radius ) return body def initSweep( profile: adsk.fusion.Profile, sktCrv: adsk.fusion.SketchCurve) -> adsk.fusion.SweepFeature: path: adsk.fusion.Path = adsk.fusion.Path.create(sktCrv, False) sweepFeats: adsk.fusion.SweepFeatures = comp.features.sweepFeatures sweepIpt: adsk.fusion.SweepFeatureInput = sweepFeats.createInput( profile, path, adsk.fusion.FeatureOperations.NewBodyFeatureOperation ) sweepFeat: adsk.fusion.SweepFeature = sweepFeats.add(sweepIpt) # dustBox.append(sweepFeat) return sweepFeat def initSketch( center: adsk.core.Point3D, vecter: adsk.core.Vector3D) -> adsk.fusion.Sketch: pln: adsk.core.Plane = adsk.core.Plane.create( center, vecter ) constPlns: adsk.fusion.ConstructionPlanes = comp.constructionPlanes constPlnIpt: adsk.fusion.ConstructionPlaneInput = constPlns.createInput() constPlnIpt.setByPlane(pln) constPln: adsk.fusion.ConstructionPlane = constPlns.add(constPlnIpt) # dustBox.append(constPln) skt: adsk.fusion.Sketch = comp.sketches.add(constPln) circles: adsk.fusion.SketchCircles = skt.sketchCurves.sketchCircles circle: adsk.fusion.SketchCircle = circles.addByCenterRadius( adsk.core.Point3D.create(0,0,0), radius ) # dustBox.append(skt) return skt def getNormal( pnt: adsk.core.Point3D, eva: adsk.core.CurveEvaluator3D) -> adsk.core.Vector3D: _, prm = eva.getParameterAtPoint(pnt) normal: adsk.core.Vector3D = None _, normal = eva.getTangent(prm) normal.normalize() return normal # ********** geo: adsk.core.Arc3D = sktCrv.worldGeometry eva: adsk.core.CurveEvaluator3D = geo.evaluator sPnt: adsk.core.Point3D = geo.startPoint ePnt: adsk.core.Point3D = geo.endPoint sVec: adsk.core.Vector3D = getNormal(sPnt, eva) eVec: adsk.core.Vector3D = getNormal(ePnt, eva) app.executeTextCommand(u'Transaction.Start kantoku_pipe_joint') sSkt: adsk.fusion.Sketch = initSketch(sPnt, sVec) sweepFeat: adsk.fusion.SweepFeature = initSweep(sSkt.profiles[0], sktCrv) pipe: adsk.fusion.BRepBody = tmpMgr.copy(sweepFeat.bodies[0]) app.executeTextCommand(u'Transaction.Abort') sCyl: adsk.fusion.BRepBody = initCylinderByVecter(sPnt, sVec, radius + offset, -offsetLength) eCyl: adsk.fusion.BRepBody = initCylinderByVecter(ePnt, eVec, radius + offset, offsetLength) unionType = adsk.fusion.BooleanTypes.UnionBooleanType [tmpMgr.booleanOperation(pipe, body, unionType) for body in [sCyl, eCyl]] # [ent.deleteMe() for ent in dustBox[::-1]] parentSkt.isLightBulbOn = True return pipe def selectEnt( msg: str, filterStr: str) -> adsk.core.Selection: try: app: adsk.core.Application = adsk.core.Application.get() ui: adsk.core.UserInterface = app.userInterface sel = ui.selectEntity(msg, filterStr) return sel except: return None
・ダイレクトモードのみ。(パラメトリックの場合はエラーになります)
・サイズ変更はコードを書き換えるしか方法無し。
取りあえず、これで良いや。