Files
kompas-plugin/plugin/skills/kompas-3d/reference/text-and-relief.md
T

118 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Надписи и рельеф — точная подгонка и отделка
Дополнение к разделу «Надписи, логотипы и рельеф» SKILL.md. Здесь — замеры и приёмы для точной
компоновки надписи (подгонка кегля и ширины, поведение каймы, стыковка блоков) и отделки рельефа.
Все числа получены пробами на конкретных начертаниях (Lobster, Bevan, Zilla Slab): это порядок
величины и форма зависимости, а не константы — свои значения перезамеряй на своём шрифте,
`widthFactor` и `thinThickness`.
## Подгонка ширины и кегля
- **`widthFactor` меняет пропорцию крупно, `height` — точно.** Замер (Lobster «OldMan», h=17):
wf 1.00 → 71.84 мм, wf 1.25 → 92.83 (+29 %) — то есть это настоящий масштаб ширины, и без него
скриптовый шрифт в вытянутое поле не вписать. Но КОМПАС **квантует его ступенями**: wf 1.25,
1.26, 1.27, 1.28 дают ячейку 100.64 и ширину 92.83…93.14 (+0.3 %), а на 1.29 ячейка прыгает на
103.34 и ширина сразу 95.49 (+2.5 %). Отсюда правило: пропорцию задаёшь `widthFactor`, точную
ширину добираешь `height` — подгонка через wf топчется на ступени.
- **`height` двигает ширину плавно, а высоту — ступенями.** Замер (Lobster «OldMan», wf 1.18):
h 17.00 → глифы 85.37 × **17.07**; h 16.94 → 85.11 × **17.07** (ширина отозвалась, высота нет);
h 16.50 → 82.90 × 16.54; h 15.50 → 77.95 × 15.60. Значит подгонять ширину кеглем можно, но
**вертикаль по нему не считается**: после пересчёта перечитай фактический габарит из ответа и
привязывай верх/низ блока ТОЧКОЙ ВСТАВКИ, а не кеглем.
- **Кегль под заданный габарит считается за ОДНУ пробу, а не подбирается.** При фиксированном
`widthFactor` прирост каймы Δ (сумма по обеим сторонам) от кегля не зависит — фигура подобна.
Значит: построил пробу с любым `height₀`, замерил ширину глифов `W₀` и суммарный прирост Δ,
дальше `height = height₀ · (W_цель Δ) / W₀` — и целевой габарит получается с первого раза.
**Δ бери только из СВОЕЙ пробы — на том же шрифте, `widthFactor` и `thinThickness`.** Числа из
этого файла (Lobster: Δ=4.62 при t=1.5/wf 1.29; Δ=4.93 при t=1.6/wf 1.18; Δ=2.92 при t=0.9/wf 1.33)
приведены как порядок величины, а не как константа: подставив чужое Δ, промахнёшься на проценты
по ширине — а именно её ты и подгоняешь.
- **Шаг второй, без которого формула обманывает: проверь ВЫСОТУ, которая из неё вышла.** Кегль
подобран по ширине, но вместе с ним задалась и высота блока букв — а от неё зависит, дотянется ли
кайма до плашки. Считай до построения: `низ каймы = низ глифов − t`, и он обязан зайти на плашку.
Замер (Lobster «OldMan», целевая ширина 90, кайма t=1.5): при `wf 1.29` формула даёт ровно
90.00 по X и глифы высотой 15.2 → низ каймы 11.77 против верха плашки 10.5, **разрыв 1.27 мм**,
деталь распалась бы на два тела; при `wf 1.18` — глифы 17.07 → низ каймы 9.93, **перекрытие
0.57 мм**, одно тело. Отсюда рабочее правило: **`widthFactor` — ручка не пропорции, а стыковки.**
При фиксированной целевой ширине больший `wf` даёт более низкий блок букв, и вертикаль
проигрывается: сначала подбери `wf` так, чтобы высота блока перекрыла плашку, и только потом
добирай точную ширину кеглем.
## Кайма (тонкая стенка вокруг букв)
- **Кайма на острых терминалах шире `thinThickness` — и по каждой стороне по-своему.** Стенка
`outward` обходит контур с миттером: на остром окончании глифа габарит растёт **на сторону** на
`t / sin(θ/2)`, а не на `t` (Lobster: слева +0.90 при t=0.9, справа +1.70 — терминал «n»).
Величина принадлежит не шрифту, а КОНКРЕТНОМУ начертанию и толщине стенки, поэтому у каждого
числа держи в уме пару (t, wf): Lobster «OldMan» при t=0.9 дал слева +0.90 / справа +1.70 при
wf 1.18 и +0.90 / +2.09 при wf 1.40; при t=1.5 — +1.50 / +3.12. Общее в них одно: **сбоку
прирост равен t, а на остром терминале — t/sin(θ/2)**, и переносить абсолютные числа между
вариантами нельзя — перезамеряй после смены `widthFactor` или `thinThickness`.
- **По вертикали кайма прибавляет ровно 2·t.** Сверху и снизу глифов миттера нет (касательные
ровные), поэтому высота блока = высота глифов + 2·t считается точно, без пробы; замером это
подтверждается на всех вариантах (t=0.9 → +1.80). Мерить нужно только ширину.
- **`align`/`vAlign` центруют ГЛИФЫ, а кайма несимметрична — значит центр надо считать.** Просьба
«поставить надпись по центру поля 90 мм» через `align="center", x=45` даёт силуэт, съехавший на
полразницы приростов: у Lobster при t=1.5 слева +1.50, справа +3.12. Целься не в центр поля, а в
тот X, при котором СИЛУЭТ ляжет в поле: `x = (Δ_лев + (L Δ_прав)) / 2`. Замер: (1.50 + 90
3.12)/2 = 44.19 → глифы 1.50…86.88, силуэт с каймой ровно 0…90.00. То же и по вертикали, только
там прирост симметричен (t сверху и снизу), поэтому `vAlign="top"` в `верх поля t` попадает без
поправки.
- **Толщина каймы — ещё и параметр стыковки блоков.** Кайма опускает силуэт надписи ниже её
глифов на `t`, и именно это перекрытие с плашкой держит деталь одним телом. Считай так: низ
каймы = низ глифов − t, и он должен зайти на плашку хотя бы на несколько десятых. Проверка —
сводка «Тел:» в ответе самого `primitive(union)`.
- **Кайма вокруг ПРЯМОУГОЛЬНОЙ плашки — вторым примитивом, а не тонкой стенкой.** Стенка обходит
контуры эскиза, а плашка по playbook'у строится `primitive`, и каймы у неё не появится. Клади под
неё второй блок на `2·t` больше и на высоту подложки (85 × 13.5 × 2 под плашкой 82 × 10.5 × 3) —
получается тот же кант. Сводить прямоугольник в один эскиз с буквами не надо: контуры пересекутся,
и эскиз станет невалидным.
## Разрядка (трекинг)
- **Разрядки (трекинга) у примитива нет — её набирают пробелами.** Ширину пробела для конкретного
шрифта и кегля вычисляют двумя пробами: «EDITION» → 38.38 мм, «E D I T I O N» → 47.11 мм,
значит пробел 1.455 мм (Bevan, cap 5.5).
## Отделка рельефа и соседняя геометрия
- **Пакетом по контуру рельефа не строится СКРУГЛЕНИЕ — ни сверху, ни на малом радиусе; фаска
строится по обоим контурам.** Скругление: на Zilla Slab «AB» (203 ребра) одиночное верхнее ребро
берёт R0.1 и R0.2, а `fillet_edge` сразу по всем отказывает при обоих радиусах — соседние
скругления конфликтуют; уменьшение радиуса не спасает (Lobster, 135 верхних рёбер: отказ и при
R0.3, и при R0.15). Фаска: `chamfer_edge(edgeIndices=[…])` проходит с первой попытки и по низу
(0.3 на 59 и на 120 рёбрах), и по ВЕРХУ рельефа (0.2 на 135 рёбрах букв, отдельно 0.2 на 133
рёбрах канта плашки с надписью) — прямые, NURBS, дуги и огрызки 0.03 мм вперемешку. Значит
притупление кромок по всему силуэту, хоть снизу против «слоновьей ноги», хоть сверху по
требованию чертежа, — это ОДНА операция, и делается она фаской. Рёбра берутся окном:
`list_edges(minZ=-0.01, maxZ=0.01)` — низ, `list_edges(minZ=h-0.01, maxZ=h+0.01)` — верх (сузить
до нужной части силуэта помогает `minY`/`maxY`). **Порядок «сначала скругления углов, потом фаска»
работает** — дуги от R0.5 фаске не мешают. В отборе встречается тип `other` (у сложных кривых) —
он тоже принимается параметром `type`.
- **Отказ фаски на НЕЧИЩЕНОМ контуре — не повод уменьшать катет: попробуй УВЕЛИЧИТЬ.** Успех
немонотонен по размеру. На контуре логотипа (54 ребра низа, острые клинья между элементами)
`chamfer_edge` отказывает при 0.4, 0.5, 0.6 и 0.7 и проходит при **0.8** — проверено подряд,
с `rebuild` между попытками и на неизменных индексах рёбер. Похоже, малый катет оставляет в остром
клине вырожденный «нос», который КОМПАС сшить не может, а большой срезает остриё целиком.
**Но это верно ТОЛЬКО пока контур не почищен**, и полагаться на такой подбор не нужно: правильное
лечение — `minSegment` (см. SKILL.md §«Надписи, логотипы и рельеф»), а не перебор катета.
Замер на том же логотипе: почищенный порогом 0.5 контур (34 примитива) фаску **0.5 принимает**,
а эталонные **0.8 отвергает** — рабочий диапазон катета сдвигается ВНИЗ вместе с узким местом
(1.98 → 1.82 мм). После чистки совет «попробуй увеличить» уже вреден.
Прежняя формулировка добавляла «исключение самых коротких рёбер картину не меняет, то есть дело
не в них» — вывод неверен: исключённое из `edgeIndices` ребро остаётся в теле, и это не то же
самое, что убрать сегмент из контура. Убранный из контура — меняет.
- **`primitive(subtract)` режет ВСЁ, что попало в его габарит — включая уже построенные буквы.**
Сверять надо **глифы, а не кайму**, и только те, что дотягиваются до кармана ПО ВЫСОТЕ: карман
обычно вычитается от z основания вверх (например от 2 до 3), а кайма ростом всего 2 мм в этот
слой не попадает — она может сколько угодно перекрывать плашку в плане, и именно это перекрытие
держит деталь одним телом. Опасны буквы: они идут на всю высоту 3 мм, поэтому их нижняя кромка
по Y должна быть выше верхней кромки кармана. Проверка постфактум — **точное равенство убыли
объёма** расчётному (79 × 7.5 × 1.0 = 592.5 против фактических 592.5 мм³): объём приходит в
сводке ответа самой операции, любое касание соседней геометрии сразу ломает равенство, а
габарит и снимок его не покажут.
- **Углы вокруг надписи — одним `fillet_edge(points=[…])`.** На теле с сотнями рёбер список из
`list_edges` неподъёмен, но точки углов известны из построения: передай их списком, и все рёбра
уйдут в ОДНУ операцию дерева. Если ребра в части точек нет (типичный случай — угол «съеден»
каймой букв), ошибка перечислит ВСЕ такие точки сразу: убери их и повтори одним вызовом.