Fusion 360 API сборка на Python

Автор: | 04.02.2018

Введение
Примеры построения сборки:

As-Built Joint
RevoluteJointMotion
SliderJointMotion
CylindricalJointMotion

Контрольные задания

Введение

Один из наиболее важных аспектов построения сборки – соединение подвижных компонентов. Fusion 360 позволяет легко определить соединения (Joints), совмещая геометрические элементы деталей и задавая определенные степени свободы в перемещениях. В зависимости от разновидностей совмещения и перемещений различают семь типов соединений:

«Rigid» (неподвижное) фиксирует все степени свободы, т.е., два компонента неподвижно прикрепляются друг к другу (см. пример реализации через API).

«Revolute» (шарнир) имеет одну степень свободы – вращение вокруг оси. В качестве оси вращения могут быть выбраны оси X, Y и Z или любое ребро в модели. См. пример реализации через API.

«Slider» (ползун) имеет одну поступательную степень свободы. В качестве направления движения могут быть выбраны оси X, Y и Z или любое ребро в модели. См. пример реализации через API.

«Сylindrical» (цилиндрическое) имеет две степени свободы – поступательное и вращательное движения, причем одна и та же ось используется как для перемещения так и для вращения. См. пример реализации через API.

«Pin Slot» (штифт и паз) также имеет две степени свободы – поступательное и вращательное движения, но в этом случае оси могут быть различными.

«Planar» (плоское) имеет три степени свободы – поступательное в 2-х измерениях плоскости и вращательное вокруг оси, перпендикулярной этой плоскости. Пример такого соединения – хоккейная шайба, которая скользит по льду

«Ball» (шар) имеет две степени свободы вращения – вокруг взаимно перпендикулярных осей.

Примеры построения сборки

As-Built Joint

Ниже Python код демонстрирует создание простой сборки из 2х цилиндрических деталей, которые создаются в разных компонентах и неподвижно прикрепляются друг к другу (соединение «Rigid»). Последовательность работы программы отражена на рисунках.

import adsk.core, adsk.fusion, traceback
def run(context):
 ui = None
 try:
  app = adsk.core.Application.get()
  ui = app.userInterface
# 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
# Create two new components under root component
  allOccs = rootComp.occurrences
  transform = adsk.core.Matrix3D.create()
  subOcc0 = allOccs.addNewComponent(transform)
# Create sketch 1 in sub component 1
  subComp0 = subOcc0.component
  sketches0 = subComp0.sketches
  sketch0 = sketches0.add(subComp0.xZConstructionPlane)
  sketchCircles0 = sketch0.sketchCurves.sketchCircles
  centerPoint = adsk.core.Point3D.create(0, 0, 0)
  sketchCircles0.addByCenterRadius(centerPoint, 2.5)
# Get the profile defined by the circle
  prof0 = sketch0.profiles.item(0)
