先日のドロップダウンリストが出来るようになったので、
今回は副産物を作る事にしました。
ドロップダウンリストを変更する - C#ATIA
個人的には、STL(だけではなくOBJ等も)データをソリッド/サーフェス
に変換しても、重たいだけで役には立たないと思っているのですが、
世の中には需要があるのも確かです。こちらもそうですね。
Convert Mesh to BRep in API - Autodesk Community
Fusion360にはその為のコマンドが用意されているものの、50000枚以下
と制限が有ります。・・・その処理を必要とする場合は恐らく50000枚は
軽く超えているハズです。
その為、変換可能なサイズまでぶった切り、複数個にして変換する為の
スクリプトを作成しました。
# Fusion360API Python script # Author-kantoku # Description-Meshをぶった切りつつBRep化 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( 'ダイレクトモードに切り替えます。\nよろしいですか?', 'ダイレクトモードに切り替える必要があります', adsk.core.MessageBoxButtonTypes.OKCancelButtonType, adsk.core.MessageBoxIconTypes.QuestionIconType) if query == adsk.core.DialogResults.DialogCancel: return else: des.designType = adsk.fusion.DesignTypes.DirectDesignType msg :str = 'メッシュボディを選択して下さい!' 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ボディを作成しました') 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 def dumpMsg(msg :str): adsk.core.Application.get().userInterface.palettes.itemById('TextCommands').writeText(str(msg)) 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 Mesh2BRepCommand') 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) reOpeFG = False while True: for mesh in meshLst: dumpMsg(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 MeshPlaneCutCommand') app.executeTextCommand(u'UI.EnableCommandInput MeshPlaneCutBodySel') sels.add(mesh) app.executeTextCommand(u'UI.EnableCommandInput MeshPlaneCutPlaneSel') sels.add(plane) app.executeTextCommand(u'Commands.SetString infoCutType MeshPlaneCutSplitBody') app.executeTextCommand(u'Commands.SetString infoFillType MeshPlaneCutFillNone') 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)
上記で50000枚以下と記載しましたが、10000枚を超えるとこの様な
警告のダイアログが出現します。
どうせなら放置したい方なのでダイアログを閉じたいのですが、
方法が見つかりませんでした。
その為、10000枚以下になるまでぶった切りまくります。
後はIgesなりStepなりでエクスポートして下さいませ。