Навыки и README: два пути формообразования, надписи, проверенные факты
kompas-3d: раздел «Два пути формообразования — выбирай по форме, а не по привычке» (призматика и карманы примитивами, текст и кривые эскизами) и раздел про надписи с числами, снятыми на практике: height задаёт высоту ПРОПИСНОЙ, а не габарит строки; разрыв между advance-длиной и габаритом глифов зависит от шрифта (1-2 % у наборных, 7-9 % у скриптовых) — прежние формулировки были выведены из одного замера и оказались неверны. Там же — почему тонкая стенка по многоконтурному эскизу не строится поверх пересекаемого тела (разложено экспериментом: число тел, происхождение тела и chooseType ни при чём) и как скруглять рельефный текст: по одному ребру строится, пакетом по всем 203 — нет. CLAUDE.md и kompas-mcp-dev: спайк-проект под кейс допустим для проверки теории, но итоговая деталь всегда строится инструментами MCP — раннер обходит тот самый слой, который мы проверяем.
This commit is contained in:
@@ -46,6 +46,13 @@ description: Внутренняя методика доработки самог
|
||||
- **Схема не запрещает неверную комбинацию полей — это делает валидация.** Сообщение называет
|
||||
`type=…` и недостающий параметр (`SketchEntityInputs`, `FeatureTools.Required`), иначе агент
|
||||
тратит лишний ход на догадки.
|
||||
- **Текст исключения доходит до клиента только через фильтр.** MCP-SDK показывает сообщение лишь у
|
||||
`McpException`, остальное подменяет на «An error occurred invoking '<tool>'» — то есть без
|
||||
фильтра ВСЕ наши подсказки в исключениях пропадают. В `Program.cs` стоит
|
||||
`WithRequestFilters(... AddCallToolFilter ...)`, который отдаёт `CallToolResult{IsError=true}` с
|
||||
текстом от `ToolErrorText.Describe` (Core/Startup: разворачивает `AggregateException`, склеивает
|
||||
до трёх вложенных причин через «←»). Пишешь новое сообщение об ошибке — помни, что до агента
|
||||
дойдёт именно оно.
|
||||
- **Мутирующая операция сама дописывает итог проверки** через `AutoValidation.AnnotateAsync`
|
||||
(`Core/Validation`). Переключатель — `set_auto_validate` и `KOMPAS_MCP_AUTOVALIDATE`; проверка
|
||||
никогда не превращает удачную операцию в ошибку (сбой самой проверки уходит в примечание).
|
||||
@@ -56,6 +63,15 @@ description: Внутренняя методика доработки самог
|
||||
> докажи механику (спайк или минимальный прогон), затем продуктизируй как **общий** инструмент MCP
|
||||
> (с тестами, TDD) и опиши приём в навыке `kompas-3d`.
|
||||
|
||||
**Спайк — только чтобы проверить теорию; результат выдаётся инструментами MCP.** Отдельный
|
||||
dotnet-проект в `usecases/<кейс>/` (ссылка на `Kompas.Mcp.Core`, `KompasInteropLoader.Install()`
|
||||
первой строкой) — законный способ измерить метрику, проверить COM-цепочку или опровергнуть
|
||||
утверждение навыка. Но **итоговая деталь/чертёж всегда строится вызовами MCP-инструментов**:
|
||||
раннер обходит ровно тот слой, который мы и проверяем (схемы инструментов, разбор входа, форму
|
||||
ответа, авто-валидацию), поэтому «построено раннером» не считается за проверку сервера. Если
|
||||
инструментов не хватает — это и есть находка кейса: доработать сервер, а не достроить в обход.
|
||||
Проверочный проект после кейса удаляй, полученные числа переноси в `plan.md` кейса и в навык.
|
||||
|
||||
Порядок для нового инструмента:
|
||||
|
||||
1. **Сигнатуры и константы** — через субагента `kompas-sdk-research` (см. ниже), затем перепроверка
|
||||
|
||||
@@ -205,3 +205,58 @@
|
||||
`.Features.cs` (extrude/revolve/fillet/chamfer). Static `SketchGeometry` (`Core/Modeling`) holds the enum maps
|
||||
+ validators (`RequirePositive`, `RequireVertexCount`, `RequirePoints`, `RequireMin`). Point lists use
|
||||
`record SketchPoint(X, Y)` (JSON names `x`/`y`).
|
||||
- **Text in a sketch → curves (`type=text`, verified live)**: a text object is *annotation* — a formative
|
||||
operation never sees it. The chain that works: build `ksTextParam` (`ko_TextParam=28`) → `Init()` →
|
||||
`GetParagraphParam()` (`ksParagraphParam`: `x`, `y`, `ang`, `height`, `width`) → `SetParagraphParam`;
|
||||
one `ksTextItemParam` (`ko_TextItemParam=31`, `type=ksTItString=0`, `s=<string>`) whose `GetItemFont()`
|
||||
(`ksTextItemFont`) carries `fontName`/`height` (mm)/`ksu` (width factor)/`bitVector`
|
||||
(`ITALIC_ON=0x40`, `BOLD_ON=0x100` — from `Include/ldefin2d.h`); wrap it in
|
||||
`KompasObject.GetDynamicArray(TEXT_ITEM_ARR=4)` → `ksTextLineParam` (`ko_TextLineParam=29`,
|
||||
`SetTextItemArr`) → `GetDynamicArray(TEXT_LINE_ARR=3)` → `SetTextLineArr`; then
|
||||
`ksDocument2D.ksTextEx(param, align)` → **`ksConvertTextToCurve(ref)`** — this is what turns glyphs into
|
||||
NURBS/lines that extrude. Traps: the `align` argument of `ksTextEx` does **not** move the string (a
|
||||
centred value still lays it out right-and-up from the insertion point) — instead read
|
||||
`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
|
||||
font name is silently substituted rather than failing; `height` sizes the cap+ascender, not the bbox.
|
||||
- **Elementary bodies / primitives (`primitive`, verified live)**: `(IPart7 as IModelContainer)
|
||||
.ElementaryBodies.Add(ksObj3dTypeEnum)` → cast to `IBlockBySizes` / `ICylinder` / `ISphere` /
|
||||
`IConeByHeight` → set sizes → `Update()`. Types: `o3d_BlockBySizes=668`, `o3d_Cylinder=663`,
|
||||
`o3d_Sphere=662`, `o3d_ConeByHeight=670` — and `Add` takes **`ksObj3dTypeEnum`, not `Obj3dType`**
|
||||
(same numbers, different type; the compiler catches it). Placement is the primitive's own
|
||||
`Position` (a `LocalCoordinateSystem` with writable X/Y/Z); for a block the anchor is a corner
|
||||
(`BlockPosition = ksVertex`), for bodies of revolution the base centre. `OperationResult`
|
||||
(`ksOperationUnion=0 / NewBody=1 / Cut=2 / Intersect=3`) makes the primitive a boolean in itself —
|
||||
a pocket needs no sketch and no cut extrusion. Traps: `Height`, `HeightType`, `HeightOffset` and
|
||||
cone's `Diameter` are **indexed properties** (`Height[true] = …`, index = the direction side), plain
|
||||
assignment does not compile; and `Update()` returns TRUE for a subtraction that misses the body
|
||||
entirely, so `PrimitiveService` compares the volume before/after and rolls the feature back
|
||||
(`Owner.Delete()`) when nothing changed.
|
||||
- **Part name/marking (`set_part_info`)**: write through API7 `IPart7.Name` / `IPart7.Marking` on
|
||||
`IKompasDocument3D.TopPart`, then **`top.Update()`** — without it the tree keeps showing «Деталь».
|
||||
Read-back through the same properties (API5 `ksPart.name` / `ksPart.marking` also expose them, which is
|
||||
what `ModelInspectionService` uses, since its `GetTopPart` is already an API5 `ksPart`). The document's
|
||||
file name is a different thing entirely: saving as `Badge.m3d` does not rename the part.
|
||||
- **`IKompasDocument.SaveAs(path)` returns `void` and fails silently** when a file of that name is already
|
||||
open in КОМПАС as another document: nothing is written, no error, the document simply stays unsaved.
|
||||
`DocumentService.SaveAsAsync` therefore verifies afterwards — `doc.PathName` must equal the requested
|
||||
path AND `File.Exists(path)` — and `SaveAsync` checks `doc.Changed == false`. Covered by
|
||||
`DocumentTests.SaveAs_over_a_name_held_by_another_open_document_fails_loudly`. To free the name,
|
||||
`document_close(all: true)` (→ `DocumentService.CloseAllAsync`) closes every open document.
|
||||
- **Thin-wall extrusion (`extrude(thinThickness, thinSide)`)**: `ksBoss/CutExtrusionDefinition.SetThinParam(
|
||||
thin, thinType, normalThickness, reverseThickness)` with `thinType` = `dtNormal` (outward), `dtReverse`
|
||||
(inward), `dtBoth` (half each side). **Trap: the thickness must sit in the field matching the direction**
|
||||
— with `dtReverse` the *reverseThickness* argument is the one read; passing it as `normalThickness`
|
||||
leaves the wall at zero and КОМПАС silently extrudes a SOLID section instead of failing (caught only by
|
||||
the volume: a 82×10.5 plate came out full instead of a 1.2 mm frame). `outward` over a closed contour is the cheap equivalent of a 2D
|
||||
equidistant: it grows a rim around it (verified — a 20×20 square with 2 mm outward wall gives a 24×24
|
||||
frame). Building the same sketch twice (solid + outward wall) yields a silhouette with an offset border,
|
||||
which is how a lettered badge gets its backing plate without `ksEquidistant`.
|
||||
**Intersection trap (isolated by experiment, not guessed):** a thin-wall extrusion over a
|
||||
*multi-contour* sketch (a text line is ~10 closed contours, several with inner loops) returns
|
||||
`Create()==FALSE` when the wall **intersects an already existing body**. Bisected: empty part → OK;
|
||||
body present but not touched by the wall → OK; wall crosses the body → FAIL. Body count is
|
||||
irrelevant (2+ bodies with a plain rectangular contour build fine), so is the body's origin
|
||||
(sketch or `ElementaryBodies` primitive), and `chooseType` (tried `-1/0/1/2/3`) changes nothing —
|
||||
the earlier "multi-body" explanation was wrong. Practical rule: build the thin wall before the body
|
||||
it would cross; `primitive(result=union|subtract)` has no such restriction.
|
||||
|
||||
@@ -85,6 +85,12 @@ is a bug report, not a reason to work around it by hand. Three feedback channels
|
||||
Reading the sources, proposing patches, editing and rebuilding are all explicitly sanctioned — including
|
||||
asking for a session restart when a rebuilt server has to be picked up.
|
||||
|
||||
- **A spike proves a theory; the deliverable is built with MCP tools.** A throwaway dotnet project under
|
||||
`usecases/<case>/` (referencing `Kompas.Mcp.Core`) is a legitimate way to measure something or falsify a
|
||||
claim — but the final part/drawing must be produced by MCP tool calls. A runner bypasses the very layer
|
||||
under test (tool schemas, input parsing, answer shape, auto-validation), so "built by the runner" proves
|
||||
nothing about the server. Missing tools are the finding, not a reason to finish by hand; delete the
|
||||
probe project afterwards and carry its numbers into the case's `plan.md` and the skill.
|
||||
- **Skills are debugged like code.** `kompas-3d` and `kompas-fdm-design` are objects of revision, not fixed
|
||||
inputs. Edit them **only** in `plugin/skills/<name>/` (the source of truth — the other trees are junctions);
|
||||
a skill edit needs no rebuild but is only picked up by a *new* session.
|
||||
|
||||
@@ -61,14 +61,14 @@ kompas-mcp.exe --version # версия бинаря, КОМПАС для эт
|
||||
}
|
||||
```
|
||||
|
||||
## Инструменты (56)
|
||||
## Инструменты (58)
|
||||
|
||||
| Группа | Инструменты |
|
||||
|---|---|
|
||||
| System | `kompas_connect`, `kompas_status`, `kompas_set_visible`, `set_auto_validate` |
|
||||
| Documents | `document_create`, `document_open`, `document_save`, `document_close`, `document_active` |
|
||||
| Documents | `document_create`, `document_open`, `document_save`, `document_close`, `document_active`, `set_part_info` |
|
||||
| Sketch | `sketch_create`, `sketch_add`, `sketch_close` |
|
||||
| Features | `extrude`, `revolve`, `fillet_edge`, `chamfer_edge`, `shell`, `rib`, `sweep`, `loft`, `pattern`, `mirror`, `hole`, `draft`, `rebuild` |
|
||||
| Features | `extrude`, `revolve`, `primitive`, `fillet_edge`, `chamfer_edge`, `shell`, `rib`, `sweep`, `loft`, `pattern`, `mirror`, `hole`, `draft`, `rebuild` |
|
||||
| Edit | `move_face`, `split_solid_by_plane`, `move_body`, `boolean_union` |
|
||||
| Inspection | `describe_model`, `list_features`, `list_bodies`, `list_variables`, `measure` |
|
||||
| Vision | `model_snapshot` (PNG-снимок; сначала — `describe_model`) |
|
||||
@@ -85,6 +85,18 @@ kompas-mcp.exe --version # версия бинаря, КОМПАС для эт
|
||||
либо точкой в мировых координатах. Эскиз строится списком примитивов за один вызов:
|
||||
`sketch_create(plane|faceIndex, entities[])`.
|
||||
|
||||
Формообразование идёт двумя путями, и их сочетают: `primitive(kind=block|cylinder|sphere|cone,
|
||||
result=new|union|subtract|intersect)` строит тело по размерам без эскиза (в том числе вычитает
|
||||
карман или паз), а `sketch_create` + `extrude` нужен там, где контур сложный — текст, кривые,
|
||||
произвольный профиль.
|
||||
|
||||
Примитивы эскиза: `line`, `circle`, `rectangle`, `arc`, `arc3points`, `ellipse`, `polyline`,
|
||||
`polygon`, `spline`, `point`, `axis`, `text`. Надпись (`type=text` с `text`, `height`, `fontName`)
|
||||
сразу переводится в кривые, поэтому её можно выдавливать — так делаются логотипы и гравировка;
|
||||
в ответе возвращается фактическая длина строки, по ней надпись выравнивают. Параметры
|
||||
`extrude(thinThickness, thinSide)` превращают контур в стенку заданной толщины: `outward`
|
||||
наращивает её наружу и даёт ободок-эквидистанту вокруг контура (например, подложку под надпись).
|
||||
|
||||
### Типовой сценарий
|
||||
|
||||
`kompas_connect` → `document_create part` →
|
||||
|
||||
@@ -47,9 +47,9 @@ MCP-сервер даёт **общие** операции КОМПАС (эски
|
||||
**Реализованы (56 инструментов).** Инструмент назван по СМЫСЛУ операции, а вид задаётся параметром —
|
||||
не ищи отдельный инструмент под каждый вариант:
|
||||
|
||||
- *Система/документы:* `kompas_connect`, `kompas_set_visible`, `kompas_status`, `set_auto_validate`; `document_create|open|save|close|active` (`document_save(path)` — сохранить новый документ или копию, без `path` — на прежнее место).
|
||||
- *Эскиз (три инструмента вместо шестнадцати):* `sketch_create` — основание задаётся `plane` (+`offset`) ЛИБО `faceIndex` ЛИБО точкой `x,y,z`, а геометрия сразу списком `entities[{type: line|circle|rectangle|arc|arc3points|ellipse|polyline|polygon|spline|point|axis, …}]`; `sketch_add` — дополнить открытый эскиз; `sketch_close`.
|
||||
- *Формообразующие:* `extrude(mode=boss|cut)`, `revolve(mode=boss|cut)`, `fillet_edge`/`chamfer_edge` (список `edgeIndices` — одной операцией на все рёбра — либо точка), `shell`, `rib`, `sweep`, `loft`, `draft`, `rebuild`.
|
||||
- *Система/документы:* `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`.
|
||||
- *Формообразующие:* `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`.
|
||||
- *Отверстия:* `hole(type=simple|counterbore|countersink|conic)` — грань по `faceIndex` (центр грани) либо точкой.
|
||||
- *Массивы и зеркало:* `pattern(kind=linear|circular)`, `mirror` (без `featureIds` — всё тело, с ними — только эти операции).
|
||||
- *Прямое редактирование (без дерева, в т.ч. импортированная B-rep):* `move_face` (сдвинуть грань на N мм по нормали; грань — `faceIndex` или точка), `split_solid_by_plane` (рассечь тело плоскостью), `move_body` (сдвинуть тело на вектор), `boolean_union` (объединить тела).
|
||||
@@ -63,6 +63,43 @@ MCP-сервер даёт **общие** операции КОМПАС (эски
|
||||
Набор растёт от версии к версии — актуальный перечень с описаниями параметров отдаёт сам
|
||||
MCP-сервер; если инструмента под задачу нет, собирай результат из имеющихся общих операций.
|
||||
|
||||
## Два пути формообразования — выбирай по форме, а не по привычке
|
||||
|
||||
«Эскиз → выдавливание» — не единственный способ. `primitive` строит тело сразу по размерам, и это
|
||||
короче и надёжнее там, где форма призматическая:
|
||||
|
||||
| Форма | Чем строить |
|
||||
|---|---|
|
||||
| Плита, брусок, бобышка, штифт, цилиндрическая стойка | `primitive(kind=block\|cylinder)` — один вызов вместо «эскиз + выдавливание» |
|
||||
| Прямоугольный карман, паз, срез угла | `primitive(..., result=subtract)` — вычитание тела вместо `extrude(mode=cut)` по эскизу |
|
||||
| Скруглённые углы призмы | `primitive` + `fillet_edge` по рёбрам (скругление после, а не дуги в эскизе) |
|
||||
| Текст, кривые, произвольный контур, переменное сечение | ТОЛЬКО эскиз: `sketch_create(entities=[…])` + `extrude`/`revolve`/`loft`/`sweep` |
|
||||
| Тонкая стенка, ободок по контуру | эскиз + `extrude(thinThickness, thinSide)` |
|
||||
|
||||
Их **сочетают в одной детали**: корпусные объёмы — примитивами, сложные контуры — эскизами.
|
||||
Точка привязки у `block` — **угол** (не центр), у тел вращения — центр основания; размеры идут по
|
||||
осям X/Y/Z текущей системы координат.
|
||||
|
||||
- **Тонкую стенку по сложному контуру строй ДО того, как появится тело, которое она пересечёт.**
|
||||
`extrude(thinThickness=…)` по многоконтурному эскизу (надпись — это десяток замкнутых контуров с
|
||||
внутренними «дырками») ОТКАЗЫВАЕТ, если стенка пересекает уже построенное тело. Разложено
|
||||
экспериментом: в пустой детали — строится; тело есть, но стенка его не задевает — строится;
|
||||
стенка пересекает тело — отказ. Ни число тел, ни то, чем тело создано (эскизом или примитивом),
|
||||
роли не играют, а простой прямоугольный контур проходит и с пересечением. Поэтому на шильдике
|
||||
«плашка → буквы → кайма» падает, а «буквы → кайма → плашка `primitive(union)` → карман
|
||||
`primitive(subtract)`» проходит: примитивам пересечение безразлично.
|
||||
- **Скругления делай, пока рёбер мало** — сразу после примитивов их видно в `list_edges` наперечёт.
|
||||
Если момент упущен и рёбер сотни, бери рёбра ПО ТОЧКЕ: `fillet_edge(radius, x, y, z)` на углу
|
||||
известных координат — по одному ребру за вызов, зато без перебора индексов.
|
||||
- **Скругление не построится там, где ребро «съедено» соседним элементом.** У шильдика угол плашки,
|
||||
накрытый каймой букв, не скругляется ни R0.5, ни R0.3 — там уже нет ребра. Это нормальный ответ
|
||||
геометрии, а не ошибка вызова: проверь снимком, что угол вообще виден снаружи.
|
||||
- **Вычитание проверяется объёмом.** `primitive(result=subtract)` мимо тела КОМПАС считает удачей;
|
||||
инструмент это ловит и сообщает, но привычку сверять `describe_model(sections="mass")` не отменяет.
|
||||
- **`result=new` даёт ОТДЕЛЬНОЕ тело.** Оно объединится с остальными, только если последующая
|
||||
операция их пересечёт; иначе в детали останется несколько тел — проверяй `list_bodies` и при
|
||||
необходимости зови `boolean_union`.
|
||||
|
||||
## Базовый цикл (эскиз → операция → осмотр)
|
||||
|
||||
Опорный сценарий построения, проверен end-to-end:
|
||||
@@ -73,11 +110,50 @@ MCP-сервер; если инструмента под задачу нет, с
|
||||
4. `extrude(mode="boss", depth=…)` / `revolve(mode="boss", …)` → читаешь итог проверки прямо в ответе (правило 2).
|
||||
5. **Осмотр — структурно:** `describe_model` (паспорт: габарит, МЦХ, топология, дерево); нужен кусок — `describe_model(sections="box,mass")`. Снимок — только если нужен визуальный контроль.
|
||||
6. Итерация «на грани»: `list_faces` (при нужде `list_faces(index=N)` за подробностями) → `sketch_create(faceIndex=N, entities=[…])` → операция.
|
||||
7. **Назови деталь** — `set_part_info(name=…)` (и `marking`, если известно обозначение). Без этого в дереве
|
||||
стоит безликая «Деталь», и она же уедет в штамп чертежа и в спецификацию; `describe_model` специально
|
||||
отмечает деталь без наименования. Имя файла при сохранении этого НЕ заменяет — это разные свойства.
|
||||
|
||||
**Не разбивай построение на лишние вызовы.** Прямоугольник с четырьмя отверстиями — это ОДИН
|
||||
`sketch_create` со списком из пяти примитивов, а не шесть вызовов. Скругление восьми рёбер — один
|
||||
`fillet_edge(radius, edgeIndices=[…])`, а не восемь. Каждый лишний вызов — лишний шанс сбиться.
|
||||
|
||||
## Надписи, логотипы и рельеф
|
||||
|
||||
Надпись в эскизе — примитив `type=text` (`points:[{x,y}]` — левый край базовой линии, `text`,
|
||||
`height` в мм, `fontName` — любой установленный в системе шрифт, плюс `bold`/`italic`,
|
||||
`widthFactor` — сужение, `angle` — наклон строки). Она **сразу переводится в кривые**, поэтому
|
||||
выдавливается как обычный контур: гравировка — `extrude(mode="cut")`, выпуклые буквы — `mode="boss"`.
|
||||
|
||||
- **Позиционирование — в два прохода, длина строки лишь для прикидки.** Ответ содержит длину
|
||||
надписи в мм («надпись «OldMan» — длина 79.05 мм»), но это ширина С боковыми просветами, и
|
||||
насколько она больше самих глифов — зависит от шрифта: замерено 1–2 % у наборных (Zilla Slab,
|
||||
Bevan) и 7–9 % у скриптовых (Lobster, Pacifico). Поэтому: вставь надпись, выдави, прочитай
|
||||
**фактический** габарит `describe_model(sections="box")` и уже по нему пересчитай точку вставки.
|
||||
- **`height` — это высота ПРОПИСНОЙ (cap height), а не габарит строки.** Замер на Zilla Slab при
|
||||
`height=10`: «HH» → 9.97 мм, «hd» → 10.71 (восходящие выше прописной), «Hy» → 13.24 мм
|
||||
(нижний выносной уходит на −3.27). Считаешь компоновку — закладывай выносные отдельно.
|
||||
- **Ширина линейна** и по `height`, и по `widthFactor`: вписать строку в заданную ширину можно
|
||||
одним пересчётом, без подбора вслепую.
|
||||
- **Подложка под надпись — тонкой стенкой, а не вторым эскизом.** `extrude(..., thinThickness=1.2,
|
||||
thinSide="outward")` по контуру букв даёт ободок-эквидистанту вокруг них; выдавь ТОТ ЖЕ эскиз
|
||||
дважды — сплошным на высоту подложки и стенкой наружу — и получишь силуэт надписи с равномерной
|
||||
каймой. `inward` съедает контур внутрь (рамка по периметру плашки), `both` делает контур средней
|
||||
линией стенки. **Проверяй стенку по объёму:** если толщина не применилась, КОМПАС молча строит
|
||||
сплошное сечение — габарит при этом тот же, и по нему подмену не увидеть.
|
||||
- **Рельеф = разница глубин.** Основание 2 мм + буквы 3 мм от той же плоскости: буквы выступают
|
||||
на 1 мм. Не строй буквы «на грани основания» — из одного эскиза на базовой плоскости получается
|
||||
и то и другое, и рельеф не зависит от порядка операций.
|
||||
- **Проверяй объёмом, а не габаритом.** Буквы дают сотни NURBS-рёбер, и ни снимок, ни габарит не
|
||||
покажут, что операция построила не то: сравнивай ПРИРОСТ объёма (`describe_model(sections="mass")`)
|
||||
с прикидкой «площадь контура × высота». Именно так ловится молча не применившаяся тонкая стенка.
|
||||
- **Скруглять рельефный текст можно, но по одному-двум рёбрам, а не пакетом.** Проверено на
|
||||
Zilla Slab «AB» (203 ребра): одиночное ребро скругляется R0.1 и R0.2, а `fillet_edge` сразу по
|
||||
всем рёбрам отказывает при обоих радиусах (соседние скругления конфликтуют). Адресно выбрать
|
||||
«только верхние» рёбра пока нечем — `list_edges` не отдаёт ни координат, ни принадлежности грани.
|
||||
- **Шрифт обязан быть установлен в системе**, где работает КОМПАС: неизвестное имя молча
|
||||
подменяется другим шрифтом, и надпись «поедет» по ширине без единого сообщения об ошибке.
|
||||
|
||||
## Работа с импортом / сборками
|
||||
|
||||
Конвейер «импорт → разбор → извлечение детали → осмотр → модификация → экспорт»:
|
||||
@@ -118,6 +194,10 @@ MCP-сервер; если инструмента под задачу нет, с
|
||||
сверяй результат числами (`describe_model(sections="box,mass")`), снимок лишь при необходимости.
|
||||
- **МЦХ.** Объём/масса меняющейся геометрии — `describe_model(sections="mass")`; перед чтением после правок — `rebuild`.
|
||||
- **id эскизов/операций** недействительны после смены активного документа (create/open/close).
|
||||
- **Имя файла занимает открытый документ.** Если та же деталь уже открыта в КОМПАС (например, прошлая
|
||||
версия из этой же папки), `document_save(path)` по этому пути не пройдёт — КОМПАС не перезаписывает
|
||||
занятый файл. Освободить имя: `document_close(all=true)`. Проверяй, что файл на диске реально
|
||||
обновился (время изменения), особенно когда перестраиваешь деталь поверх прежней.
|
||||
- **Единицы — мм** (геометрия) и кг (масса). Локальные координаты эскиза ≠ мировые координаты модели.
|
||||
|
||||
## Открытые вопросы / границы
|
||||
|
||||
Reference in New Issue
Block a user