Skip to main content

Someone wanted to learn this too, so Grasp built them a personal learning path.

You can keep exploring this one or create your own

Разделение модели режущей плоскостью

Recommended resources

The freely available resources this lesson will direct you to.

Здравствуйте!

На прошлом уроке мы сделали важный шаг: превратили монолитный блок в полую коробку с помощью операции thicken. Теперь у нас есть основа, но для настоящего корпуса нужны как минимум две части — основание и крышка.

Цель этого урока — научиться разделять нашу полую модель на две части (основание и крышку) с помощью режущей плоскости. Этот метод гарантирует, что обе половины будут идеально подходить друг к другу, так как они созданы из единого целого.

1. Концепция разделения (Split)

Представьте, что вы берете нож и разрезаете яблоко. В CAD-моделировании мы делаем то же самое, только вместо ножа используем воображаемую бесконечную плоскость (Plane), а вместо яблока — нашу 3D-модель.

U-образный кронштейн, разделенный плоскостью
Пример разделения U-образного кронштейна горизонтальной плоскостью. Нижняя часть сделана прозрачной для наглядности. Мы применим тот же принцип к нашей полой коробке.

В build123d за это отвечает операция split. Она принимает объект, режущий инструмент (в нашем случае Plane) и указание, какую часть объекта сохранить.

2. Подготовка к разделению: Параметры и режущая плоскость

Для начала создайте копию файла из прошлого урока enclosure_v2.py и назовите ее enclosure_v3.py.

Чтобы сделать наш дизайн параметрическим, давайте определим высоту, на которой будет проходить разрез. Мы можем задать высоту нижней части (основания).

Добавьте новый параметр в секцию ПАРАМЕТРЫ:

# Высота нижней части корпуса (основания)
base_height = 15.0

Теперь нам нужно создать саму режущую плоскость. Поскольку наш solid_block был создан с align=(Align.CENTER, Align.CENTER, Align.CENTER), его центр находится в точке (0, 0, 0), а по высоте он простирается от -enclosure_height / 2 до +enclosure_height / 2.

Плоскость разреза должна находиться на высоте base_height от дна корпуса. Координата Z дна равна -enclosure_height / 2. Следовательно, координата Z режущей плоскости будет:

split_z = -enclosure_height / 2 + base_height

Теперь мы можем создать саму плоскость. Это будет стандартная плоскость XY, смещенная вверх на split_z.

В коде, после создания hollow_box, добавим:

# 4. Определяем плоскость для разрезания модели
split_z = -enclosure_height / 2 + base_height
cutting_plane = Plane.XY.offset(split_z)

3. Выполнение операции split

Теперь, когда у нас есть и объект (hollow_box), и инструмент (cutting_plane), мы можем выполнить разделение. Мы хотим сохранить обе части, поэтому используем опцию keep=Keep.BOTH.

# 5. Разделяем полую коробку на две части
# split возвращает Compound - составной объект, содержащий все части
split_parts = split(hollow_box, bisect_by=cutting_plane, keep=Keep.BOTH)

Операция split с keep=Keep.BOTH возвращает объект типа Compound, который является контейнером для нескольких Solid (твердых тел). Нам нужно извлечь из него наши две части и присвоить их переменным base и lid.

Порядок тел внутри Compound не гарантирован, поэтому самый надежный способ их различить — отсортировать по положению центра по оси Z. Тело с меньшей координатой Z будет основанием (base), а с большей — крышкой (lid).

# 6. Извлекаем и сортируем части
# .solids() возвращает список всех твердых тел из Compound
# Сортируем их по Z-координате центра, чтобы надежно определить основание и крышку
all_solids = split_parts.solids()
sorted_solids = sorted(all_solids, key=lambda s: s.center().Z)

base = sorted_solids[0]
lid = sorted_solids[1]

Теперь у нас есть две отдельные переменные, base и lid, каждая из которых хранит свою часть корпуса.

4. Итоговый код и визуализация

Ваш файл enclosure_v3.py должен выглядеть следующим образом. Обратите внимание на блок визуализации: чтобы лучше рассмотреть обе части, мы немного приподнимем крышку перед отображением.

# enclosure_v3.py
from build123d import *

# ================== ПАРАМЕТРЫ ==================
# Внешние габариты будущего корпуса в миллиметрах
enclosure_length = 100.0
enclosure_width = 70.0
enclosure_height = 35.0

# Толщина стенок корпуса
wall_thickness = 2.0

# Высота нижней части корпуса (основания)
base_height = 15.0

# ================== ПРОЕКТИРОВАНИЕ ==================
# 1. Создаем монолитный блок
solid_block = Box(
    length=enclosure_length,
    width=enclosure_width,
    height=enclosure_height,
    align=(Align.CENTER, Align.CENTER, Align.CENTER)
)

# 2. Выбираем верхнюю грань для удаления
top_face = solid_block.faces().filter_by(Axis.Z).last

# 3. Применяем thicken для создания полости
hollow_box = solid_block.thicken(amount=-wall_thickness, faces=top_face)

# 4. Определяем плоскость для разрезания модели
split_z = -enclosure_height / 2 + base_height
cutting_plane = Plane.XY.offset(split_z)

# 5. Разделяем полую коробку на две части
split_parts = split(hollow_box, bisect_by=cutting_plane, keep=Keep.BOTH)

# 6. Извлекаем и сортируем части
all_solids = split_parts.solids()
sorted_solids = sorted(all_solids, key=lambda s: s.center().Z)

base = sorted_solids[0]
lid = sorted_solids[1]

# ================== ВИЗУАЛИЗАЦИЯ ==================
# Проверяем, что получилось
if "show_object" in locals():
    # Отображаем основание
    show_object(base, name="Base")
    # Отображаем крышку, немного сместив ее вверх для наглядности
    show_object(lid.moved(Location(Vector(0, 0, 10))), name="Lid")

Запустите этот код. В окне OCP CAD Viewer вы увидите две части корпуса, расположенные одна над другой. Вы только что успешно разделили модель!

Для справки: другие примеры `split`

Операция split очень универсальна. Например, ее часто используют для создания плоских поверхностей на криволинейных объектах, чтобы их было проще печатать на 3D-принтере.

Чтобы увидеть такой пример, вы можете изучить следующий ресурс.

The build123d Examples - Peg Board Hook

В официальной документации build123d есть пример создания крючка для перфорированной панели. Обратите внимание, как split используется там для срезания верхней и нижней частей изогнутого тела, чтобы создать плоские поверхности, которые хорошо лягут на стол 3D-принтера.

Найдите раздел 'Peg Board Hook'. Просмотрите код в секции 'Reference Implementation (Builder Mode)' и обратите внимание на последние две строки внутри блока with BuildPart() as mainp:.

Проверьте себя!

Представьте, что вам нужно спроектировать не корпус с крышкой, а выставочный стенд, где модель разрезана вертикально, чтобы показать внутреннее устройство.

Задание: Модифицируйте код enclosure_v3.py так, чтобы он разделял коробку не горизонтально, а вертикально, точно посередине вдоль длинной стороны (оси X). В результате у вас должны получиться левая и правая половинки.

Подсказка: Какую плоскость нужно использовать для разрезания по центру вдоль оси X? Как нужно изменить логику сортировки?

Показать решение

Для вертикального разреза по центру нам нужна плоскость YZ. Поскольку коробка отцентрована, эта плоскость уже проходит через x=0.

Логику сортировки нужно изменить так, чтобы она работала с координатой X, а не Z.

Вот ключевые изменения в коде:

# enclosure_v3_exercise.py
...
# 4. Определяем плоскость для разрезания модели
# Используем плоскость YZ, которая проходит через x=0
cutting_plane = Plane.YZ

# 5. Разделяем полую коробку на две части
split_parts = split(hollow_box, bisect_by=cutting_plane, keep=Keep.BOTH)

# 6. Извлекаем и сортируем части
all_solids = split_parts.solids()
# Сортируем по X-координате центра
sorted_solids = sorted(all_solids, key=lambda s: s.center().X)

left_part = sorted_solids[0]
right_part = sorted_solids[1]

# ================== ВИЗУАЛИЗАЦИЯ ==================
if "show_object" in locals():
    # Смещаем правую часть вправо для наглядности
    show_object(left_part, name="Left Part")
    show_object(right_part.moved(Location(Vector(10, 0, 0))), name="Right Part")

Этот пример показывает, как легко изменить логику разделения, просто поменяв режущую плоскость и ключ сортировки. Это демонстрирует мощь и гибкость параметрического подхода.

Ключевые выводы

  • Мы научились разделять 3D-модели с помощью операции split, используя Plane в качестве режущего инструмента.
  • Опция keep=Keep.BOTH позволяет сохранить обе части после разделения, которые возвращаются в виде объекта Compound.
  • Мы научились извлекать отдельные тела из Compound и надежно идентифицировать их путем сортировки по координатам их центров.
  • Мы сделали наш дизайн параметрическим, вынеся высоту разреза в отдельную переменную base_height.

Что дальше?

Мы успешно разделили наш корпус на основание и крышку. Однако, если мы их сейчас напечатаем, крышка будет просто лежать на основании без какой-либо фиксации и может легко соскользнуть. Чтобы решить эту проблему, в следующем уроке мы спроектируем выступ-фальц (lip/groove). Этот элемент позволит крышке и основанию точно позиционироваться и плотно прилегать друг к другу.

Can't find a good explanation? Sign up and we'll make it for you

Sign up