- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report
I am trying to place points in 3D space according to parametric mathematical formulas (and join them with a spline, but that's not relevant here).
If I have 5 or fewer iterations in my loop (5 construction points + 5 spline points for a total of 10 points), my sketch is fully constrained.
If I have 6 or more iterations (12 or more points), my sketch is not fully constrained.
Here it is with 10 iterations. As you can see, only the first 5 point pairs are constrained.
As I am applying all the same constraints to all points - it's a loop - this makes no sense to me. Can anyone explain what's going on?
import adsk
from adsk.core import (Application, ObjectCollection, Point3D, ValueInput)
from adsk.fusion import (Design, DimensionOrientations)
import math, traceback
handlers = []
def run(context):
ui = None
try:
app = Application.get()
ui = app.userInterface
drawSplines = ui.commandDefinitions.addButtonDefinition(
"DrawTrigSpline",
"Draw Trig Spline",
"Draw Trig Spline"
)
drawSplinesCreated = DrawSplinesCreatedEventHandler()
drawSplines.commandCreated.add(drawSplinesCreated)
handlers.append(drawSplinesCreated)
drawSplines.execute()
adsk.autoTerminate(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 the command definition.
cmdDef = ui.commandDefinitions.itemById('DrawTrigSpline')
if cmdDef:
cmdDef.deleteMe()
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
class DrawSplinesCreatedEventHandler(adsk.core.CommandCreatedEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
args = adsk.core.CommandCreatedEventArgs.cast(args)
onExecute = DrawSplinesExecuteEventHandler()
args.command.execute.add(onExecute)
handlers.append(onExecute)
class DrawSplinesExecuteEventHandler(adsk.core.CommandEventHandler):
def __init__(self):
super().__init__()
def notify(self, args):
ui = None
try:
app = Application.get()
ui = app.userInterface
# API uses cm for all lengths
maj_d = 1
min_d = 0.2
# avoid dealing with zero or negative constraint distances
xyoffset = maj_d * 2
zoffset = min_d * 2
# API uses rad for all angles, but these are in degrees and we convert them later
minDeg = -90
maxDeg = 90
steps = 6
design = Design.cast(app.activeProduct)
parameters = design.userParameters
parameters.add("maj_d", ValueInput.createByReal(maj_d), "mm", "major diameter")
parameters.add("min_d", ValueInput.createByReal(min_d), "mm", "minor diameter")
component = design.rootComponent
refPlane = component.xYConstructionPlane
sketch = component.sketches.add(refPlane)
sketch.isComputeDeferred = True
sketch.areProfilesShown = False
origin = sketch.originPoint
points = sketch.sketchPoints
lines = sketch.sketchCurves.sketchLines
constraints = sketch.geometricConstraints
dimensions = sketch.sketchDimensions
radials = []
axials = []
if steps > 1:
stepDeg = (maxDeg - minDeg) / (steps - 1)
else:
stepDeg = 0
for thetaDeg in (minDeg + i*stepDeg for i in range(steps)):
thetaRad = thetaDeg * math.pi / 180
r = maj_d
x = xyoffset + r * math.sin(thetaRad)
y = xyoffset + r * math.cos(thetaRad)
z = zoffset + math.cos(4 * thetaRad) * (min_d/2)
radial = points.add(Point3D.create(x,y,0))
radials.append(radial)
xDim = dimensions.addDistanceDimension(radial, origin,
DimensionOrientations.HorizontalDimensionOrientation,
Point3D.create(x/2,y,0))
xDim.parameter.expression = f"{xyoffset} cm + sin({thetaDeg} deg) * maj_d"
yDim = dimensions.addDistanceDimension(radial, origin,
DimensionOrientations.VerticalDimensionOrientation,
Point3D.create(x,y/2,0))
yDim.parameter.expression = f"{xyoffset} cm + cos({thetaDeg} deg) * maj_d"
axial = lines.addByTwoPoints(radial, Point3D.create(x, y, z))
axial.isConstruction = True
axials.append(axial)
zDim = dimensions.addDistanceDimension(axial.endSketchPoint, radial,
DimensionOrientations.AlignedDimensionOrientation,
Point3D.create(x, y, z/2))
zDim.parameter.expression = f"{zoffset} cm + {z / (min_d/2)} * (min_d/2)"
sketch.isComputeDeferred = False
for radial in radials:
constraints.addCoincidentToSurface(radial, refPlane)
for axial in axials:
constraints.addPerpendicularToSurface(axial, refPlane)
for constraint in constraints:
if not constraint.isValid:
ui.messageBox(f'{constraint.classType} is not valid')
adsk.terminate()
except:
if ui:
ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
Solved! Go to Solution.