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.

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

В прошлом уроке мы научились делать точечные, одиночные вырезы для портов. Вы освоили ключевую технику: выбор грани, создание на ней 2D-эскиза и его вычитание из основного тела. Это основа для создания большинства функциональных отверстий.

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

Мы рассмотрим два подхода: интуитивный, но не всегда эффективный, и более производительный, который рекомендован для сложных моделей.

Классическая вентиляционная решётка с узором из продолговатых отверстий. Это один из вариантов дизайна, который мы сможем реализовать после этого урока.

1. "Прямолинейный" подход: Вычитание в цикле

Самый очевидный способ создать массив отверстий, учитывая ваш опыт в программировании, — это организовать цикл.

  1. Создать базовую стенку.
  2. В цикле сгенерировать множество 3D-тел (например, цилиндров или параллелепипедов), расположенных по сетке.
  3. Вычесть каждое из этих тел из базовой стенки.

Давайте посмотрим, как это выглядит в коде. Создадим простую перфорированную пластину с квадратными отверстиями.

# enclosure_v14.py
from build123d import *

# ================== ПАРАМЕТРЫ ==================
plate_len = 80
plate_wid = 60
plate_thk = 3

hole_size = 4
hole_spacing = 8

# ================== МОДЕЛИРОВАНИЕ ==================

# 1. Создаем базовую пластину
with BuildPart() as plate:
    Box(plate_len, plate_wid, plate_thk)

    # 2. Создаем сетку расположений для отверстий
    # GridLocations генерирует сетку точек
    grid = GridLocations(dx=hole_spacing, dy=hole_spacing, x_count=int(plate_len/hole_spacing)-1, y_count=int(plate_wid/hole_spacing)-1)
    
    # 3. В цикле создаем и вычитаем "пуансоны"
    with Locations(grid):
        Box(hole_size, hole_size, plate_thk, mode=Mode.SUBTRACT)

if "show_object" in locals():
    show_object(plate.part)

Как это работает:

  • GridLocations — это удобный инструмент для создания прямоугольной сетки точек (Location). Мы задаём шаг (dx, dy) и количество точек по каждой оси.
  • Контекст with Locations(grid): применяет последующие операции ко всем точкам сетки.
  • Box(..., mode=Mode.SUBTRACT) создаёт в каждой точке сетки параллелепипед и немедленно вычитает его из текущего Context.part.

Этот метод прост и понятен, но у него есть существенный недостаток. Каждая булева операция (в данном случае Mode.SUBTRACT) — это вычислительно сложная задача для CAD-ядра. Когда отверстий сотни или тысячи, время генерации модели может значительно возрасти. Учитывая ваш опыт в HPC, вы понимаете, что последовательное выполнение большого числа таких операций неэффективно.

2. Эффективный подход: паттерн на уровне 2D-эскиза

Гораздо более производительный метод — это создать один сложный 2D-эскиз, который уже содержит и внешний контур, и все внутренние отверстия, а затем выдавить его за одну операцию.

Логика: Вместо (Деталь - Отверстие) - Отверстие - ..., мы делаем (Эскиз с отверстиями) -> Выдавливание -> Деталь.

Этот подход реализован в одном из официальных примеров build123d, который демонстрирует создание 625 шестиугольных отверстий. Давайте его изучим.

examples_1.rst.txt

Этот пример, озаглавленный 'Fast Grid Holes', идеально иллюстрирует эффективный метод. Он показывает, как создать сложную перфорированную панель почти мгновенно.

Найдите на странице раздел 'Fast Grid Holes'. Изучите код в выпадающем списке 'Algebra Mode'. Обратите внимание, как создается список контуров отверстий (hole_wires) и как он передается в конструктор Face вместе с внешним контуром (perimeter).

Ключевая идея примера заключается в строке:
panel_face = Face(perimeter, holes=hole_wires)

Конструктор Face принимает на вход:

  1. perimeter: один замкнутый контур (Wire), определяющий внешнюю границу.
  2. holes: список замкнутых контуров (Wire), определяющих отверстия внутри этой границы.

Затем вся эта сложная грань выдавливается одной командой: extrude(panel_face, amount=part_thickness).

2.1. Применяем на практике: шестигранная решётка

Давайте интегрируем этот подход в наш пример с корпусом. Мы создадим вентиляционную решётку на одной из стенок. Для этого нам нужно:

  1. Выбрать грань на корпусе.
  2. Создать на этой грани 2D-эскиз, содержащий множество отверстий.
  3. Выполнить вычитающее выдавливание этого эскиза.
# enclosure_v15.py
from build123d import *

# ================== ПАРАМЕТРЫ ==================
enclosure_length = 100
enclosure_width = 80
enclosure_height = 40
wall_thickness = 2

# Параметры решетки
grill_width = 40
grill_height = 30
hex_radius = 2.5  # Радиус описанной окружности шестигранника
hex_spacing_factor = 1.1 # Множитель для расстояния между центрами

# ================== МОДЕЛИРОВАНИЕ ==================

