3mf export script issue

3mf export script issue

marcus_harrysson
Explorer Explorer
850 Views
5 Replies
Message 1 of 6

3mf export script issue

marcus_harrysson
Explorer
Explorer

Keeping this short and concise. I have a snippet of code that has been outputting STLs. now I want 3mf. 
As I understand this support is pretty new therefore I found no good example on its use. 

I need to call the exportmanager and tell it to go with 3mf some how, but not sure if im doing it right, the error I got seem to indicate im using this row wrong below since it being a variable.  

So could a kind helper guide me how to setup my code for 3mf? 🙂 

Thanks in advance!

 

 

exportMgr = exportManager_var.createC3MFExportOptions(geometry)

 

 



 

 

import adsk.core, adsk.fusion, adsk.cam, traceback
import math, os.path
from os import path
 
def captureThumpnail(filename, app, view):
 
    camera = view.camera
 
    target = adsk.core.Point3D.create(0,0,0)
    up = adsk.core.Vector3D.create(0,0,1)
    dist = imageDistance
    # eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)))
    eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (6/16)))
    
    camera.eye = eye
    camera.target = target
    camera.upVector = up
 
    camera.isSmoothTransition = False
    view.camera = camera
    adsk.doEvents() 
    view.refresh()
    app.activeViewport.saveAsImageFile(filename, 0, 0)
 
def captureSweep(filename, app, view):
    try:
        camera = view.camera
        
        target = adsk.core.Point3D.create(0,0,0)
        up = adsk.core.Vector3D.create(0,0,1)
        steps = 1000
        
        dist = imageDistance
    
        for i in range(0, steps):
            eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (i/steps)), dist * math.sin((math.pi*2) * (i/steps)), dist * math.sin((math.pi*2) * (7/16)))
            
            camera.eye = eye
            camera.target = target
            camera.upVector = up
        
            camera.isSmoothTransition = False
            view.camera = camera
            adsk.doEvents()
            view.refresh()
            app.activeViewport.saveAsImageFile(filename + str(i).zfill(int(math.log10(steps))+1), 0, 0)
    except:
        ui = app.userInterface
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
 
def createRotationTransformation(rotationVector):
    trans = adsk.core.Matrix3D.create(
    
    rotX = adsk.core.Matrix3D.create()
    rotX.setToRotation(math.pi/2*rotationVector[0], adsk.core.Vector3D.create(1,0,0), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotX)
    
    rotY = adsk.core.Matrix3D.create()
    rotY.setToRotation(math.pi/2*rotationVector[1], adsk.core.Vector3D.create(0,1,0), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotY)
    
    rotZ = adsk.core.Matrix3D.create()
    rotZ.setToRotation(math.pi/2*rotationVector[2], adsk.core.Vector3D.create(0,0,1), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotZ)
 
    return trans
 
def processToSave(app, ui, design, outputFolder):
    des = app.activeProduct
    allComps = des.allComponents
    # comp = comps.itemByName('CompName')
 
    # f = open(outputFolder + '/' + "demofile2.txt", "a")
    # f.write("Now the file has more content!")
    # f.close()
 
    for outputSubfolder in toSave.keys():
        subfolder = outputFolder + '/' + outputSubfolder + '/'
        # ui.messageBox(subfolder)
        if not os.path.exists(subfolder):
            os.makedirs(subfolder)
        for outputObject in toSave[outputSubfolder]:
 
            exportMgr = exportManager_var.createC3MFExportOptions(geometry)
            inputentities = adsk.core.ObjectCollection.create()
 
            if 'filename' in outputObject.keys():
                filename = subfolder + outputObject['filename'] + '.3mf'
            else:
                if 'body' in outputObject.keys():
                    filename = subfolder + outputObject['component'] + ' ' + outputObject['body'] + '.3mf'
                else:
                    filename = subfolder + outputObject['component'] + '.3mf'
                
 
            if 'body' in outputObject.keys():
               # ui.messageBox(filename)
                comp = allComps.itemByName(outputObject['component'])
                inputentities.add(comp.bRepBodies.itemByName(outputObject['body']))
                stlOptions = exportMgr.createSTLExportOptions(comp.bRepBodies.itemByName(outputObject['body']))
            else:
                # ui.messageBox(filename)
                comp = allComps.itemByName(outputObject['component'])
                inputentities.add(comp.bRepBodies.item(0))
                stlOptions = exportMgr.createSTLExportOptions(comp.bRepBodies.item(0))
 
 
 
            # ui.messageBox("working on %s" % comp.bRepBodies.item(0).name)
            
            trans = createRotationTransformation(outputObject['rotation'])
 
            moveInput = comp.features.moveFeatures.createInput(inputentities, trans)
            comp.features.moveFeatures.add(moveInput)
 
            stlOptions.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementMedium
            stlOptions.filename = filename
            exportMgr.execute(stlOptions)
 
            # ui.messageBox("moveFeatures count %d" % comp.features.moveFeatures.count)
            comp.features.moveFeatures.item(comp.features.moveFeatures.count-1).deleteMe()
 
            
 
def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
            
        design = adsk.fusion.Design.cast(app.activeProduct) 
        userParams = design.userParameters
        rootComp = design.rootComponent
 
        msg = ''
        outputFolder = ''                
            
        # Set styles of file dialog.
        folderDlg = ui.createFolderDialog()
        folderDlg.title = 'Fusion Folder Dialog' 
        
        # Show folder dialog
        dlgResult = folderDlg.showDialog()
        if dlgResult == adsk.core.DialogResults.DialogOK:
            msg += '\nselect folder: {}'.format(folderDlg.folder)
            outputFolder = folderDlg.folder
            if path.exists(outputFolder):
                for designConfig in designConfigs:
                    filename = outputFolder + '/' + designConfig['foldername'] + '/' + designConfig['foldername']
                    if 'parameters' in designConfig.keys():
                        for paramKey in designConfig['parameters'].keys():
                            userParams.itemByName(paramKey).expression = designConfig['parameters'][paramKey]    
                        app.activeViewport.refresh()
                    if designConfig['generateTurntable']:
                        captureSweep(filename + '-sweep/', app, app.activeViewport)
                    if designConfig['generateMockup']:
                        captureThumpnail(filename + '-mockup', app, app.activeViewport)
                    if designConfig['generate3mfs']:
                        processToSave(app, ui, design, outputFolder + '/' + designConfig['foldername'])
                ui.messageBox('done')
            else:
                ui.messageBox('Bad Path')
        else: # User cancelled
            pass
 
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

 

0 Likes
851 Views
5 Replies
Replies (5)
Message 2 of 6

marcus_harrysson
Explorer
Explorer

Another attempt, I think this is more along the correct lines but still messed up! 

Error generated included below:

marcus_harrysson_0-1648065799668.png

 

 

import adsk.core, adsk.fusion, adsk.cam, traceback
import math, os.path
from os import path

def captureThumpnail(filename, app, view):

    camera = view.camera

    target = adsk.core.Point3D.create(0,0,0)
    up = adsk.core.Vector3D.create(0,0,1)
    dist = imageDistance
    # eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)))
    eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (3/8)), dist * math.sin((math.pi*2) * (6/16)))
    
    camera.eye = eye
    camera.target = target
    camera.upVector = up

    camera.isSmoothTransition = False
    view.camera = camera
    adsk.doEvents() 
    view.refresh()
    app.activeViewport.saveAsImageFile(filename, 0, 0)

