Reply
Community Visitor
5 Posts
Accepted Solution

Trouble passing ValueInput as argument to features

101 Views, 9 Replies
2 weeks ago

I'm creating some UserParameters, and trying to pass them as arguments during creation of various shapes and features. When passing them, I use ValueInput.createByString("nameOfParameter"). This isn't working (error messages below). It works in the GUI. Here's my code:

 

import adsk.core, adsk.fusion, traceback

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

        # Get the root component of the active design
        rootComp = design.rootComponent
        
        #defining userParams
        userParams = design.userParameters
        userParams.add("strawDia", adsk.core.ValueInput.createByString("10 mm"), "mm", "")
        userParams.add("noOfPegs", adsk.core.ValueInput.createByString("3"), "", "") 
                
        origin = adsk.core.Point3D.create(0, 0, 0)
        
        #first sketch, central hub
        hubSketch = rootComp.sketches.add(rootComp.xYConstructionPlane)
        hubCircles = hubSketch.sketchCurves.sketchCircles
        hubCircles.addByCenterRadius(origin, adsk.core.ValueInput.createByString("strawDia"))
        
        #uMag = adsk.core.UnitsManager
        #print(uMag.isValidExpression("strawDia*2", "mm"))
        
        

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

To see if it was getting evaluated correctly, I tried to use evaluateExpression and isValidExpression, but it always tells me I have the wrong type/number of arguments despite me adhering to the specification in the documentation.

 

I cannot use any of the ValueInput creation methods, not even createByReal. Only sending an actual double seems to work.

Screen Shot 2017-04-13 at 11.16.06 AM.png

 

 

Screen Shot 2017-04-13 at 10.14.20 AM.png

 

Could I pointed to what I'm missing?

You can deal with the ModelParameters collection.

 

I modified the CircularPattern feature API sample available here

 

import adsk.core, adsk.fusion, traceback
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
# Create a document.
doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
# Define user parameters
userParams = design.userParameters
if userParams.itemByName("strawDia"):
userParams.itemByName("strawDia").deleteMe()
if userParams.itemByName("noOfPegs"):
userParams.itemByName("noOfPegs").deleteMe()
userParams.add("strawDia", adsk.core.ValueInput.createByString("10 mm"), "mm", "")
userParams.add("noOfPegs", adsk.core.ValueInput.createByString("3"), "", "")
# Get the root component of the active design.
rootComp = design.rootComponent
# Create sketch
sketches = rootComp.sketches
sketch = sketches.add(rootComp.xZConstructionPlane)
sketchCircles = sketch.sketchCurves.sketchCircles
centerPoint = adsk.core.Point3D.create(10, 0, 0)
circle = sketchCircles.addByCenterRadius(centerPoint, userParams.itemByName("strawDia").value)
centerPoint.x = 1.0
dim = sketch.sketchDimensions.addDiameterDimension(sketchCircles.item(0), centerPoint)
dim.parameter.expression = "strawDia"
# Get the profile defined by the circle.
prof = sketch.profiles.item(0)
# Create an extrusion input
extrudes = rootComp.features.extrudeFeatures
extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Define that the extent is a distance extent of 5 cm.
distance = adsk.core.ValueInput.createByReal(5)
extInput.setDistanceExtent(False, distance)
# Create the extrusion.
ext = extrudes.add(extInput)
# Get the body created by extrusion
body = rootComp.bRepBodies.item(0)
# Create input entities for circular pattern
inputEntites = adsk.core.ObjectCollection.create()
inputEntites.add(body)
# Get Y axis for circular pattern
yAxis = rootComp.yConstructionAxis
# Create the input for circular pattern
circularFeats = rootComp.features.circularPatternFeatures
circularFeatInput = circularFeats.createInput(inputEntites, yAxis)
# Set the quantity of the elements
circularFeatInput.quantity = adsk.core.ValueInput.createByReal(userParams.itemByName("noOfPegs").value)
# Set the angle of the circular pattern
circularFeatInput.totalAngle = adsk.core.ValueInput.createByString('180 deg')
# Set symmetry of the circular pattern
circularFeatInput.isSymmetric = False
# Create the circular pattern
circularFeat = circularFeats.add(circularFeatInput)
# Link feature properties withg user parameters
for param in rootComp.modelParameters:
if param.role=="AlongDistance":
param.expression = "1.5*strawDia"
if param.role=="countU":
param.expression = "noOfPegs"
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

