Maintaining User Parameter references

Maintaining User Parameter references

Anonymous
Not applicable
2,146 Views
4 Replies
Message 1 of 5

Maintaining User Parameter references

Anonymous
Not applicable

Evening...

    I'm working my way through different parts of the API reference trying to find what I need for a larger project and writing mini test scripts. In the following example I create a user-parameterized sketch, extrude it and make it a component and then create some copies of the component and the naming the different bits along the way. 

 

    If after the script runs I change either of the user-parameters, the drawing does not update. I expect that this is because I am setting the value of the radius and separation to be equal to the "value" of the respective user-parameters (i.e. a double) and its not storing a direct reference to the user-parameters, but I'm not sure how to do this. If someone could let me know know to keep the sketches referenced to the user-parameters it would be appreciated. Also and general comments about coding best practices relative to my example are welcome too.

 

    

import adsk.core, adsk.fusion, adsk.cam, traceback

# Globals
_user_parameters = {}


def createNewComponent(rootComp):
    allOccs = rootComp.occurrences
    newOcc = allOccs.addNewComponent(adsk.core.Matrix3D.create())
    return newOcc.component

def createParam(design, name, value, units, comment):
    userValue = adsk.core.ValueInput.createByString(value)
    design.userParameters.add(name, userValue, units, comment)

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

        #create user parameters
        cm = design.unitsManager.defaultLengthUnits
        createParam(design, 'radius', '5cm', cm, '')
        createParam(design, 'separation', '10cm', cm, '')
 
        
        #create a new component and name it
        comp = createNewComponent(rootComp)
        comp.name = "myComponent"
 
        #create and name a circle sketch within the component
        sketches = comp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketch.name = "mySketch"
        sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), _user_parameters['radius'].value)

        #create an extrusion of the circle within the component and name the body it produces
        extrudes = comp.features.extrudeFeatures
        prof = sketch.profiles[0]
        extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        distance = adsk.core.ValueInput.createByReal(5)
        extInput.setDistanceExtent(False, distance)
        extrusion = extrudes.add(extInput)
        body = extrusion.bodies.item(0)
        body.name = "myBody"


        #Create some copies (3x3)
        allOccs = rootComp.occurrences
        transform = adsk.core.Matrix3D.create()
        
        separation = _user_parameters['separation'].value
        for x in range(0,3):
            for z in range (0, 3):
                transform.translation = adsk.core.Vector3D.create(x * separation, 0, z * separation)
                allOccs.addExistingComponent(comp, transform)
                
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
0 Likes
Accepted solutions (1)
2,147 Views
4 Replies
Replies (4)
Message 2 of 5

ekinsb
Alumni
Alumni
Accepted solution

It looks like you're creating the parameters OK but the problem is how you're using the parameters.  When you're using a parameter you are getting the parameter but then you're just getting the current value of the parameter and using that as input instead of the parameter itself.  Let's look at your code to create the sketch circle, which is below.  

 

        #create and name a circle sketch within the component
        sketches = comp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketch.name = "mySketch"
        sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), _user_parameters['radius'].value)

 

A circle all by itself is not driven by any parameters so even though you're getting the current value of the parameter and using that to create the circle it's not associated with the parameter in any way.  In order to control sketch geometry parametrically you need to add dimension constraints to it.  Here's a modified version of your code to do that and to set the dimension so it's dependent on the parameter named 'radius'.

 

        #create and name a circle sketch within the component
        sketches = comp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketch.name = "mySketch"
        circ = sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), _user_parameters['radius'].value)

 

Here's a version that adds the dimension constraint and makes it dependent on the user parameter 'radius'.

        #create and name a circle sketch within the component
        sketches = comp.sketches
        sketch = sketches.add(rootComp.xZConstructionPlane)
        sketch.name = "mySketch"
        circ = sketch.sketchCurves.sketchCircles.addByCenterRadius(adsk.core.Point3D.create(0,0,0), _user_parameters['radius'].value)

        # Add a dimension constraint and edit it's parameter to be dependent on 'radius'.
        dims = sketch.sketchDimensions
        circDim = dims.addRadialDimension(circ, adsk.core.Point3D.create(3,3,0))
        circDim.parameter.expression = 'radius'

When you're moving occurrences using the API it's the equivalent of dragging an occurrence around in the UI and that is not a parametric operation that you can control with parameters.


Brian Ekins
Inventor and Fusion 360 API Expert
Mod the Machine blog
Message 3 of 5

Anonymous
Not applicable

Thanks Brian,

    Just what I was after. In case anyone else find this example useful (and is wondering why it doesn't work) I'd accidentally deleted part of the CreateParam function (which I later referenced) before posting so I wasn't populating the _user_parameters dictionary.

 

def createParam(design, name, value, units, comment):
    userValue = adsk.core.ValueInput.createByString(value)
    newParam = design.userParameters.add(name, userValue, units, comment)
    _user_parameters[name] = newParam

Paul.

0 Likes
Message 4 of 5

jaco.waes
Contributor
Contributor

This really should go in to the examples in the documentation !

 

@ekinsb  ... how about using the same tie for an extrusion.

 

    extrude_input = extrudes.createInput(profile, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
    thickness_distance = adsk.fusion.DistanceExtentDefinition.create(ValueInput.createByReal(project_top_thickness))
thickness_distance.distance.expression = 'top_thickness'
    extrude_input.setOneSideExtent(thickness_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection)
    top_extrusion = extrudes.add(extrude_input)
    

 

I tried the above but in 'thickness_distance.distance' distance is noneType ?

 

0 Likes
Message 5 of 5

BrianEkins
Mentor
Mentor

I agree that this should be explained in the documentation. There should be an overview topic on both sketches and features where this could be covered. Hopefully, in the future.

 

Assuming "project_top_thickness_name" is a variable referencing an existing parameter you want the depth of the extrusion to use, the following code should do that.

extrude_input = extrudes.createInput(profile, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
thickness_distance = adsk.fusion.DistanceExtentDefinition.create(ValueInput.createByString(project_top_thickness.name))
extrude_input.setOneSideExtent(thickness_distance, adsk.fusion.ExtentDirections.PositiveExtentDirection)
top_extrusion = extrudes.add(extrude_input)

 

 

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