Hi @kandennti , thanks for taking another look at this for me.
When I tried to execute the script with the changes you suggested I got an error:
Failed:
Traceback (most recent call last):
File "C:/Users/rory/AppData/Roaming/Autodesk/Autodesk Fusion 360/API/Scripts/Intersection-EDIT/Intersection-EDIT.py", line 103, in notify
_selIpt1Id,
NameError: name '_selIpt1Id' is not defined
Was I meant to declare the variable elsewhere? Sorry if I missed something obvious, I'm not an expert in Python. Here is a dump of the full script:
#Author-Autodesk Inc.
#Description-Caculate the intersections between the selected curve/surface/body/component/occurrence and curve/surface.
# non planar surface does not support for now
import adsk.core, adsk.fusion, traceback
import os
pi = 3.1415926
nearZero = 0.000001
# global set of event handlers to keep them referenced for the duration of the command
handlers = []
app = adsk.core.Application.get()
if app:
ui = app.userInterface
class IntersectionCommandExecuteHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
command = args.firingEvent.sender
inputs = command.commandInputs
input0 = inputs[0];
sel0 = input0.selection(0);
input1 = inputs[1];
sel1 = input1.selection(0);
intersections = Intersections();
intersections.Execute(sel0.entity, sel1.entity);
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class IntersectionCommandDestroyHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
# when the command is done, terminate the script
# this will release all globals which will remove all event handlers
adsk.terminate()
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class IntersectionValidateInputHandler(adsk.core.ValidateInputsEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
adsk.core.Application.get().log(args.firingEvent.name)
try:
adsk.core.Application.get().log(args.firingEvent.name)
# command inputs
inputs: adsk.core.CommandInputs = args.inputs
# Make sure that the respective SelectionCommandInput is selected.
global _selIpt1Id, _selIpt2Id
for id in [_selIpt1Id, _selIpt2Id]:
selIpt: adsk.core.SelectionCommandInput = inputs.itemById(id)
if not selIpt:
continue
if selIpt.selectionCount != 1:
args.areInputsValid = False
return
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class IntersectionCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
try:
cmd = args.command
onExecute = IntersectionCommandExecuteHandler()
cmd.execute.add(onExecute)
handlers.append(onExecute)
onDestroy = IntersectionCommandDestroyHandler()
cmd.destroy.add(onDestroy)
handlers.append(onDestroy)
onValidateInput = IntersectionValidateInputHandler()
cmd.validateInputs.add(onValidateInput)
handlers.append(onValidateInput)
# Added
onPreSelect = MyPreSelectHandler()
cmd.preSelect.add(onPreSelect)
handlers.append(onPreSelect)
#define the inputs
inputs = cmd.commandInputs
global _selIpt1Id
i1: adsk.core.SelectionCommandInput = inputs.addSelectionInput(
_selIpt1Id,
'Entity One',
'Please select a curve, planear entity or a BRepBody, Component, Occurrence'
)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.Edges)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.PlanarFaces)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.SketchCurves)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.ConstructionLines)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.ConstructionPlanes)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.Bodies)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.Occurrences)
i1.addSelectionFilter(adsk.core.SelectionCommandInput.RootComponents)
i1.setSelectionLimits(0) # Added
global _selIpt2Id
i2 = inputs.addSelectionInput(
_selIpt2Id,
'Entity Two',
'Please select a linear or planear entity'
)
i2.addSelectionFilter(adsk.core.SelectionCommandInput.PlanarFaces)
i2.addSelectionFilter(adsk.core.SelectionCommandInput.LinearEdges)
i2.addSelectionFilter(adsk.core.SelectionCommandInput.SketchLines)
i2.addSelectionFilter(adsk.core.SelectionCommandInput.ConstructionLines)
i2.addSelectionFilter(adsk.core.SelectionCommandInput.ConstructionPlanes)
i2.setSelectionLimits(0) # Added
#adding this line seems to break the validateInputs functionality
inputs.addTextBoxCommandInput('readonly_textBox1', 'text', 'This is where the text will be', 2, True)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class MyPreSelectHandler(adsk.core.SelectionEventHandler):
def __init__(self):
super().__init__()
def notify(self, args: adsk.core.SelectionEventArgs):
adsk.core.Application.get().log(args.firingEvent.name)
# Irrelevant except for SelectionCommandInput.
if args.activeInput.classType() != adsk.core.SelectionCommandInput.classType():
return
# If the selection has already been made, do not allow the selection.
if args.activeInput.selectionCount > 0:
args.isSelectable = False
class Intersections:
def Execute(self, entityOne, entityTwo):
#caculate the intersections
sectionResults = adsk.core.ObjectCollection.create()
def getGeometry(entity):
geom = entity
if isinstance(entity, adsk.fusion.BRepFace) or \
isinstance(entity, adsk.fusion.BRepEdge) or \
isinstance(entity, adsk.fusion.ConstructionAxis) or\
isinstance(entity,adsk.fusion.ConstructionPlane):
geom = entity.geometry
elif isinstance(entity, adsk.fusion.SketchCurve):
geom = entity.worldGeometry;
return geom;
def intersectWith(surfaceOrCurve, section):
surfaceOrCurve = getGeometry(surfaceOrCurve)
section = getGeometry(section)
result = None
if isinstance(surfaceOrCurve, adsk.core.Curve3D):
result = section.intersectWithCurve(surfaceOrCurve)
elif isinstance(section, adsk.core.Curve3D):
result = surfaceOrCurve.intersectWithCurve(section)
else:
if surfaceOrCurve.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType and section.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType :
result = section.intersectWithPlane(surfaceOrCurve)
if result:
sectionResults.add(result)
return
if result:
for resultI in result:
sectionResults.add(resultI)
def intersectWithBody(body, section):
fs = body.faces;
for fsI in fs:
intersectWith(fsI, section)
def intersectWithComponent(comp, occ, section):
if isinstance(comp,adsk.fusion.Component):
bodies = comp.bRepBodies
for body in bodies:
if(not body):
continue
if occ :
body = body.createForAssemblyContext(occ)
intersectWithBody(body, section)
childOccs = None
if occ :
childOccs = occ.childOccurrences
else:
childOccs = comp.occurrences
for childOcc in childOccs:
if not childOcc:
continue
intersectWithComponent(childOcc.component, childOcc, section);
if isinstance(entityOne,adsk.fusion.Component):
intersectWithComponent(entityOne, None, entityTwo)
elif isinstance(entityOne,adsk.fusion.Occurrence):
intersectWithComponent(entityOne.component, entityOne, entityTwo)
elif isinstance(entityOne, adsk.fusion.BRepBody):
intersectWithBody(entityOne, entityTwo)
else:
intersectWith(entityOne, entityTwo)
if len(sectionResults) == 0:
if ui:
ui.messageBox('No intersection found')
return
def isPlanearEntity(entity):
planearEnt = False
if isinstance(entity, adsk.fusion.ConstructionPlane):
planearEnt = True
elif isinstance(entity, adsk.fusion.BRepFace):
sur = entity.geometry
if(sur.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType):
planearEnt = True
return planearEnt
doc = app.activeDocument
d = doc.design
rootComp = d.rootComponent
sketch = None
if isPlanearEntity(entityTwo):
sketch = rootComp.sketches.add(entityTwo)
elif isPlanearEntity(entityOne):
sketch = rootComp.sketches.add(entityOne)
else:
sketch = rootComp.sketches.add(rootComp.xYConstructionPlane)
for geom in sectionResults:
if not geom or not sketch:
continue
m = sketch.transform
m.invert()
geom.transformBy(m)
if isinstance(geom,adsk.core.Point3D):
sketch.sketchPoints.add(geom)
elif isinstance(geom,adsk.core.Curve3D):
sketchCurve = None
if isinstance(geom, adsk.core.Line3D):
sketchCurve = sketch.sketchCurves.sketchLines.addByTwoPoints(geom.startPoint, geom.endPoint);
elif isinstance(geom,adsk.core.Arc3D):
sweepAngle = 2 * pi if abs(geom.endAngle - geom.startAngle) < nearZero else geom.startAngle
sketchCurve = sketch.sketchCurves.sketchArcs.addByCenterStartSweep(geom.center, geom.startPoint, sweepAngle)
elif isinstance(geom,adsk.core.Circle3D):
sketchCurve = sketch.sketchCurves.sketchCircles.addByCenterRadius(geom.center, geom.radius)
elif isinstance (geom,adsk.core.Ellipse3D):
curveEva = geom.evaluator
startParameter = None
endParameter = None
curveEva.getParameterExtents(startParameter, endParameter)
pointOnCurve = None
curveEva.getPointAtParameter((startParameter + endParameter)/3, pointOnCurve)
majorAxisPoint = geom.center
majorAxisVec = geom.majorAxis
majorAxisVec.scaleBy(geom.majorRadius)
majorAxisPoint.translateBy(majorAxisVec)
sketchCurve = sketch.sketchCurves.sketchEllipses.add(geom.center, majorAxisPoint, pointOnCurve)
elif isinstance(geom, adsk.core.NurbsCurve3D):
pts = geom.controlPoints
ptCol = adsk.core.ObjectCollection.create()
for ptsI in pts:
ptCol.add(ptsI)
sketchCurve = sketch.sketchCurves.SketchFittedSplines.add(ptCol)
elif isinstance(geom,adsk.core.InfiniteLine3D):
start = geom.origin
end = geom.origin
dir = geom.direction
dir.scaleBy(10)
end.translateBy(dir)
sketchCurve = sketch.sketchCurves.sketchLines.addByTwoPoints(start, end)
if sketchCurve:
sketchCurve.isConstruction = True
def run(context):
try:
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
if not design:
ui.messageBox('It is not supported in current workspace, please change to MODEL workspace and try again.')
return
commandDefinitions = ui.commandDefinitions
# check the command exists or not
cmdDef = commandDefinitions.itemById('IntersectionCMDDef')
if not cmdDef:
resourceDir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'resources') # absolute resource file path is specified
cmdDef = commandDefinitions.addButtonDefinition('IntersectionCMDDef',
'Intersections',
'Calculate the intersections of two selected entities',
resourceDir)
onCommandCreated = IntersectionCommandCreatedHandler()
cmdDef.commandCreated.add(onCommandCreated)
# keep the handler referenced beyond this function
handlers.append(onCommandCreated)
cmdDef.execute()
# prevent this module from being terminate when the script returns, because we are waiting for event handlers to fire
adsk.autoTerminate(False)
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))