Создание и манипуляция геометрией
- Введение
- Открываем для себя FreeCAD
- Работа с FreeCAD
- Первый взгляд на все верстаки
- Традиционное моделирование методом CSG (КБГ)
- Традиционное двумерное черчение
- Моделирование для проектирования продукта
- Подготовка для 3D печати
- Создание двумерных чертежей
- Моделирование BIM
- Использование электронных таблиц
- Создание анализа методом конечных элементов
- Создание визуализаций (рендеринга)
- Написание скриптов на Python
- Сообщество
В предыдущих главах мы рассмотрели различные верстаки FreeCAD и то, как каждый из них предоставляет свой собственный набор инструментов и типов геометрии. Те же принципы применимы и при работе с FreeCAD через скрипты Python.
Мы также отметили, что большинство верстаков FreeCAD опираются на один основополагающий верстак: Верстак Деталь (Part). Многие другие верстаки, такие как
Верстак Набросок (Draft), используют инструменты и геометрию Верстака Деталь, и именно это мы будем делать в этой главе - использовать Python для создания и работы с геометрией деталей.
Чтобы начать работу с геометрией Детали (Part) в Python, нам нужно выполнить скриптовый эквивалент перехода в Верстак Деталь: импортировать модуль Part.
import Part
Удели время изучению модуля Деталь, набрав Part. в консоли Python и просмоти доступные методы и атрибуты в окне автозаполнения. Это отличный способ ознакомиться с функциональностью модуля. Ты найдёшь множество удобных функций, таких как makeBox и makeCircle, которые позволяют быстро создавать геометрические фигуры и объекты с помощью всего одной команды. Многие из этих функций также имеют дополнительные параметры, что позволяет точно контролировать их размеры и расположение.
Потратив некоторое время на просмотр содержимого модуля, ты не только узнаешь, какие инструменты находятся в твоём распоряжении, но и получишь представление о том, как работает Верстак Деталь "под капотом". Эти базовые знания окажутся бесценными, когда мы будем двигаться дальше и начнём программно создавать геометрию и манипулировать ею. Введи следующую команду
Part.makeBox(3,5,7)
Эта команда создает 3D-куб, также известный как прямоугольная призма, с заданными размерами. Первый параметр, 3, задаёт длину куба по оси X. Второй параметр, 5, задаёт ширину по оси Y, а третий параметр, 7, - высоту по оси Z. Хотя эта функция генерирует геометрию куба, она не добавляет её автоматически в активный документ FreeCAD. В консоли Python вы увидите следующее:
<Solid object at 0x5f43600>
Вывод <Solid object at 0x5f43600> указывает на то, что в памяти была создана Форма Детали (Part Shape). Это геометрический объект, хранящийся по определённому адресу памяти, о чём свидетельствует шестнадцатеричное значение (0x5f43600). Однако важно понимать, что то, что мы создали здесь, ещё не является объектом документа FreeCAD - оно существует только как необработанная геометрическая форма в памяти.
Это обстоятельство указывает на фундаментальную концепцию FreeCAD: объекты и их геометрия независимы. Объект документа FreeCAD служит контейнером, в который помещается фигура. Эти объекты документа могут иметь дополнительные свойства, такие как длина, ширина и высота, и могут быть параметрическими. Параметрические объекты динамически пересчитывают свою геометрию (или форму) при изменении одного из своих свойств. Например, при изменении длины параметрического куба его геометрия автоматически пересчитывается с учётом обновлённого значения.
В данном случае мы вручную создали фигуру с помощью функции Part.makeBox(). Эта фигура является непараметрическим объектом, то есть она не будет автоматически обновляться на основе каких-либо свойств - она статична, если только мы не манипулируем ею программно. Чтобы сделать эту фигуру частью активного документа FreeCAD, её нужно привязать к объекту документа (например, Part::Feature), что свяжет её с графическим интерфейсом и сделает её видимой и управляемой в среде FreeCAD.
Такое разделение фигур и объектов документов делает FreeCAD очень универсальным, позволяя пользователям программно манипулировать фигурами и интегрировать их в процесс параметрического моделирования по мере необходимости.
Теперь мы можем легко создать "общий" объект документа в текущем документе (убедись, что у тебя открыт хотя бы один новый документ) и придать ему форму куба, подобную той, которую мы только что создали:
boxShape = Part.makeBox(3,5,7)
myObj = FreeCAD.ActiveDocument.addObject("Part::Feature","MyNewBox")
myObj.Shape = boxShape
FreeCAD.ActiveDocument.recompute()
Ниже приведена разбивка предыдущих команд:
- boxShape = Part.makeBox(3,5,7): Создаёт 3D куб с размерами 3x5x7 (длина, ширина и высота) и сохраняет его в переменной boxShape как Форму Детали (Part Shape). Эта форма существует только в памяти и пока не является частью документа FreeCAD.
- myObj = FreeCAD.ActiveDocument.addObject("Part::Feature", "MyNewBox"): Добавляет новый объект Part::Feature с именем "MyNewBox" в активный документ FreeCAD и присваивает его переменной myObj. Новый объект появится в дереве проекта FreeCAD.
- myObj.Shape = boxShape: Связывает геометрию boxShape со свойством Shape объекта myObj, интегрируя геометрию в документ FreeCAD.
- FreeCAD.ActiveDocument.recompute(): Обновляет документ с учётом внесённых изменений, обеспечивая появление нового объекта и его геометрии на экране графического интерфейса.
Обратите внимание, как мы обработали myObj.Shape. Это было сделано так же, как и в предыдущей главе, где мы изменяли другие свойства объекта, например box.Height = 5. На самом деле, Shape - это тоже свойство, как и Height. Однако вместо того, чтобы принимать число, Shape требует Part Shape. В следующей главе мы подробнее рассмотрим, как строятся эти параметрические объекты.
А сейчас давай рассмотрим Part Shapes более подробно. В главе о традиционном моделировании с помощью Верстака Деталь - Part мы представили таблицу, объясняющую, как строятся Part Shapes и из каких компонентов они состоят, таких как вершины - vertexes, рёбра - edges и грани - faces. Эти же компоненты доступны при работе с Part Shapes в Python, что позволяет детально исследовать геометрию и манипулировать ею. Part Shapes в FreeCAD всегда имеют следующие атрибуты:
- Vertexes - Вершины: Точки в 3D пространстве, определяющие концы или углы геометрических фигур.
- Edges - Рёбра: Прямые или кривые линии, соединяющие две вершины.
- Wires - Кривые/ломанные: Замкнутые или разомкнутые контуры, образованные одним или несколькими соединёнными рёбрами.
- Faces - Грани: Поверхности, ограниченные одной или несколькими кривыми.
- Shells - Оболочки: Группы соединённых граней, образующих сплошную поверхность.
- Solids - Твёрдые тела: 3D-объемы, заключенные в одну или несколько оболочек.
В Python все эти атрибуты представлены в виде списков. Каждый список может содержать любое количество элементов или быть пустым, в зависимости от конкретной формы. Например, у куба будет восемь Vertexes - Вершин, двенадцать Edges - Рёбер, шесть Faces - Граней, одна Shell - Оболочка и одно Solid - Твёдаое тело, в то время как у линии будет только две Vertexes - Вершины и одно Edge - Ребро, а все остальные атрибуты будут пустыми. Эти компоненты являются фундаментальными строительными блоками геометрии Part - Детали, и к ним можно обращаться и манипулировать ими программно. Понимание того, как они взаимодействуют, обеспечивает мощный контроль над созданием и изменением 3D-моделей. Мы можем получить доступ к этим спискам следующим образом:
print(boxShape.Vertexes)
print(boxShape.Edges)
print(boxShape.Wires)
print(boxShape.Faces)
print(boxShape.Shells)
print(boxShape.Solids)
Давай найдём площадь каждой грани нашей квадратной формы: (Не забудьте сделать отступ во второй строке, как показано ниже. После последней строки дважды нажмите Enter, чтобы запустить команду Python).
for f in boxShape.Faces:
print(f.Area)
Или, для каждого ребра, начальную и конечную точку:
for e in boxShape.Edges:
print("New edge")
print("Start point:")
print(e.Vertexes[0].Point)
print("End point:")
print(e.Vertexes[1].Point)
Как видишь, если у нашей формы boxShape есть атрибут "Vertexes", то у каждой грани формы boxShape также есть атрибут "Vertexes". Как и следовало ожидать, у boxShape будет 8 вершин, а у edge - только 2, которые обе являются частями списка из 8 вершин.
Мы всегда можем проверить, каков тип формы:
print(boxShape.ShapeType)
print(boxShape.Faces[0].ShapeType)
print(boxShape.Vertexes[2].ShapeType)
Вот краткое объяснение вышеприведённых команд::
- print(boxShape.ShapeType): Отображает тип фигуры верхнего уровня, представленной boxShape. В данном случае, поскольку boxShape была создана как куб с помощью Part.makeBox, выводится значение "Solid", указывающее на то, что фигура является 3D-твёрдым объектом.
- print(boxShape.Faces[0].ShapeType): Получает доступ к первой грани Faces в списке boxShape (индекс 0) и выводит тип её формы. Для куба каждая грань представляет собой плоскую поверхность, поэтому выводится "Face".
- print(boxShape.Vertexes[2].ShapeType): Получает доступ к третьей вершине Vertexes в списке boxShape (индекс 2) и выводит тип её формы. Поскольку это конкретная точка в 3D-пространстве, то выводится "Vertex".
Вкратце о концепции Part Shapes: Всё начинается с Vertexes - Вершин, самых базовых элементов геометрии. Используя одну или две Vertexes - Вершины, можно создать Edge - Ребро (обратите внимание, что для замкнутых окружностей требуется только одна Вершина). Одно или несколько Рёбер могут образовать Кривую - Wire, которая может быть как открытой, так и замкнутой. Когда у тебя есть одна или несколько замкнутых Кривых, ты можешь создать Грань - Face. Дополнительные Кривые внутри основной Кривой будут действовать как "отверстия" в Грани. Комбинируя одну или несколько Граней, ты можешь построить Оболочку - Shell, которая по сути является набором соединённых поверхностей. Если «Оболочка» полностью закрыта и герметична, её можно использовать для формирования Твёрдого тела - Solid - 3D-объекта с объёмом. Наконец, любое количество фигур любого типа, включая Вершины, Рёбра, Кривые, Грани, Оболочки или Твёрдые тела, можно объединить в Объединение (Группу/Компаунд) - Compound, которая выступает в качестве контейнера для множества фигур.
Теперь мы попробуем создать сложные формы с нуля, конструируя все их компоненты один за другим. Например, попробуем создать объём вроде этого:
Начнём с создания плоской формы вроде этой:
Сначала создадим четыре базовые точки:
V1 = FreeCAD.Vector(0,10,0)
V2 = FreeCAD.Vector(30,10,0)
V3 = FreeCAD.Vector(30,-10,0)
V4 = FreeCAD.Vector(0,-10,0)
Затем создадим два линейных сегмента
L1 = Part.LineSegment(V1,V2)
L2 = Part.LineSegment(V4,V3)
Обрати внимание, что нам не нужно было создавать Vertexes - Вершины явно. Вместо этого мы можем напрямую создать Part.LineSegments, используя FreeCAD Vectors. Это происходит потому, что на данном этапе мы работаем с базовой геометрией, а не с реальными Edges - Рёбрами. Part.LineSegment, как и Part.Circle, Part.Arc, Part.Ellipse или Part.BSpline, определяет базовую геометрию, но сам по себе не генерирует ребро. В FreeCAD рёбра всегда строятся из такой базовой геометрии, которая хранится в атрибуте Curve - Кривая у Edge - Ребра. Это означает, что ребро, по сути, является обёрткой вокруг базовой геометрии, наследуя её свойства. Если у вас есть ребро, вы можете получить доступ к его базовой геометрии, обратившись к атрибуту curve. Следующая команда:
print(Edge.Curve)
позволяет понять базовую структуру ребра и то, как оно было построено. Теперь давай вернёмся к нашему упражнению и продолжим построение сегментов дуги. Чтобы создать дугу, нам нужны три точки: начальная, конечная и средняя, определяющая кривизну. Для этого мы можем использовать удобную функцию Part.Arc, которая принимает эти три точки на вход и создаёт базовую геометрию для дуги.
VC1 = FreeCAD.Vector(-10,0,0)
C1 = Part.Arc(V1,VC1,V4)
VC2 = FreeCAD.Vector(40,0,0)
C2 = Part.Arc(V2,VC2,V3)
Теперь у нас есть 2 линии (L1 и L2) и 2 дуги (C1 и C2). Их надо превратить в рёбра - edges:
E1 = Part.Edge(L1)
E2 = Part.Edge(L2)
E3 = Part.Edge(C1)
E4 = Part.Edge(C2)
В качестве альтернативы у базовых геометрий есть функция toShape(), которая делает то же самое:
E1 = L1.toShape()
E2 = L2.toShape()
...
Когда у нас есть ряд рёбер, мы можем сформировать Wire - Кривую, передав ей список рёбер. При этом нужно обратить внимание на порядок. Также обратите внимание на скобки.
W = Part.Wire([E1,E4,E2,E3])
И мы можем проверить, правильно ли была понята наша кривая и правильно ли она замкнута:
print( W.isClosed() )
В результате будет выведено "True" или "False". Чтобы создать Face - Грань, нам нужны closed Wires - замкнутые Кривые, поэтому всегда полезно проверить это перед созданием грани. Теперь мы можем создать грань, задав ей одну кривую (или список кривых, если нам нужны отверстия):
F = Part.Face(W)
Затем мы выдавим её:
P = F.extrude(FreeCAD.Vector(0,0,10))
Обратите внимание, что P уже является Solid - Твёрдым телом:
print(P.ShapeType)
Это происходит потому, что при выдавливании одной грани мы всегда получаем твёрдое тело. Этого бы не произошло, например, если бы мы выдавливали кривую:
S = W.extrude(FreeCAD.Vector(0,0,10))
print(S.ShapeType)
Это, разумеется, даст нам полую оболочку, без верхней и нижней плоскости.
Теперь, когда у нас есть окончательная форма, мы с нетерпением желаем увидеть её на экране! Так что создадим общий объект, и присвоим ему наше новое Твёрдое тело - Solid:
myObj2 = FreeCAD.ActiveDocument.addObject("Part::Feature","My_Strange_Solid")
myObj2.Shape = P
FreeCAD.ActiveDocument.recompute()
Как альтернатива, модуль Деталь - Part также содержит быструю команду, которая выполняет вышеуказанную операцию быстрее (но при этом ты не можешь выбрать имя объекта):
Part.show(P)
Всё вышеизложенное и многое другое подробно описано на странице Деталь Написание скриптов, а также там даны примеры.
Читать далее:
- FreeCAD scripting: Python, Introduction to Python, Python scripting tutorial, FreeCAD Scripting Basics
- Modules: Builtin modules, Units, Quantity
- Workbenches: Workbench creation, Gui Commands, Commands, Installing more workbenches
- Meshes and Parts: Mesh Scripting, Topological data scripting, Mesh to Part, PythonOCC
- Parametric objects: Scripted objects, Viewproviders (Custom icon in tree view)
- Scenegraph: Coin (Inventor) scenegraph, Pivy
- Graphical interface: Interface creation, Interface creation completely in Python (1, 2, 3, 4, 5), PySide, PySide examples beginner, intermediate, advanced
- Macros: Macros, How to install macros
- Embedding: Embedding FreeCAD, Embedding FreeCADGui
- Other: Expressions, Code snippets, Line drawing function, FreeCAD vector math library (deprecated)
- Hubs: User hub, Power users hub, Developer hub



