C#ATIA

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

パイプジョイント風

こんなスケッチを描き、フィレット部分をクリック

そうするとこんなボディを作ります。

頑張れば比較的少ない手数で、こんなのが作れます。

# 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

・ダイレクトモードのみ。(パラメトリックの場合はエラーになります)
・サイズ変更はコードを書き換えるしか方法無し。

取りあえず、これで良いや。