# Create an extrude input and make sure it's in the new component
  extrudes0 = subComp0.features.extrudeFeatures
  extInput0 = extrudes0.createInput(prof0, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Set the extrude input
  distance0 = adsk.core.ValueInput.createByString("5 mm")
  extInput0.setDistanceExtent(False, distance0)
  extInput0.isSolid = True
# Create the extrude
  extrude0 = extrudes0.add(extInput0)
# Get the end face of the created extrude
  endFaceOfExtrude0 = extrude0.endFaces.item(0)
# Create a construction plane for extrude 2
  constructionPlanes = subComp0.constructionPlanes
  constructionPlaneInput = constructionPlanes.createInput()
  constructionPlaneInput.setByOffset(endFaceOfExtrude0, adsk.core.ValueInput.createByString("20 mm"))
  constructionPlane = constructionPlanes.add(constructionPlaneInput)
  constructionPlaneProxy = constructionPlane.createForAssemblyContext(subOcc0)
# Create sketch 2 in sub component 2
  subOcc1 = allOccs.addNewComponent(transform)
  subComp1 = subOcc1.component
  sketches1 = subComp1.sketches
  sketch1 = sketches1.add(constructionPlaneProxy)
  sketchCircles1 = sketch1.sketchCurves.sketchCircles
  sketchCircles1.addByCenterRadius(centerPoint, 0.5)
# Get the profile defined by the circle
  prof1 = sketch1.profiles.item(0)
# Create an extrude input and make sure it's in the new component
  extrudes1 = subComp1.features.extrudeFeatures
  extInput1 = extrudes1.createInput(prof1, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Set the extrude input
  distance1 = adsk.core.ValueInput.createByString("50 mm")
  extInput1.setDistanceExtent(False, distance1)
  extInput1.isSolid = False
# Create the extrude
  extrudes1.add(extInput1)
# Create the AsBuiltJointInput
  asBuiltJoints_ = rootComp.asBuiltJoints
  asBuiltJointInput = asBuiltJoints_.createInput(subOcc0, subOcc1, None)
# Create the AsBuiltJoint
  asBuiltJoints_.add(asBuiltJointInput)
 except:
  if ui:
   ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Для создания сборки  в программе были выполнены следующие действия:

RevoluteJointMotion

Ниже Python код демонстрирует создание соединения «Revolute» (шарнир) для цилиндра. Цилиндр имеет одну степень свободы – вращение вокруг горизонтальной оси.

Последовательность работы программы отражена на рисунках.

import adsk.core, adsk.fusion, traceback
def run(context):
 ui = None
 try:
  app = adsk.core.Application.get()
  ui = app.userInterface
# 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
# Create sketch in root component
  sketches = rootComp.sketches
  sketch = sketches.add(rootComp.xZConstructionPlane)
  sketchCircles = sketch.sketchCurves.sketchCircles
  centerPoint0 = adsk.core.Point3D.create(0, 0, 0)
  circle0 = sketchCircles.addByCenterRadius(centerPoint0, 5.0)
  centerPoint1 = adsk.core.Point3D.create(10, 10, 0)
  circle1 = sketchCircles.addByCenterRadius(centerPoint1, 5.0)
# Get the profile defined by the circle
  prof0 = sketch.profiles.item(0)
  prof1 = sketch.profiles.item(1)
# Create an extrusion input and make sure it's in a new component
  extrudes = rootComp.features.extrudeFeatures
  extInput = extrudes.createInput(prof0, adsk.fusion.FeatureOperations.NewComponentFeatureOperation)
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(5)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion
  ext = extrudes.add(extInput)
# Get the side face of the created extrusion body
  sideFace = ext.sideFaces.item(0)
# Create the first joint geometry with the side face
  geo0 = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint)
# Create the second joint geometry with prof1
  geo1 = adsk.fusion.JointGeometry.createByProfile(prof1, circle1, adsk.fusion.JointKeyPointTypes.CenterKeyPoint)
# Create joint input
  joints = rootComp.joints
  jointInput = joints.createInput(geo0, geo1)
# Set the joint input
  angle = adsk.core.ValueInput.createByString('90 deg')
  jointInput.angle = angle
  offset = adsk.core.ValueInput.createByString('1 cm')
  jointInput.offset = offset
  jointInput.isFlipped = True        
  jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.YAxisJointDirection)
# Create the joint
  joint = joints.add(jointInput)
  revoluteMotion = joint.jointMotion
  limits = revoluteMotion.rotationLimits
  limits.isMinimumValueEnabled = True
  limits.minimumValue = 3.14 / 3
  limits.isMaximumValueEnabled = True
  limits.maximumValue = 3.14 / 3 * 2
 except:
  if ui:
   ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Для создания сборки  в программе были выполнены следующие действия:

  • Создается эскиз с 2-я окружностями в плоскости XZ корневого компонента.
  • Профиль одной из окружностей (prof0) используется для выдавливания цилиндра и создания тела в новом компоненте.
  • Ось боковой поверхности цилиндра (sideFace) с началом (StartKeyPoint)используется для создания первой соединительной геометрии  (geo0).
  • Центр (CenterKeyPoint) второй окружности (prof1, circle1) используем для создания второй joint геометрии (geo1).
  • Создается соединение в соответствии с joint input данными – угол (90 deg ), параллельное смещение (1 см) и ось вращения.
  • Устанавливаются параметры соединения – минимальный и максимальный углы поворота цилиндра.

SliderJointMotion

Ниже Python код демонстрирует создание соединения «Slider»  для цилиндра. Цилиндр имеет одну степень свободы – перемещение вдоль вертикальной оси от заданной точки. Последовательность работы программы отражена на рисунках.

import adsk.core, adsk.fusion, traceback
def run(context):
 ui = None
 try:
  app = adsk.core.Application.get()
  ui = app.userInterface
# 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
# Create sketch in root component
  sketches = rootComp.sketches
  sketch = sketches.add(rootComp.xZConstructionPlane)
  sketchPts = sketch.sketchPoints
  point = adsk.core.Point3D.create(1, 0, 1)
  sketchPt = sketchPts.add(point)
  sketchCircles = sketch.sketchCurves.sketchCircles
  centerPoint = adsk.core.Point3D.create(0, 0, 0)
  circle = sketchCircles.addByCenterRadius(centerPoint, 5.0)
