How to perform operations on User Parameters?

How to perform operations on User Parameters?

ph0en1x01
Contributor Contributor
4,621 Views
13 Replies
Message 1 of 14

How to perform operations on User Parameters?

ph0en1x01
Contributor
Contributor

 

 

Width='Width'
widthValue='65.7 cm'
unitsMgr=design.unitsManager
realInputNumber=unitsMgr.evaluateExpression(widthValue,unitsMgr.defaultLengthUnits)
realValueInput=adsk.core.ValueInput.createByReal(realInputNumber)
design.userParameters.add(Width,realValueInput,unitsMgr.defaultLengthUnits,'')
Width = adsk.core.ValueInput.createByString(Width)
multiply=Width*2 #Error
addition=Width+Width #Error

 

I get various errors when I directly multiply the variables.
My solution:

 

Width2 = design.userParameters.itemByName(Width).value

 

However, in this case, the Width2 value in the 3D model does not change when I adjust the slider in the GUI. Is there a way to dynamically change the Width value with the slider and still perform operations on it?"

0 Likes
4,622 Views
13 Replies
Replies (13)
Message 2 of 14

BrianEkins
Mentor
Mentor

Your code is failing because you are attempting to perform operations on variable types that don't support those operations.

 

At first, the variable "Width" is a string, but then in line 7, you reassign it so it is now a ValueInput object. A ValueInput object doesn't support any mathematical operations.

 

It's not clear to me what you want to do. Do you want to create a new parameter that uses an existing parameter and has an equation using a mathematical operator? Or do you want to have a variable in your code that uses a parameter and does some math with it?

 

Here's some code that does the latter.

# Get the existing parameter named "Width".
widthParam = design.userParameters.itemByName('Width')

# Get 2 times the width.
multiply = widthParam.value * 2

# Add the value to itself.
add = widthParam.value + widthParam.value

 

The value property of a parameter returns a floating point number that is the value of the parameter in database units. In this case, it's a distance value, so it will be in centimeters.

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

ph0en1x01
Contributor
Contributor

Edited Response:

 

Width1 = adsk.core.ValueInput.createByString(Width) # Width changes with slider Add-in
Width2 = design.userParameters.itemByName(Width).value # Width doesn't change with slider Add-in GUI

 


It seems that the variable Width2 is only initialized once when I first set it to the value of design.userParameters.itemByName(Width).value.

After that, the value of Width2 remains the same even if I change the value of the slider Add-in.

Here is my whole code:
EV Chassis Code
https://github.com/purushottamnawale/cad-customization-of-ev-chassis/blob/main/Chassis.py

Slider Add-in Code:
https://github.com/purushottamnawale/cad-customization-of-ev-chassis/tree/main/Add-in



0 Likes
Message 4 of 14

kandennti
Mentor
Mentor

Hi @ph0en1x01 .

 

Since the link you provided did not have a slider, I was unable to reproduce the situation.

Instead, I created a simple body using user parameters, and created a sample that allows the parameters to be changed by changing the slider.

# Fusion360API Python script

import traceback
import adsk
import adsk.core as core
import adsk.fusion as fusion

_app: core.Application = None
_ui: core.UserInterface = None
_handlers = []

CMD_INFO = {
    'id': 'kantoku_test',
    'name': 'test',
    'tooltip': 'test'
}

_widthSliderIpt: core.FloatSliderCommandInput = None
_widthPrm: fusion.UserParameter = None

class MyCommandCreatedHandler(core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: core.CommandCreatedEventArgs):
        core.Application.get().log(args.firingEvent.name)
        try:
            global _handlers
            cmd: core.Command = core.Command.cast(args.command)
            inputs: core.CommandInputs = cmd.commandInputs

            # event
            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onExecutePreview = MyExecutePreviewHandler()
            cmd.executePreview.add(onExecutePreview)
            _handlers.append(onExecutePreview)

            # inputs
            global _widthPrm
            _widthPrm = create_base_body_with_parameter(
                'Width',
                1,
            )

            global _widthSliderIpt
            _widthSliderIpt = inputs.addFloatSliderCommandInput(
                '_widthSliderIptId',
                'Width',
                _widthPrm.unit,
                0.01,
                100,
                False,
            )
            _widthSliderIpt.valueOne = _widthPrm.value

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


class MyExecutePreviewHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.CommandEventArgs):

        # update UserParameter
        global _widthPrm, _widthSliderIpt
        _widthPrm.expression = _widthSliderIpt.expressionOne

        core.Application.get().activeViewport.fit()

        args.isValidResult = True


class MyCommandDestroyHandler(core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args: core.CommandEventArgs):
        core.Application.get().log(args.firingEvent.name)
        adsk.terminate()


def run(context):
    try:
        global _app, _ui
        _app = core.Application.get()
        _ui = _app.userInterface

        cmdDef: core.CommandDefinition = _ui.commandDefinitions.itemById(
            CMD_INFO['id']
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                CMD_INFO['id'],
                CMD_INFO['name'],
                CMD_INFO['tooltip']
            )

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

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


def create_base_body_with_parameter(
    name: str,
    value: float,
) -> fusion.UserParameter:

    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct

    # create sketch
    root: fusion.Component = des.rootComponent
    skt: fusion.Sketch = root.sketches.add(
        root.yZConstructionPlane
    )

    # create SketchCircle
    circles: fusion.SketchCircles = skt.sketchCurves.sketchCircles
    circles.addByCenterRadius(
        core.Point3D.create(0,0,0),
        5,
    )

    # create UserParameter
    widthPrm: fusion.UserParameter = get_user_parameter(
        name,
        value,
    )

    # create ExtrudeFeature
    extrudeFeats: fusion.ExtrudeFeatures = root.features.extrudeFeatures
    extrudeFeats.addSimple(
        skt.profiles[-1],
        core.ValueInput.createByString(widthPrm.name),
        fusion.FeatureOperations.NewBodyFeatureOperation,
    )

    return widthPrm


def get_user_parameter(
    name: str,
    value: float,
) -> fusion.UserParameter:

    app: core.Application = core.Application.get()
    des: fusion.Design = app.activeProduct

    unitsMgr: core.UnitsManager = des.unitsManager

    prm: fusion.UserParameter = des.userParameters.itemByName(name)

    if prm:
        return prm

    return des.userParameters.add(
        name,
        core.ValueInput.createByReal(value),
        unitsMgr.defaultLengthUnits,
        'test'
    )

 

(view in My Videos)


I think it would be better to practice parametric modeling before the API.

Message 5 of 14

ph0en1x01
Contributor
Contributor

Thank you for response,
but can we perform operations on ValueInput?
Width2 = adsk.core.ValueInput.createByString(Width)

0 Likes
Message 6 of 14

BrianEkins
Mentor
Mentor

You can't perform operations on a ValueInput, but why would you want to? It's not clear what you want to do. So far, it seems you have a slider and a parameter, but I'm not sure if you want to create a parameter using the value from the slider or edit the value of an existing parameter using the slider, or something else.

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

ph0en1x01
Contributor
Contributor

@BrianEkins @kandennti 

Apologies, if my previous responses were unclear.

Here, I created a body and mirrored it. The width parameter I used, dynamically changes with Command Dialog slider add-in. i.e., dimension of chassis changes in real time when I use slider add-in.
This snippet of chassis script:

 

 

# User Parameters
Width='Width'
widthValue='65.7 cm'
newInputName=ui.inputBox("Enter a new User Parameter Name: ", "New User Parameter",Width)
newInputNumber=ui.inputBox("Enter a User Parameter Value: ","New User Parameter",widthValue)
realInputNumber=unitsMgr.evaluateExpression(newInputNumber[0],unitsMgr.defaultLengthUnits)
realValueInput=adsk.core.ValueInput.createByReal(realInputNumber)  value=design.userParameters.add(newInputName[0],realValueInput,unitsMgr.defaultLengthUnits,'')

# Create a Mirror of body
planeInput = planes.createInput()
offsetDistance = adsk.core.ValueInput.createByString(Width)
planeInput.setByOffset(face1, offsetDistance)
plane = planes.add(planeInput)
plane.isLightBulbOn=False
inputEntites = adsk.core.ObjectCollection.create()
inputEntites.add(body1)
mirrorFeatures = features.mirrorFeatures
mirrorInput = mirrorFeatures.createInput(inputEntites, plane)
mirrorFeature = mirrorFeatures.add(mirrorInput)

 

 

Now, if I use the same distance in point3D, it gives an error.
TypeError: Wrong number or type of arguments for overloaded function 'Point3D_create'

 

offsetDistance = adsk.core.ValueInput.createByString(Width)
pointA = adsk.core.Point3D.create(-15, -4.3, 0)
pointB = adsk.core.Point3D.create(offsetDistance, -4.3, 0)
lineAB = lines1.addByTwoPoints(pointA, pointB)

 


This somewhat worked for me, but it doesn't change the dimensions in real time with slider

 

realInputNumber=unitsMgr.evaluateExpression(newInputNumber[0],unitsMgr.defaultLengthUnits)
pointB = adsk.core.Point3D.create(realInputNumber, -4.3, 0)

# or

Width = design.userParameters.itemByName(Width).value
pointB = adsk.core.Point3D.create(Width, -4.3, 0)

 

 

It seems that the above variable Width is only initialized once when I first set it to the value of design.userParameters.itemByName(Width).value.
After that, the value of Width remains the same even if I change the value of the slider Add-in.

What I want is to change the width dynamically using Point3D using Command Dialog slider add-in in real time. I also want to perform some operations on width in Point3D, like adsk.core.Point3D.create(Width*2, -4.3, 0).

Here is my whole code:
EV Chassis Code
https://github.com/purushottamnawale/cad-customization-of-ev-chassis/blob/main/Chassis.py

Slider Add-in Code:
https://github.com/purushottamnawale/cad-customization-of-ev-chassis/tree/main/Add-in

I have uploaded a GIF where a selected part is supposed to change the dimensions with respect to slider. 

0 Likes
Message 8 of 14

kandennti
Mentor
Mentor

@ph0en1x01 .

 

The volume is too large to correct immediately.

Are the "EV Chassis Code" and "Slider Add-in Code" processed separately?

Message 9 of 14

ph0en1x01
Contributor
Contributor

The volume is too large to correct immediately.


The dimensions are large, but the volume changes immediately with the slider due to the mirror command, except for the front bar (as shown in the selected bar in the GIF)

Are the "EV Chassis Code" and "Slider Add-in Code" processed separately?


I'm not sure what you mean exactly, but first I created a script for the chassis, and then I created an add-in for it. After that, I ran the chassis script and then the add-in.

0 Likes
Message 10 of 14

kandennti
Mentor
Mentor

@ph0en1x01 .

 

"pointB" is a Point3D object, but it is not possible to associate parameters with a Point3D object.
The "pointB" appears on the screen when it is created as an endpoint of "lineAB".
Therefore, you need to find the endpoint of "lineAB" in order to link it to the slider.

1.png

 

The sketch your script produces is not dimensionally constrained at all, so it may be difficult to locate.
That is what I meant when I stated "I think it would be better to practice parametric modeling before the API."

Message 11 of 14

ph0en1x01
Contributor
Contributor
Are there alternative methods for dynamically modifying a sketch created with point3D using slider parameters?
0 Likes
Message 12 of 14

joergDVRXK
Contributor
Contributor

Is there any chance to save a mathematical Operation of two userparameters as a new parameter to let the user factor sketch dimensions later by these parameters? I want to scale several parameters.

 

0 Likes
Message 13 of 14

Jorge_Jaramillo
Collaborator
Collaborator

Hi,

 

Yes, you can a write a user parameter's expression making reference to any other user parameters.

Here you have an example:

Jorge_Jaramillo_0-1726338857735.png

 

Then you can use the new user parameter to dimension a sketch object.

The new user parameter will be updated as long as the dependent are updated.

 

Is this what you are looking for?  Or what kind of mathematical operation do you need?

 

Regards,

Jorge Jaramillo

 

0 Likes
Message 14 of 14

joergDVRXK
Contributor
Contributor

Hi, thank you, I wanted to do this in the api and just found out that it works there over expressions, too like:

        lin = lines.addByTwoPoints(start, end)
        lin_len = dims.addDistanceDimension(start, end, 0, adsk.core.Point3D.create(0, 0, 0), True)
        lin_len.parameter.expression = "wurzelfaktor / test"
0 Likes