Jump to content

Создание и манипуляция геометрией

From FreeCAD Documentation
This is the approved revision of this page, as well as being the most recent.

В предыдущих главах мы рассмотрели различные верстаки 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)

Всё вышеизложенное и многое другое подробно описано на странице Деталь Написание скриптов, а также там даны примеры.

Читать далее: