kompas 0.3.0 (из fcedb44f5661313ffd0570e3808a5309f6ae8cb7)
This commit is contained in:
@@ -0,0 +1,63 @@
|
||||
# Сборка: собрать своё
|
||||
|
||||
Дополнение к SKILL.md — методика для сборки С НУЛЯ. Разбор ЧУЖОЙ сборки (пришедшей STEP/импортом) —
|
||||
`reference/import-playbook.md`.
|
||||
|
||||
Плейбук: **создать → вставить → ЗАФИКСИРОВАТЬ базовую → сопрячь → rebuild → проверить.**
|
||||
|
||||
1. **Детали сначала сохрани в файлы.** Компонент вставляется ссылкой на `.m3d`/`.a3d`, поэтому
|
||||
несохранённую деталь вставить нельзя.
|
||||
2. **`document_create assembly` → `assembly_add_component(filePath, x, y, z, rx, ry, rz)`.** Углы — в
|
||||
градусах, вокруг СОБСТВЕННЫХ осей компонента и по очереди X→Y→Z: второй угол считается уже от
|
||||
повёрнутого положения. Пока задан один угол, разницы с мировыми осями нет.
|
||||
3. **Зафиксируй базовую деталь СРАЗУ: `assembly_fix_component(componentIndex=0, fixedState=true)`.** КОМПАС не закрепляет
|
||||
никого сам, включая первый компонент, и решатель двигает того, кого сочтёт нужным — в том числе
|
||||
основание, вокруг которого ты собираешь всё остальное. Это самая частая причина «сопряжение
|
||||
верное, а сборка расползлась».
|
||||
4. **Сопрягай:** `assembly_add_mate(mateType, …)` — семь типов, адресация гранью и смысл
|
||||
`orientation` в `help(topic="assembly-mates")`. Что решаешь ты, а не справочник:
|
||||
- **Грань адресуй индексом, а не координатами:** `list_faces(component=N)` → пара
|
||||
`faceIndex`+`componentIndex`. Точки на бумаге считать не нужно, и сервер сам проверит, что
|
||||
грань принадлежит этому компоненту.
|
||||
- **Сторону зазора у `distance` задаёт ВЫБОР ПАРЫ ГРАНЕЙ, и от стартового положения она не
|
||||
зависит.** «Closest» — не «ближайшее»: при сонаправленных нормалях объект 1 садится со стороны
|
||||
−n относительно объекта 2 (замерено двойным прогоном). Практическое правило: бери пару граней,
|
||||
которые смотрят ДРУГ НА ДРУГА. Вышло зеркально — меняй грань, а не `orientation`.
|
||||
- **Первое сопряжение вешай на зафиксированную деталь.** Пока в цепочке нет ни одного
|
||||
закреплённого звена, решатель волен двигать любое; связка «каждый новый компонент — к уже
|
||||
стоящему на месте» разваливается вдвое реже, чем связка «все ко всем».
|
||||
5. **`rebuild`,** если авто-валидация написала «ℹ Требуется перестроение». Это НЕ ошибка построения:
|
||||
так помечает себя свежий компонент или только что наложенная связь. Бросать работу здесь не надо
|
||||
— правило «не продолжай при ⚠» касается строки со знаком ⚠, а не этой.
|
||||
**Исключение из правила «⚠ = стоп».** После КАЖДОГО сопряжения авто-валидация пишет
|
||||
«⚠ N операц. в ошибке: „Сопряжения“ (код 0: ошибки нет)». Это то же «требуется перестроение»,
|
||||
только под знаком ⚠: код 0 и имя операции «Сопряжения» означают, что ломаться нечему. Делай
|
||||
`rebuild` и иди дальше. Настоящая беда со связью видна не здесь, а в
|
||||
`describe_model(sections=mates)` — по пометке `valid:false`.
|
||||
6. **Проверь:**
|
||||
- `describe_model(sections=components)` — origin, поворот ЧИСЛАМИ (`rx/ry/rz` в градусах, та же
|
||||
семантика, что у вставки) и «зафиксирован/свободен» у каждого: этим и видно, КОГО и НА СКОЛЬКО
|
||||
подвинул решатель;
|
||||
- `describe_model(sections=mates)` — что с чем связано, с каким значением и не выродилось ли.
|
||||
Это ключевой детектор: `assembly_add_mate` может ответить успехом, а связь окажется
|
||||
вырожденной;
|
||||
- `measure(kind1=face, index1=…, componentIndex1=…, kind2=face, index2=…, componentIndex2=…)` —
|
||||
зазор между деталями напрямую, без арифметики по габаритам;
|
||||
- `assembly_check_interference(componentIndex1, componentIndex2)` — **не налезли ли детали друг
|
||||
на друга.** Проверяй все пары, которые должны идти впритирку.
|
||||
|
||||
**Неудачную связь не нужно пересобирать с нуля:** `assembly_delete(target="mate"|"component", index)`
|
||||
снимает сопряжение или компонент вместе с опирающимися на него связями. Индексы после удаления
|
||||
сдвигаются — иди от больших к меньшим и перечитывай `describe_model(sections=mates)`.
|
||||
|
||||
**Пересечение деталей не видно НИГДЕ, кроме `assembly_check_interference`.** Сборка складывается из
|
||||
готовых тел, и КОМПАС их не вычитает: две детали могут занимать общий объём, а сопряжения при этом
|
||||
останутся `valid`, раздел `errors` — пустым, объём экспорта — простой суммой компонентов. `measure`
|
||||
тоже не спасает: нулевой зазор одинаково означает и касание, и взаимопроникновение. Проверяй все
|
||||
пары, которые должны идти впритирку.
|
||||
|
||||
**«Тела: 0» в сборке означает не «пусто», а «спрошено не то»:** тела принадлежат компонентам
|
||||
(`describe_model(component=N, …)`), а `box` и `mass` без `component` честно дают габарит и МЦХ сборки
|
||||
целиком. Про разные системы координат внутри паспорта компонента —
|
||||
`help(topic="model-inspection")`; про локальные координаты граней и `pointOnFace` —
|
||||
`help(topic="face-addressing")`.
|
||||
@@ -0,0 +1,81 @@
|
||||
# Чертёж: оформить деталь по ГОСТ
|
||||
|
||||
Дополнение к SKILL.md — методика оформления 2D-чертежа. Чертёж строится не так, как деталь:
|
||||
**авто-валидации здесь нет**. Правило трёх проверок из SKILL.md §«Два правила прежде всего» в 2D не
|
||||
работает — операция не отчитывается «построилось верно», потому что верность тут не про геометрию,
|
||||
а про место на листе. Проверять приходится самому, и способ ровно один: посмотреть.
|
||||
|
||||
**Порядок, который окупается:**
|
||||
|
||||
1. **Деталь строится в чертёжной ориентации.** Набор видов задаётся ОТ модели: `mainOrientation`
|
||||
выбирает, какую ориентацию модели показывает главный вид, но саму ориентацию модели он не
|
||||
вращает. Если самая информативная проекция детали — не одна из шести стандартных, чертежа по
|
||||
ГОСТ не выйдет; планируешь чертёж — строй эскизы так, чтобы главный вид попадал на плоскость
|
||||
с наибольшей информацией.
|
||||
2. **`drawing_set_sheet_format`** (формат до видов — иначе виды придётся двигать), при
|
||||
необходимости `drawing_add_sheet` для второго листа.
|
||||
3. **`drawing_create_standard_views(views=[…], mainOrientation=…, hiddenLines=…)`** — бери ровно те
|
||||
проекции, которые нужны: лишний вид — лишнее место и лишний повод ошибиться видом. **Главный вид
|
||||
входит в набор сам**: перечисленные коды — это проекции ОТНОСИТЕЛЬНО него, поэтому `views=["top"]`
|
||||
даёт ДВА вида (главный и сверху). Ответ возвращает НОМЕРА видов, и дальше всё адресуется ими.
|
||||
4. **Координаты — замером, а не формулой.** `drawing_get_view_info(viewNumber)` отдаёт паспорт вида
|
||||
одним вызовом: положение на листе, масштаб, габарит и — главное — локальную СК: куда попадает
|
||||
начало координат модели и куда смотрят её оси +X/+Y/+Z в координатах вида (нулевой орт = ось
|
||||
проекции, вдоль неё вид смотрит). Этого хватает, чтобы пересчитывать точки модели в вид
|
||||
арифметикой; отдельные точки переводит `drawing_project_point(x, y, z, viewNumber)`.
|
||||
Выводить оси из головы не надо и вредно: у КОМПАС «спереди» показывает плоскость XY детали, а
|
||||
«сверху» — X и **минус Z**, и **знаки инверсии зависят от `mainOrientation`** — формула,
|
||||
выведенная на одном чертеже, на соседнем врёт.
|
||||
5. **Разрез — до размеров, а не после.** Внутреннюю геометрию (зенковка, ступенчатое отверстие,
|
||||
паз, глубокая расточка, полость) показывай разрезом, а не невидимыми линиями: по штриховой линии
|
||||
нельзя ни поставить нормальный размер, ни разобрать форму. `drawing_add_section_view` — см.
|
||||
§«Разрез» ниже. Размеры внутренней геометрии ставятся УЖЕ НА РАЗРЕЗЕ, поэтому строить его надо
|
||||
раньше простановки, иначе размеры придётся переносить.
|
||||
6. **Размеры**, `drawing_add_axis` (осевые и центровые), шероховатость, выноски, техтребования,
|
||||
штамп. **Осевые сначала посмотри, потом добивай**: ассоциативные виды приходят со СВОИМИ
|
||||
центровыми и осевыми, которые КОМПАС ставит сам, и `drawing_add_axis` вслепую даёт дубли поверх
|
||||
существующих. Сначала `list_drawing_objects(kind="axis"|"centreMarker", viewNumber=…)`.
|
||||
7. **`drawing_export_image`** — посмотреть глазами. Пока картинки не было, чертёж не сдан.
|
||||
|
||||
## Разрез
|
||||
|
||||
`drawing_add_section_view` делает всё сразу: проводит линию разреза на базовом виде и строит по ней
|
||||
производный вид со штриховкой. Механика, ступенчатый разрез и встроенная проверка честности —
|
||||
`help(topic="drawing-sections")`; здесь только решения, которые принимаешь ты:
|
||||
|
||||
- **Разрез или `hiddenLines`.** Разрез — когда внутреннее нужно ИЗМЕРИТЬ или показать форму:
|
||||
зенковка и цековка, ступенчатое или резьбовое отверстие, паз, канавка, глубокая расточка, тонкая
|
||||
стенка полой детали. Невидимые линии — только намёк на то, что уже показано где-то ещё; размер к
|
||||
штриховой линии не привязывают.
|
||||
- **Веди линию с запасом за габарит** (плита 60 мм → от −40 до +40): линия по самому краю режет не
|
||||
всю деталь. Координаты — в ЛСК БАЗОВОГО вида, её даёт `drawing_get_view_info`.
|
||||
- **Строй разрез, когда модель готова**: после правки детали перестраивается только ПЕРВЫЙ разрез
|
||||
базового вида. Модель всё же изменилась — снеси разрезы и построй заново.
|
||||
- Сам разрез дальше — обычный вид: размеры и обозначения ставятся на него по его номеру.
|
||||
|
||||
**Промах простановки лечится, а не остаётся навсегда.** Отката (undo) у чертежа нет, но
|
||||
`list_drawing_objects` показывает обозначения с индексами, `drawing_delete_object` убирает одно, а
|
||||
`drawing_move_object` его СДВИГАЕТ — слипшиеся тексты соседних размеров лечат именно сдвигом, а не
|
||||
заменой размера на выноску. Так же правится и компоновка: `drawing_move_view` переставляет вид со
|
||||
всеми обозначениями, `drawing_add_view` доносит недостающую проекцию, `drawing_delete_view` убирает
|
||||
лишнюю. Пересоздавать документ ради компоновки не нужно. Подробности адресации и порядок удаления —
|
||||
`help(topic="drawing-fixing")`.
|
||||
|
||||
**Три вещи, на которых чертёж молча выходит неверным** — держи их в голове, детали в справочнике:
|
||||
|
||||
- `viewNumber=0` — это НЕ главный вид, а координаты ЛИСТА; знак, поставленный «на главном виде» с
|
||||
нулём, уезжает за границы формата (`help(topic="drawing-views")`);
|
||||
- ассоциативны только диаметральный и радиальный размеры; линейный и угловой меряют координаты, и
|
||||
«60» останется, когда деталь станет 70 — после правки модели перепроверяй их сам
|
||||
(`help(topic="drawing-dimensions")`);
|
||||
- допуск, не легший в размер, виден только по пустому read-back в ответе — техтребования его не
|
||||
заменят (`help(topic="drawing-dimension-text")`).
|
||||
|
||||
Ещё две ловушки, о которых узнаёшь только столкнувшись: штамп частично ведёт МОДЕЛЬ, а не чертёж
|
||||
(`help(topic="drawing-title-block")`), и у цилиндрической грани нет «координат оси» — её
|
||||
восстанавливают и проверяют сходимостью площадей (`help(topic="cylinder-axis")`).
|
||||
|
||||
**Чего нет.** Выносного элемента (увеличенный фрагмент), МЕСТНОГО разреза внутри вида, местного
|
||||
вида и вида с разрывом. Ассоциативного ЛИНЕЙНОГО размера нет и не будет: в API у него нет привязки к геометрии
|
||||
ни под каким именем (проверено QI, поздним связыванием и размером с обрывом). Экспорта в PDF/DXF
|
||||
тоже нет — наружу уходит растр (`drawing_export_image`) и STEP.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Исполнения: одна модель — несколько геометрий
|
||||
|
||||
Дополнение к SKILL.md. Типоразмеры (профиль на 100, 200, 500 мм), правое и левое зеркало, версии с
|
||||
отверстием и без часто живут **в одном файле** исполнениями. Тогда всё, что ты меришь и
|
||||
экспортируешь, относится к **текущему** исполнению — не к «детали вообще».
|
||||
|
||||
- **Признак замечаешь не ты, а ответ.** У модели с несколькими исполнениями `describe_model` сам
|
||||
пишет, сколько их и какое сейчас текущее. Увидел эту строку — прежде чем считать массу или резать
|
||||
чертёж, посмотри `describe_model(sections=embodiments)`: там габарит и масса **каждого**, и это
|
||||
чтение ничего не переключает.
|
||||
- **Переключение равно смене документа.** `embodiment(action="set", target="L200")` обнуляет
|
||||
сессию построения: хендлы `sk_…`/`op_…` после него мертвы. Сохраняй документ до переключения.
|
||||
- **Индекс живёт до первой правки дерева**: после `delete` индексы смещаются. Адресуй обозначением
|
||||
(«L500»), а индексом — только сразу после того, как увидел список. У **варианта** обозначение
|
||||
родительское, и адресовать его номером нельзя вовсе — под «-01» подходят двое; зови его по имени
|
||||
(«M5-01») или индексом.
|
||||
- **Исполнения делай ПОСЛЕДНИМ шагом.** Переключение убивает хендлы, и дальнейшая правка дерева
|
||||
идёт уже через `feature_delete(featureIndex=…)` по `describe_model(sections=tree)` — путь рабочий,
|
||||
но менее удобный. Сначала доведи базовую геометрию и параметризацию, потом размножай.
|
||||
- **Строишь новое исполнение** — `embodiment(action="add", number="02")`; оно сразу становится
|
||||
текущим, строй в нём немедленно. `depended=false` нужен, когда правки НЕ должны наследоваться от
|
||||
родителя, — иначе изменение уедет и в него.
|
||||
- **В сборку исполнение выбирается явно**: `assembly_add_component(embodiment="L500")`. Без
|
||||
параметра встанет **базовое** исполнение, а не то, что сохранено в файле текущим. Обозначение
|
||||
нужно ПОЛНОЕ («ПРОБА.001-01», а не «-01»); сервер откажет, если КОМПАС подсунет базовое.
|
||||
- **«Удлинить эти профили с 500 до 600» — это смена исполнения экземпляра, а не новая вставка**:
|
||||
`embodiment(action="set", target="L600", component=N)` и затем `rebuild`. Сопряжения при этом
|
||||
**сохраняются** — пересоздание вставки, наоборот, порвало бы их все. Какие исполнения есть у
|
||||
конкретного экземпляра, показывает `describe_model(sections="embodiments", component=N)`.
|
||||
- **Выгнать всю линейку на печать** — `export_model(embodiment="all")`: каждое исполнение в свой
|
||||
файл с суффиксом обозначения.
|
||||
- **После смены исполнения в собранном узле проверь сопряжения** (`sections="mates"`): если у нового
|
||||
исполнения нет объекта, на который опиралась связь, она рвётся — «ССЫЛКА ПОТЕРЯНА», `valid: false`,
|
||||
компонент недоопределён. Что было потеряно, хранит имя сопряжения; `assembly_delete` сотрёт и его.
|
||||
|
||||
Подробности и границы — `help(topic="embodiments")`.
|
||||
@@ -0,0 +1,25 @@
|
||||
# Фрагмент — переиспользуемый чертёж, а не сечение
|
||||
|
||||
Дополнение к SKILL.md. Эскиз живёт внутри дерева построения и вне его не существует; фрагмент (*.frw)
|
||||
— самостоятельный файл, который переживает деталь. `fragment_create` его пишет, `fragment_place`
|
||||
кладёт в активный чертёж или другой фрагмент, а `mode` решает, чем он там станет — и это разные
|
||||
объекты, а не оттенки одного:
|
||||
|
||||
- **`reference`** — вставка-ссылка: содержимым владеет файл, правка файла меняет все документы, куда
|
||||
он вставлен. Ради этого фрагменты и заводят: одна заготовка на десять чертежей.
|
||||
- **`copy`** — копия внутри документа, живёт своей жизнью; файл потом можно удалить.
|
||||
- **`local`** — вставка, переиспользуемая только внутри этого документа.
|
||||
- **`explode`** — россыпь обычных примитивов: правится по одному, но связи с файлом уже нет.
|
||||
|
||||
`angle` (градусы), `scale` и `mirror` задают размещение; зеркалить можно только вставку — у россыпи
|
||||
отражать нечего. **Зеркало отражает относительно вертикали через точку вставки**, поэтому контур
|
||||
уходит в другую сторону от неё: вставка в x=220 после `mirror` занимает 160…220, а не 220…280.
|
||||
|
||||
Проверять результат — `list_drawing_objects`: он показывает состав по типам, габарит и все вставки
|
||||
с их файлами. Вставка, чей файл потерялся, рисуется пустым местом — в списке она помечена
|
||||
недействительной, и это единственный способ отличить её от удавшейся, не глядя на экран.
|
||||
|
||||
Контур, который переживёт конкретную деталь (логотип, шаблон, профиль), клади во фрагмент —
|
||||
`fragment_create(path, entities)` тем же списком примитивов. Активный документ он не подменяет,
|
||||
поэтому фрагмент можно снять посреди построения детали; габарит в ответе снят с самого документа —
|
||||
сверяй его с задуманным.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Работа с импортом / сборками
|
||||
|
||||
Дополнение к SKILL.md — конвейер разбора ЧУЖОЙ модели/сборки: «импорт → разбор → извлечение детали →
|
||||
осмотр → модификация → экспорт». Сборка С НУЛЯ — `reference/assembly-playbook.md`.
|
||||
|
||||
1. **`import_model`** — `type` задаёт документ: `assembly` (по умолчанию) или `part`.
|
||||
Формат берётся из расширения; `.prt` и `.asm` носят несколько САПР сразу — там задавай `format`
|
||||
явно. Нужна отдельная деталь файлом — включай `createComponentFiles` (по умолчанию `false`).
|
||||
**Выключенный переключатель чистого диска НЕ гарантирует:** конвертер пишет файлы рядом с
|
||||
ИСХОДНИКОМ и помимо него — замерено, четыре импорта положили четыре незапрошенных `.m3d`.
|
||||
Что реально изменилось в каталоге исходника, ответ перечисляет поимённо; не хочешь засорять
|
||||
чужой каталог — копируй файл во временный (`help(topic="model-exchange")`).
|
||||
**STL/OBJ приходят СЕТКОЙ:** «тел 0, объём 0.0 мм³» после такого импорта — норма, а не провал,
|
||||
проверяй габаритом; ответ говорит это вслух и называет число треугольников из самого файла.
|
||||
Плоский чертёж (.dxf/.dwg) читает не он, а `import_drawing`.
|
||||
2. **Разбор:** `describe_model(sections=components)` (у каждого компонента — origin, поворот,
|
||||
фиксация) и `describe_model(sections=mates)`, если сборка пришла со связями; грани компонента —
|
||||
`list_faces(component=N)`. Извлечённую деталь открывай самостоятельным документом.
|
||||
Гашение видимости компонента на снимок **не влияет** — изоляция так не делается.
|
||||
3. **Осмотр — структурно** (`describe_model`: какая ось «высота», МЦХ, топология). Снимок
|
||||
`model_snapshot(view=…)` — ракурс выбирай по плоскости детали (плоскую смотри сверху или
|
||||
спереди, не в изометрии); один и тот же `view` даёт воспроизводимый кадр «до/после».
|
||||
**Пары ракурсов противоположны по оси:** `front` смотрит из +Z, `rear` — из −Z, так же
|
||||
`top`/`bottom` и `left`/`right`. Следствие, которое нужно чаще всего: деталь, лежащая на столе
|
||||
гранью Z=0 (эскиз на XOY, выдавливание вперёд), видна столу как **`rear`**, а `front` покажет
|
||||
зеркальную картинку. Читаемость надписи или логотипа доказывают снимком с нужной стороны, а не
|
||||
рассуждением.
|
||||
**Но «ортогонально» — правило про ПЛОСКУЮ деталь.** Как только форма выходит из одной плоскости
|
||||
(кронштейн, косынка, изогнутый профиль), ортогональный кадр перестаёт читаться: он плоский,
|
||||
подписей осей на нём нет, и сопоставить увиденное с координатами не выходит — `right` даёт
|
||||
картинку, по которой не сказать, где перёд. Профиль такой детали смотри `view="iso"`: там видно,
|
||||
что куда загнуто.
|
||||
4. **Модификация «тупой» B-rep** (итог — в ответе каждой операции). Инструмент выбирается по тому,
|
||||
ЧТО задано в требовании, а не по тому, что привычнее:
|
||||
|
||||
| Требование звучит как | Инструмент | Почему не `move_face` |
|
||||
|---|---|---|
|
||||
| «сдвинуть грань на N мм» | `move_face` | это он и есть |
|
||||
| «диаметр отверстия (бобышки) должен стать D» | **`resize_face`** | задаётся ДИАМЕТР, ось не двигается; `move_face` сдвинул бы стенку на (D−d)/2, и это пришлось бы считать самому |
|
||||
| «грань должна встать НА объект: на плоскость, на грань соседнего тела» | **`replace_face`** | расстояние считает КОМПАС; `move_face` требует вычислить его заранее |
|
||||
| вставка N мм в призматическую ножку | `split_solid_by_plane` → `move_body` → `move_face` (мост) → `boolean_union` | цепочка проверена end-to-end: проставка 39.45 → 41.45 мм |
|
||||
|
||||
`resize_face` и `replace_face` требуют КОМПАС v25; на версиях старше они отвечают отказом с
|
||||
номером установленной версии, и тогда остаётся `move_face` с арифметикой.
|
||||
|
||||
**Проверяйте прямое редактирование РАЗНОСТЬЮ ОБЪЁМОВ против аналитической формулы** — объём и так
|
||||
печатается в сводке каждой операции, лишних вызовов не нужно. Расточка отверстия обязана снять
|
||||
ровно `π(R²−r²)·h`, наращивание грани — добавить ровно `площадь_грани × Δh`. Считайте формулу по
|
||||
СВОИМ числам и сверяйте с тем, что напечатала операция: одно число ловит и «операция ушла не
|
||||
туда», и «отверстие перестало быть сквозным».
|
||||
|
||||
**Оси отверстий сверяют полем `axis`.** У грани типа `cylinder`, `cone`, `torus` `list_faces`
|
||||
отдаёт `axis` — точку на оси и направление, в мировых координатах; у цилиндра и сферы там же
|
||||
`radius`. Требование «оси сдвигать нельзя» доказывается сравнением `axis` до и после, а не
|
||||
арифметикой по расстояниям. Осторожно с двумя соседними полями: `normal` у цилиндра — про
|
||||
сторону поверхности, а не про ось, а `pointOnFace` лежит на стенке (help(topic="cylinder-axis")).
|
||||
5. **Перед выдачей:** последняя операция «Построение чистое» → `export_model` (STEP для обмена,
|
||||
STL для печати).
|
||||
@@ -0,0 +1,38 @@
|
||||
# Параметризация: сначала переменные, потом геометрия
|
||||
|
||||
Дополнение к SKILL.md §«Параметризация». Читай это перед первым эскизом нового документа — план
|
||||
переменными стоит один вызов на размер, пока деталь пуста, и пересборку после десятка операций.
|
||||
|
||||
**В новом документе первым делом опиши будущую модель переменными — до первого эскиза.** Набор
|
||||
переменных — это план построения числами и паспорт, по которому человек поймёт модель, не разбирая
|
||||
дерево.
|
||||
|
||||
- **Заводи переменной то, что было РЕШЕНИЕМ**: габариты из ТЗ, толщины, зазоры, отступы, кегли,
|
||||
радиусы. Выводимое задавай формулой (`plate_L = badge_L - 2*edge_gap`) — правка ведущего размера
|
||||
пересчитает зависимые сама. Позиции, подобранные замером, оставляй числами: связь — обещание,
|
||||
что правка переменной даст осмысленный результат, а на позиционных числах она чаще ломает деталь.
|
||||
- **Размер передавай выражением прямо в операцию** (`extrude(depth="badge_T")`) — параметр сразу
|
||||
становится ведомым, внутреннее имя параметра («Расстояние 1») знать не нужно. Переменная должна
|
||||
существовать ДО операции — потому паспорт и заводят первым. Задним числом и для параметров,
|
||||
которых нет среди аргументов инструмента (углы уклона, второе направление), — `link_parameter`.
|
||||
- **Промахи сервер ловит сам:** ссылка на несуществующее имя — отказ с перечнем виновных (и в
|
||||
выражениях операций, и в `set_variable`; регистр значим), функции в формулах — предупреждение
|
||||
(тригонометрия в радианах, разделитель аргументов «;», непонятая запись = молчаливый 0).
|
||||
Твоя часть — **сверить вычисленные значения из ответа со своей прикидкой**.
|
||||
- **`note` обязателен** и пишется по-русски, со смыслом и единицей; `(ТЗ)` в тексте по-прежнему
|
||||
полезен человеку, но для машины число из ТЗ метится ПРИЗНАКОМ:
|
||||
`set_variable([{name:"dish_r", expression:"90", note:"по ТЗ", information:true}])`. Комментарий
|
||||
вычистка не читает, признак — читает. **Что замерил — верни в переменную** (фактический кегль,
|
||||
прирост каймы), иначе паспорт разойдётся с моделью и станет дезинформацией. Переосмысливать можно
|
||||
всё, кроме помеченного `(ТЗ)`.
|
||||
- **После связывания правка паспорта перестраивает деталь** (проверено: `set_variable(badge_T=4)` →
|
||||
габарит по Z 3.00 → 4.00, объём 5154.5 → 5861.5 мм³). Это и есть параметрическая модель,
|
||||
а не комментарий к ней. **До связывания — не перестраивает**, и `set_variable` говорит об этом
|
||||
прямо: «⚠ НИЧЕГО НЕ ВЕДЁТ». Такой ответ — не успех: число поменялось, деталь нет. Исключение одно —
|
||||
переменная и не должна ничего вести (справка из ТЗ): пометь её `information=true`, и пометка уйдёт
|
||||
вместе с риском вычистки.
|
||||
- **Сверка и уборка в конце:** `describe_model(sections=variables)` помечает «⚠ ничего не ведёт» — это либо забытая
|
||||
связь, либо справка, которую забыли пометить, либо мусор; разбери все три.
|
||||
`delete_variable(unused=true)` не трогает справочные (`information`) и внешние (`external`) —
|
||||
остальное сносит без разбора. Значит порядок такой: `link_parameter` на всё, что должно вести
|
||||
геометрию, `set_variable(information=true)` на всё, что остаётся справкой, и только потом уборка.
|
||||
@@ -1,10 +1,65 @@
|
||||
# Надписи и рельеф — точная подгонка и отделка
|
||||
|
||||
Дополнение к разделу «Надписи, логотипы и рельеф» SKILL.md. Здесь — замеры и приёмы для точной
|
||||
компоновки надписи (подгонка кегля и ширины, поведение каймы, стыковка блоков) и отделки рельефа.
|
||||
Все числа получены пробами на конкретных начертаниях (Lobster, Bevan, Zilla Slab): это порядок
|
||||
величины и форма зависимости, а не константы — свои значения перезамеряй на своём шрифте,
|
||||
`widthFactor` и `thinThickness`.
|
||||
Дополнение к разделу «Надписи, логотипы и рельеф» SKILL.md: выбор маршрута для внешнего контура,
|
||||
перевод SVG-логотипа в примитивы эскиза, точная подгонка надписи (кегль, ширина, кайма, стыковка
|
||||
блоков) и отделка рельефа. Все числа получены пробами на конкретных начертаниях (Lobster, Bevan,
|
||||
Zilla Slab): это порядок величины и форма зависимости, а не константы — свои значения перезамеряй
|
||||
на своём шрифте, `widthFactor` и `thinThickness`.
|
||||
|
||||
## Внешний контур: не диктуй координаты, если фигуру нельзя описать формулой
|
||||
|
||||
Три маршрута, и выбор между ними механический — не по вкусу, а по происхождению геометрии.
|
||||
|
||||
| Откуда фигура | Чем строить |
|
||||
|---|---|
|
||||
| **Вычисляется**: пластины, рёбра, сетка отверстий | `sketch_create(entities[])` — прямо в вызове, размеры вяжи переменными |
|
||||
| **Срисована**: логотип, шаблон, кулачок, профиль | внешний вектор → JSON → `sketch_create(entitiesFile=…)` |
|
||||
| **Пришла в CAD-формате**: файл от смежника | `import_drawing` (.dxf/.dwg) → фрагмент → `fragment_place` |
|
||||
|
||||
**Обводка занимает сотни примитивов, и переписывать их в тело вызова незачем.** У `sketch_create`,
|
||||
`sketch_add` и `fragment_create` есть `entitiesFile` — путь к JSON того же формата, что `entities`;
|
||||
сервер читает файл сам. Замер на эмблеме Volvo: SVG в 1.5 КБ даёт 96 примитивов (50 отрезков +
|
||||
46 дуг) и 9.5 КБ JSON; через `entitiesFile` это один вызов на одну строку аргументов, а эскиз
|
||||
строится за один заход. Оба параметра можно задать вместе — сначала `entities`, следом файл:
|
||||
так к готовому контуру дописывают рамку или ось, не трогая файл.
|
||||
|
||||
Что проверить **до** постройки, а не после: габарит в ответе (`fragment_create` печатает
|
||||
фактический — сверь с задуманным) и вложенные контуры. Правил заливки у эскиза КОМПАС нет: любой
|
||||
вложенный контур он режет как отверстие, даже там, где вектор заливал материал. Конвертер такие
|
||||
места называет заранее — на них смотри до выдавливания, иначе дыры обнаружатся на снимке.
|
||||
|
||||
## Логотип, которого нет в шрифте: SVG → примитивы эскиза
|
||||
|
||||
Переводи готовый вектор в примитивы эскиза сам — `line` и `arc3points`, а не ломаной: контур из
|
||||
сотен звеньев даёт деталь в сотни граней, и фаска по такому низу не строится. Кубические Безье режь
|
||||
пополам, пока дуга по трём точкам не ляжет в допуск. Четыре вещи, каждая из которых стоила захода:
|
||||
|
||||
- **Ось Y в SVG смотрит вниз** — без инверсии контур встаёт вверх ногами, и это видно только на снимке.
|
||||
- **Дуги задавай тремя точками** (`arc3points`): концы заданы явно, соседние примитивы стыкуются
|
||||
точно. Перед постройкой проверь цепочку — конец примитива против начала следующего, разрыв 0.
|
||||
- **Чисти мелочь под масштаб детали — параметром `minSegment`.** SVG рисуют в своём габарите (сотня
|
||||
условных единиц), и его скругления после масштабирования превращаются в дуги по 0.02–0.5 мм;
|
||||
замыкающий `z` часто даёт ещё и сегмент нулевой длины. `chamfer_edge` по такому набору отвечает
|
||||
«катет больше длины N из M рёбер» — и это правда. Передай `sketch_create(minSegment=катет)` (тот же
|
||||
параметр есть у `sketch_update` и `fragment_create`), и та же фаска пройдёт с первой попытки;
|
||||
отчёт о выброшенном читай, а не пролистывай — `help(topic="contour-cleanup")`.
|
||||
|
||||
**Порядок для фаски по контуру логотипа — только такой, и он неочевиден:**
|
||||
|
||||
1. **чистка** порогом ≈ будущего катета (`minSegment`);
|
||||
2. **замер ЧИЩЕНОГО силуэта** — `sketch_measure_thickness(entitiesFile, minSegment=тот же порог)`;
|
||||
3. **катет по узкому месту** чищеного силуэта: `c ≤ (узкое_место − 2·w)/2`, где `w` — ширина нити.
|
||||
|
||||
Менять шаги местами нельзя: **чистка СУЖАЕТ узкое место**. Она заменяет скругление острым углом —
|
||||
в выпуклом углу это добавляет материал (габарит подрастает), а в вогнутом срезает его, и именно
|
||||
вогнутые углы образуют перемычки между штрихами. Сужение доходит до единиц процентов узкого места —
|
||||
этого хватает, чтобы катет, подобранный по нечищеному контуру, перестал проходить свой же критерий.
|
||||
Числа снимай на СВОЁМ контуре: они принадлежат рисунку, а не приёму.
|
||||
|
||||
- **Ширину штриха и узкое место меряй инструментом, а не глазом** — `sketch_measure_thickness`
|
||||
ничего не строит и документа не требует, поэтому зовётся ДО эскиза
|
||||
(`help(topic="silhouette-thickness")`). От этих чисел зависит, останется ли что-то от рисунка
|
||||
после фаски и напечатается ли он вообще; шаг растра в ответе — точность округления катета.
|
||||
|
||||
## Подгонка ширины и кегля
|
||||
|
||||
@@ -61,7 +116,11 @@
|
||||
- **Толщина каймы — ещё и параметр стыковки блоков.** Кайма опускает силуэт надписи ниже её
|
||||
глифов на `t`, и именно это перекрытие с плашкой держит деталь одним телом. Считай так: низ
|
||||
каймы = низ глифов − t, и он должен зайти на плашку хотя бы на несколько десятых. Проверка —
|
||||
сводка «Тел:» в ответе самого `primitive(union)`.
|
||||
сводка «Тел:» в ответе самого `primitive(union)`: у примитивов она надёжна, потому что сервер
|
||||
сам сверяет объём до и после и отвергает объединение, ничего не давшее. **У `loft`/`sweep` этой
|
||||
сводке верить нельзя** — там она однажды напечатала «Тел: 1», когда тел было два (см. основной
|
||||
навык, п. «Ответ мутирующей операции»); в сомнительном случае считай тела
|
||||
`describe_model(sections="bodies")`.
|
||||
- **Кайма вокруг ПРЯМОУГОЛЬНОЙ плашки — вторым примитивом, а не тонкой стенкой.** Стенка обходит
|
||||
контуры эскиза, а плашка по playbook'у строится `primitive`, и каймы у неё не появится. Клади под
|
||||
неё второй блок на `2·t` больше и на высоту подложки (85 × 13.5 × 2 под плашкой 82 × 10.5 × 3) —
|
||||
@@ -89,16 +148,15 @@
|
||||
до нужной части силуэта помогает `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 мм). После чистки совет «попробуй увеличить» уже вреден.
|
||||
- **Отказ фаски на НЕЧИЩЕНОМ контуре — не повод уменьшать катет: успех немонотонен по размеру.**
|
||||
На контуре с острыми клиньями между элементами `chamfer_edge` отказывает на нескольких катетах
|
||||
подряд и проходит на большем — проверено подряд, с `rebuild` между попытками и на неизменных
|
||||
индексах рёбер. Похоже, малый катет оставляет в остром клине вырожденный «нос», который КОМПАС
|
||||
сшить не может, а большой срезает остриё целиком. **Но перебирать катет не надо**: правильное
|
||||
лечение — `minSegment` (см. SKILL.md §«Надписи, логотипы и рельеф»). После чистки совет «попробуй
|
||||
увеличить» становится вреден: рабочий диапазон катета сдвигается ВНИЗ вместе с узким местом, и
|
||||
катет, проходивший на нечищеном контуре, чищеный отвергает. Не переносите подобранное значение
|
||||
между состояниями контура — оно к ним привязано.
|
||||
Прежняя формулировка добавляла «исключение самых коротких рёбер картину не меняет, то есть дело
|
||||
не в них» — вывод неверен: исключённое из `edgeIndices` ребро остаётся в теле, и это не то же
|
||||
самое, что убрать сегмент из контура. Убранный из контура — меняет.
|
||||
|
||||
Reference in New Issue
Block a user