Here's the model and program that I used in the image I posted earlier. The program is fairly rough since it was just a proof of concept. There are two functions; one that creates the points on the surface and the second one positions a selected component at the point at a specified depth and random orientation and subtracts it from the model.
import adsk.core, adsk.fusion, traceback
import random, math
def run(context):
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
#createPoints()
createGouges()
#ui.messageBox('U: ' + str(avgULength) + ', V: ' + str(avgVLength))
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def createGouges():
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
des = app.activeProduct
root = adsk.fusion.Component.cast(des.rootComponent)
# Have the body selected.
face = ui.selectEntity('Select a face on the body to cut', 'Faces').entity
mainBody = face.body
# Have the sketch with the points selected.
sketch = ui.selectEntity('Select a sketch in the browser', 'Sketches').entity
# Have the gouge occurrence selected.
occ = ui.selectEntity('Select a component', 'Occurrences').entity
gougeBody = occ.bRepBodies.item(0)
mainBody.isVisible = False
baseFeature = root.features.baseFeatures.add()
baseFeature.startEdit()
targetBody = mainBody.copyToComponent(root)
targetBody.isVisible = True
adsk.doEvents()
pnts = []
first = True
for skPnt in sketch.sketchPoints:
if not first:
pnts.append(skPnt.geometry)
else:
first = False
surfEval = face.evaluator
(returnValue, normals) = surfEval.getNormalsAtPoints(pnts)
ui.messageBox('Number of gouges that will be created: ' + str(len(pnts)))
depth = 0.75
toolBodies = adsk.core.ObjectCollection.create()
for i in range(0, len(pnts)):
# Compute the origin of the gouge using the specified depth.
# The depth could be random but it's not implemented yet.
origin = pnts[i].copy()
depthVec = normals[i].copy()
depthVec.normalize()
depthVec.scaleBy(-depth)
origin.translateBy(depthVec)
zAxis = normals[i]
# Get a random direction angle.
angle = random.uniform(0, math.pi * 0.75)
# Create a temporary X vector using the random direction.
tempVec = adsk.core.Vector3D.create(math.cos(angle), math.sin(angle), angle)
# Compute the y axis.
yAxis = zAxis.crossProduct(tempVec)
yAxis.normalize()
# Compute the X axis.
xAxis = yAxis.crossProduct(zAxis)
xAxis.normalize()
trans = adsk.core.Matrix3D.create()
trans.setWithCoordinateSystem(origin, xAxis, yAxis, zAxis)
bodyCollection = adsk.core.ObjectCollection.create()
newGougeBody = gougeBody.copyToComponent(root)
bodyCollection.add(newGougeBody)
toolBodies.add(newGougeBody)
moveInput = root.features.moveFeatures.createInput(bodyCollection, trans)
root.features.moveFeatures.add(moveInput)
if (i % 25) == 0 and i != 0:
combineInput = root.features.combineFeatures.createInput(targetBody, toolBodies)
combineInput.targetBaseFeature = baseFeature
combineInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation
combineInput.isKeepToolBodies = False
combine = root.features.combineFeatures.add(combineInput)
toolBodies = adsk.core.ObjectCollection.create()
adsk.doEvents()
if toolBodies.count > 0:
combineInput = root.features.combineFeatures.createInput(targetBody, toolBodies)
combineInput.targetBaseFeature = baseFeature
combineInput.operation = adsk.fusion.FeatureOperations.CutFeatureOperation
combineInput.isKeepToolBodies = False
combine = root.features.combineFeatures.add(combineInput)
baseFeature.finishEdit()
ui.messageBox('Finished')
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def createPoints():
ui = None
try:
app = adsk.core.Application.get()
ui = app.userInterface
des = app.activeProduct
root = des.rootComponent
face = ui.selectEntity('Select a face', 'Faces').entity
meshCalc = face.meshManager.createMeshCalculator()
meshCalc.surfaceTolerance = 0.9
meshCalc.maxSideLength = 1
#meshCalc.maxAspectRatio = .9
mesh = meshCalc.calculate()
sk = root.sketches.add(root.xYConstructionPlane)
sk.isComputeDeferred = True
skPoints = sk.sketchPoints
coords = mesh.nodeCoordinatesAsDouble
result = ui.messageBox(str(len(coords)/3) + ' points will be created. Do you want to continue?', 'Continue?', adsk.core.MessageBoxButtonTypes.YesNoButtonType, adsk.core.MessageBoxIconTypes.QuestionIconType)
if result == adsk.core.DialogResults.DialogNo:
return
for i in range(0, mesh.nodeCount-1):
pnt1 = getPoint(coords, i)
skPoints.add(pnt1)
sk.isComputeDeferred = False
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
def getPoint(array, index):
return adsk.core.Point3D.create(array[index*3], array[index*3+1], array[index*3+2])