From 46648f7635868d336a4cc0b8e3d0dcb6d45ca41b Mon Sep 17 00:00:00 2001 From: Shahovalov MIkhail Date: Wed, 27 May 2026 14:09:43 +0300 Subject: [PATCH] =?UTF-8?q?docs:=20=D1=81=D0=BF=D0=B5=D0=BA=20drawing=5Fcr?= =?UTF-8?q?eate=5Fstandard=5Fviews=20=E2=80=94=20=D1=81=D1=82=D0=B0=D0=BD?= =?UTF-8?q?=D0=B4=D0=B0=D1=80=D1=82=D0=BD=D1=8B=D0=B5=20=D0=B2=D0=B8=D0=B4?= =?UTF-8?q?=D1=8B=20=D1=87=D0=B5=D1=80=D1=82=D0=B5=D0=B6=D0=B0=20(API7)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Веха 2 (2D-ЧЕРТЁЖ), инкремент 1. Механизм подтверждён спайком: doc2d. ViewsAndLayersManager.Views.AddStandartViews(path, "#Спереди", {1,3,5}, ...); object[]→SAFEARRAY VT_I4 ОК, 3 вида создаются (Count 1→4). Новый DrawingService. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...026-05-27-drawing-standard-views-design.md | 101 ++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-27-drawing-standard-views-design.md diff --git a/docs/superpowers/specs/2026-05-27-drawing-standard-views-design.md b/docs/superpowers/specs/2026-05-27-drawing-standard-views-design.md new file mode 100644 index 0000000..8f29851 --- /dev/null +++ b/docs/superpowers/specs/2026-05-27-drawing-standard-views-design.md @@ -0,0 +1,101 @@ +# Дизайн: стандартные виды чертежа (drawing_create_standard_views) через API7 + +**Дата:** 2026-05-27 +**Статус:** спайк зелёный (механизм подтверждён вживую); спроектировано; на ревью (Codex) + +## Цель + +Веха 2 — **2D-ЧЕРТЁЖ** (новый класс функционала после деталей и сборок). Инкремент 1: создать на +активном чертеже **стандартные ассоциативные виды** (спереди/сверху/слева) по сохранённой 3D-модели +`.m3d`/`.a3d`. Это фундамент чертежа — без видов лист пуст. Чертёж проверяется не объёмом, а +**числом созданных видов**. + +## Спайк: механизм подтверждён вживую (НЕ разучивать) + +Спайк (`DrawingSpikeTests`, зелёный) подтвердил путь API7: + +``` +IKompasDocument2D doc2d = (IKompasDocument2D)app.ActiveDocument; // активный чертёж +IViews views = doc2d.ViewsAndLayersManager.Views; // COM-свойства (не QI) +object[] projTypes = { 1, 3, 5 }; // ksPtFront=1, ksPtUp=3, ksPtLeft=5 (SAFEARRAY VT_I4) +bool ok = views.AddStandartViews(path, "#Спереди", projTypes, X:100, Y:150, Scale:1.0, DX:20, DY:20); +int count = views.Count; +``` + +**Проверенные факты:** +- `object[] { 1, 3, 5 }` **маршалится в SAFEARRAY VT_I4 без проблем** (риск из ревью SDK снят). +- Новый чертёж стартует с `Views.Count == 1` (системный вид #0). После `AddStandartViews` с тремя + кодами проекций `Count == 4` → **создано ровно 3 вида** (спереди/сверху/слева). `ok == True`. +- `ProjectionName = "#Спереди"` — ориентация главного вида (стандартное имя проекции 3D-модели). +- `IKompasDocument2D` напрямую (без QI к `IKompasDocument2D1`) даёт `ViewsAndLayersManager.Views` + (подтверждено рефлексией interop — отличие от ревью SDK). +- Явный rebuild/save после `AddStandartViews` НЕ нужен — виды уже в документе (`Count` сразу 4). + +**Параметры `AddStandartViews(FileName, ProjectionName, ProjectionsTypes, X, Y, Scale, DX, DY)`:** +- `FileName` — путь к `.m3d`/`.a3d`. +- `ProjectionName` — ориентация главного вида (`"#Спереди"`). +- `ProjectionsTypes` — `SAFEARRAY VT_I4` кодов `ksRelativeProjectionTypeEnum`: `ksPtFront=1`, + `ksPtRear=2`, `ksPtUp=3`, `ksPtDown=4`, `ksPtLeft=5`, `ksPtRight=6`, `ksPtIsoXYZ=7`. +- `X, Y` — точка привязки главного вида на листе, мм. +- `Scale` — масштаб (1.0 = 1:1). +- `DX, DY` — зазоры между видами, мм. Возврат: `bool` (успех). + +## Архитектура + +Новый класс (как сборки — отдельный от `PartModeler`). Сервис `DrawingService` (API7), инструменты +`DrawingTools`, namespace `Kompas.Mcp.Core.Drawings`. + +- `src/Kompas.Mcp.Core/Drawings/DrawingService.cs` — сервис. +- `src/Kompas.Mcp.Core/Drawings/DrawingValidation.cs` — чистые static-валидаторы (unit). +- `src/Kompas.Mcp.Host/Tools/DrawingTools.cs` — MCP-инструмент. +- DI: `AddSingleton()` в `Program.cs`. + +## MCP-инструмент + +| Инструмент | Параметры | Поведение | +|---|---|---| +| `drawing_create_standard_views` | `partFilePath: string`, `scale=1.0` | На активном чертеже создать стандартные ассоциативные виды (спереди/сверху/слева) сохранённой детали/сборки. Возвращает число созданных видов. | + +Контракт: активный документ — чертёж (`ksDocumentDrawing`); файл модели существует. Набор видов +фиксирован (спереди+сверху+слева, 3 вида); позиция/зазоры — дефолты (X=100, Y=150, DX=20, DY=20 мм). +Выбор набора видов / позиции / изометрии — будущие инкременты (YAGNI). + +## Валидация (чистые static, unit-тест) + +`DrawingValidation`: +- `NormalizeModelPath(string? path)` — `Trim` → непустота → расширение `.m3d`/`.a3d` → `Path.GetFullPath`. +- `RequireScale(double scale)` — конечный и `> 0`. + +`File.Exists` — в сервисе (`FileNotFoundException` с абсолютным путём). + +## Проверка активного документа + +`RequireActiveDrawing()` — раздельные ошибки: нет документа / тип != `ksDocumentDrawing` / не +приводится к `IKompasDocument2D`. + +## Реализация + +`CreateStandardViewsAsync(partFilePath, scale, ct)` — на STA-потоке: валидация (`NormalizeModelPath`, +`RequireScale`) → `File.Exists` → `RequireActiveDrawing` → `views.Count` (before) → +`AddStandartViews(path, "#Спереди", {1,3,5}, 100, 150, scale, 20, 20)` (результат проверяем: FALSE → +ошибка) → `created = views.Count - before` (ожидаем 3; если 0 — ошибка «виды не созданы»). Возврат — +число созданных видов. Транзитные RCW не освобождаем точечно (долг v2-2). + +## Тестирование + +### Unit (`DrawingValidationTests`) +- `NormalizeModelPath` — бросает на пустом/чужом расширении (`.step`); принимает `.m3d`/`.a3d` + (регистр, пробелы), возвращает абсолютный путь. +- `RequireScale` — бросает на 0/отрицательном/NaN/Infinity; принимает положительный. + +### Integration (`DrawingTests`) +Паттерн: построить деталь 40×30×20 → `SaveAsAsync(.m3d)` → проверить файл → `CloseAsync` → создать +чертёж → `CreateStandardViewsAsync` → проверить → `finally CloseAsync` (база `IntegrationTestBase`). +1. **Создание видов**: `AddStandartViews` → возврат `== 3`; `Views.Count` вырос на 3 (с 1 до 4). +2. **Не-чертёж**: активный документ — деталь → `CreateStandardViewsAsync` бросает (понятная ошибка). + +(Сценарий 1 = промотированный спайк; спайк-файл удаляется.) + +## Дальнейшее (вне спека) +- Выбор набора видов (+изометрия, +сечения), позиция/масштаб листа, размеры/обозначения на видах, + рамка/основная надпись.