💬
Fusion360で数式を使った曲線の描き方
背景
風洞のノズルを設計するにあたり、ノズルの曲線は基本的に数式で描かれます。
普段CADとしてFusion360を使用していますが、基本機能としてはこのような機能がないため、色々調べてみました。
fusion360EquationCurveというのがあったので、試してみました
スクリプトの設定
githubからダウンロードして、解凍し、ドキュメント/Fusion360/scripts/の中に移動させます。
ユーティリティ->アドイン->スクリプトとアドインを選択

スクリプトタブのマイスクリプトのプラス部分をクリックすると、フォルダの選択画面に移ります


これでマイスクリプトに反映されます
操作方法
CurveFromEquationをダブルクリックしてスクリプトを起動します


デフォルトのままOKを押してみましたが、私の環境だと何も変化がなく、何も描けませんでした。
本来だったら、このスクリプトなんて使わないで、別のスクリプトを探すのですが、ちょっと興味が湧いたので、調べてみました。
デバッグ

スクリプトとアドインの右下の実行ボタンのところをデバッグにすると、VSCodeが立ち上がります

どこで引っかかっているのか確認したところ、astevalの挙動がおかしいことがわかりました。
ということで、astevalの変わりにevalを使って書き換えてみました。
CurveクラスのbuildCurve関数の部分だけ書き換えました。
CurveFromEquation.py
class Curve:
def __init__(self):
self.curveName = defaultCurveName
self.xFunction = defaultCurveFunctionX
self.yFunction = defaultCurveFunctionY
self.zFunction = defaultCurveFunctionZ
self.tStart = defaultTStart
self.tEnd = defaultTEnd
self.tStep = defaultTStep
def buildCurve(self):
global newComp
newComp = createNewComponent()
if newComp is None:
ui.messageBox('New component failed to create', 'New Component Failed')
return
product = app.activeProduct
design = adsk.fusion.Design.cast(product)
unitsMgr = design.unitsManager
# Create a new sketch.
sketches = newComp.sketches
xyPlane = newComp.xYConstructionPlane
aeval = Interpreter()
aeval.symtable['pi'] = math.pi
points = adsk.core.ObjectCollection.create()
'''
try:
for time in frange(aeval(self.tStart), aeval(self.tEnd), aeval(self.tStep)):
aeval.symtable['t'] = time
x = unitsMgr.convert(aeval(self.xFunction), unitsMgr.defaultLengthUnits, "internalUnits")
y = unitsMgr.convert(aeval(self.yFunction), unitsMgr.defaultLengthUnits, "internalUnits")
z = unitsMgr.convert(aeval(self.zFunction), unitsMgr.defaultLengthUnits, "internalUnits")
point = adsk.core.Point3D.create(x,y,z)
points.add(point)
except:
print('something wrong')
'''
safe_dict = {'pi': math.pi, 'sin': math.sin, 'cos': math.cos, 'tan': math.tan, 'sqrt': math.sqrt, 'log': math.log}
try:
t_start = eval(self.tStart, {"__builtins__": None}, safe_dict)
t_end = eval(self.tEnd, {"__builtins__": None}, safe_dict)
t_step = eval(self.tStep, {"__builtins__": None}, safe_dict)
for time in frange(t_start, t_end, t_step):
safe_dict['t'] = time
x = unitsMgr.convert(eval(self.xFunction, {"__builtins__": None}, safe_dict), unitsMgr.defaultLengthUnits, "internalUnits")
y = unitsMgr.convert(eval(self.yFunction, {"__builtins__": None}, safe_dict), unitsMgr.defaultLengthUnits, "internalUnits")
z = unitsMgr.convert(eval(self.zFunction, {"__builtins__": None}, safe_dict), unitsMgr.defaultLengthUnits, "internalUnits")
point = adsk.core.Point3D.create(x, y, z)
points.add(point)
except Exception as e:
ui.messageBox(f"評価エラー: {e}")
return
newComp.name = self.curveName
sketch = newComp.sketches.add(newComp.xYConstructionPlane)
sketch.name = self.curveName
try:
sketch.sketchCurves.sketchFittedSplines.add(points)
# sketch.sketchCurves.sketchLines.addByTwoPoints(vertices[(i+1) %6], vertices[i])
except:
print('something wrong')
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('Equation Curve')
if not cmdDef:
cmdDef = commandDefinitions.addButtonDefinition('Equation Curve',
'Create curve from equation',
'Create sketch curve from parametric equation')
onCommandCreated = CurveCommandCreatedHandler()
cmdDef.commandCreated.add(onCommandCreated)
# keep the handler referenced beyond this function
handlers.append(onCommandCreated)
inputs = adsk.core.NamedValues.create()
cmdDef.execute(inputs)
# 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()))
確認

無事動くことがわかりました
これで数式を使って曲線を描くことができます
Discussion