def captureSweep(filename, app, view):
    try:
        camera = view.camera
        
        target = adsk.core.Point3D.create(0,0,0)
        up = adsk.core.Vector3D.create(0,0,1)
        steps = 1000
        
        dist = imageDistance
    
        for i in range(0, steps):
            eye = adsk.core.Point3D.create(dist * math.cos((math.pi*2) * (i/steps)), dist * math.sin((math.pi*2) * (i/steps)), dist * math.sin((math.pi*2) * (7/16)))
            
            camera.eye = eye
            camera.target = target
            camera.upVector = up
        
            camera.isSmoothTransition = False
            view.camera = camera
            adsk.doEvents()
            view.refresh()
            app.activeViewport.saveAsImageFile(filename + str(i).zfill(int(math.log10(steps))+1), 0, 0)
    except:
        ui = app.userInterface
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

def createRotationTransformation(rotationVector):
    trans = adsk.core.Matrix3D.create()
    
    rotX = adsk.core.Matrix3D.create()
    rotX.setToRotation(math.pi/2*rotationVector[0], adsk.core.Vector3D.create(1,0,0), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotX)
    
    rotY = adsk.core.Matrix3D.create()
    rotY.setToRotation(math.pi/2*rotationVector[1], adsk.core.Vector3D.create(0,1,0), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotY)
    
    rotZ = adsk.core.Matrix3D.create()
    rotZ.setToRotation(math.pi/2*rotationVector[2], adsk.core.Vector3D.create(0,0,1), adsk.core.Point3D.create(0,0,0))
    trans.transformBy(rotZ)

    return trans

def processToSave(app, ui, design, outputFolder):
    des = app.activeProduct
    allComps = des.allComponents
    # comp = comps.itemByName('CompName')

    # f = open(outputFolder + '/' + "demofile2.txt", "a")
    # f.write("Now the file has more content!")
    # f.close()

    for outputSubfolder in toSave.keys():
        subfolder = outputFolder + '/' + outputSubfolder + '/'
        # ui.messageBox(subfolder)
        if not os.path.exists(subfolder):
            os.makedirs(subfolder)
        for outputObject in toSave[outputSubfolder]:

            exportMgr = adsk.fusion.ExportManager.cast(design.exportManager)
            inputentities = adsk.core.ObjectCollection.create()

            if 'filename' in outputObject.keys():
                filename = subfolder + outputObject['filename'] + '.3mf'
            else:
                if 'body' in outputObject.keys():
                    filename = subfolder + outputObject['component'] + ' ' + outputObject['body'] + '.3mf'
                else:
                    filename = subfolder + outputObject['component'] + '.3mf'
                

            if 'body' in outputObject.keys():
               # ui.messageBox(filename)
                comp = allComps.itemByName(outputObject['component'])
                inputentities.add(comp.bRepBodies.itemByName(outputObject['body']))
                C3MFOptions = exportMgr.createC3MFExportOptions(comp.bRepBodies.itemByName(outputObject['body']))
            else:
                # ui.messageBox(filename)
                comp = allComps.itemByName(outputObject['component'])
                inputentities.add(comp.bRepBodies.item(0))
                C3MFOptions = exportMgr.createC3MFExportOptions(comp.bRepBodies.item(0))



            # ui.messageBox("working on %s" % comp.bRepBodies.item(0).name)
            
            trans = createRotationTransformation(outputObject['rotation'])

            moveInput = comp.features.moveFeatures.createInput(inputentities, trans)
            comp.features.moveFeatures.add(moveInput)

            C3MFoptions.meshRefinement = adsk.fusion.MeshRefinementSettings.MeshRefinementMedium
            C3MFoptions.filename = filename
            exportMgr.execute(C3MFoptions)

            # ui.messageBox("moveFeatures count %d" % comp.features.moveFeatures.count)
            comp.features.moveFeatures.item(comp.features.moveFeatures.count-1).deleteMe()

            

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
            
        design = adsk.fusion.Design.cast(app.activeProduct) 
        userParams = design.userParameters
        rootComp = design.rootComponent

        msg = ''
        outputFolder = ''                
            
        # Set styles of file dialog.
        folderDlg = ui.createFolderDialog()
        folderDlg.title = 'Fusion Folder Dialog' 
        
        # Show folder dialog
        dlgResult = folderDlg.showDialog()
        if dlgResult == adsk.core.DialogResults.DialogOK:
            msg += '\nselect folder: {}'.format(folderDlg.folder)
            outputFolder = folderDlg.folder
            if path.exists(outputFolder):
                for designConfig in designConfigs:
                    filename = outputFolder + '/' + designConfig['foldername'] + '/' + designConfig['foldername']
                    if 'parameters' in designConfig.keys():
                        for paramKey in designConfig['parameters'].keys():
                            userParams.itemByName(paramKey).expression = designConfig['parameters'][paramKey]    
                        app.activeViewport.refresh()
                    if designConfig['generateTurntable']:
                        captureSweep(filename + '-sweep/', app, app.activeViewport)
                    if designConfig['generateMockup']:
                        captureThumpnail(filename + '-mockup', app, app.activeViewport)
                    if designConfig['generateC3MFs']:
                        processToSave(app, ui, design, outputFolder + '/' + designConfig['foldername'])
                ui.messageBox('done')
            else:
                ui.messageBox('Bad Path')
        else: # User cancelled
            pass

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

 

 

0 Likes
Message 3 of 6

kandennti
Mentor
Mentor

Hi @marcus_harrysson .

 

We were not able to try it due to many deficiencies.
(imageDistance,toSave,C3MFoptions,designConfigs)

 

I created and tested a sample that exports a very simple 3MF file and was able to export it without any problems.

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

_exportDir = 'C:/temp'

def run(context):
    ui: adsk.core.UserInterface = 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

        exportMgr: adsk.fusion.ExportManager = des.exportManager

        global _exportDir
        path = f'{_exportDir}/{root.name}.3mf'
        c3mfOpt: adsk.fusion.C3MFExportOptions = exportMgr.createC3MFExportOptions(
            root,
            path
        )
        exportMgr.execute(c3mfOpt)

        ui.messageBox(f'Done\n{path}')

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Message 4 of 6

marcus_harrysson
Explorer
Explorer
Thank you so much, I think I should be able to join that into my code and make it work.
STL-sample code helped me before, so shall this, once again thanks 😃
0 Likes
Message 5 of 6

marcus_harrysson
Explorer
Explorer

well I manage to export the entire model like this so it it working somewhat BUT, in the old script I have that output STL there is this part  in the beginning:

 

toSave = {
    'Y Axis': [
      {'component':'Y Axis','component':'Left','component':'BF12-EndStopMount v8','component':'BF12 Block','filename':'BF12 Mount', 'rotation':[1,0,0]},
      {'component':'Y Axis','component':'Left','component':'Y Roller','component':'Ball Screw Faceplate','filename':'Ballscrew Faceplate Front', 'rotation':[1,0,0]},
      {'component':'Y Axis','component':'Left','component':'Y Roller','component':'Ball Screw Faceplate','component':'Rear','filename':'Ballscrew Faceplate Rear', 'rotation':[3,0,0]},
      {'component':'Y Axis','component':'Left','component':'Nema23','filename':'Y Axis Nema23 Motor Mount', 'filename':'Y Axis Nema 23 Mount' , 'rotation':[1,0,0]},
      {'component':'Y Axis','component':'Left','component':'BK12LimitMount v5','component': 'BK12 Block','filename':'Y Axis BK12 Mount', 'rotation':[3,0,0]},
    ],

 

Which sets which parts of the model I want to export, how do I adapt the 3mf-output to use these?

0 Likes
Message 6 of 6

kandennti
Mentor
Mentor

@marcus_harrysson .

 

I don't understand what you mean, and without the entire code and sample data, I can't try.

0 Likes