Навыки и README по итогам регресс-прогона
Снято два неверных утверждения kompas-3d: ширина линейна по widthFactor (замер даёт +0.55 % коэффициента → +0.07 % ширины) и проекции #Спереди/#Сверху у model_snapshot, которых у инструмента нет. Добавлено: габарит глифов вместо ячейки, миттер на острых терминалах (t/sin(θ/2)), трекинг кратными пробелами, замер в черновом документе, требование называть каждую операцию. kompas-mcp-dev: правила формы (name у операции, ответ несёт данные для следующего шага), проверенные COM-цепочки, делегирование субагенту cad-engineer. В бэклог CLAUDE.md — отсутствие feature_delete/sketch_update и фильтра подмножества рёбер.
This commit is contained in:
@@ -53,6 +53,13 @@ description: Внутренняя методика доработки самог
|
|||||||
текстом от `ToolErrorText.Describe` (Core/Startup: разворачивает `AggregateException`, склеивает
|
текстом от `ToolErrorText.Describe` (Core/Startup: разворачивает `AggregateException`, склеивает
|
||||||
до трёх вложенных причин через «←»). Пишешь новое сообщение об ошибке — помни, что до агента
|
до трёх вложенных причин через «←»). Пишешь новое сообщение об ошибке — помни, что до агента
|
||||||
дойдёт именно оно.
|
дойдёт именно оно.
|
||||||
|
- **У мутирующей операции есть `name` — имя узла в дереве построения.** Прокидывается до создания
|
||||||
|
объекта (`PartModeler.NewEntity` для API5, `IModelObject.Name` до `Update()` для API7-путей),
|
||||||
|
нормализуется в `FeatureName`. Заводишь новую операцию — добавь параметр сразу: дерево из
|
||||||
|
«Эскиз:1…Эскиз:9» нечитаемо ни человеку, ни агенту, вернувшемуся к модели.
|
||||||
|
- **Ответ операции несёт то, что нужно для СЛЕДУЮЩЕГО шага.** Надпись отдаёт габарит глифов
|
||||||
|
(`TextMetrics`), а не только ширину ячейки; примитив проверяется по объёму. Иначе агент строит
|
||||||
|
вслепую и пересобирает документ ради замера — цикл, который стоил регресс-прогону четырёх кругов.
|
||||||
- **Мутирующая операция сама дописывает итог проверки** через `AutoValidation.AnnotateAsync`
|
- **Мутирующая операция сама дописывает итог проверки** через `AutoValidation.AnnotateAsync`
|
||||||
(`Core/Validation`). Переключатель — `set_auto_validate` и `KOMPAS_MCP_AUTOVALIDATE`; проверка
|
(`Core/Validation`). Переключатель — `set_auto_validate` и `KOMPAS_MCP_AUTOVALIDATE`; проверка
|
||||||
никогда не превращает удачную операцию в ошибку (сбой самой проверки уходит в примечание).
|
никогда не превращает удачную операцию в ошибку (сбой самой проверки уходит в примечание).
|
||||||
@@ -102,6 +109,14 @@ CI гоняет только `Category=Unit&Requires!=Windows` на Linux-ран
|
|||||||
|
|
||||||
## Делегирование
|
## Делегирование
|
||||||
|
|
||||||
|
**Прогон задачи целиком** — субагент **`cad-engineer`** (`.claude/agents/`, наследует модель; из
|
||||||
|
инструментов — только навыки, чтение и MCP `kompas`, ничего пишущего). Отладочный цикл навыка и
|
||||||
|
каталога: правишь `plugin/skills/*` или сервер → натравливаешь субагента на ту же задачу с нуля →
|
||||||
|
читаешь его протокол (вызовы, затыки, цитаты из навыка, чего не хватило в инструментах). Смысл именно
|
||||||
|
в чистом контексте: если задача решается только с твоими подсказками по ходу — значит, недоработан
|
||||||
|
навык, а не субагент. Правок он не делает принципиально, поэтому нехватка инструмента возвращается
|
||||||
|
находкой, а не самодельным обходом. В плагин не входит.
|
||||||
|
|
||||||
**Поиск по справке SDK** (сигнатуры, константы, перечисления, цепочки COM-вызовов) — субагент
|
**Поиск по справке SDK** (сигнатуры, константы, перечисления, цепочки COM-вызовов) — субагент
|
||||||
**`kompas-sdk-research`** (Haiku, read-only). Справка живёт **не в репозитории**, а в RAG-базе
|
**`kompas-sdk-research`** (Haiku, read-only). Справка живёт **не в репозитории**, а в RAG-базе
|
||||||
`kompas-sdk` (MCP-сервер, репозиторий `kompas-sdk-docs`) — грепать по проекту бесполезно, доступ к
|
`kompas-sdk` (MCP-сервер, репозиторий `kompas-sdk-docs`) — грепать по проекту бесполезно, доступ к
|
||||||
|
|||||||
@@ -219,6 +219,20 @@
|
|||||||
`ksGetTextLengthFromReference(ref)` (advance width in mm, ≈ 10 % wider than the glyph bbox) and place the
|
`ksGetTextLengthFromReference(ref)` (advance width in mm, ≈ 10 % wider than the glyph bbox) and place the
|
||||||
text yourself; the dynamic arrays live in КОМПАС, so `ksDeleteArray()` them in a `finally`; an unknown
|
text yourself; the dynamic arrays live in КОМПАС, so `ksDeleteArray()` them in a `finally`; an unknown
|
||||||
font name is silently substituted rather than failing; `height` sizes the cap+ascender, not the bbox.
|
font name is silently substituted rather than failing; `height` sizes the cap+ascender, not the bbox.
|
||||||
|
- **Glyph bounding box (verified live)**: `ksConvertTextToCurve(ref)` **returns a new reference — the
|
||||||
|
curves**, and only that one gives the real box. `ksDocument2D.ksGetObjGabaritRect(reference, ksRectParam)`
|
||||||
|
(`ko_RectParam`; `GetpBot()`/`GetpTop()` → `ksMathPointParam.x/y`, **millimetres of the sketch**, not
|
||||||
|
sheet centimetres) on the *text* reference returns the cell (23.75 mm for Arial h=10 «HH») while the
|
||||||
|
same call on the *converted* reference returns the glyphs (19.97 mm, matching the extruded solid to
|
||||||
|
0.05 mm). Returns 0 rather than throwing when the object has no box — treat as «unknown», don't fail
|
||||||
|
the primitive. Test: `SketchTextTests.Reported_glyph_box_matches_the_extruded_geometry`.
|
||||||
|
- **Feature names in the tree (`name` on every mutating tool, verified live)**: API5 `ksEntity.name` is
|
||||||
|
read/write and must be assigned **before `Create()`** — `PartModeler.NewEntity(part, type, name)` does it
|
||||||
|
for every entity, sketches included. API7 objects created outside `ksPart` (`IElementaryBody` from
|
||||||
|
`ElementaryBodies.Add`, `IHole3D` from `Holes3D.Add`) take it via `IModelObject.Name` set before
|
||||||
|
`Update()`. Reading back is asymmetric: `ksFeature.name` (what `list_features`/`describe_model` walk) is
|
||||||
|
**read-only** — the tree shows the assigned name, but you cannot rename through `ksFeature`.
|
||||||
|
Test: `FeatureNamingTests`.
|
||||||
- **Elementary bodies / primitives (`primitive`, verified live)**: `(IPart7 as IModelContainer)
|
- **Elementary bodies / primitives (`primitive`, verified live)**: `(IPart7 as IModelContainer)
|
||||||
.ElementaryBodies.Add(ksObj3dTypeEnum)` → cast to `IBlockBySizes` / `ICylinder` / `ISphere` /
|
.ElementaryBodies.Add(ksObj3dTypeEnum)` → cast to `IBlockBySizes` / `ICylinder` / `ISphere` /
|
||||||
`IConeByHeight` → set sizes → `Update()`. Types: `o3d_BlockBySizes=668`, `o3d_Cylinder=663`,
|
`IConeByHeight` → set sizes → `Update()`. Types: `o3d_BlockBySizes=668`, `o3d_Cylinder=663`,
|
||||||
|
|||||||
@@ -65,6 +65,13 @@ a *general* tool with tests, and describe the method in the `kompas-3d` skill.
|
|||||||
arc/angular/rough dimensions (needs its own spike — `ILineDimension` has no `BaseObject`).
|
arc/angular/rough dimensions (needs its own spike — `ILineDimension` has no `BaseObject`).
|
||||||
- **Assembly**: mate types beyond `coincidence`/`distance` — `parallel`, `perpendicular`, `concentric`,
|
- **Assembly**: mate types beyond `coincidence`/`distance` — `parallel`, `perpendicular`, `concentric`,
|
||||||
`angle`, `tangency` (enum values exist in `MateType.cs`, not verified live).
|
`angle`, `tangency` (enum values exist in `MateType.cs`, not verified live).
|
||||||
|
- **Editing the tree** (raised by the `cad-engineer` regression run): there is no `feature_delete` /
|
||||||
|
`sketch_update`, so any fit-up of a sketch means `document_close(all)` + rebuilding from scratch —
|
||||||
|
four full rounds in that run. `IFeature7.Delete()` exists and `ksDocument3D.DeleteObject` is the API5
|
||||||
|
counterpart; neither is verified live yet.
|
||||||
|
- **Addressing a subset of edges/faces**: on a body with hundreds of edges `list_edges` is unusable by
|
||||||
|
answer size and there is no filter (by operation, by bounding window). Points now work in a batch
|
||||||
|
(`fillet_edge(points=[…])`), but discovery still has no cheap path.
|
||||||
- **Known caveat:** boss/cut direction on a *selected face* depends on the face-normal orientation —
|
- **Known caveat:** boss/cut direction on a *selected face* depends on the face-normal orientation —
|
||||||
`forward` may need flipping. Pick the direction from the `list_faces(index=…)` normal or a snapshot
|
`forward` may need flipping. Pick the direction from the `list_faces(index=…)` normal or a snapshot
|
||||||
before building.
|
before building.
|
||||||
@@ -152,7 +159,14 @@ junction by the `ReparsePoint` attribute rather than by resolving the target, wh
|
|||||||
still works once the target is gone. No `post-checkout` hook on purpose — it fires after checkout already
|
still works once the target is gone. No `post-checkout` hook on purpose — it fires after checkout already
|
||||||
broke, too late to help.
|
broke, too late to help.
|
||||||
|
|
||||||
## Delegation subagent
|
## Delegation subagents
|
||||||
|
|
||||||
|
**`cad-engineer`** (`.claude/agents/`, model inherit — Skill/Read/Glob/Grep + the `kompas` MCP server,
|
||||||
|
no write access): runs a whole CAD task end-to-end from a clean context, building **only** through MCP
|
||||||
|
tools. It is a **debugging harness**, not a shortcut: this session fixes the skills and the server, then
|
||||||
|
re-runs the same task through the subagent and reads its protocol — calls made, dead ends, complaints
|
||||||
|
against the skill (quoted), complaints against the catalog. It can't patch anything, so a missing tool
|
||||||
|
comes back as a finding instead of a hand-made workaround. Project-local, never shipped in the plugin.
|
||||||
|
|
||||||
**`kompas-sdk-research`** (`.claude/agents/`, model **Haiku**, read-only — MCP `kompas-sdk` tools only):
|
**`kompas-sdk-research`** (`.claude/agents/`, model **Haiku**, read-only — MCP `kompas-sdk` tools only):
|
||||||
finds an interface/method/enum/constant signature in the SDK knowledge base and returns a compressed
|
finds an interface/method/enum/constant signature in the SDK knowledge base and returns a compressed
|
||||||
|
|||||||
@@ -82,8 +82,10 @@ kompas-mcp.exe --version # версия бинаря, КОМПАС для эт
|
|||||||
Инструменты сгруппированы по смыслу операции, а не по способу вызова: тип задаётся параметром
|
Инструменты сгруппированы по смыслу операции, а не по способу вызова: тип задаётся параметром
|
||||||
(`extrude(mode=boss|cut)`, `hole(type=simple|counterbore|countersink|conic)`,
|
(`extrude(mode=boss|cut)`, `hole(type=simple|counterbore|countersink|conic)`,
|
||||||
`pattern(kind=linear|circular)`), а объект — либо индексом из `list_faces`/`list_edges`,
|
`pattern(kind=linear|circular)`), а объект — либо индексом из `list_faces`/`list_edges`,
|
||||||
либо точкой в мировых координатах. Эскиз строится списком примитивов за один вызов:
|
либо точкой в мировых координатах (рёбра под скругление/фаску — и списком точек `points[]`,
|
||||||
`sketch_create(plane|faceIndex, entities[])`.
|
чтобы N углов давали одну операцию). Эскиз строится списком примитивов за один вызов:
|
||||||
|
`sketch_create(plane|faceIndex, entities[])`. У каждой операции есть `name` — имя узла в дереве
|
||||||
|
построения; без него дерево состоит из безликих «Эскиз:1», «Элемент выдавливания:2».
|
||||||
|
|
||||||
Формообразование идёт двумя путями, и их сочетают: `primitive(kind=block|cylinder|sphere|cone,
|
Формообразование идёт двумя путями, и их сочетают: `primitive(kind=block|cylinder|sphere|cone,
|
||||||
result=new|union|subtract|intersect)` строит тело по размерам без эскиза (в том числе вычитает
|
result=new|union|subtract|intersect)` строит тело по размерам без эскиза (в том числе вычитает
|
||||||
@@ -93,7 +95,7 @@ result=new|union|subtract|intersect)` строит тело по размера
|
|||||||
Примитивы эскиза: `line`, `circle`, `rectangle`, `arc`, `arc3points`, `ellipse`, `polyline`,
|
Примитивы эскиза: `line`, `circle`, `rectangle`, `arc`, `arc3points`, `ellipse`, `polyline`,
|
||||||
`polygon`, `spline`, `point`, `axis`, `text`. Надпись (`type=text` с `text`, `height`, `fontName`)
|
`polygon`, `spline`, `point`, `axis`, `text`. Надпись (`type=text` с `text`, `height`, `fontName`)
|
||||||
сразу переводится в кривые, поэтому её можно выдавливать — так делаются логотипы и гравировка;
|
сразу переводится в кривые, поэтому её можно выдавливать — так делаются логотипы и гравировка;
|
||||||
в ответе возвращается фактическая длина строки, по ней надпись выравнивают. Параметры
|
в ответе возвращается габарит глифов (и отдельно ширина ячейки строки), по нему надпись выравнивают. Параметры
|
||||||
`extrude(thinThickness, thinSide)` превращают контур в стенку заданной толщины: `outward`
|
`extrude(thinThickness, thinSide)` превращают контур в стенку заданной толщины: `outward`
|
||||||
наращивает её наружу и даёт ободок-эквидистанту вокруг контура (например, подложку под надпись).
|
наращивает её наружу и даёт ободок-эквидистанту вокруг контура (например, подложку под надпись).
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ MCP-сервер даёт **общие** операции КОМПАС (эски
|
|||||||
|
|
||||||
- *Система/документы:* `kompas_connect`, `kompas_set_visible`, `kompas_status`, `set_auto_validate`; `document_create|open|save|close|active` (`document_save(path)` — сохранить новый документ или копию, без `path` — на прежнее место); `set_part_info(name, marking)` — наименование и обозначение детали.
|
- *Система/документы:* `kompas_connect`, `kompas_set_visible`, `kompas_status`, `set_auto_validate`; `document_create|open|save|close|active` (`document_save(path)` — сохранить новый документ или копию, без `path` — на прежнее место); `set_part_info(name, marking)` — наименование и обозначение детали.
|
||||||
- *Эскиз (три инструмента вместо шестнадцати):* `sketch_create` — основание задаётся `plane` (+`offset`) ЛИБО `faceIndex` ЛИБО точкой `x,y,z`, а геометрия сразу списком `entities[{type: line|circle|rectangle|arc|arc3points|ellipse|polyline|polygon|spline|point|axis|text, …}]`; `sketch_add` — дополнить открытый эскиз; `sketch_close`.
|
- *Эскиз (три инструмента вместо шестнадцати):* `sketch_create` — основание задаётся `plane` (+`offset`) ЛИБО `faceIndex` ЛИБО точкой `x,y,z`, а геометрия сразу списком `entities[{type: line|circle|rectangle|arc|arc3points|ellipse|polyline|polygon|spline|point|axis|text, …}]`; `sketch_add` — дополнить открытый эскиз; `sketch_close`.
|
||||||
- *Формообразующие:* `primitive(kind=block|cylinder|sphere|cone, result=new|union|subtract|intersect)` — тело по размерам БЕЗ эскиза, `extrude(mode=boss|cut)`, `revolve(mode=boss|cut)`, `fillet_edge`/`chamfer_edge` (список `edgeIndices` — одной операцией на все рёбра — либо точка), `shell`, `rib`, `sweep`, `loft`, `draft`, `rebuild`.
|
- *Формообразующие:* `primitive(kind=block|cylinder|sphere|cone, result=new|union|subtract|intersect)` — тело по размерам БЕЗ эскиза, `extrude(mode=boss|cut)`, `revolve(mode=boss|cut)`, `fillet_edge`/`chamfer_edge` (одной операцией на все рёбра: список `edgeIndices` ЛИБО список `points[{x,y,z}]`, либо одна точка), `shell`, `rib`, `sweep`, `loft`, `draft`, `rebuild`. У всех — `name`: имя операции в дереве построения.
|
||||||
- *Отверстия:* `hole(type=simple|counterbore|countersink|conic)` — грань по `faceIndex` (центр грани) либо точкой.
|
- *Отверстия:* `hole(type=simple|counterbore|countersink|conic)` — грань по `faceIndex` (центр грани) либо точкой.
|
||||||
- *Массивы и зеркало:* `pattern(kind=linear|circular)`, `mirror` (без `featureIds` — всё тело, с ними — только эти операции).
|
- *Массивы и зеркало:* `pattern(kind=linear|circular)`, `mirror` (без `featureIds` — всё тело, с ними — только эти операции).
|
||||||
- *Прямое редактирование (без дерева, в т.ч. импортированная B-rep):* `move_face` (сдвинуть грань на N мм по нормали; грань — `faceIndex` или точка), `split_solid_by_plane` (рассечь тело плоскостью), `move_body` (сдвинуть тело на вектор), `boolean_union` (объединить тела).
|
- *Прямое редактирование (без дерева, в т.ч. импортированная B-rep):* `move_face` (сдвинуть грань на N мм по нормали; грань — `faceIndex` или точка), `split_solid_by_plane` (рассечь тело плоскостью), `move_body` (сдвинуть тело на вектор), `boolean_union` (объединить тела).
|
||||||
@@ -114,9 +114,16 @@ MCP-сервер; если инструмента под задачу нет, с
|
|||||||
стоит безликая «Деталь», и она же уедет в штамп чертежа и в спецификацию; `describe_model` специально
|
стоит безликая «Деталь», и она же уедет в штамп чертежа и в спецификацию; `describe_model` специально
|
||||||
отмечает деталь без наименования. Имя файла при сохранении этого НЕ заменяет — это разные свойства.
|
отмечает деталь без наименования. Имя файла при сохранении этого НЕ заменяет — это разные свойства.
|
||||||
|
|
||||||
|
**Называй каждую операцию.** У `sketch_create`, `extrude`, `primitive`, `fillet_edge`, `hole`,
|
||||||
|
`pattern`, `shell` и остальных есть `name` — имя узла в дереве построения. Без него дерево выглядит
|
||||||
|
как «Эскиз:1, Эскиз:2, Элемент выдавливания:3», и по нему нельзя понять, что чем построено, —
|
||||||
|
ни человеку, ни тебе самому через сотню вызовов. Имя пиши по смыслу: «Контур плашки», «Рельеф букв
|
||||||
|
OldMan», «Карман под площадку», «Скругления углов плашки».
|
||||||
|
|
||||||
**Не разбивай построение на лишние вызовы.** Прямоугольник с четырьмя отверстиями — это ОДИН
|
**Не разбивай построение на лишние вызовы.** Прямоугольник с четырьмя отверстиями — это ОДИН
|
||||||
`sketch_create` со списком из пяти примитивов, а не шесть вызовов. Скругление восьми рёбер — один
|
`sketch_create` со списком из пяти примитивов, а не шесть вызовов. Скругление восьми рёбер — один
|
||||||
`fillet_edge(radius, edgeIndices=[…])`, а не восемь. Каждый лишний вызов — лишний шанс сбиться.
|
`fillet_edge(radius, edgeIndices=[…])` или `fillet_edge(radius, points=[…])`, а не восемь.
|
||||||
|
Каждый лишний вызов — лишний шанс сбиться.
|
||||||
|
|
||||||
## Надписи, логотипы и рельеф
|
## Надписи, логотипы и рельеф
|
||||||
|
|
||||||
@@ -125,16 +132,28 @@ MCP-сервер; если инструмента под задачу нет, с
|
|||||||
`widthFactor` — сужение, `angle` — наклон строки). Она **сразу переводится в кривые**, поэтому
|
`widthFactor` — сужение, `angle` — наклон строки). Она **сразу переводится в кривые**, поэтому
|
||||||
выдавливается как обычный контур: гравировка — `extrude(mode="cut")`, выпуклые буквы — `mode="boss"`.
|
выдавливается как обычный контур: гравировка — `extrude(mode="cut")`, выпуклые буквы — `mode="boss"`.
|
||||||
|
|
||||||
- **Позиционирование — в два прохода, длина строки лишь для прикидки.** Ответ содержит длину
|
- **Ответ даёт ГАБАРИТ ГЛИФОВ — по нему и позиционируй.** «надпись «OldMan» — глифы X 1.00…87.93,
|
||||||
надписи в мм («надпись «OldMan» — длина 79.05 мм»), но это ширина С боковыми просветами, и
|
Y 12.14…28.94 (86.93 × 16.80 мм), ширина ячейки 94.57 мм». Первые числа — прямоугольник, реально
|
||||||
насколько она больше самих глифов — зависит от шрифта: замерено 1–2 % у наборных (Zilla Slab,
|
занятый буквами (совпадает с тем, что получится после выдавливания); *ширина ячейки* — шаг строки
|
||||||
Bevan) и 7–9 % у скриптовых (Lobster, Pacifico). Поэтому: вставь надпись, выдави, прочитай
|
с боковыми просветами, она больше на 1–2 % у наборных шрифтов (Zilla Slab, Bevan) и на 7–9 % у
|
||||||
**фактический** габарит `describe_model(sections="box")` и уже по нему пересчитай точку вставки.
|
скриптовых (Lobster, Pacifico). Вписываешь надпись в поле — считай по габариту, не по ячейке.
|
||||||
|
- **Мерить дешевле в черновом документе.** Пока деталь пуста, габарит надписи — это габарит всей
|
||||||
|
модели, и подбор кегля идёт без пересборки: `document_create part` → эскиз с текстом → прочитать
|
||||||
|
метрики → закрыть без сохранения. В собранном теле (сотни граней) выделить рельеф уже нечем.
|
||||||
- **`height` — это высота ПРОПИСНОЙ (cap height), а не габарит строки.** Замер на Zilla Slab при
|
- **`height` — это высота ПРОПИСНОЙ (cap height), а не габарит строки.** Замер на Zilla Slab при
|
||||||
`height=10`: «HH» → 9.97 мм, «hd» → 10.71 (восходящие выше прописной), «Hy» → 13.24 мм
|
`height=10`: «HH» → 9.97 мм, «hd» → 10.71 (восходящие выше прописной), «Hy» → 13.24 мм
|
||||||
(нижний выносной уходит на −3.27). Считаешь компоновку — закладывай выносные отдельно.
|
(нижний выносной уходит на −3.27). Считаешь компоновку — закладывай выносные отдельно.
|
||||||
- **Ширина линейна** и по `height`, и по `widthFactor`: вписать строку в заданную ширину можно
|
- **Ширина линейна по `height`** (проверено до 0.01 мм) — им и подгоняй точный размер.
|
||||||
одним пересчётом, без подбора вслепую.
|
**По `widthFactor` линейности НЕТ:** замер даёт +0.55 % коэффициента → +0.07 % ширины
|
||||||
|
(КОМПАС квантует кегль). Поэтому `widthFactor` — грубая пропорция начертания, а не масштаб:
|
||||||
|
выставил его один раз, дальше набираешь ширину высотой.
|
||||||
|
- **Толщина каймы на острых терминалах больше, чем `thinThickness`.** Стенка `outward` обходит
|
||||||
|
контур с миттером: на остром окончании глифа (скриптовые «n», «l») габарит растёт на
|
||||||
|
`t / sin(θ/2)`, а не на `t` — замерено 2.11 мм при `t`=1.0 у Lobster. Считать «глиф + 2t» нельзя,
|
||||||
|
габарит после операции надо перечитывать.
|
||||||
|
- **Разрядки (трекинга) у примитива нет — её набирают пробелами.** Ширину пробела для конкретного
|
||||||
|
шрифта и кегля вычисляют двумя пробами: «EDITION» → 38.38 мм, «E D I T I O N» → 47.11 мм,
|
||||||
|
значит пробел 1.455 мм (Bevan, cap 5.5).
|
||||||
- **Подложка под надпись — тонкой стенкой, а не вторым эскизом.** `extrude(..., thinThickness=1.2,
|
- **Подложка под надпись — тонкой стенкой, а не вторым эскизом.** `extrude(..., thinThickness=1.2,
|
||||||
thinSide="outward")` по контуру букв даёт ободок-эквидистанту вокруг них; выдавь ТОТ ЖЕ эскиз
|
thinSide="outward")` по контуру букв даёт ободок-эквидистанту вокруг них; выдавь ТОТ ЖЕ эскиз
|
||||||
дважды — сплошным на высоту подложки и стенкой наружу — и получишь силуэт надписи с равномерной
|
дважды — сплошным на высоту подложки и стенкой наружу — и получишь силуэт надписи с равномерной
|
||||||
@@ -151,6 +170,10 @@ MCP-сервер; если инструмента под задачу нет, с
|
|||||||
Zilla Slab «AB» (203 ребра): одиночное ребро скругляется R0.1 и R0.2, а `fillet_edge` сразу по
|
Zilla Slab «AB» (203 ребра): одиночное ребро скругляется R0.1 и R0.2, а `fillet_edge` сразу по
|
||||||
всем рёбрам отказывает при обоих радиусах (соседние скругления конфликтуют). Адресно выбрать
|
всем рёбрам отказывает при обоих радиусах (соседние скругления конфликтуют). Адресно выбрать
|
||||||
«только верхние» рёбра пока нечем — `list_edges` не отдаёт ни координат, ни принадлежности грани.
|
«только верхние» рёбра пока нечем — `list_edges` не отдаёт ни координат, ни принадлежности грани.
|
||||||
|
- **Углы вокруг надписи — одним `fillet_edge(points=[…])`.** На теле с сотнями рёбер список из
|
||||||
|
`list_edges` неподъёмен, но точки углов известны из построения: передай их списком, и все рёбра
|
||||||
|
уйдут в ОДНУ операцию дерева. Если ребра в части точек нет (типичный случай — угол «съеден»
|
||||||
|
каймой букв), ошибка перечислит ВСЕ такие точки сразу: убери их и повтори одним вызовом.
|
||||||
- **Шрифт обязан быть установлен в системе**, где работает КОМПАС: неизвестное имя молча
|
- **Шрифт обязан быть установлен в системе**, где работает КОМПАС: неизвестное имя молча
|
||||||
подменяется другим шрифтом, и надпись «поедет» по ширине без единого сообщения об ошибке.
|
подменяется другим шрифтом, и надпись «поедет» по ширине без единого сообщения об ошибке.
|
||||||
|
|
||||||
@@ -166,9 +189,10 @@ MCP-сервер; если инструмента под задачу нет, с
|
|||||||
компоненты пишутся как отдельные `.m3d` рядом; открывать деталь самостоятельным документом
|
компоненты пишутся как отдельные `.m3d` рядом; открывать деталь самостоятельным документом
|
||||||
(`OpenSourceDocument`). Гашение видимости компонента на снимок **не влияет** — изоляция так не делается.
|
(`OpenSourceDocument`). Гашение видимости компонента на снимок **не влияет** — изоляция так не делается.
|
||||||
4. **Осмотр детали — структурно:** `describe_model` (габарит по осям → какая ось «высота», МЦХ,
|
4. **Осмотр детали — структурно:** `describe_model` (габарит по осям → какая ось «высота», МЦХ,
|
||||||
тела, топология). Грани/рёбра под операцию — `list_faces`/`list_faces(index=N)`, `measure`. `model_snapshot`
|
тела, топология). Грани/рёбра под операцию — `list_faces`/`list_faces(index=N)`, `measure`.
|
||||||
(или стандартные проекции `#Спереди/#Сверху/#Слева/#Справа/#Изометрия`) — **только** если нужен
|
`model_snapshot` — **только** если нужен визуально-пространственный контроль формы; выбора вида
|
||||||
визуально-пространственный контроль формы.
|
у него нет (снимок идёт с текущей ориентации окна, параметры — только разрешение и оттенки серого),
|
||||||
|
так что фронтальный контроль плоской детали им не сделать: сверяй числа.
|
||||||
5. **Модификация** на «тупой» импортированной B-rep (итог проверки читаешь в ответе каждой операции):
|
5. **Модификация** на «тупой» импортированной B-rep (итог проверки читаешь в ответе каждой операции):
|
||||||
- *Простой случай* — `move_face`: сдвинуть плоскую грань на +N мм (наружу) или −N (внутрь);
|
- *Простой случай* — `move_face`: сдвинуть плоскую грань на +N мм (наружу) или −N (внутрь);
|
||||||
грань бери по `faceIndex` из `list_faces`. ⚠ На сложном торце (с отверстием/пазом) FaceMover
|
грань бери по `faceIndex` из `list_faces`. ⚠ На сложном торце (с отверстием/пазом) FaceMover
|
||||||
@@ -198,6 +222,7 @@ MCP-сервер; если инструмента под задачу нет, с
|
|||||||
версия из этой же папки), `document_save(path)` по этому пути не пройдёт — КОМПАС не перезаписывает
|
версия из этой же папки), `document_save(path)` по этому пути не пройдёт — КОМПАС не перезаписывает
|
||||||
занятый файл. Освободить имя: `document_close(all=true)`. Проверяй, что файл на диске реально
|
занятый файл. Освободить имя: `document_close(all=true)`. Проверяй, что файл на диске реально
|
||||||
обновился (время изменения), особенно когда перестраиваешь деталь поверх прежней.
|
обновился (время изменения), особенно когда перестраиваешь деталь поверх прежней.
|
||||||
|
Несуществующий каталог в пути — не помеха: `document_save` и `export_step` создают его сами.
|
||||||
- **Единицы — мм** (геометрия) и кг (масса). Локальные координаты эскиза ≠ мировые координаты модели.
|
- **Единицы — мм** (геометрия) и кг (масса). Локальные координаты эскиза ≠ мировые координаты модели.
|
||||||
|
|
||||||
## Открытые вопросы / границы
|
## Открытые вопросы / границы
|
||||||
|
|||||||
Reference in New Issue
Block a user