mirror of
https://github.com/PotentiaRobotics/Fusion2PyBullet-Redux.git
synced 2025-04-09 23:00:18 -04:00
261 lines
8.5 KiB
Python
261 lines
8.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
"""
|
|
Copy to new components and export stls.
|
|
|
|
@syuntoku
|
|
@yanshil
|
|
"""
|
|
|
|
import adsk, adsk.core, adsk.fusion
|
|
import os.path, re
|
|
from xml.etree import ElementTree
|
|
from xml.dom import minidom
|
|
|
|
def export_stl(_app, save_dir):
|
|
"""
|
|
export stl files into "sace_dir/"
|
|
|
|
|
|
Parameters
|
|
----------
|
|
_app: adsk.core.Application.get()
|
|
save_dir: str
|
|
directory path to save
|
|
"""
|
|
|
|
def traverse( occ):
|
|
# recursive method to get all bodies from components and sub-components
|
|
body = adsk.fusion.BRepBody.cast(None)
|
|
liste = []
|
|
if occ.childOccurrences and occ.isLightBulbOn:
|
|
for child in occ.childOccurrences:
|
|
liste = liste + traverse(child)
|
|
if occ.isLightBulbOn:
|
|
liste = liste + [body for body in occ.bRepBodies if body.isLightBulbOn and occ.component.isBodiesFolderLightBulbOn]
|
|
return liste
|
|
|
|
|
|
des: adsk.fusion.Design = _app.activeProduct
|
|
root: adsk.fusion.Component = des.rootComponent
|
|
|
|
showBodies = []
|
|
body = adsk.fusion.BRepBody.cast(None)
|
|
if root.isBodiesFolderLightBulbOn:
|
|
lst = [body for body in root.bRepBodies if body.isLightBulbOn]
|
|
if len(lst) > 0:
|
|
showBodies.append(['root', lst])
|
|
|
|
occ = adsk.fusion.Occurrence.cast(None)
|
|
for occ in root.allOccurrences:
|
|
if not occ.assemblyContext and occ.isLightBulbOn:
|
|
lst = [body for body in occ.bRepBodies if body.isLightBulbOn and occ.component.isBodiesFolderLightBulbOn]
|
|
if occ.childOccurrences:
|
|
for child in occ.childOccurrences:
|
|
lst = lst + traverse(child)
|
|
if len(lst) > 0:
|
|
showBodies.append([occ.name, lst])
|
|
|
|
# get clone body
|
|
tmpBrepMng = adsk.fusion.TemporaryBRepManager.get()
|
|
tmpBodies = []
|
|
for name, bodies in showBodies:
|
|
lst = [tmpBrepMng.copy(body) for body in bodies]
|
|
if len(lst) > 0:
|
|
tmpBodies.append([name, lst])
|
|
|
|
# create export Doc - DirectDesign
|
|
fusionDocType = adsk.core.DocumentTypes.FusionDesignDocumentType
|
|
expDoc: adsk.fusion.FusionDocument = _app.documents.add(fusionDocType)
|
|
expDes: adsk.fusion.Design = expDoc.design
|
|
expDes.designType = adsk.fusion.DesignTypes.DirectDesignType
|
|
|
|
# get export rootComponent
|
|
expRoot: adsk.fusion.Component = expDes.rootComponent
|
|
|
|
# paste clone body
|
|
mat0 = adsk.core.Matrix3D.create()
|
|
for name, bodies in tmpBodies:
|
|
occ = expRoot.occurrences.addNewComponent(mat0)
|
|
comp = occ.component
|
|
comp.name = name
|
|
for body in bodies:
|
|
comp.bRepBodies.add(body)
|
|
|
|
# export stl
|
|
try:
|
|
os.mkdir(save_dir + '/meshes')
|
|
except:
|
|
pass
|
|
exportFolder = save_dir + '/meshes'
|
|
|
|
exportMgr = des.exportManager
|
|
for occ in expRoot.allOccurrences:
|
|
if "base_link" in occ.component.name:
|
|
expName = "base_link"
|
|
else:
|
|
expName = re.sub('[ :()]', '_', occ.component.name)
|
|
expPath = os.path.join(exportFolder, '{}.stl'.format(expName))
|
|
stlOpts = exportMgr.createSTLExportOptions(occ, expPath)
|
|
exportMgr.execute(stlOpts)
|
|
|
|
# remove export Doc
|
|
expDoc.close(False)
|
|
|
|
## https://github.com/django/django/blob/master/django/utils/text.py
|
|
def get_valid_filename(s):
|
|
"""
|
|
Return the given string converted to a string that can be used for a clean
|
|
filename. Remove leading and trailing spaces; convert other spaces to
|
|
underscores; and remove anything that is not an alphanumeric, dash,
|
|
underscore, or dot.
|
|
>>> get_valid_filename("john's portrait in 2004.jpg")
|
|
'johns_portrait_in_2004.jpg'
|
|
"""
|
|
s = str(s).strip().replace(' ', '_')
|
|
return re.sub(r'(?u)[^-\w.]', '', s)
|
|
|
|
|
|
def copy_occs(root):
|
|
"""
|
|
duplicate all the components
|
|
"""
|
|
def copy_body(allOccs, occs):
|
|
"""
|
|
copy the old occs to new component
|
|
"""
|
|
|
|
bodies = occs.bRepBodies
|
|
transform = adsk.core.Matrix3D.create()
|
|
|
|
# Create new components from occs
|
|
# This support even when a component has some occses.
|
|
|
|
new_occs = allOccs.addNewComponent(transform) # this create new occs
|
|
if occs.component.name == 'base_link':
|
|
occs.component.name = 'old_component'
|
|
new_occs.component.name = 'base_link'
|
|
else:
|
|
key = get_valid_filename(occs.fullPathName)
|
|
new_occs.component.name = key
|
|
# new_occs.component.name = re.sub('[ :()]', '_', occs.name)
|
|
new_occs = allOccs.item((allOccs.count-1))
|
|
for i in range(bodies.count):
|
|
body = bodies.item(i)
|
|
body.copyToComponent(new_occs)
|
|
|
|
allOccs = root.occurrences
|
|
# allOccs = root.allOccurrences
|
|
|
|
oldOccs = []
|
|
# coppy_list = [occs for occs in allOccs]
|
|
coppy_list = [occs for occs in root.allOccurrences]
|
|
for occs in coppy_list:
|
|
if occs.bRepBodies.count > 0:
|
|
copy_body(allOccs, occs)
|
|
oldOccs.append(occs)
|
|
|
|
for occs in oldOccs:
|
|
occs.component.name = 'old_component'
|
|
|
|
|
|
# def export_stl(design, save_dir, components):
|
|
# """
|
|
# export stl files into "sace_dir/"
|
|
|
|
|
|
# Parameters
|
|
# ----------
|
|
# design: adsk.fusion.Design.cast(product)
|
|
# save_dir: str
|
|
# directory path to save
|
|
# components: design.allComponents
|
|
# """
|
|
|
|
# # create a single exportManager instance
|
|
# exportMgr = design.exportManager
|
|
# # get the script location
|
|
# try: os.mkdir(save_dir + '/meshes')
|
|
# except: pass
|
|
# scriptDir = save_dir + '/meshes'
|
|
# # export the occurrence one by one in the component to a specified file
|
|
# for component in components:
|
|
# allOccus = component.allOccurrences
|
|
# for occ in allOccus:
|
|
# ## Don't export nested component
|
|
# if occ.childOccurrences.count > 0:
|
|
# continue
|
|
|
|
# if 'old_component' not in occ.component.name:
|
|
# try:
|
|
# key = get_valid_filename(occ.fullPathName)
|
|
# key = key[:-1] ## Will generate an extra "1" in the end, remove it
|
|
# print("Export file: {}".format(key))
|
|
# # fileName = scriptDir + "/" + occ.component.name
|
|
# fileName = scriptDir + "/" + key
|
|
# # create stl exportOptions
|
|
# stlExportOptions = exportMgr.createSTLExportOptions(occ, fileName)
|
|
# stlExportOptions.sendToPrintUtility = False
|
|
# stlExportOptions.isBinaryFormat = True
|
|
# # options are .MeshRefinementLow .MeshRefinementMedium .MeshRefinementHigh
|
|
# stlExportOptions.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementLow
|
|
# exportMgr.execute(stlExportOptions)
|
|
# except:
|
|
# print('Component ' + occ.component.name + ' has something wrong.')
|
|
|
|
|
|
def file_dialog(ui):
|
|
"""
|
|
display the dialog to save the file
|
|
"""
|
|
# Set styles of folder dialog.
|
|
folderDlg = ui.createFolderDialog()
|
|
folderDlg.title = 'Fusion Folder Dialog'
|
|
|
|
# Show folder dialog
|
|
dlgResult = folderDlg.showDialog()
|
|
if dlgResult == adsk.core.DialogResults.DialogOK:
|
|
return folderDlg.folder
|
|
return False
|
|
|
|
|
|
def origin2center_of_mass(inertia, center_of_mass, mass):
|
|
"""
|
|
convert the moment of the inertia about the world coordinate into
|
|
that about center of mass coordinate
|
|
|
|
|
|
Parameters
|
|
----------
|
|
moment of inertia about the world coordinate: [xx, yy, zz, xy, yz, xz]
|
|
center_of_mass: [x, y, z]
|
|
|
|
|
|
Returns
|
|
----------
|
|
moment of inertia about center of mass : [xx, yy, zz, xy, yz, xz]
|
|
"""
|
|
x = center_of_mass[0]
|
|
y = center_of_mass[1]
|
|
z = center_of_mass[2]
|
|
translation_matrix = [y**2+z**2, x**2+z**2, x**2+y**2,
|
|
-x*y, -y*z, -x*z]
|
|
return [ i - mass*t for i, t in zip(inertia, translation_matrix)]
|
|
|
|
|
|
def prettify(elem):
|
|
"""
|
|
Return a pretty-printed XML string for the Element.
|
|
Parameters
|
|
----------
|
|
elem : xml.etree.ElementTree.Element
|
|
|
|
|
|
Returns
|
|
----------
|
|
pretified xml : str
|
|
"""
|
|
rough_string = ElementTree.tostring(elem, 'utf-8')
|
|
reparsed = minidom.parseString(rough_string)
|
|
return reparsed.toprettyxml(indent=" ")
|
|
|