# Get the profile defined by the circle
  prof = sketch.profiles.item(0)
# Create an extrusion input and make sure it's in a new component
  extrudes = rootComp.features.extrudeFeatures
  extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewComponentFeatureOperation)
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(5)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion
  ext = extrudes.add(extInput)
# Get the end face of the created extrusion body
  endFace = ext.endFaces.item(0)
# Get the occurrence of the new component
  occ = rootComp.occurrences.item(0)
# Create a new sketch in the occurrence
  sketchInOcc = sketches.add(endFace, occ)
# Get the sketch curve projected to the sketch
  curve = sketchInOcc.sketchCurves.item(0)
# Create the first joint geometry with the sketch curve
  geo0 = adsk.fusion.JointGeometry.createByCurve(curve, adsk.fusion.JointKeyPointTypes.CenterKeyPoint)
# Create the second joint geometry with sketch point
  geo1 = adsk.fusion.JointGeometry.createByPoint(sketchPt)
# Create joint input
  joints = rootComp.joints
  jointInput = joints.createInput(geo0, geo1)
# Set the joint input
  jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection)
# Create the joint
  joint = joints.add(jointInput)
  sliderMotion = joint.jointMotion
  limits = sliderMotion.slideLimits
  limits.isRestValueEnabled = True
  limits.restValue = 1.0
 except:
  if ui:
   ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Для создания сборки  в программе были выполнены следующие действия:

  • Создается эскиз в плоскости XZ корневого компонента. В нем отображаются точка sketchPt и окружность circle, из которой получаем профиль.
  • Создается новый компонент, а в нем – тело цилиндра, полученное выдавливанием профиля окружности.
  • Получаем верхнюю грань цилиндра endFace и вхождение нового компонента occ. Используя грань endFace, создаем эскиз sketchInOcc во вхождении occ. Получаем эскиз curve, в который проецируется окружность на эскизе sketchInOcc.
  • Создаются объекты geo0 и geo1 (JointGeometry), в которых задаются элементы для совмещения. При создании соединения центр окружности curve совместится с точкой sketchPt .
  • Подготавливаются другие jointInput данные. В качестве направления движения выбрана вертикальная ось. Создается объект joint (соединение) и устанавливаются его параметры.

CylindricalJointMotion

Ниже Python код демонстрирует создание соединения «Cylindrical». Последовательность работы программы отражена на рисунках.

 

import adsk.core, adsk.fusion, traceback
def run(context):
 ui = None
 try:
  app = adsk.core.Application.get()
  ui = app.userInterface
# 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
# Create sketch in root component
  sketches = rootComp.sketches
  sketch = sketches.add(rootComp.xZConstructionPlane)
  sketchPts = sketch.sketchPoints
  point = adsk.core.Point3D.create(1, 0, 1)
  sketchPt = sketchPts.add(point)
  sketchLines = sketch.sketchCurves.sketchLines
  point1 = adsk.core.Point3D.create(1, 0, 2)
  point2 = adsk.core.Point3D.create(2, 0, 1)
  point1SketchSpace = sketch.modelToSketchSpace(point1)
  point2SketchSpace = sketch.modelToSketchSpace(point2)
  lines = sketchLines.addTwoPointRectangle(point1SketchSpace, point2SketchSpace)
# Get the profile defined by the circle
  prof = sketch.profiles.item(0)
# Create an extrusion input and make sure it's in a new component
  extrudes = rootComp.features.extrudeFeatures
  extInput = extrudes.createInput(prof, adsk.fusion.FeatureOperations.NewComponentFeatureOperation)
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(5)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion
  ext = extrudes.add(extInput)
# Get the end face of the created extrusion body
  endFace = ext.endFaces.item(0)
# Get the occurrence of the new component
  occ = rootComp.occurrences.item(0)
# Create a new sketch in the occurrence
  sketchInOcc = sketches.add(endFace, occ)
# Get the sketch curve projected to the sketch
  curve = sketchInOcc.sketchCurves.item(0)
# Create the first joint geometry with the sketch curve
  geo0 = adsk.fusion.JointGeometry.createByCurve(curve, adsk.fusion.JointKeyPointTypes.StartKeyPoint)
# Create the second joint geometry with sketch point
  geo1 = adsk.fusion.JointGeometry.createByPoint(sketchPt)
