Шестигранная крышка литофанового насоса - Cooler Master A...
Это шестигранная крышка помпы для Cooler Master AIO с прорезью для специальных литофановых вставок.
В крышке имеется чистый вырез, предназначенный для размещения литофановой пластины.
Включен скрипт Python для создания литофанов, которые точно подходят к этому отверстию.
Рабочий процесс прост: создайте изображение, распечатайте его и вставьте в обложку.
Литофановый генератор (Python)
Вы можете сгенерировать литофан, используя Тонни и предоставленный скрипт Python.
Необходимые библиотеки:
ПИЛ
бестолковый
numpy-stl
Скрипт:
# Весна 2026 г. — Гидролитовый генератор (гладкая шестигранная версия)
импортировать tkinter как tk
из tkinter import filedialog, messagebox, ttk
из импорта PIL Image, ImageOps, ImageDraw, ImageTk
импортировать numpy как np
из сетки импорта stl
импортировать ОС
#************************ Шестнадцатеричные параметры **********************************#
SIDE_LENGTH_MM = 28,28434
ШИРИНА_ММ = 2 * ДЛИНА_СТОРОНЫ_ММ
HEIGHT_MM = np.sqrt(3) * SIDE_LENGTH_MM
BORDER_WIDTH_MM = 2,0
#************************ ГЛАДКАЯ ШЕСТИГРАННАЯ МАСКА *********************************#
def hex_mask_mm (w_px, h_px, разрешение, сторона_длина_мм, масштаб = 1,0, масштабирование = 16):
up_w = w_px * повышение масштаба
up_h = h_px * повышение уровня
маска_img = Image.new(«L», (up_w, up_h), 0)
ничья = ImageDraw.Draw(mask_img)
сх, cy = up_w/2, up_h/2
s_px = (side_length_mm * масштаб) / разрешение * масштаб выше
Р = s_px
# Шестиугольник с плоской вершиной
баллы = [
(
сх + R * np.cos(i * np.pi/3),
cy + R * np.sin(i * np.pi/3)
)
для меня в диапазоне(6)
]
draw.polygon(точки, заливка=255)
# Сглаженное уменьшение масштаба
маска = маска_img.resize((w_px, h_px), resample=Image.LANCZOS)
return np.array(mask) / 255.0 # сглаживающая маска
#************************ Генерация литофана ***************************#
Защиту create_lithophane (image_path, выходной_путь, min_thick, max_thick, разрешение, border_height, инвертировать = False, Progress_callback = Нет):
px_per_mm = 1/разрешение
size_px = (int(WIDTH_MM * px_per_mm), int(HEIGHT_MM * px_per_mm))
img_raw = Image.open(image_path).convert(«L»)
img = ImageOps.fit(img_raw, size_px, метод=Image.LANCZOS, центрирование=(0,5, 0,5))
img = img.transpose(Image.Transpose.FLIP_TOP_BOTTOM)
оттенки серого = np.asarray(img)/255,0
если инвертировать:
оттенки серого = 1,0 — оттенки серого
height_map = min_thick + (1,0 — оттенки серого) * (max_thick — min_thick)
ч, ш = height_map.shape
external_mask = hex_mask_mm (ш, в, разрешение, SIDE_LENGTH_MM, масштаб = 1,0)
внутренний_масштаб = 1,0 — (BORDER_WIDTH_MM / SIDE_LENGTH_MM)
внутренняя_маска = шестнадцатеричная_маска_мм (ш, в, разрешение, SIDE_LENGTH_MM, масштаб = внутренний_масштаб)
маска = внешняя_маска
rim_mask = внешняя_маска * (1.0 — внутренняя_маска)
# weiche Kante → physsch glatter Übergang
карта_высот = минимальная_толщина + (карта_высот — минимальная_толщина) * маска
вершины = []
лица = []
vertex_index = {}
Защиту get_index (x, y, ztype):
ключ = (x, y, zтип)
если ключ отсутствует в vertex_index:
если ztype == 'сверху':
z = карта_высот[y, x]
elif ztype == 'обод':
z = высота_границы
еще:
г = 0,0
vertices.append([x * разрешение, y * разрешение, z])
vertex_index[ключ] = len(вершины) — 1
вернуть vertex_index[ключ]
порог = 0,5
для y в диапазоне (h — 1):
для x в диапазоне (w — 1):
если нет (маска[y, x] > порог и
маска[y, x+1] > порог и
маска[y+1, x] > порог и
маска[y+1, x+1] > порог):
продолжать
Защиту ztype(ix, iy):
вернуть «rim», если rim_mask[iy, ix] > порог, иначе «top»
i0 = get_index(x, y, ztype(x, y))
i1 = get_index(x + 1, y, ztype(x + 1, y))
i2 = get_index(x, y + 1, ztype(x, y + 1))
i3 = get_index(x + 1, y + 1, ztype(x + 1, y + 1))
b0 = get_index(x, y, 'низ')
b1 = get_index(x + 1, y, 'низ')
b2 = get_index(x


























