from typing import List import FreeCAD as App import Part import Mesh import Part import MeshPart import os import json import FreeCADGui as Gui class FS: def readJSON(path: str): return json.loads((open(path)).read()) def writeFile(data, filePath, fileName): file_to_open = filePath + fileName f = open(file_to_open, 'w', encoding='utf-8', errors='ignore') f.write(data) f.close() def createFolder(path: str): if (not os.path.exists(path)): return os.mkdir(path) class SimpleCopyPartModel: id = None copyLink = None label = None part = None def getPart(self): return self.part def __init__(self, part) -> None: try: from random import randrange self.id = str(randrange(1000000)) childObj = part print(part) __shape = Part.getShape( childObj, '', needSubElement=False, refine=False) obj = App.ActiveDocument.addObject('Part::Feature', self.id) obj.Shape = __shape self.part = obj self.label = obj.Label App.ActiveDocument.recompute() except Exception as e: print(e) def remove(self): App.ActiveDocument.removeObject(self.label) class MeshPartModel: id = None mesh = None def __init__(self, part) -> None: try: from random import randrange self.id = 'mesh' + str(randrange(1000000)) document = App.ActiveDocument mesh = document.addObject("Mesh::Feature", self.id) shape = Part.getShape(part, "") mesh.Mesh = MeshPart.meshFromShape( Shape=shape, LinearDeflection=20, AngularDeflection=0.1, Relative=False) mesh.Label = self.id self.mesh = mesh except Exception as e: print(e) pass def remove(self): try: App.ActiveDocument.removeObject(self.mesh.Label) except Exception as e: print(e) class JoinMeshModel: id = None mesh = None def __init__(self, meshesPartModels: list['MeshPartModel']) -> None: meshes = [] from random import randrange for el in meshesPartModels: meshes.append(el.mesh.Mesh) self.id = 'MergedMesh' + str(randrange(1000000)) doc = App.ActiveDocument merged_mesh = Mesh.Mesh() for el in meshes: merged_mesh.addMesh(el) new_obj = doc.addObject("Mesh::Feature", self.id) new_obj.Mesh = merged_mesh new_obj.ViewObject.DisplayMode = "Flat Lines" self.mesh = new_obj def remove(self): try: App.ActiveDocument.removeObject(self.id) except Exception as e: print(e) class ExportAssemblyThemAllUseCase: def call(self, path:str, assemblys:list[str]): assembly = assemblys asmStructure = {} inc = 0 for el in assembly: if (inc != 0): asmStructure[inc] = { "child": el, "parents": assembly[0:inc] } inc += 1 objectsFreeCad = App.ActiveDocument.Objects asmSolids = {} for k, v in asmStructure.items(): assemblyParentList = v['parents'] assemblyChild = v['child'] for el in assemblyParentList: for solid in objectsFreeCad: if (el == solid.Label): if (asmSolids.get(k) is None): asmSolids[k] = {'parents': [], 'child': list( filter(lambda x: x.Label == assemblyChild, objectsFreeCad))[0]} asmSolids[k]['parents'].append(solid) inc = 0 for k, v in asmSolids.items(): geometry = {"0": [], "1": []} if (k != 0): App.activeDocument().addObject("Part::Compound", "Compound") copyLinks = list( map(lambda el: SimpleCopyPartModel(el), v['parents'])) if copyLinks != None: App.activeDocument().Compound.Links = list( map(lambda el: el.getPart(), copyLinks)) object = App.activeDocument().getObject('Compound') boundBox = object.Shape.BoundBox geometry['0'].append(boundBox.XMax) geometry['0'].append(boundBox.YMax) geometry['0'].append(boundBox.ZMax) boundBoxChild = v['child'].Shape.BoundBox geometry['1'].append(boundBoxChild.XMax) geometry['1'].append(boundBoxChild.YMax) geometry['1'].append(boundBoxChild.ZMax) meshParents = [] for el in v['parents']: meshParents.append(MeshPartModel(el)) joinMesh = JoinMeshModel(meshParents) for el in meshParents: el.remove() import importOBJ importOBJ.export(joinMesh.mesh, path + str(1) + '.obj') joinMesh.remove() importOBJ.export(v['child'], path + str(0) + '.obj') FS.writeFile(json.dumps(geometry), path, 'translation.json') App.ActiveDocument.removeObject("Compound") for el in copyLinks: el.remove() App.activeDocument().recompute() inc += 1 def main(): env = FS.readJSON('./env.json') env.get('cadDoc') aspDir = env.get('aspDir') sequences = FS.readJSON(env.get('sequences')).get('sequences') App.openDocument(env.get('cadDoc')) for sequencyNumber in range(len(sequences)): FS.createFolder(aspDir + 'assemblys/') mainFolder = aspDir + 'assemblys/' + str(sequencyNumber) + '/' FS.createFolder(mainFolder) for subSequenceNumber in range(len(sequences[sequencyNumber])): if(subSequenceNumber != 0): subFolder = aspDir + 'assemblys/' + \ str(sequencyNumber) + '/' + str(subSequenceNumber) + '/' FS.createFolder(subFolder) ExportAssemblyThemAllUseCase().call(path=subFolder,assemblys=sequences[sequencyNumber][0:subSequenceNumber+1]) App.closeDocument(App.ActiveDocument.Name) freecadQTWindow = Gui.getMainWindow() freecadQTWindow.close() main()