API to assign equation dimensions to spline points

API to assign equation dimensions to spline points

Bart_Imler
Contributor Contributor
363 Views
2 Replies
Message 1 of 3

API to assign equation dimensions to spline points

Bart_Imler
Contributor
Contributor

I'll start out by saying that I am pretty much a noob at Fusion, and a complete noob at API and Python.  Please be gentle...

 

In another thread, I was attempting to create a super-ellipse curve using User Parameters.

 

With the help of ChatGPT I was able to create an API to draw a full super-ellipse curve (simplified to 9 points) that was not fully parametric (it is drawn using parameters, but will not respond to parameter changes after it is drawn):

 

 

 

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

def get_user_parameter_value(design, param_name ) :

 

    """ Retrieve the value of a user parameter by name. """
    user_params = design.userParameters
    try:
        param = user_params.itemByName(param_name)
        if param:
            return param.value
        else:
            raise ValueError(f"Parameter '{param_name}' not found.")
    except Exception as e:
        raise ValueError(f"Failed to retrieve '{param_name}': {str(e)}")

def create_parametric_super_ellipse_curve(sketch, a, b, n, num_points=9) :

 

    """ Creates a parametric super-ellipse curve by adding points. """
    points = []
    for i in range(num_points) :

 

        t = 2 * math.pi * i / (num_points - 1)  # Parametric step from 0 to 2π
        x = a * math.copysign(1, math.cos(t)) * abs(math.cos(t))**(2/n)
        y = b * math.copysign(1, math.sin(t)) * abs(math.sin(t))**(2/n)
       
        # Create a point at (x, y)
        point = adsk.core.Point3D.create(x, y, 0)
        points.append(point)
   
    # Convert the list of points into an ObjectCollection
    points_collection = adsk.core.ObjectCollection.create()
    for point in points:
        points_collection.add(point)
   
    # Create a spline through the points using the ObjectCollection
    spline = sketch.sketchCurves.sketchFittedSplines.add(points_collection)
    return spline

def run(context) :

 

    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        design = app.activeProduct
       
        # Get the active component and create a new sketch
        active_comp = design.activeComponent
        sketches = active_comp.sketches
        sketch = sketches.add(active_comp.xYConstructionPlane)
       
        # Fetch user parameters a, b, n from Fusion 360's User Parameters
        a = get_user_parameter_value(design, 'a')
        b = get_user_parameter_value(design, 'b')
        n = get_user_parameter_value(design, 'n')
       
        # Create the parametric super-ellipse curve
        create_parametric_super_ellipse_curve(sketch, a, b, n)
       
        # Notify user
        ui.messageBox('Super-ellipse curve created successfully!')
   
    except Exception as e:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

In order to make it fully parametric, I then went in and manually added dimensions with the equations as expressions to the points.  I used construction lines as the distance reference , and I used coincident constraints where X=0 and Y = 0, rather than equations.

 

Bart_Imler_4-1731351357333.jpeg

 

 

The sign issue (sign (-1)  = 0) reared it's head when the equation should have resulted in a negative value (X in quadrant II and III, Y in quadrant III & IV).  For those points, I used the corresponding positive dimension's name as the equation.

 

Bart_Imler_5-1731351357265.jpeg

 

 

This curve is now fully parametric, in that I can change the shape and size of the curve using User Parameters a, b, & n.  It produces a very rough approximation of a true super-ellipse curve.  A more accurate representation of a super-ellipse curve would be possible if the number of spline points is increased, but for now I'm sticking with 9 points until all of the bugs are worked out.

 

Question #1 - is it possible to (and how do I ) use an equation for those dimensions where the sign formula currently doesn't produce a valid equation in Fusion?  (In other words, what is the correct equation to use in these locations?)

 

Question #2 - how do I modify the API program to assign parameterized dimensions (equations) to these points? 

 

Question #2.1 - should the approach be to assign dimensions after they are drawn as a separate API, or should the approach be to create the dimensions as part of the API that draws the curve.  

 

Question #2.2 - Where can I find specific examples of successful implementations of assigning parameterized dimensions to spline points.  Examples I have found so far all produce duplicate points, run errors, or sketches that are not fully parametric. 

 

Any hints or suggestions as to how to make the API assign parameterized dimensions to the spline points is much appreciated.

0 Likes
364 Views
2 Replies
Replies (2)
Message 2 of 3

BrianEkins
Mentor
Mentor

Here's a starting point that will hopefully get you going. It creates the user parameters that drive the size. It then defines the points as Point3D objects, which are just wrappers over the X, Y, and Z values that define the coordinates. It then uses those points to create the spline and then adds distance dimensions to control the position of the spline points. After adding the dimension, it sets the equation of the parameter created for the dimension. It creates horizontal dimensions for two of the points, but you'll need to add the code to add dimensions to the rest of the points.

app = adsk.core.Application.get()
ui  = app.userInterface
des = adsk.fusion.Design.cast(app.activeProduct)
root = adsk.fusion.Component.cast(des.rootComponent)

# Create the user parameters.
a = 120
des.userParameters.add('a', adsk.core.ValueInput.createByReal(a), des.unitsManager.defaultLengthUnits, '')
b = 60
des.userParameters.add('b', adsk.core.ValueInput.createByReal(b), des.unitsManager.defaultLengthUnits, '')
n = 2.5
des.userParameters.add('n', adsk.core.ValueInput.createByReal(n), '', '')
inset = 10
des.userParameters.add('Inset', adsk.core.ValueInput.createByReal(inset), des.unitsManager.defaultLengthUnits, '')

sk = root.sketches.add(root.xYConstructionPlane)
xOffset = 90.943
yOffset = 45.4715
pnts = adsk.core.ObjectCollection.create()
pnts.add(adsk.core.Point3D.create(a, 0, 0))
pnts.add(adsk.core.Point3D.create(xOffset, yOffset, 0))
pnts.add(adsk.core.Point3D.create(0, b, 0))
pnts.add(adsk.core.Point3D.create(-xOffset, yOffset, 0))
pnts.add(adsk.core.Point3D.create(-a, 0, 0))
pnts.add(adsk.core.Point3D.create(-xOffset, -yOffset, 0))
pnts.add(adsk.core.Point3D.create(0, -b, 0))
pnts.add(adsk.core.Point3D.create(xOffset, -yOffset, 0))
pnts.add(pnts[0])

spline = sk.sketchCurves.sketchFittedSplines.add(pnts)

origin = sk.originPoint
dim = sk.sketchDimensions.addDistanceDimension(origin, spline.fitPoints.item(0), 
                                                adsk.fusion.DimensionOrientations.HorizontalDimensionOrientation, 
                                                adsk.core.Point3D.create(a/2, b*1.2, 0))
dim.parameter.expression = 'a *(cos(0 deg)) ^ (2/n) * sign((cos(0 deg)))'

dim = sk.sketchDimensions.addDistanceDimension(origin, spline.fitPoints.item(1), 
                                                adsk.fusion.DimensionOrientations.HorizontalDimensionOrientation, 
                                                adsk.core.Point3D.create(xOffset/2, b*1.1, 0))
dim.parameter.expression = 'a *(cos(45 deg)) ^ (2/n) * sign((cos(45 deg)))'

 

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

Bart_Imler
Contributor
Contributor

@BrianEkins- Thanks for the response.  Life got really busy suddenly, so I haven't had a chance to pursue your suggestion yet/  I'll report back once life settles down a bit and I get the opportunity to test it out.

0 Likes