Hello,
I am trying to create 4 holes via extrude>cut.
User specifies distance apart in both X and Y axis.
r
I am creating TWO different sketches in the function and 2 extrusions per sketch to create 4 holes total. Any guesses? I know this has been discussed HERE<--- but not much info was given.
Thanks in advance.
Here is the code:
def holePat(hole_dia, hole_spcX, hole_spcY, hole_cb, length_in, width_in, thick_in): act = app.activeProduct rootComp = act.rootComponent ui = app.userInterface #total_length = inputs.itemById('length_in').value # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch2 = sketches.add(xyPlane) sketch3 = sketches.add(xyPlane) spcX_plus_holerad = (hole_spcX + (hole_dia)) spcY_plus_holerad = (hole_spcY + (hole_dia)) if hole_cb == True and hole_dia > 0: if spcX_plus_holerad >= length_in: ui.messageBox('Oops! User Specified Hole Spacing Greater Than or Equal To Part Length') else: sketch2 = sketches.add(xyPlane) Load_circles = sketch2.sketchCurves.sketchCircles circle1 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/2), 0, (thick_in)), (hole_dia/2)) circle2 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/-2),0, (thick_in)), (hole_dia/2)) circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput1 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput2 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput1.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput2.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext1 = cuts.add(extInput1) ext2 = cuts.add(extInput2) if spcY_plus_holerad >= width_in and hole_dia > 0: ui.messageBox('Oops! User Specified Hole Spacing Outside Part Extents') else: sketch3 = sketches.add(xyPlane) Load_circles = sketch3.sketchCurves.sketchCircles circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput3 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput4 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput3.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput4.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext3 = cuts.add(extInput3) ext4 = cuts.add(extInput4)
Hello,
It would be great if you can provide a runnable script to reproduce the issue. It is hard to judge what's wrong with the codes you posted.
I also took a look at the code sample you posted in another thread. Unfortunately I didn't reproduce the issue you mentioned. Instead I saw the error during creating second combined feature. It was because tool body "extrude_2" has been deleted during creating the first combined feature.
BTW: I did a minor change and commented red line out. All extent extrude would not work if there are no existing tool bodies in the design. Of course, the API "setDistanceExtent" and "setAllExtent" have been retired. We recommend to use new API "setOneSideExtent" and "setTwoSideExtent".
Thanks,
Marshal
#ucf-fusion-loader. #Author-Harry Keen #Description-Fusion360 addin to load and build ultimate CAD format json files. import adsk.core, adsk.fusion, adsk.cam, traceback #import system modules import os, sys #get the path of add-in ADDIN_PATH = os.path.dirname(os.path.realpath(__file__)) #print(ADDIN_PATH) #add the path to the searchable path collection if not ADDIN_PATH in sys.path: sys.path.append(ADDIN_PATH) import simplejson as json IMPORT = ADDIN_PATH + "/template.json" SKETCHES_LOC = ADDIN_PATH + "/sketches/" def run(context): try: app = adsk.core.Application.get() ui = app.userInterface # Get import manager importManager = app.importManager # Create a document. #doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) product = app.activeProduct design = adsk.fusion.Design.cast(product) # Get the root component of the active design rootComp = design.rootComponent with open(IMPORT) as data_file: data = json.load(data_file) # print(json.dumps(data, sort_keys=True, indent=4 * ' ')) # for n in data.keys(): # print(n) # print('-------') # for feature in data['features'].keys(): # print(data['features'][feature]['type']) # Import all sketches for sketch in data['sketches']: sketch_name = data['sketches'][sketch]['name'] # Get dxf2d import options sketch_loc = SKETCHES_LOC + sketch_name + '.dxf'#'sketch_2.dxf' # returnValue = importManager_var.createDXF2DImportOptions(filename, planarEntity) dxf2dOptions = importManager.createDXF2DImportOptions(sketch_loc, rootComp.xYConstructionPlane) # Import dxf file to root component importManager.importToTarget(dxf2dOptions, rootComp) # Rename sketch for sketch in rootComp.sketches: if 'sketch' not in sketch.name: sketch.name = sketch_name # Extrude all extrusion features for feature in data['features']: feature = data['features'][feature] if feature['type'] == 'extrude': # Run extrude # Get base_sketch for sketch in rootComp.sketches: if sketch.name == feature['base_sketch']: base_sketch = sketch break # Get profiles # Create an object collection to use an input. profiles = adsk.core.ObjectCollection.create() # Add all of the profiles to the collection. for prof in base_sketch.profiles: profiles.add(prof) # Define Fusion type of extrude # Currently only going to use new_bodies and then combines to get any subtraction # Create extrusion input extrudes = rootComp.features.extrudeFeatures extInput = extrudes.createInput(profiles, adsk.fusion.FeatureOperations.NewBodyFeatureOperation) # extInput = extrudes.createInput(profiles, adsk.fusion.FeatureOperations.JoinFeatureOperation) # Define distance of extrude distance = adsk.core.ValueInput.createByReal(feature['distance']/10) # Set the distance extent to be symmetric extInput.setDistanceExtent(True, distance) # Set the extrude to be a solid # extInput.isSolid = True # Set direction # extInput.setAllExtent(1) # Create the extrusion ext = extrudes.add(extInput) # Rename sketch for body in rootComp.bRepBodies: if 'extrude' not in body.name: body.name = feature['name'] # Apply combines for feature in data['features']: feature = data['features'][feature] if feature['type'] == 'combine': # Define target_body for body in rootComp.bRepBodies: if body.name == feature['solid_1']: target_body = body # Get tool_bodies # Create an object collection to use an input. tool_bodies = adsk.core.ObjectCollection.create() # Add all of the tool_bodies to the collection. for body in rootComp.bRepBodies: if body.name == feature['solid_2']: #if feature['solid_2'] in body.name: tool_bodies.add(body) # Create combine input combines = rootComp.features.combineFeatures combInput = combines.createInput(target_body, tool_bodies) # Keep tool bodies combInput.isKeepToolBodies = False # Cut operation combInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation # Create the extrusion comb = combines.add(combInput) # Was going to rename but actually target body may have other combine features applied to it. # for body in rootComp.bRepBodies: # if body.name == target_body.name: # body.name = feature['name'] # 28160 mm / 1108mm = 25.4 -> need to scale down to mm except: if ui: #print('Failed:\n{}'.format(traceback.format_exc())) ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Marshal,
Thanks for reply. Still not sure what you're saying. I don't see why the way I am doing this won't work.
It works with two of the cut extrusions. Then the last two circles to be cut, it fails.
import adsk.core, adsk.fusion, adsk.cam, traceback # Global list to keep all event handlers in scope. # This is only needed with Python. handlers = [] def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Get the CommandDefinitions collection. cmdDefs = ui.commandDefinitions # Create a button command definition. buttonSample = cmdDefs.addButtonDefinition('MainButton','BM Addin Pro', 'This is an Addin for generating boxes','./Resources/Main Icons') # Connect to the command created event. MainButtonEvent = SampleCommandCreatedEventHandler() buttonSample.commandCreated.add(MainButtonEvent) handlers.append(MainButtonEvent) # Get the ADD-INS panel in the model workspace. addInsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') # Add the button to the bottom of the panel. buttonControl = addInsPanel.controls.addCommand(buttonSample) buttonControl.isPromoted = True except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # Event handler for the commandCreated event. class SampleCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandCreatedEventArgs.cast(args) app = adsk.core.Application.get() # Get the command cmd = eventArgs.command # Get the CommandInputs collection to create new command inputs. inputs = cmd.commandInputs #Add image input imageinput1 = inputs.addImageCommandInput('imageinput1','Diagram:','./Resources/Image Input/image main.png') # Create the value inputs length_in = inputs.addValueInput('length_in', 'Length','', adsk.core.ValueInput.createByReal(3)) width_in = inputs.addValueInput('width_in','Width','',adsk.core.ValueInput.createByReal(2)) thick_in = inputs.addValueInput('thick_in','Thickness','',adsk.core.ValueInput.createByReal(1)) fillet_cb = inputs.addBoolValueInput('fillet_cb','Add Fillets', False,'./Resources/Other Icons/fillet_32.png', True) fillet_in = inputs.addValueInput('fillet_in','Fillet Radius','',adsk.core.ValueInput.createByReal(0)) hole_cb = inputs.addBoolValueInput('hole_cb','Add Hole Pattern', True,'', True) hole_dia = inputs.addValueInput('hole_dia','Hole Diameter','',adsk.core.ValueInput.createByReal(0)) hole_spcX = inputs.addValueInput('hole_spcX','Hole Spacing in X','',adsk.core.ValueInput.createByReal(0)) hole_spcY = inputs.addValueInput('hole_spcY','Hole Spacing in Y','',adsk.core.ValueInput.createByReal(0)) inputChanged = inputChangedEvent() cmd.inputChanged.add(inputChanged) handlers.append(inputChanged) onExecute = SampleCommandExecuteHandler() cmd.execute.add(onExecute) handlers.append(onExecute) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # Event handler for the execute event. class SampleCommandExecuteHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandEventArgs.cast(args) # Code to react to the event. app = adsk.core.Application.get() ui = app.userInterface ui.messageBox('In command execute event handler.') eventArgs = adsk.core.CommandEventArgs.cast(args) # Get the values from the command inputs. inputs = eventArgs.command.commandInputs length = inputs.itemById('length_in').value width = inputs.itemById('width_in').value thickness = inputs.itemById('thick_in').value fillet = inputs.itemById('fillet_in').value filletcb = inputs.itemById('fillet_cb').value hole_dia = inputs.itemById('hole_dia').value hole_spcX = inputs.itemById('hole_spcX').value hole_spcY = inputs.itemById('hole_spcY').value holecb = inputs.itemById('hole_cb').value #call drawBox function and add input values drawBox(length, width, thickness, fillet, filletcb) holePat(hole_dia, hole_spcX, hole_spcY, holecb, length, width, thickness) #call addFillets function and add input value except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def drawBox(length_in, width_in, thick_in, fillet_in, fillet_cb): #these values are item IDs - not variables (see above) try: # Get the active sketch. app = adsk.core.Application.get() sketch = adsk.fusion.Sketch.cast(app.activeEditObject) ui = app.userInterface doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) act = app.activeProduct # Get the root component of the active design. rootComp = act.rootComponent # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch1 = sketches.add(xyPlane) # Load the lines collection and draw geometry for BOX sketch (division for center around origin) Load_lines = sketch1.sketchCurves.sketchLines #load the line API L1 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/-2), (width_in/-2), 0), adsk.core.Point3D.create((length_in/2),(width_in/-2), 0)) L2 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/2),(width_in/-2),0), adsk.core.Point3D.create((length_in/2),(width_in/2),0)) L3 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/2),(width_in/2),0), adsk.core.Point3D.create((length_in/-2),(width_in/2),0)) #draw lines (start, end) L4 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/-2),(width_in/2),0), adsk.core.Point3D.create((length_in/-2),(width_in/-2),0)) #get sketch profile prof1 = sketch1.profiles.item(0) #Extrude thickness extrude1 = rootComp.features.extrudeFeatures extrude1_prof = extrude1.createInput(prof1,adsk.fusion.FeatureOperations.NewComponentFeatureOperation) distance = adsk.core.ValueInput.createByReal(thick_in) extrude1_prof.setDistanceExtent(False, distance) finish_extrude1 = extrude1.add(extrude1_prof) #executes the extrusion if fillet_cb == True and fillet_in > 0: #fillets---------------------- #find each Brep Edge extrude1_face0 = finish_extrude1.sideFaces.item(0) #endFace, sideFaces, startFaces etc get_loops0 = extrude1_face0.loops loop_0 = get_loops0.item(0) # 0 = closed loop, 1 = open load_edges = loop_0.edges brep_edge_0 = load_edges.item(3) #which edge on the face and loop # extrude1_face1 = finish_extrude1.sideFaces.item(1) get_loops1 = extrude1_face1.loops loop_1 = get_loops1.item(0) load_edges = loop_1.edges brep_edge_1 = load_edges.item(3) extrude1_face2 = finish_extrude1.sideFaces.item(2) get_loops2 = extrude1_face2.loops loop_2 = get_loops2.item(0) # load_edges = loop_2.edges brep_edge_2 = load_edges.item(3) extrude1_face3 = finish_extrude1.sideFaces.item(3) get_loops3 = extrude1_face3.loops loop_3 = get_loops3.item(0) load_edges = loop_3.edges brep_edge_3 = load_edges.item(3) load_fillets = rootComp.features.filletFeatures # Create an edge collection, then add each found brep_edge edgeCollection0 = adsk.core.ObjectCollection.create() edgeCollection0.add(brep_edge_0) edgeCollection1 = adsk.core.ObjectCollection.create() edgeCollection1.add(brep_edge_1) edgeCollection2 = adsk.core.ObjectCollection.create() edgeCollection2.add(brep_edge_2) edgeCollection3 = adsk.core.ObjectCollection.create() edgeCollection3.add(brep_edge_3) #bring in the valueInput radius1 = adsk.core.ValueInput.createByReal(fillet_in) input1 = load_fillets.createInput() input1.addConstantRadiusEdgeSet(edgeCollection0, radius1, True) input1.isG2 = False input2 = load_fillets.createInput() input2.addConstantRadiusEdgeSet(edgeCollection1, radius1, True) input2.isG2 = False input3 = load_fillets.createInput() input3.addConstantRadiusEdgeSet(edgeCollection2, radius1, True) input3.isG2 = False input4 = load_fillets.createInput() input4.addConstantRadiusEdgeSet(edgeCollection3, radius1, True) input4.isG2 = False #execute the fillets fillet1 = load_fillets.add(input1) fillet2 = load_fillets.add(input2) fillet3 = load_fillets.add(input3) fillet4 = load_fillets.add(input4) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def holePat(hole_dia, hole_spcX, hole_spcY, hole_cb, length_in, width_in, thick_in): #these values are item IDs - not variables (see above) try: app = adsk.core.Application.get() act = app.activeProduct rootComp = act.rootComponent ui = app.userInterface #total_length = inputs.itemById('length_in').value # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch2 = sketches.add(xyPlane) sketch3 = sketches.add(xyPlane) spcX_plus_holerad = (hole_spcX + (hole_dia)) spcY_plus_holerad = (hole_spcY + (hole_dia)) if hole_cb == True and hole_dia > 0: if spcX_plus_holerad >= length_in: ui.messageBox('Oops! User Specified Hole Spacing Greater Than or Equal To Part Length') else: sketch2 = sketches.add(xyPlane) Load_circles = sketch2.sketchCurves.sketchCircles circle1 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/2), 0, (thick_in)), (hole_dia/2)) circle2 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/-2),0, (thick_in)), (hole_dia/2)) circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput1 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput2 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput1.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput2.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext1 = cuts.add(extInput1) ext2 = cuts.add(extInput2) if spcY_plus_holerad >= width_in and hole_dia > 0: ui.messageBox('Oops! User Specified Hole Spacing Outside Part Extents') else: sketch3 = sketches.add(xyPlane) Load_circles = sketch3.sketchCurves.sketchCircles circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput3 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput4 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput3.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput4.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext3 = cuts.add(extInput3) ext4 = cuts.add(extInput4) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class inputChangedEvent(adsk.core.InputChangedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.InputChangedEventArgs.cast(args) changedInput = eventArgs.input fillet_in = None if changedInput.id == 'fillet_cb': inputs = eventArgs.firingEvent.sender.commandInputs fillet_in = inputs.itemById('fillet_in') # Change the visibility of the scale value input. if fillet_in: if changedInput.value == True: fillet_in.isVisible = True else: fillet_in.isVisible = False except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def stop(context): try: app = adsk.core.Application.get() ui = app.userInterface #Delete Button Def buttonSample = ui.commandDefinitions.itemById('MainButton') if buttonSample: buttonSample.deleteMe() #Delete Button Control addinsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') cntrl = addinsPanel.controls.itemById('MainButton') if cntrl: cntrl.deleteMe() except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Hello,
Thank you for the sample codes. I can reproduce your issue. The root cause was you were trying to create two holes in same locations(circle3 in sketch2, circle3 in sketch3). The first hole was created successfully, but the second hole failed because we cannot find tool body to cut(it has been cut by the first hole).
What I understand is you want to create hole pattern in a block with specific length and width. It would be better to use RectangularPatternFeature to create those holes.
Thanks,
Marshal
def holePat(hole_dia, hole_spcX, hole_spcY, hole_cb, length_in, width_in, thick_in): #these values are item IDs - not variables (see above) try: app = adsk.core.Application.get() act = app.activeProduct rootComp = act.rootComponent ui = app.userInterface #total_length = inputs.itemById('length_in').value # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch2 = sketches.add(xyPlane) sketch3 = sketches.add(xyPlane) spcX_plus_holerad = (hole_spcX + (hole_dia)) spcY_plus_holerad = (hole_spcY + (hole_dia)) if hole_cb == True and hole_dia > 0: if spcX_plus_holerad >= length_in: ui.messageBox('Oops! User Specified Hole Spacing Greater Than or Equal To Part Length') else: sketch2 = sketches.add(xyPlane) Load_circles = sketch2.sketchCurves.sketchCircles circle1 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/2), 0, (thick_in)), (hole_dia/2)) circle2 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/-2),0, (thick_in)), (hole_dia/2)) circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput1 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput2 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput1.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput2.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext1 = cuts.add(extInput1) ext2 = cuts.add(extInput2) if spcY_plus_holerad >= width_in and hole_dia > 0: ui.messageBox('Oops! User Specified Hole Spacing Outside Part Extents') else: sketch3 = sketches.add(xyPlane) Load_circles = sketch3.sketchCurves.sketchCircles circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput3 = cuts.createInput(sketch3.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput4 = cuts.createInput(sketch3.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput3.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput4.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext3 = cuts.add(extInput3) ext4 = cuts.add(extInput4) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Marshal,
You are a life saver. I guess I should be looking over my code a bit more clearly. Thanks for your help with this and I will use your rectangular pattern suggestion.
Regards
Marshal,
I fixed the issue you mentioned, it still does not fix my issue. I have not tried the rectangular method yet, which confuses me still, even after looking at the rectangular pattern API sample.
Here is the fixed code and you will notice it still produces the same tool body creation error:
import adsk.core, adsk.fusion, adsk.cam, traceback # Global list to keep all event handlers in scope. # This is only needed with Python. handlers = [] def run(context): ui = None try: app = adsk.core.Application.get() ui = app.userInterface # Get the CommandDefinitions collection. cmdDefs = ui.commandDefinitions # Create a button command definition. buttonSample = cmdDefs.addButtonDefinition('MainButton','Plate Generator', 'An Add-in which generates a solid rectangle and applies holes or slots equidistant from part center.','./Resources/Main Icons') # Connect to the command created event. MainButtonEvent = SampleCommandCreatedEventHandler() buttonSample.commandCreated.add(MainButtonEvent) handlers.append(MainButtonEvent) # Get the ADD-INS panel in the model workspace. addInsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') # Add the button to the bottom of the panel. buttonControl = addInsPanel.controls.addCommand(buttonSample) buttonControl.isPromoted = True except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # Event handler for the commandCreated event. class SampleCommandCreatedEventHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandCreatedEventArgs.cast(args) app = adsk.core.Application.get() # Get the command cmd = eventArgs.command cmd.okButtonText = ("Generate") #text in "OK" button # Get the CommandInputs collection to create new command inputs. inputs = cmd.commandInputs #Add image input imageinput1 = inputs.addImageCommandInput('imageinput1','Diagram:','./Resources/Image Input/Diagram/diagram.png') # Create the value inputs length_in = inputs.addValueInput('length_in', 'Length','', adsk.core.ValueInput.createByReal(3)) width_in = inputs.addValueInput('width_in','Width','',adsk.core.ValueInput.createByReal(2)) thick_in = inputs.addValueInput('thick_in','Thickness','',adsk.core.ValueInput.createByReal(1)) fillet_cb = inputs.addBoolValueInput('fillet_cb','Add Corner Fillets', False,'./Resources/Image Input/Fillets', False) fillet_in = inputs.addValueInput('fillet_in','Fillet Radius','',adsk.core.ValueInput.createByReal(0)) hole_cb = inputs.addBoolValueInput('hole_cb','Add Hole Pattern', True,'', True) hole_dia = inputs.addValueInput('hole_dia','Hole Diameter','',adsk.core.ValueInput.createByReal(0)) hole_spcX = inputs.addValueInput('hole_spcX','Hole Spacing in X','',adsk.core.ValueInput.createByReal(0)) hole_spcY = inputs.addValueInput('hole_spcY','Hole Spacing in Y','',adsk.core.ValueInput.createByReal(0)) inputChanged = inputChangedEvent() cmd.inputChanged.add(inputChanged) handlers.append(inputChanged) onExecute = SampleCommandExecuteHandler() cmd.execute.add(onExecute) handlers.append(onExecute) # onExecutePreview = MyExecutePreviewHandler() # cmd.executePreview.add(onExecutePreview) # handlers.append(onExecutePreview) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # Event handler for the execute event. class SampleCommandExecuteHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandEventArgs.cast(args) # Code to react to the event. app = adsk.core.Application.get() ui = app.userInterface ui.messageBox('In command execute event handler.') eventArgs = adsk.core.CommandEventArgs.cast(args) # Get the values from the command inputs. inputs = eventArgs.command.commandInputs length = inputs.itemById('length_in').value width = inputs.itemById('width_in').value thickness = inputs.itemById('thick_in').value fillet = inputs.itemById('fillet_in').value filletcb = inputs.itemById('fillet_cb').value hole_dia = inputs.itemById('hole_dia').value hole_spcX = inputs.itemById('hole_spcX').value hole_spcY = inputs.itemById('hole_spcY').value holecb = inputs.itemById('hole_cb').value #call drawBox function and add input values drawBox(length, width, thickness, fillet, filletcb) holePat(hole_dia, hole_spcX, hole_spcY, holecb, length, width, thickness) #call addFillets function and add input value except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MyExecutePreviewHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.CommandEventArgs.cast(args) # Get the values from the command inputs. inputs = eventArgs.command.commandInputs length = inputs.itemById('length_in').value width = inputs.itemById('width_in').value thickness = inputs.itemById('thick_in').value fillet = inputs.itemById('fillet_in').value filletcb = inputs.itemById('fillet_cb').value hole_dia = inputs.itemById('hole_dia').value hole_spcX = inputs.itemById('hole_spcX').value hole_spcY = inputs.itemById('hole_spcY').value holecb = inputs.itemById('hole_cb').value #call drawBox function and add input values drawBox(length, width, thickness, fillet, filletcb) holePat(hole_dia, hole_spcX, hole_spcY, holecb, length, width, thickness) #call addFillets function and add input value eventArgs.isValidResult except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def drawBox(length_in, width_in, thick_in, fillet_in, fillet_cb): #these values are item IDs - not variables (see above) try: # Get the active sketch. app = adsk.core.Application.get() sketch = adsk.fusion.Sketch.cast(app.activeEditObject) ui = app.userInterface doc = app.documents.add(adsk.core.DocumentTypes.FusionDesignDocumentType) act = app.activeProduct # Get the root component of the active design. rootComp = act.rootComponent # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch1 = sketches.add(xyPlane) # Load the lines collection and draw geometry for BOX sketch (division for center around origin) Load_lines = sketch1.sketchCurves.sketchLines #load the line API L1 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/-2), (width_in/-2), 0), adsk.core.Point3D.create((length_in/2),(width_in/-2), 0)) L2 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/2),(width_in/-2),0), adsk.core.Point3D.create((length_in/2),(width_in/2),0)) L3 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/2),(width_in/2),0), adsk.core.Point3D.create((length_in/-2),(width_in/2),0)) #draw lines (start, end) L4 = Load_lines.addByTwoPoints(adsk.core.Point3D.create((length_in/-2),(width_in/2),0), adsk.core.Point3D.create((length_in/-2),(width_in/-2),0)) #get sketch profile prof1 = sketch1.profiles.item(0) #Extrude thickness extrude1 = rootComp.features.extrudeFeatures extrude1_prof = extrude1.createInput(prof1,adsk.fusion.FeatureOperations.NewComponentFeatureOperation) distance = adsk.core.ValueInput.createByReal(thick_in) extrude1_prof.setDistanceExtent(False, distance) finish_extrude1 = extrude1.add(extrude1_prof) #executes the extrusion if fillet_cb == True and fillet_in > 0: #fillets---------------------- #find each Brep Edge extrude1_face0 = finish_extrude1.sideFaces.item(0) #endFace, sideFaces, startFaces etc get_loops0 = extrude1_face0.loops loop_0 = get_loops0.item(0) # 0 = closed loop, 1 = open load_edges = loop_0.edges brep_edge_0 = load_edges.item(3) #which edge on the face and loop # extrude1_face1 = finish_extrude1.sideFaces.item(1) get_loops1 = extrude1_face1.loops loop_1 = get_loops1.item(0) load_edges = loop_1.edges brep_edge_1 = load_edges.item(3) extrude1_face2 = finish_extrude1.sideFaces.item(2) get_loops2 = extrude1_face2.loops loop_2 = get_loops2.item(0) # load_edges = loop_2.edges brep_edge_2 = load_edges.item(3) extrude1_face3 = finish_extrude1.sideFaces.item(3) get_loops3 = extrude1_face3.loops loop_3 = get_loops3.item(0) load_edges = loop_3.edges brep_edge_3 = load_edges.item(3) load_fillets = rootComp.features.filletFeatures # Create an edge collection, then add each found brep_edge edgeCollection0 = adsk.core.ObjectCollection.create() edgeCollection0.add(brep_edge_0) edgeCollection1 = adsk.core.ObjectCollection.create() edgeCollection1.add(brep_edge_1) edgeCollection2 = adsk.core.ObjectCollection.create() edgeCollection2.add(brep_edge_2) edgeCollection3 = adsk.core.ObjectCollection.create() edgeCollection3.add(brep_edge_3) #bring in the valueInput radius1 = adsk.core.ValueInput.createByReal(fillet_in) input1 = load_fillets.createInput() input1.addConstantRadiusEdgeSet(edgeCollection0, radius1, True) input1.isG2 = False input2 = load_fillets.createInput() input2.addConstantRadiusEdgeSet(edgeCollection1, radius1, True) input2.isG2 = False input3 = load_fillets.createInput() input3.addConstantRadiusEdgeSet(edgeCollection2, radius1, True) input3.isG2 = False input4 = load_fillets.createInput() input4.addConstantRadiusEdgeSet(edgeCollection3, radius1, True) input4.isG2 = False #execute the fillets fillet1 = load_fillets.add(input1) fillet2 = load_fillets.add(input2) fillet3 = load_fillets.add(input3) fillet4 = load_fillets.add(input4) length_in.inputs except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def holePat(hole_dia, hole_spcX, hole_spcY, hole_cb, length_in, width_in, thick_in): #these values are item IDs - not variables (see above) try: app = adsk.core.Application.get() act = app.activeProduct rootComp = act.rootComponent ui = app.userInterface #total_length = inputs.itemById('length_in').value # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch2 = sketches.add(xyPlane) sketch3 = sketches.add(xyPlane) spcX_plus_holerad = (hole_spcX + (hole_dia)) spcY_plus_holerad = (hole_spcY + (hole_dia)) if hole_cb == True and hole_dia > 0: if spcX_plus_holerad >= length_in: ui.messageBox('Oops! User Specified Hole Spacing Greater Than or Equal To Part Length') else: sketch2 = sketches.add(xyPlane) Load_circles = sketch2.sketchCurves.sketchCircles circle1 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/2), 0, (thick_in)), (hole_dia/2)) circle2 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/-2),0, (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput1 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput2 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput1.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput2.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext1 = cuts.add(extInput1) ext2 = cuts.add(extInput2) if spcY_plus_holerad >= width_in and hole_dia > 0: ui.messageBox('Oops! User Specified Hole Spacing Outside Part Extents') else: sketch3 = sketches.add(xyPlane) Load_circles = sketch3.sketchCurves.sketchCircles circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput3 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput4 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput3.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput4.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext3 = cuts.add(extInput3) ext4 = cuts.add(extInput4) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class inputChangedEvent(adsk.core.InputChangedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: eventArgs = adsk.core.InputChangedEventArgs.cast(args) changedInput = eventArgs.input fillet_in = None if changedInput.id == 'fillet_cb': inputs = eventArgs.firingEvent.sender.commandInputs fillet_in = inputs.itemById('fillet_in') # Change the visibility of the scale value input. if fillet_in: if changedInput.value == True: fillet_in.isVisible = True else: fillet_in.isVisible = False except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) def stop(context): try: app = adsk.core.Application.get() ui = app.userInterface #Delete Button Def buttonSample = ui.commandDefinitions.itemById('MainButton') if buttonSample: buttonSample.deleteMe() #Delete Button Control addinsPanel = ui.allToolbarPanels.itemById('SolidScriptsAddinsPanel') cntrl = addinsPanel.controls.itemById('MainButton') if cntrl: cntrl.deleteMe() except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Hello,
I found a minor typo error(marked as red) in your codes. It worked well after correcting the error.
Thanks,
Marshal
def holePat(hole_dia, hole_spcX, hole_spcY, hole_cb, length_in, width_in, thick_in): #these values are item IDs - not variables (see above) try: app = adsk.core.Application.get() act = app.activeProduct rootComp = act.rootComponent ui = app.userInterface #total_length = inputs.itemById('length_in').value # Create a new sketch on the xy plane. sketches = rootComp.sketches xyPlane = rootComp.xYConstructionPlane sketch2 = sketches.add(xyPlane) sketch3 = sketches.add(xyPlane) spcX_plus_holerad = (hole_spcX + (hole_dia)) spcY_plus_holerad = (hole_spcY + (hole_dia)) if hole_cb == True and hole_dia > 0: if spcX_plus_holerad >= length_in: ui.messageBox('Oops! User Specified Hole Spacing Greater Than or Equal To Part Length') else: sketch2 = sketches.add(xyPlane) Load_circles = sketch2.sketchCurves.sketchCircles circle1 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/2), 0, (thick_in)), (hole_dia/2)) circle2 = Load_circles.addByCenterRadius(adsk.core.Point3D.create((hole_spcX/-2),0, (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput1 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput2 = cuts.createInput(sketch2.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput1.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput2.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext1 = cuts.add(extInput1) ext2 = cuts.add(extInput2) if spcY_plus_holerad >= width_in and hole_dia > 0: ui.messageBox('Oops! User Specified Hole Spacing Outside Part Extents') else: sketch3 = sketches.add(xyPlane) Load_circles = sketch3.sketchCurves.sketchCircles circle3 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0, (hole_spcY/2), (thick_in)), (hole_dia/2)) circle4 = Load_circles.addByCenterRadius(adsk.core.Point3D.create(0,(hole_spcY/-2), (thick_in)), (hole_dia/2)) cuts = rootComp.features.extrudeFeatures extInput3 = cuts.createInput(sketch3.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation) extInput4 = cuts.createInput(sketch3.profiles.item(1), adsk.fusion.FeatureOperations.CutFeatureOperation) extent_all_ne = adsk.fusion.ThroughAllExtentDefinition.create() extInput3.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) extInput4.setOneSideExtent(extent_all_ne, adsk.fusion.ExtentDirections.NegativeExtentDirection) ext3 = cuts.add(extInput3) ext4 = cuts.add(extInput4) except: if ui: ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Marshal,
Thanks for the reply. What is the typo? I have been using item numbers 0 and 1 with success. I am currently resorting to the rectangular pattern method you suggested. But still curious what is wrong here.
Thanks
Hello,
Sorry, I thought you can easily find the issue. The original code line was as below. You used the first profile of sketch2 though you defined sketch3. So I changed it from sketch2 to sketch3.
extInput3 = cuts.createInput(sketch2.profiles.item(0), adsk.fusion.FeatureOperations.CutFeatureOperation)
Thanks,
Marshal