C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)※記載されている内容は個人の意見であり、所属する団体等を代表する意見では御座いません・・・・よ!

メッシュをBRepに変換する

もう3年ぐらい前のものですが、フォーラムに投げたスクリプトです。
こちらに投げたもので、偶に需要がありその都度探すのが大変なのでブログにも転載です。
https://forums.autodesk.com/t5/fusion-api-and-scripts/is-it-possible-to-use-text-command-within-a-script-to-run-the/m-p/10995389/highlight/true#M16058

メッシュ->BRep変換はメッシュの面数が10000枚を超えると警告が出てスクリプトが止まってしまう為、
一個のメッシュボディが10000枚以下になるまで分割し、メッシュ->BRep変換処理してます。

# Fusion360API Python script
# Author-kantoku
# Description-Split Mesh and convert to BRepBody

import adsk.core, adsk.fusion, traceback

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        des :adsk.fusion.Design = _app.activeProduct

        if des.designType == adsk.fusion.DesignTypes.ParametricDesignType:
            query = _ui.messageBox(
                'Switch to direct mode.\nIs it OK?',
                'Need to switch to direct mode',
                adsk.core.MessageBoxButtonTypes.OKCancelButtonType,
                adsk.core.MessageBoxIconTypes.QuestionIconType)

            if query == adsk.core.DialogResults.DialogCancel:
                return
            else:
                des.designType = adsk.fusion.DesignTypes.DirectDesignType

        msg :str = 'Please select a mesh body!'
        selFiltter :str = 'MeshBodies'
        sel :adsk.core.Selection = selectEnt(msg ,selFiltter)
        if not sel: return
        mesh = sel.entity

        fact = Mesh2BRepFactry(mesh)
        bodies = fact.toBrep()

        _ui.messageBox(f'{len(bodies)} BRep body created')

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

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

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


class Mesh2BRepFactry:
    def __init__(self, mesh :adsk.fusion.MeshBody):
        self.mesh = mesh

    def toBrep(self, maxCount = 10000) -> list:
        comp :adsk.fusion.Component = self.mesh.parentComponent

        if maxCount > 10000:
            maxCount = 10000

        # split
        meshLst = self._MeshsSplit(self.mesh, maxCount)

        # toBrep
        return self._Mesh2BRepCommand(meshLst)


    def _Mesh2BRepCommand(
        self,
        meshLst :list) -> list:

        app :adsk.core.Application = adsk.core.Application.get()
        ui :adsk.core.UserInterface = app.userInterface
        sels :adsk.core.Selections = ui.activeSelections
        comp :adsk.fusion.Component = self.mesh.parentComponent
        exceptionLst = [b for b in comp.bRepBodies]

        for mesh in meshLst:
            sels.clear()
            sels.add(mesh)
            app.executeTextCommand(u'Commands.Start ParaMeshConvertCommand')
            app.executeTextCommand(u'NuCommands.CommitCmd')

            adsk.doEvents()
        
        return self._list_difference([b for b in comp.bRepBodies], exceptionLst)


    def _MeshsSplit(
        self,
        mesh :adsk.fusion.MeshBody,
        maxCount) -> list:

        comp :adsk.fusion.Component = self.mesh.parentComponent

        meshLst = [self.mesh]

        exceptionLst = [m for m in comp.meshBodies]
        exceptionLst.remove(self.mesh)

        global _app
        reOpeFG = False
        while True:
            for mesh in meshLst:
                _app.log(f'{mesh.name}:{mesh.displayMesh.triangleCount}')

                if maxCount < mesh.displayMesh.triangleCount:
                    tool :adsk.fusion.ConstructionPlane = self._getSplitPlane(mesh)
                    self._MeshPlaneCutCommand(mesh, tool)
                    tool.deleteMe()
                    reOpeFG = True

                adsk.doEvents()
            
            if reOpeFG:
                meshLst = self._list_difference([m for m in comp.meshBodies], exceptionLst)
                reOpeFG = False
            else:
                break
        
        return meshLst


    def  _MeshPlaneCutCommand(
        self,
        mesh: adsk.fusion.MeshBody,
        plane: adsk.fusion.ConstructionPlane):

        app: adsk.core.Application = adsk.core.Application.get()
        ui: adsk.core.UserInterface = app.userInterface
        sels: adsk.core.Selections = ui.activeSelections

        sels.clear()
        app.executeTextCommand(u'Commands.Start ParaMeshPlaneCutCommand')

        app.executeTextCommand(u'UI.EnableCommandInput infoBodyToModify')
        sels.add(mesh)

        app.executeTextCommand(u'UI.EnableCommandInput planeSelectionInfo')
        sels.add(plane)

        app.executeTextCommand(u'Commands.SetString infoCutType infoCutTypeSplitBody')
        app.executeTextCommand(u'Commands.SetString infoFillType infoFillTypeNoFill')

        app.executeTextCommand(u'NuCommands.CommitCmd')


    def _list_difference(self, list1, list2):
        result = list1.copy()
        for value in list2:
            if value in result:
                result.remove(value)

        return result


    def _getSplitPlane(
        self,
        mesh :adsk.fusion.MeshBody) -> adsk.fusion.ConstructionPlane:

        comp :adsk.fusion.Component = mesh.parentComponent

        pnts = [p for p in mesh.displayMesh.nodeCoordinates]
        bound = adsk.core.BoundingBox3D.create(pnts[0], pnts[1])
        for p in pnts[2:]:
            bound.expand(p)

        pntMin :adsk.core.Point3D = bound.minPoint
        pntMax :adsk.core.Point3D = bound.maxPoint

        pntMid = adsk.core.Point3D.create(
            (pntMin.x + pntMax.x) * 0.5,
            (pntMin.y + pntMax.y) * 0.5,
            (pntMin.z + pntMax.z) * 0.5)

        width = [abs(pntMax.x) + abs(pntMin.x), comp.xConstructionAxis]
        length = [abs(pntMax.y) + abs(pntMin.y), comp.yConstructionAxis]
        height = [abs(pntMax.z) + abs(pntMin.z), comp.zConstructionAxis]

        direction = max([width, length, height], key=(lambda x: x[0]))

        plane = adsk.core.Plane.create(pntMid, direction[1].geometry.direction)
        conPlanes :adsk.fusion.ConstructionPlanes = comp.constructionPlanes
        planeIpt :adsk.fusion.ConstructionPlaneInput = conPlanes.createInput()
        planeIpt.setByPlane(plane)

        return conPlanes.add(planeIpt)