# Надписи и рельеф — точная подгонка и отделка Дополнение к разделу «Надписи, логотипы и рельеф» 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` неподъёмен, но точки углов известны из построения: передай их списком, и все рёбра уйдут в ОДНУ операцию дерева. Если ребра в части точек нет (типичный случай — угол «съеден» каймой букв), ошибка перечислит ВСЕ такие точки сразу: убери их и повтори одним вызовом.