Hey everyone!
First time poster, and I'm new to this API stuff, and I'm new to coding for that matter. So sorry if I'm missing something obvious, or use a word incorrectly.
My end-goal with this script is to automate the production of generative artwork by creating 2D artwork in an existing sketch, extruding it onto an existing model, and then regenerating and posting GCODE from the manufacturing environment. But I haven't gotten that far yet. Right now I am just trying to extrude a collection of lines.
The problem I am running into is that I have only figured out how to extrude closed profiles, rather than open curves. I am able to do it manually in the normal Fusion modeling environment, but the Thin Extrude method doesn't seem to accept open curves. Is there a way to make it work with open lines like you can in the modeling environment? or does the API not allow that?
I've attached two pictures, one show the results of my script, and the other one shows the desired outcome, which I was able to manually extrude in the modeling environment.
import adsk.core, adsk.fusion, adsk.cam, traceback, random
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
#Pattern Definitions
PatternWidth = 10 #in cm
PatternHeight = 10 #in cm
Instances = 10 #unitless
Weight = .7 #unitless
ExtrudeThickness = "1" #in cm UOS
ExtrudeDepth = "1" #in cm UOS
#Prompt User to select a sketch
Sketch=getSelectedSketchName()
#Draw Lines in pattern
for X in frange(-PatternWidth/2, PatternWidth/2, PatternWidth/Instances):
for Y in frange(-PatternHeight/2, PatternHeight/2, PatternHeight/Instances):
RandomLine(Sketch, X, Y,PatternWidth/Instances,Weight)
#Extrude Sketch
ThinExtrude(Sketch, ExtrudeThickness, ExtrudeDepth)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
# Get the selected sketch name; otherwise an empty string
def getSelectedSketchName():
#setup stuff
app = adsk.core.Application.get()
ui = app.userInterface
#Prompt to select sketch
Selection = ui.selectEntity("Select Sketch", "Sketches")
return Selection.entity
#Draws a line from a designated start point, to a designated end point in a given sketch
def DrawLine(mySketch,Start,End):
#start and end should be in the form (x, y).
LineStart = adsk.core.Point3D.create(Start[0],Start[1],Start[2])
LineEnd = adsk.core.Point3D.create(End[0],End[1],End[2])
# Get the SketchLines collection from an existing sketch.
lines = mySketch.sketchCurves.sketchLines
# Call an add method on the collection to create a new line.
NewLine = lines.addByTwoPoints(LineStart,LineEnd)
return NewLine
#Creates a diagnol line randomly between the specfied X and Y coordinated.
def RandomLine(Sketch,X,Y,Step,Weight):
X=float(X)
Y=float(Y)
Step=float(Step)
if (random.uniform(0,1))<Weight:
DrawLine(Sketch,(X,Y,0),(X+Step,Y+Step,0))
else:
DrawLine(Sketch,(X+Step,Y,0),(X,Y+Step,0))
return
#Creates a list of float numbers, just like the range comand, but flotats. Float range, Frange, get it?
def frange(A, L=None, D=None):
#Use float number in range() function
# if L and D argument is null set A=0.0 and D = 1.0
if L == None:
L = A + 0.0
A = 0.0
if D == None:
D = 1.0
while True:
if D > 0 and A >= L:
break
elif D < 0 and A <= L:
break
yield ("%g" % A) # return float number
A = A + D
#Do a thin extrude on everything in a sketch
def ThinExtrude(Sketch, Distance, Thickness):
app = adsk.core.Application.get()
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
rootComp = design.rootComponent
#set all inputs needed for extrude
extrudeFeatures = rootComp.features.extrudeFeatures
operation = adsk.fusion.FeatureOperations.NewBodyFeatureOperation
wallLocation = adsk.fusion.ThinExtrudeWallLocation.Center
wallThickness = adsk.core.ValueInput.createByString(Thickness)
distance = adsk.core.ValueInput.createByString(Distance)
isFullLength = True
NumberOfProfiles = Sketch.sketchCurves.count
#extrude all profiles in sketch
for I in range(0,NumberOfProfiles,1):
Profile = Sketch.profiles.item(I)
input = extrudeFeatures.createInput(Profile, operation)
input.setSymmetricExtent(distance, isFullLength)
input.setThinExtrude(wallLocation, wallThickness)
extrudeFeature = extrudeFeatures.add(input)
return extrudeFeature
Solved! Go to Solution.
Solved by kandennti. Go to Solution.
Hi @AudacityMicro .
I tried it.
Since the sketch lines cannot be used as-is for the profile, I used the Component.createOpenProfile method to create the profile.
Only the ThinExtrude function was changed.
def ThinExtrude(Sketch: adsk.fusion.Sketch, Distance, Thickness):
app = adsk.core.Application.get()
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
rootComp = design.rootComponent
#set all inputs needed for extrude
extrudeFeatures = rootComp.features.extrudeFeatures
operation = adsk.fusion.FeatureOperations.NewBodyFeatureOperation
wallLocation = adsk.fusion.ThinExtrudeWallLocation.Center
wallThickness = adsk.core.ValueInput.createByString(Thickness)
distance = adsk.core.ValueInput.createByString(Distance)
isFullLength = True
comp: adsk.fusion.Component = Sketch.parentComponent
pros = []
objs: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
for crv in Sketch.sketchCurves:
objs.clear()
objs.add(crv)
pros.append(comp.createOpenProfile(objs, False))
for profile in pros:
extIpt: adsk.fusion.ExtrudeFeatureInput = extrudeFeatures.createInput(profile, operation)
extIpt.setSymmetricExtent(distance, isFullLength)
extIpt.setThinExtrude(wallLocation, wallThickness)
extrudeFeature = extrudeFeatures.add(extIpt)
return extrudeFeature
However, the state after execution is not so beautiful.
I have not examined it in detail, but it may be necessary to change the way the sketch line is written.
I just checked it on my end, and I think I can make that work! Thank you so much!
It'll take a little tinkering to get the corners to match up right, but that should be a solvable problem.
Here's some code that is able to get everything connected together. Here you can see the sketch and the resulting extrude.
There are a couple of quirks with how this works that it took me some experimenting to understand. You can see the same behavior in the command, but when using the API, you need to take care to create the same input.
The main issue is defining the profiles to use as input for the command. The input for this specific case should be an ObjectCollection that contains two open profiles. One profile consists of two connected lines and the other is a profile of one line. I use the createOpenProfile method to create the profiles. If you draw the two connected lines you'll usually end up with a coincident constraint tieing the two ends together. If there is a coincident point and you have the "chaining" option selected in the dialog, it will automatically select the second when you pick the first. If there isn't a coincident constraint between them but their ends happen to end at the same coordinate, it won't automatically chain them but when you pick the second line, the command sees they are geometrically connected and still creates a single profile. You can see this in the selection input because even after selecting the second line it will still say there is one item selected. When you select the third line there will be two items selected because it's not connected.
In the API, if the two lines have a coincident point and you set the second argument of createOpenProfile to True, it will automatically find the second line and include both lines in the profile. If there isn't a coincident point, you can still create a single profile by creating an ObjectCollection containing both of the lines. When you create sketch geometry and provide a sketch point as input, a coincident constraint is automatically created. These are both demonstrated in the code below.
def thinExtrude():
app = adsk.core.Application.get()
ui = app.userInterface
try:
doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType, True)
des: adsk.fusion.Design = app.activeProduct
root = des.rootComponent
sk: adsk.fusion.Sketch = root.sketches.add(root.xYConstructionPlane)
linesColl = sk.sketchCurves.sketchLines
autoChain = True
if autoChain:
line1 = linesColl.addByTwoPoints(adsk.core.Point3D.create(0,5,0),
adsk.core.Point3D.create(0,0,0))
line2 = linesColl.addByTwoPoints(line1.endSketchPoint,
adsk.core.Point3D.create(7,0,0))
line3 = linesColl.addByTwoPoints(adsk.core.Point3D.create(0,3,0),
adsk.core.Point3D.create(5,3,0))
prof1 = root.createOpenProfile(line1, True)
prof2 = root.createOpenProfile(line3, True)
else:
line1 = linesColl.addByTwoPoints(adsk.core.Point3D.create(0,5,0),
adsk.core.Point3D.create(0,0,0))
line2 = linesColl.addByTwoPoints(adsk.core.Point3D.create(0,0,0),
adsk.core.Point3D.create(7,0,0))
line3 = linesColl.addByTwoPoints(adsk.core.Point3D.create(0,3,0),
adsk.core.Point3D.create(5,3,0))
lines = adsk.core.ObjectCollection.create()
lines.add(line1)
lines.add(line2)
prof1 = root.createOpenProfile(lines, False)
prof2 = root.createOpenProfile(line3, True)
profs = adsk.core.ObjectCollection.create()
profs.add(prof1)
profs.add(prof2)
exts = root.features.extrudeFeatures
extInput = exts.createInput(profs, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
extInput.setThinExtrude(adsk.fusion.ThinExtrudeWallLocation.Center,
adsk.core.ValueInput.createByReal(1))
distanceExtent = adsk.fusion.DistanceExtentDefinition.create(adsk.core.ValueInput.createByReal(5))
extInput.setOneSideExtent(distanceExtent, adsk.fusion.ExtentDirections.PositiveExtentDirection)
ext = exts.add(extInput)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
app.log('Failed:\n{}'.format(traceback.format_exc()))
Can't find what you're looking for? Ask the community or share your knowledge.