# Функция для создания эскиза решетки
def create_hex_grill_sketch(width, height, radius, spacing_factor):
    """Создает эскиз с гексагональной решеткой отверстий."""
    
    # HexLocations создает сотовую структуру расположений
    locations = HexLocations(
        radius, 
        x_count=int(width / (radius * 1.732 * spacing_factor)), 
        y_count=int(height / (radius * 1.5 * spacing_factor))
    )
    
    with BuildSketch() as grill_sketch:
        # Создаем отверстия в каждой точке
        with Locations(locations):
            Polygon(6, radius=radius) # 6 - кол-во сторон
        
        # Добавляем внешний контур, который будет вырезан из стенки
        # Он должен быть больше, чем область с отверстиями
        Rectangle(width, height)

    # Возвращаем только внутренние отверстия для вычитания
    return grill_sketch.inner_wires()


# --- Основная модель корпуса ---
with BuildPart() as enclosure:
    Box(enclosure_length, enclosure_width, enclosure_height)
    offset(amount=-wall_thickness, openings=enclosure.faces().sort_by(Axis.Z)[-1])

    # Выбираем "заднюю" стенку
    target_face = enclosure.faces().sort_by(Axis.Y)[0]

    # --- Создание решетки ---
    with BuildSketch(target_face) as grill_on_face:
        # Позиционируем решетку по центру грани
        # и добавляем в эскиз только отверстия
        add(create_hex_grill_sketch(grill_width, grill_height, hex_radius, hex_spacing_factor))

    # Вычитаем эскиз из стенки
    extrude(amount=-wall_thickness, mode=Mode.SUBTRACT)


if "show_object" in locals():
    show_object(enclosure.part)

Разбор кода:

  • create_hex_grill_sketch(...): Мы инкапсулировали логику создания решётки в отдельную функцию, что соответствует хорошим практикам программирования.
  • HexLocations: Аналогично GridLocations, этот класс создаёт паттерн расположений, но в виде пчелиных сот.
  • return grill_sketch.inner_wires(): Вместо возврата сложной грани (Face), мы возвращаем только список контуров (Wire) отверстий. Это более гибко.
  • with BuildSketch(target_face) as ...: add(...): Мы создаём эскиз на нужной грани корпуса и добавляем в него ранее сгенерированные контуры отверстий.
  • extrude(...): Вся группа отверстий вычитается за одну операцию. Это быстро и эффективно.

3. Другие виды паттернов

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

  • Решётка из прорезей (слотов): Используйте PolarLocations для расположения объектов по кругу и Rectangle или SlotOverall для создания самих прорезей.
*Более сложный "плетёный" узор можно получить, комбинируя несколько линейных паттернов с разными ориентациями.*
  • Линейные паттерны: LinearPattern позволяет создавать массивы вдоль одной или двух осей, что является альтернативой GridLocations.

Главное — помнить, что создание паттерна на 2D-уровне перед одной операцией выдавливания почти всегда будет производительнее, чем множество 3D-операций.

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

Представьте, что вам нужно создать простую решётку из круглых отверстий. Модифицируйте функцию create_hex_grill_sketch так, чтобы она создавала прямоугольную сетку круглых отверстий. Назовите новую функцию create_circular_grill_sketch.

Какие классы build123d вы будете использовать вместо HexLocations и Polygon?

Показать ответ

Вам понадобятся GridLocations для создания прямоугольной сетки и Circle для самих отверстий.

Пример реализации функции:

def create_circular_grill_sketch(width, height, hole_radius, spacing):
    """Создает эскиз с прямоугольной сеткой круглых отверстий."""
    
    locations = GridLocations(
        dx=spacing, 
        dy=spacing, 
        x_count=int(width / spacing), 
        y_count=int(height / spacing)
    )
    
    with BuildSketch() as grill_sketch:
        with Locations(locations):
            Circle(radius=hole_radius)
        # Внешний контур не обязателен, если мы возвращаем только отверстия
        # Rectangle(width, height)
    
    return grill_sketch.wires() # .wires() вернет все контуры (в данном случае - только окружности)

# ... затем в основном коде
# add(create_circular_grill_sketch(...))

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

  • Для создания массивов отверстий (решёток) существует два основных подхода: "прямолинейный" (цикл с 3D-вычитанием) и эффективный (создание сложного 2D-эскиза с последующим выдавливанием).
  • Эффективный метод, основанный на создании Face с отверстиями или добавлении множества Wire в BuildSketch, значительно производительнее.
  • build123d предоставляет мощные инструменты для создания паттернов расположений, такие как GridLocations, HexLocations и PolarLocations.
  • Инкапсуляция логики создания паттерна в отдельную функцию делает код чище, параметрическим и легко переиспользуемым.

Что дальше?

Мы добавили в наш корпус вырезы для портов и вентиляции. Однако все наши рёбра и углы пока острые. В реальных изделиях они часто скругляются или срезаются. В следующем уроке мы изучим, как применять скругления (fillets) и фаски (chamfers), чтобы улучшить и эстетику, и функциональность наших деталей. Это завершающий урок в модуле, посвященном базовым элементам корпуса.

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

Sign up