It's up to you to find the correct parameter in the modelParameters list.

I checked the role property in the code above but it could be different in more complex model.

Explorer
4 Posts
3 Kudos
1 Solution

Re: Trouble passing ValueInput as argument to features

2 weeks ago in reply to: swagath.sivakumar

Try this :

 

hubCircles.addByCenterRadius(origin, userParams.itemByName("strawDia").value)
Community Visitor
5 Posts

Re: Trouble passing ValueInput as argument to features

2 weeks ago in reply to: jbtechlab

Okay, this works, but now if I change the value of strawDia under 'Change User Parameters', the model doesn't update automatically. How do I pass strawDia such that anytime it is modified, the whole model is recomputed and redrawn, just like in the GUI? Or in C++ parlance, how do I pass by reference and not by value?

Participant
14 Posts

Re: Trouble passing ValueInput as argument to features

2 weeks ago in reply to: swagath.sivakumar
ui.commandDefinitions.itemById('FusionComputeAllCommand').execute()

is your friend to force a recmputation

Explorer
4 Posts
3 Kudos
1 Solution

Re: Trouble passing ValueInput as argument to features

2 weeks ago in reply to: stefan

Add a dimension and link it to the parameter:

        origin.x = 1.0
        dim = hubSketch.sketchDimensions.addDiameterDimension(hubCircles.item(0), origin)
        dim.parameter.expression = "strawDia"

And as you specify diameter instead of radius, my previous answer should be:

 

hubCircles.addByCenterRadius(origin, 0.5*userParams.itemByName("strawDia").value)
Community Visitor
5 Posts

Re: Trouble passing ValueInput as argument to features

a week ago in reply to: jbtechlab

This seems to be workable.

 

But why do you change the x-coordinate of origin? Without it, I get an error saying input argument is invalid. What is the text point/dimension text mentioned in the docs?

 

Also, after using your code, the circle becomes of size strawDia, while I've assigned the expression "strawDia*2* to it.

Explorer
4 Posts
3 Kudos
1 Solution

Re: Trouble passing ValueInput as argument to features

a week ago in reply to: swagath.sivakumar

swagath.sivakumar a écrit :

But why do you change the x-coordinate of origin? Without it, I get an error saying input argument is invalid. What is the text point/dimension text mentioned in the docs?


To add diameter dimension, you need to specify a point that is not the origin of the circle. Read this thread : Possible bug in addDiameterDimension

 


swagath.sivakumar a écrit :

Also, after using your code, the circle becomes of size strawDia, while I've assigned the expression "strawDia*2* to it.


Sorry but I don't understant what you mean.
What value is represented by strawDia ? A diameter or a radius ?

Community Visitor
5 Posts

Re: Trouble passing ValueInput as argument to features

a week ago in reply to: jbtechlab

strawDia is a diameter, but the component I'm creating is not the straw. So all the measurements for this component are proportional to what the straw diameter will be.

 

Anyway, thank you for the tip regarding dimensions. The cylinder radii in my model are now completely parametric. Any idea how I can do the same for pattern arguments? Right now, I'm passing a user parameter's value for the countU of a pattern like so:

userParams = design.userParameters
userParams.add("noOfPegs", adsk.core.ValueInput.createByString("3"), "", "")
noOfPegs = userParams.itemByName("noOfPegs")


circularFeats = rootComp.features.circularPatternFeatures
circularFeatInput = circularFeats.createInput(inputEntities, zAxis)
circularFeatInput.quantity = adsk.core.ValueInput.createByReal(noOfPegs.value) #<------------------------------- here
circularFeatInput.totalAndle = adsk.core.ValueInput.createByString('360 deg')
circularFeat = circularFeats.add(circularFeatInput)

I'm also wanting to use strawDia similarly to set some extrude distances:

#make circle for profile, create extrude input, blah blah

extrusionInput.setDistanceExtent(True, adsk.core.ValueInput.createByReal(strawDia.value*1.5))
extrusion = extrudes.add(extrusionInput)

I need the measurements to automatically update whenever strawDia changes. Solving this would completely solve my doubt. And thank you, you've been really helpful so far!

 

 

Explorer
4 Posts
3 Kudos
1 Solution

Re: Trouble passing ValueInput as argument to features

a week ago in reply to: swagath.sivakumar

You can deal with the ModelParameters collection.

 

I modified the CircularPattern feature API sample available here

 

import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        
        # Create a document.
        doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType)
 
        product = app.activeProduct
        design = adsk.fusion.Design.cast(product)

        # Define user parameters
        userParams = design.userParameters
        
        if userParams.itemByName("strawDia"):
            userParams.itemByName("strawDia").deleteMe()
        if userParams.itemByName("noOfPegs"):
            userParams.itemByName("noOfPegs").deleteMe()
            
        userParams.add("strawDia", adsk.core.ValueInput.createByString("10 mm"), "mm", "")
        userParams.add("noOfPegs", adsk.core.ValueInput.createByString("3"), "", "") 

        # Get the root component of the active design.
        rootComp = design.rootComponent
        
        # Create sketch
        sketches = rootComp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketchCircles = sketch.sketchCurves.sketchCircles
        centerPoint = adsk.core.Point3D.create(10, 0, 0)
        circle = sketchCircles.addByCenterRadius(centerPoint, userParams.itemByName("strawDia").value)

        centerPoint.x = 1.0
        dim = sketch.sketchDimensions.addDiameterDimension(sketchCircles.item(0), centerPoint)
        dim.parameter.expression = "strawDia"        
        
        # Get the profile defined by the circle.
        prof = sketch.profiles.item(0)

        # Create an extrusion input
        extrudes = rootComp.features.extrudeFeatures
        extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        
        # Define that the extent is a distance extent of 5 cm.
        distance = adsk.core.ValueInput.createByReal(5)
        extInput.setDistanceExtent(False, distance)

        # Create the extrusion.
        ext = extrudes.add(extInput)
        
        # Get the body created by extrusion
        body = rootComp.bRepBodies.item(0)
        
        # Create input entities for circular pattern
        inputEntites = adsk.core.ObjectCollection.create()
        inputEntites.add(body)
        
        # Get Y axis for circular pattern
        yAxis = rootComp.yConstructionAxis
        
        # Create the input for circular pattern
        circularFeats = rootComp.features.circularPatternFeatures
        circularFeatInput = circularFeats.createInput(inputEntites, yAxis)
        
        # Set the quantity of the elements
        circularFeatInput.quantity = adsk.core.ValueInput.createByReal(userParams.itemByName("noOfPegs").value)
        
        # Set the angle of the circular pattern
        circularFeatInput.totalAngle = adsk.core.ValueInput.createByString('180 deg')
        
        # Set symmetry of the circular pattern
        circularFeatInput.isSymmetric = False
        
        # Create the circular pattern
        circularFeat = circularFeats.add(circularFeatInput)
        
        # Link feature properties withg user parameters
        for param in rootComp.modelParameters:
            if param.role=="AlongDistance":
                param.expression = "1.5*strawDia"
            if param.role=="countU":
                param.expression = "noOfPegs"
                
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

It's up to you to find the correct parameter in the modelParameters list.

I checked the role property in the code above but it could be different in more complex model.

Autodesk Support
1259 Posts
353 Kudos
369 Solutions

Re: Trouble passing ValueInput as argument to features

a week ago in reply to: swagath.sivakumar

Here's a version of your original program that I believe does what you want.

 

import adsk.core, adsk.fusion, traceback

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

        # Get the root component of the active design
        rootComp = design.rootComponent

        #defining userParams
        userParams = design.userParameters
        param = userParams.add("strawDia", adsk.core.ValueInput.createByString("10 mm"), "mm", "")
        diaValue = param.value
        userParams.add("noOfPegs", adsk.core.ValueInput.createByString("3"), "", "") 
                
        origin = adsk.core.Point3D.create(0, 0, 0)
        
        hubSketch = rootComp.sketches.add(rootComp.xYConstructionPlane)
        
        # Draw the circle.
        hubCircles = hubSketch.sketchCurves.sketchCircles
        circle = hubCircles.addByCenterRadius(origin, diaValue/2)

        # Add a dimnension constraint to control the size.
        dims = hubSketch.sketchDimensions
        txtPnt = adsk.core.Point3D.create(origin.x + diaValue*.5, origin.y + diaValue*.5, 0)
        diaDim = dims.addDiameterDimension(circle, txtPnt, True)        
        diaDim.parameter.expression = param.name
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog