Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Creating joined splines using Fusion 360 API

1 REPLY 1
Reply
Message 1 of 2
Anonymous
901 Views, 1 Reply

Creating joined splines using Fusion 360 API

Hi guys -

 

I'm attempting to design a model using Fusion 360 API. Goal is to use Python to create the spline shapes that would represent accurate dimensions based on the input parameters. The process to begin with is simple. Drawing abdomen shape like splines, with reasonable gaps in between, from the top to the bottom, then using loft tool to combine and create a solid body. Tweaking the points on each spline should change the shape and surface of the body created. Would like to do all this and more (later on)through the API in Fusion. At the moment  knowledge on scripting and using Fusion API (or any API for that matter) is a work in progress.

Any help would be greatly appreciated. Thanks in advance.

1 REPLY 1
Message 2 of 2
OceanHydroAU
in reply to: Anonymous

This is an example from another forum post of python that inserts splines and then lofts them - this should get you close to where you want to be!!

 

#Author-pcapjp96
#Description-from forums

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

def run(context):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        
        #define geometry
        PropOD = 17.78 # outer diameter of the whole propeller
        numSections = 20 # number of airfoil cross sections defined per blade
        heightVal = PropOD*.0486 #define the thickness of the hub as a percent of the Propeller diameter
        
        #roR = radius of cross section/propeller radius
        #coD = chord/propeller diameter
        #t0oc = max thickness/chord
        #f0oc = max camber/chord                
        roR =  [0.0675, 0.1407, 0.2134, 0.2852, 0.3557, 0.4243, 0.4908, 0.5547, 0.6156, 0.6731, 0.7269, 0.7766, 0.8219, 0.8626, 0.8984, 0.929, 0.9544, 0.9742, 0.9885, 0.9971, 1.0] 
        coD =  [0.0409, 0.0622, 0.0846, 0.1019, 0.1116, 0.1151, 0.1138, 0.1088, 0.1015, 0.0927, 0.0834, 0.0745, 0.0662, 0.058, 0.0518, 0.0486, 0.0416, 0.0315, 0.0208, 0.0102, 0.001] 
        t0oc =  [0.1157, 0.081, 0.0719, 0.0711, 0.071, 0.071, 0.0713, 0.0714, 0.0716, 0.0715, 0.0708, 0.0705, 0.0704, 0.0715, 0.0718, 0.0702, 0.072, 0.064, 0.0465, 0.0244, -0.0] 
        f0oc =  [0.3638, 0.2974, 0.1941, 0.1415, 0.1137, 0.098, 0.0888, 0.0838, 0.0817, 0.0815, 0.0825, 0.0838, 0.085, 0.0861, 0.0826, 0.077, 0.0737, 0.0716, 0.0704, 0.0697, 0.0695] 
        pitch =  [37.8052, 36.0376, 28.5569, 23.1935, 19.4709, 16.8137, 14.8683, 13.4188, 12.3222, 11.485, 10.836, 10.3208, 9.9027, 9.5636, 9.1906, 8.8226, 8.5587, 8.3667, 8.2378, 8.1642, 8.1403]
        #----------------------------------------------------------------------
        
        design = app.activeProduct # what's open at the time

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

        #create planes
        planes = rootComp.constructionPlanes
        planeInput = planes.createInput()
        
        R = PropOD/2 #propeller radius
        attackAngleList = pitch
        offsetVals = [] #create a list of values for the offset planes
        for i in range(0,numSections):
            offsetVal = adsk.core.ValueInput.createByReal(roR[i]*R)
            offsetVals.append(offsetVal)
            
        xSec0 = .4632*heightVal #define the radius of the initial cross section
        chordScale = [] #creat list of chord scaling
        attackAngleList_rad = [] #create list of attack angles in radians
        
        for i in range(0,len(roR)):
            attackAngleList_rad.append(attackAngleList[i]*math.pi/180) # make the angles into radians
            chordScale.append(coD[i]*PropOD)
       
        # Create a new sketch on the xy plane.
        sketches = rootComp.sketches #sketches comes from the object model(that big tree)
        xyPlane = rootComp.xYConstructionPlane # tell it to use xy plane
        sketch = sketches.add(xyPlane) #take sketches object and add it to the xy plane
        
        # add cross section 0 in here (the xy plane) the radius should be adjusted to reflect the height value
        circles = sketch.sketchCurves.sketchCircles
        circle1 = circles.addByCenterRadius(adsk.core.Point3D.create(0, 0, 0), xSec0)

        #get sketch profile
        profile = sketch.profiles.item(0)
        
        # Create loft feature input
        loftFeats = rootComp.features.loftFeatures
        loftInput = loftFeats.createInput(adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
        loftSectionsObj = loftInput.loftSections
        loftSectionsObj.add(profile)
        
        #create the second profile
        planeInput.setByOffset(xyPlane, offsetVals[0])
        Plane_1 = planes.add(planeInput)        
        sketches = rootComp.sketches #sketches comes from the object model(that big tree)
        sketch = sketches.add(Plane_1) #take sketches object and add it to the PLane_1          
        circles = sketch.sketchCurves.sketchCircles
        circle2 = circles.addByCenterRadius(adsk.core.Point3D.create(0, 0, 0), xSec0)
        profile = sketch.profiles.item(0)
        loftSectionsObj.add(profile)

        for i in range(2,numSections): #create the cross sections for each point of the radius, starting from the 3rd radial point becasue the first two cross section wer too thin and had too much camber
            profile = crossSectionCreator(attackAngleList_rad[i],chordScale[i],PropOD,numSections,offsetVals[i],f0oc[i],t0oc[i])
            loftSectionsObj.add(profile)
            
        loftInput.isSolid = True        
        blade = loftFeats.add(loftInput)        
        
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


def crossSectionCreator(attackAngle,chord,PropOD,numSections,offset,f0oc,t0oc):
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface
        design = app.activeProduct #what's open at the time
                
        # Get the root component of the active design.
        rootComp = design.rootComponent #sets up the top level component of the design in fusion
        xyPlane = rootComp.xYConstructionPlane # tell it to use xy plane
        
        #create 16 planes from 0 to R
        planes = rootComp.constructionPlanes
        planeInput = planes.createInput()
        
        planeInput.setByOffset(xyPlane, offset)
        Plane_1 = planes.add(planeInput)        
        
        # Create a new sketch on the work plane 1.
        sketches = rootComp.sketches #sketches comes from the object model(that big tree)
        sketch_1 = sketches.add(Plane_1) #take sketches object and add it to the PLane_1          
        
        pointsList_1 = [] #a list of all the points for the first cross section
        points_1 = adsk.core.ObjectCollection.create() #create the point collection for the first cross section
        xCoorList = [] #create a list of all x coordinates
        xCoordList = [0,.005,.0075,.0125,.025,.05,.075,.10,.15,.20,.25,.30,.35,.40,.45,.50,.55,.60,.65,.70,.75,.80,.85,.90,.95,1]
        yCoorList = []
        #toc is the thickness/chord at each x value
        toc = [0,.00765,.00928,.01183,.01623,.02182,.0265,.0304,.03658,.04127,.04483,.04742,.04912,.04995,.04983,.04863,.04632,.04304,.03899,.03432,.02912,.02352,.01771,.01188,.00604,.00021]
        t0oc_scale = t0oc/max(toc)
        toc = [i * t0oc_scale for i in toc]
        pointsList = [] # create an empty list to keep track of the points to plot the airfoil
        xyCoordList = [0,0]
        for i in range(0,len(xCoordList)-1): #run thru the list backwards to create negative y coor
            xCoord = xCoordList[len(xCoordList)-1-i]
            yCoord = (-(toc[len(toc)-1-i])/2)
            xyCoordList[0] = xCoord
            xyCoordList[1] = yCoord
            pointsList.append(xyCoordList[:])
        
        xyCoordList = [0,0]
        pointsList.append(xyCoordList[:])
        for i in range(1,len(xCoordList)):#run thru the list forward to create positive y coor
            xCoord = xCoordList[i]
            yCoord = ((toc[i])/2)
            xyCoordList[0] = xCoord
            xyCoordList[1] = yCoord
            pointsList.append(xyCoordList[:])
            
        #add camber
        fof0 = [0,0.0422424851726010,0.0593926061968285,0.0906323084802032,0.158483525134397,0.270931306877788,0.365394143890664,0.447811008675706,0.586552890627142,0.698817437077800,0.789957166562438,0.862944523603016,0.919556283803553,0.960850115191575,0.987381517219326,0.999299100103072,0.996365017088989,0.977907976432830,0.942682218138460,0.888536838448501,0.811548821711142,0.702243798510330,0.542003516481535,0.358366674805168,0.171113059574976,4.65743561188795e-11]
        yCoorMeanCamberLine = [] #this is f
        #dfof0dxoc is dimensionless slope of the mean camber line
        dfof0dxoc = [8.86648212455747,7.14348529861109,6.61217039234403,5.94005607895737,5.01947707446513,4.07954342980629,3.51284803126115,3.09821832429069,2.48609887456089,2.02135629339510,1.63380592532664,1.29146814418333,0.976460919354681,0.677114163075186,0.384630792942005,0.0912942925837331,-0.210851915769909,-0.531483751613063,-0.884477130569965,-1.29366100928359,-1.81194534231248,-2.70919436130699,-3.52064353360441,-3.76526230389796,-3.66538904077040,-3.00042531135620]        
        
        for i in range(0,len(fof0)): #loop for upper values
            yCoorMeanCamberLine.append(fof0[i]*f0oc)
            theta = math.atan(dfof0dxoc[i]*f0oc)
            yCoord = yCoorMeanCamberLine[i]+(toc[i]/2)*math.cos(theta)
            xCoord = pointsList[len(pointsList)-len(fof0)+i][0]-(toc[i]/2)*math.sin(theta)
            xyCoordList = [xCoord,yCoord]
            pointsList[len(pointsList)-len(fof0)+i] = (xyCoordList[:])
            
        for i in range(0,len(fof0)):#loop for lower values
            theta = math.atan(dfof0dxoc[len(dfof0dxoc)-1-i]*f0oc)
            yCoord = yCoorMeanCamberLine[len(yCoorMeanCamberLine)-1-i]-(toc[len(toc)-1-i]/2)*math.cos(theta)
            xCoord = pointsList[i][0]+(toc[len(toc)-1-i]/2)*math.sin(theta)
            xyCoordList = [xCoord,yCoord]
            pointsList[i] = xyCoordList[:]

        for i in range(0,len(pointsList)): #this loop will step through and manipulate each point
            #get the x and y point as a decimal
            xcoord = float(pointsList[i][0])
            ycoord = float(pointsList[i][1])
            
            if xcoord == 0 or ycoord == 0:#leave the point at 0,0 alone
                xcoord = xcoord
                ycoord = ycoord
            else:
                #scale the chord length of the cross section
                xcoord = xcoord*chord
                ycoord = ycoord*chord          
                #change the attack angle of the cross section
                s = (xcoord**2+ycoord**2)**(1/2) #length from origin to the point
                theta = attackAngle-math.atan(ycoord/xcoord)
                xcoord = s*math.cos(theta)
                ycoord = -s*math.sin(theta)
               
            # make a list of the x and y coordinates
            xCoorList.append(xcoord)
            yCoorList.append(ycoord)
            #save the coordinate in the list
            xy_1 = [xcoord,ycoord]
            pointsList_1.append(xy_1)
            
        for i in range(0,len(pointsList_1)): #move the the cross section to the middle now that its been scaled and twisted
            xcoord = float(pointsList_1[i][0])
            ycoord = float(pointsList_1[i][1])
            
            xcoord = xcoord-max(xCoorList)/2
            ycoord = ycoord-min(yCoorList)/2
            
            xy_1 = [xcoord,ycoord]
            pointsList_1[i] = xy_1
            
            points_1.add(adsk.core.Point3D.create(xcoord, ycoord, 0)) #add the new point to the collection
            
        lines = sketch_1.sketchCurves.sketchLines;
        # connect the end of the spline to complete the sketch
        lines.addByTwoPoints(adsk.core.Point3D.create(pointsList_1[0][0], pointsList_1[0][1], 0), adsk.core.Point3D.create(pointsList_1[i][0], pointsList_1[i][1], 0))
        sketch_1.sketchCurves.sketchFittedSplines.add(points_1) # create a spline curve connecting the points

        profile = sketch_1.profiles.item(0) #creates the profile to be lofted
        return profile # allow to profile to be accessed outside this function
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Technology Administrators