# Create joint input
  joints = rootComp.joints
  jointInput = joints.createInput(geo0, geo1)
# Set the joint input
  jointInput.setAsCylindricalJointMotion(adsk.fusion.JointDirections.CustomJointDirection,curve.createForAssemblyContext(occ))
# Create the joint
  joint = joints.add(jointInput)
  cylindricalMotion = joint.jointMotion
  rotLimits = cylindricalMotion.rotationLimits
  rotLimits.isRestValueEnabled = True
  rotLimits.restValue = 3.14 / 3
  slideLimits = cylindricalMotion.slideLimits
  slideLimits.isMinimumValueEnabled = True
  slideLimits.minimumValue = 0.1
 except:
  if ui:
   ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

Для создания соединения  в программе были выполнены следующие действия:

  • Создается эскиз в плоскость XZ корневого компонента. В нем отображается точка sketchPt и прямоугольник lines, из которого получаем профиль prof.
  • Создается новый компонент, а в нем – тело параллелепипеда, полученное выдавливанием профиля prof.
  • Получаем верхнюю грань параллелепипеда endFace и вхождение нового компонента occ. Используя грань endFace, создаем эскиз sketchInOcc во вхождении occ. Получаем эскиз curve, в который проецируется параллелепипед на эскизе sketchInOcc.
  • Создаются объекты geo0 и geo1 (JointGeometry), в которых задаются элементы для совмещения. При создании соединения стартовая точка curve совместится с точкой sketchPt .
  • Подготавливаются другие jointInput данные. В качестве направления движения и вращения выбрана вертикальная ось. Создается объект joint (соединение) и устанавливаются его параметры.

Контрольные задания

Задание 1

Разработать Python приложение для создания модели тележки с амортизацией колес. Вращение колес обеспечивается относительно нижних горизонтальных ребер параллелепипеда. Амортизация колес обеспечивается вдоль боковых вертикальных ребер.

Задание 2

Модифицировать  Python приложение «Модель тележки» (см. задание 1) в приложение «Модель самоходной артиллерийской установки (САУ)» либо в «Модель танка»:

  • В САУ верхняя часть корпуса неподвижно прикреплена к основанию (см. соединение «Rigid»). У танка верхняя часть корпуса (башня) вращается относительно вертикальной оси по центру корпусных деталей (см. соединение «Revolute»).
  • В САУ ствол  поворачивается в горизонтальной и вертикальной плоскостях (см. соединение «Ball»).  У танка ствол  поворачивается только в вертикальной плоскости (см. соединение «Revolute»).
  • Колеса вращаются на цилиндрической оси (см. соединение «Revolute»), при этом ось амортизирует (см. соединение «Slider») вдоль вертикальных ребер основания.  Схема зависимой подвески показана на рисунке:

  • Усложненный вариант задания — использовать в сборке схему независимой подвески, самостоятельно изменив форму основания и подобрав необходимые детали и   типы соединений между ними.

Порядок выполнения заданий 1 и 2

Корпус моделируется параллелепипедом – создается выдавливанием прямоугольника в корневом компоненте. Из параллелепипеда через B-Rep моделирование получаем геометрию для соединения с дисками колес — боковую грань и нижнее ребро на ней

В корневом компоненте создается компонент 1, а в нем моделируется диск колеса.

Между геометрией диска компонента 1 и геометрией параллелепипеда устанавливается соединение SliderJointMotion.

В корневом компоненте создается новое вхождение компонента 1. Из диска  вхождения через B-Rep моделирование получаем геометрию для соединения. Между геометрией диска вхождения компонента 1  и геометрией параллелепипеда устанавливается соединение SliderJointMotion.

В компоненте 1 создается компонент 2, а в нем колесо. Из диска и колеса через B-Rep моделирование получаем геометрию для соединения — цилиндрические поверхности колес. Между геометрией диска и колеса устанавливается соединение RevoluteJointMotion в компоненте 1.

 

Ниже приводится приложение, которое создает модель тележки с 2-я колесами. Доработать это приложение, чтобы создавалась модель тележки с 4-я колесами, а затем перейти к моделированию САУ или танка.

 

import adsk.core, adsk.fusion, adsk.cam, traceback
def run(context):
 ui = None
 try:
  app = adsk.core.Application.get()
  ui = app.userInterface
# 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
# Create sketch in root component
  sketch_root = rootComp.sketches.add(rootComp.xYConstructionPlane) 
  sketchLines = sketch_root.sketchCurves.sketchLines
  centerPoint = adsk.core.Point3D.create(0, 0, 0)
  conerPoint = adsk.core.Point3D.create(20, 10,0) 
  rect = sketchLines.addCenterPointRectangle(centerPoint, conerPoint)
# Get the profile defined by the rectangle
  prof_rect = sketch_root.profiles.item(0)
  features = rootComp.features 
  extrudes = features.extrudeFeatures 
  extInput = extrudes.createInput(prof_rect,adsk.fusion.FeatureOperations.NewBodyFeatureOperation)  
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(5)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion. 
  ext = extrudes.add(extInput) 
# Create joint geometry with body 
  body1 = ext.bodies.item(0)
  face = body1.faces.item(5)
  edge = face.edges.item(3) 
  geo0 = adsk.fusion.JointGeometry.createByPlanarFace(face, edge, adsk.fusion.JointKeyPointTypes.EndKeyPoint)
  geo01 = adsk.fusion.JointGeometry.createByPlanarFace(face, edge, adsk.fusion.JointKeyPointTypes.StartKeyPoint) 
# Create component 1 in root component
  trans = adsk.core.Matrix3D.create(); 
# Create component #1
  Comp1 = rootComp.occurrences.addNewComponent(trans).component
# Create a sketch in component #1
  sketch1 = Comp1.sketches.add(Comp1.xYConstructionPlane)
  sketchCircles = sketch1.sketchCurves.sketchCircles 
  centerPoint = adsk.core.Point3D.create(0, 0, 0)
  circle = sketchCircles.addByCenterRadius(centerPoint, 5.0)
# Get the profile defined by the circle
  prof_circle = sketch1.profiles.item(0)
# Create an extrusion input
  extrudes = Comp1.features.extrudeFeatures
  extInput = extrudes.createInput(prof_circle, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(1)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion
  ext = extrudes.add(extInput)
# Get the side face of the created extrusion body
  sideFace = ext.sideFaces.item(0)
# Create joint geometry with wheel
  geo_cil = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint)
 # Create joint wheel and body
  jointInput = rootComp.joints.createInput(geo_cil, geo0)
  jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.XAxisJointDirection)
# Create the joint
  rootComp.joints.add(jointInput) 
# Create a new occurrence for the component #1
  newOcc = rootComp.occurrences.addExistingComponent(Comp1, trans) 
  body = newOcc.bRepBodies.item(0)
  sideFace = body.faces.item(1)
# Create joint wheel and body
  geo_cil_new = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint)
  jointInput = rootComp.joints.createInput(geo_cil_new, geo01)
 #jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection)
  jointInput.setAsSliderJointMotion(adsk.fusion.JointDirections.XAxisJointDirection)
# Create the joint
  rootComp.joints.add(jointInput) 
# Create component #2 in component #1
  Comp2 = Comp1.occurrences.addNewComponent(trans).component 
 # Create a sketch in component #2
  sketch1 = Comp2.sketches.add(Comp1.xYConstructionPlane)
  sketchCircles = sketch1.sketchCurves.sketchCircles 
  centerPoint = adsk.core.Point3D.create(0, 0, 0)
  circle = sketchCircles.addByCenterRadius(centerPoint, 7.0)
# Get the profile defined by the circle
  prof_circle = sketch1.profiles.item(0)
# Create an extrusion input and make sure it's in a new component
  extrudes = Comp2.features.extrudeFeatures
  extInput = extrudes.createInput(prof_circle, adsk.fusion.FeatureOperations.NewBodyFeatureOperation)
# Set the extrusion input
  distance = adsk.core.ValueInput.createByReal(1)
  extInput.setDistanceExtent(True, distance)
  extInput.isSolid = True
# Create the extrusion
  ext = extrudes.add(extInput) 
# Get the side face of the created extrusion body
  sideFace = ext.sideFaces.item(0)
# Create the first joint geometry with wheel
  geo_cil1 = adsk.fusion.JointGeometry.createByNonPlanarFace(sideFace, adsk.fusion.JointKeyPointTypes.StartKeyPoint) 
  jointInput = Comp1.joints.createInput(geo_cil, geo_cil1)
  jointInput.setAsRevoluteJointMotion(adsk.fusion.JointDirections.ZAxisJointDirection)
# Create the joint
  Comp1.joints.add(jointInput)
 
 except:
  if ui: 
   ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

Задание на олимпиаду по САПР

См. пример моделирования задачи автоматизированного проектирования многодисковой фрикционной муфты

 

 

 

Автор: Николай Свирневский

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *