way to change the thread paramters like pitch using the API script

way to change the thread paramters like pitch using the API script

f20212766GTEE9
Explorer Explorer
498 Views
4 Replies
Message 1 of 5

way to change the thread paramters like pitch using the API script

f20212766GTEE9
Explorer
Explorer

I am kind off facing issues in the script part where i want to query threads with different pitch each time it is generated.  

sideFace = bodyExt.sideFaces[0]

threads = newComp.features.threadFeatures

threadDataQuery = threads.threadDataQuery

defaultThreadType = threadDataQuery.defaultMetricThreadType

recommendData = threadDataQuery.recommendThreadData(self.bodyDiameter, False, defaultThreadType)

if recommendData[0] : threadInfo = threads.createThreadInfo(False, defaultThreadType, recommendData[1], recommendData[2]) faces = adsk.core.ObjectCollection.create() faces.add(sideFace) threadInput = threads.createInput(faces, threadInfo) threads.add(threadInput) except: if ui: ui.messageBox('Failed to compute the bolt. This is most likely because the input values define an invalid bolt.')

I suppose I would have to make changes in this part of the sample script which i have taken from the product documentation page pf fusion 360 but On changing the recommendData[0] , recommendData[1], recommendData[2] to any other values, fusion throws an error saying invalid params and genarates a plain bolt without any threads. can you please help me with the script part please ?

0 Likes
499 Views
4 Replies
Replies (4)
Message 2 of 5

BrianEkins
Mentor
Mentor

Here are a couple of samples that will hopefully help. This first one creates a new thread feature on a selected cylindrical face. It passed in the thread type and uses the recommended designation and class.

def createThread(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        try:
            cylFace: adsk.fusion.BRepFace = ui.selectEntity('Select a cylindrical face', adsk.core.SelectionFilters.CylindricalFaces).entity
        except:
            return
        
        cyl: adsk.core.Cylinder = cylFace.geometry
        
        des: adsk.fusion.Design = app.activeProduct
        root = des.rootComponent
        threads = root.features.threadFeatures
        type = 'ANSI Unified Screw Threads'
        (success, threadDesignation, threadClass) = threads.threadDataQuery.recommendThreadData(cyl.radius * 2, False, type)
        if success:
            threadInfo = threads.createThreadInfo(False, type, threadDesignation, threadClass)
            input = threads.createInput(cylFace, threadInfo)
            thread = threads.add(input)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

  

 

This next sample edits a selected thread feature. It changes the pitch, which is defined by the designation. It shows two ways of doing this: one is to modify the thread's designation, and the second is to create a new ThreadInfo object, where you could change all of the thread information and use the new ThreadInfo to modify the thread.

def editThread(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        threadFeature: adsk.fusion.ThreadFeature = None
        try:
            feature = ui.selectEntity('Select a thread feature', adsk.core.SelectionFilters.Features).entity
            if feature.objectType == adsk.fusion.ThreadFeature.classType():
                threadFeature = feature
        except:
            return

        threadInfo = threadFeature.threadInfo

        comp = threadFeature.parentComponent
        threads = comp.features.threadFeatures
        designations = threads.threadDataQuery.allDesignations(threadInfo.threadType, threadInfo.threadSize)

        des = comp.parentDesign
        example1 = True
        if example1:
            # Create a new threadInfo.
            newThreadInfo = threads.createThreadInfo(False, threadInfo.threadType, designations[len(designations)-1], threadInfo.threadClass)
            threadFeature.timelineObject.rollTo(True)
            threadFeature.threadInfo = newThreadInfo
            des.timeline.moveToEnd()
        else:
            threadFeature.timelineObject.rollTo(True)
            threadInfo.threadDesignation = designations[0]
            des.timeline.moveToEnd()
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 3 of 5

f20212766GTEE9
Explorer
Explorer

 

#

 

 

0 Likes
Message 4 of 5

f20212766GTEE9
Explorer
Explorer

I am actually working on a script that detects or identifies the cylindrical portion of the bolt by traversing through the bodies i.e this task has to be performed by the script itself and creates external threading on it, but without using the recommendThreadData function, I wish to know if or not I could set the thread designation and thread class manually every time without changing the default parameters to generate a valid bolt. I am attaching the script below i am having issues when i try to run this fusion shows error and creates a bolt without thread, please suggest necessary changes that could be made in order to perform the intended task of generating bolt with variation in thread designation and thread class to be able to vary the pitch of the thread?

# Author-Autodesk Inc.
# Description-Create bolt with manual threading

import adsk.core, adsk.fusion, traceback
import math

defaultBoltName = 'Bolt'
defaultHeadDiameter = 0.75
defaultBodyDiameter = 0.5
defaultHeadHeight = 0.3125
defaultBodyLength = 1.0
defaultCutAngle = 30.0 * (math.pi / 180)
defaultChamferDistance = 0.03845
defaultFilletRadius = 0.02994
defaultThreadDesignation = 'M10x1.5'  # Example of a metric designation
defaultThreadClass = '6g'  # Example class for external threads

# Global set of event handlers to keep them referenced for the duration of the command
handlers = []
app = adsk.core.Application.get()
if app:
    ui = app.userInterface

newComp = None

def createNewComponent():
    # Get the active design.
    product = app.activeProduct
    design = adsk.fusion.Design.cast(product)
    rootComp = design.rootComponent
    allOccs = rootComp.occurrences
    newOcc = allOccs.addNewComponent(adsk.core.Matrix3D.create())
    return newOcc.component

class BoltCommandExecuteHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            unitsMgr = app.activeProduct.unitsManager
            command = args.firingEvent.sender
            inputs = command.commandInputs

            bolt = Bolt()
            for input in inputs:
                if input.id == 'boltName':
                    bolt.boltName = input.value
                elif input.id == 'headDiameter':
                    bolt.headDiameter = unitsMgr.evaluateExpression(input.expression, "cm")
                elif input.id == 'bodyDiameter':
                    bolt.bodyDiameter = unitsMgr.evaluateExpression(input.expression, "cm")
                elif input.id == 'headHeight':
                    bolt.headHeight = unitsMgr.evaluateExpression(input.expression, "cm")
                elif input.id == 'bodyLength':
                    bolt.bodyLength = adsk.core.ValueInput.createByString(input.expression)
                elif input.id == 'cutAngle':
                    bolt.cutAngle = unitsMgr.evaluateExpression(input.expression, "deg") 
                elif input.id == 'chamferDistance':
                    bolt.chamferDistance = adsk.core.ValueInput.createByString(input.expression)
                elif input.id == 'filletRadius':
                    bolt.filletRadius = adsk.core.ValueInput.createByString(input.expression)
                elif input.id == 'threadDesignation':
                    bolt.threadDesignation = input.value
                elif input.id == 'threadClass':
                    bolt.threadClass = input.value

            bolt.buildBolt()
            args.isValidResult = True

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

class BoltCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args):
        try:
            adsk.terminate()
        except:
            if ui:
                ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

class BoltCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):    
    def __init__(self):
        super().__init__()        
    def notify(self, args):
        try:
            cmd = args.command
            cmd.isRepeatable = False
            onExecute = BoltCommandExecuteHandler()
            cmd.execute.add(onExecute)
            onExecutePreview = BoltCommandExecuteHandler()
            cmd.executePreview.add(onExecutePreview)
            onDestroy = BoltCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            handlers.append(onExecute)
            handlers.append(onExecutePreview)
            handlers.append(onDestroy)

            # Define the inputs
            inputs = cmd.commandInputs
            inputs.addStringValueInput('boltName', 'Bolt Name', defaultBoltName)

            initHeadDiameter = adsk.core.ValueInput.createByReal(defaultHeadDiameter)
            inputs.addValueInput('headDiameter', 'Head Diameter','cm',initHeadDiameter)

            initBodyDiameter = adsk.core.ValueInput.createByReal(defaultBodyDiameter)
            inputs.addValueInput('bodyDiameter', 'Body Diameter', 'cm', initBodyDiameter)

            initHeadHeight = adsk.core.ValueInput.createByReal(defaultHeadHeight)
            inputs.addValueInput('headHeight', 'Head Height', 'cm', initHeadHeight)

            initBodyLength = adsk.core.ValueInput.createByReal(defaultBodyLength)
            inputs.addValueInput('bodyLength', 'Body Length', 'cm', initBodyLength)

            initCutAngle = adsk.core.ValueInput.createByReal(defaultCutAngle)
            inputs.addValueInput('cutAngle', 'Cut Angle', 'deg', initCutAngle)

            initChamferDistance = adsk.core.ValueInput.createByReal(defaultChamferDistance)
            inputs.addValueInput('chamferDistance', 'Chamfer Distance', 'cm', initChamferDistance)

            initFilletRadius = adsk.core.ValueInput.createByReal(defaultFilletRadius)
            inputs.addValueInput('filletRadius', 'Fillet Radius', 'cm', initFilletRadius)

            # Thread designation and class inputs
            inputs.addStringValueInput('threadDesignation', 'Thread Designation', defaultThreadDesignation)
            inputs.addStringValueInput('threadClass', 'Thread Class', defaultThreadClass)

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

class Bolt:
    def __init__(self):
        self._boltName = defaultBoltName
        self._headDiameter = defaultHeadDiameter
        self._bodyDiameter = defaultBodyDiameter
        self._headHeight = defaultHeadHeight
        self._bodyLength = adsk.core.ValueInput.createByReal(defaultBodyLength)
        self._cutAngle = defaultCutAngle
        self._chamferDistance = adsk.core.ValueInput.createByReal(defaultChamferDistance)
        self._filletRadius = adsk.core.ValueInput.createByReal(defaultFilletRadius)
        self._threadDesignation = defaultThreadDesignation
        self._threadClass = defaultThreadClass

    def buildBolt(self):
        try:
            global newComp
            newComp = createNewComponent()
            if newComp is None:
                ui.messageBox('New component failed to create', 'New Component Failed')
                return

            # Step 1: Create a new sketch on the X-Y plane
            sketches = newComp.sketches
            xyPlane = newComp.xYConstructionPlane
            sketch = sketches.add(xyPlane)

            # Step 2: Draw a circle for the bolt body
            sketchCircles = sketch.sketchCurves.sketchCircles
            bodyDiameter = self._bodyDiameter
            bodyCenter = adsk.core.Point3D.create(0, 0, 0)
            sketchCircles.addByCenterRadius(bodyCenter, bodyDiameter / 2)

            # Step 3: Extrude the circle to create the bolt body
            prof = sketch.profiles.item(0)
            extrudes = newComp.features.extrudeFeatures
            bodyLength = self._bodyLength
            extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
            distance = adsk.core.ValueInput.createByReal(bodyLength)
            extInput.setDistanceExtent(False, distance)
            extInput.isSolid = True
            bodyExt = extrudes.add(extInput)

            # Step 4: Verify if bodyExt has side faces, which are required for threading
            if bodyExt and bodyExt.sideFaces.count > 0:
                sideFace = bodyExt.sideFaces[0]  # Get the first side face for threading
                threads = newComp.features.threadFeatures
                threadDataQuery = threads.threadDataQuery

                # Set the thread info manually
                threadInfo = threads.createThreadInfo(False, 'Metric', self._threadDesignation, self._threadClass)
                faces = adsk.core.ObjectCollection.create()
                faces.add(sideFace)
                threadInput = threads.createInput(faces, threadInfo)
                threadInput.isFullLength = True  # Adjust this if you want a custom thread length
                threads.add(threadInput)
            else:
                ui.messageBox('Error: The body or side faces of the extrude were not created correctly.')

        except:
            if ui:
                ui.messageBox('Failed to compute the bolt. This is most likely because the input values define an invalid bolt.')

def run(context):
    try:
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)
        if not design:
            ui.messageBox('The DESIGN workspace must be active when running this script.')
            return
        commandDefinitions = ui.commandDefinitions
        cmdDef = commandDefinitions.itemById('Bolt')
        if not cmdDef:
            cmdDef = commandDefinitions.addButtonDefinition('Bolt', 'Create Bolt', 'Create a bolt.', './resources')
        onCommandCreated = BoltCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        handlers.append(onCommandCreated)
        inputs = adsk.core.NamedValues.create()
        cmdDef.execute(inputs)
        adsk.autoTerminate(False)
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

0 Likes
Message 5 of 5

BrianEkins
Mentor
Mentor

You don't have to use the recommended thread data, but you do have to use values that correspond to one of the threads in the XML files installed here: C:\Users\<username>\AppData\Local\Autodesk\webdeploy\production\<VersionSpecificID>\Fusion\Server\Fusion\Configuration\ThreadData. The API provides the ThreadDataQuery object to make it relatively easy to query these XML files.

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes