docs: спек drawing_add_linear_dimension — линейный размер на виде (API7)
Веха 2D-ЧЕРТЁЖ, инкремент 3. Спайк подтвердил: (ISymbols2DContainer)view QI → LineDimensions.Add → X1..Y3 (локальная СК вида) + Orientation + Update; авто-значение ((IDimensionText)dim).NominalValue == расстояние (проверено 40). Плюс: DrawingViewsResult += ViewNumbers (адресация видов, закрывает замечание Codex из ревью видов). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
# Дизайн: линейный размер на виде чертежа (drawing_add_linear_dimension) через API7
|
||||
|
||||
**Дата:** 2026-05-27
|
||||
**Статус:** спайк зелёный (механизм + авто-значение подтверждены); спроектировано; на ревью (Codex)
|
||||
|
||||
## Цель
|
||||
|
||||
Веха 2D-ЧЕРТЁЖ, инкремент 3 (размеры). После видов и основной надписи — **линейный размер** на
|
||||
ассоциативном виде: между двумя точками (в локальной СК вида) с авто-измерением длины. Размеры —
|
||||
самый ценный элемент оформления (несут размерную информацию). Начинаем с линейного
|
||||
(горизонтальный/вертикальный/параллельный); диаметральные/радиальные/угловые — далее.
|
||||
|
||||
## Спайк: механизм подтверждён вживую (НЕ разучивать)
|
||||
|
||||
Спайк (`DrawingDimensionSpikeTests`, зелёный) подтвердил путь API7:
|
||||
|
||||
```
|
||||
IView view = первый вид с Number != 0; // системный вид — #0, пропускаем
|
||||
ISymbols2DContainer symbols = (ISymbols2DContainer)view; // COM-QI ОТ ВИДА (не от документа!)
|
||||
ILineDimension dim = symbols.LineDimensions.Add();
|
||||
dim.X1=x1; dim.Y1=y1; dim.X2=x2; dim.Y2=y2; // выносные точки (ЛОКАЛЬНАЯ СК вида, мм)
|
||||
dim.X3=x3; dim.Y3=y3; // положение размерной линии
|
||||
dim.Orientation = ksLinDHorizontal; // 0=Parallel / 1=Horizontal / 2=Vertical
|
||||
bool ok = dim.Update();
|
||||
double value = ((IDimensionText)dim).NominalValue; // авто-измеренное значение (мм)
|
||||
```
|
||||
|
||||
**Проверено (вид спереди коробки 40×30×20):** размер (0,0)-(40,0) горизонтальный →
|
||||
`Update()=True`, `Valid=True`, `NominalValue == 40` (авто `|X2-X1|`), `view.ObjectCount` вырос.
|
||||
|
||||
**Подтверждённые факты:**
|
||||
- **`ISymbols2DContainer` берётся COM-QI ОТ КОНКРЕТНОГО `IView`** — размер попадает именно в этот
|
||||
вид (не нужен `Current=true`). (Аналогично 3D: `part`→`IModelContainer`.)
|
||||
- **Координаты X1..Y3 — ЛОКАЛЬНАЯ СК вида** (= координаты модели на плоскости вида, при масштабе
|
||||
1:1 совпадают с мм модели). НЕ координаты листа.
|
||||
- **`AutoNominalValue=true` по умолчанию** → `NominalValue` = расстояние между точками
|
||||
(горизонтальный: `|X2-X1|`, вертикальный: `|Y2-Y1|`, параллельный: реальная длина). Значение
|
||||
читается `((IDimensionText)dim).NominalValue` (QI).
|
||||
- `Orientation` (`ksLineDimensionOrientationEnum`): `ksLinDParallel=0`, `ksLinDHorizontal=1`,
|
||||
`ksLinDVertical=2` (в `Kompas6Constants`).
|
||||
- `Update()` обязателен; перестроение документа не нужно.
|
||||
|
||||
## Адресация вида (часть инкремента)
|
||||
|
||||
Чтобы указать, НА КАКОМ виде ставить размер, нужен его `Number`. Сейчас
|
||||
`drawing_create_standard_views` возвращает только `{Created, Total}`. **Расширяем `DrawingViewsResult`
|
||||
полем `ViewNumbers` (номера созданных видов)** — уже собираются как `newViews` в
|
||||
`CreateStandardViewsCore` (тривиально: `newViews.Select(v => v.Number)`). Это закрывает замечание
|
||||
Codex из ревью видов (#10: «нет ссылок на созданные виды») и делает размеры адресуемыми.
|
||||
|
||||
## MCP-инструмент
|
||||
|
||||
| Инструмент | Параметры | Поведение |
|
||||
|---|---|---|
|
||||
| `drawing_add_linear_dimension` | `x1,y1,x2,y2` (выносные точки), `x3,y3` (положение размерной линии), `orientation="horizontal"`, `viewNumber=0` | Поставить линейный размер на виде активного чертежа между точками (x1,y1)-(x2,y2) в ЛОКАЛЬНОЙ СК вида (мм). `orientation`: horizontal/vertical/parallel. `viewNumber`: номер вида (0 = первый ассоциативный/главный). Значение измеряется автоматически. Возвращает измеренное значение и номер вида. |
|
||||
|
||||
Контракт: активный документ — чертёж; на чертеже есть хотя бы один ассоциативный вид. Координаты —
|
||||
локальные вида (см. выше). `drawing_create_standard_views` возвращает `ViewNumbers` для адресации.
|
||||
|
||||
## Архитектура
|
||||
|
||||
В существующем `DrawingService`. Свой enum `DimensionOrientation` (паттерн `MateType`/`StampField`).
|
||||
|
||||
- `src/Kompas.Mcp.Core/Drawings/DimensionOrientation.cs` — enum + static `DimensionOrientations`
|
||||
(`Parse(string)`, `ToKompas` → `ksLineDimensionOrientationEnum`).
|
||||
- `DrawingService.AddLinearDimensionAsync(viewNumber, x1,y1,x2,y2,x3,y3, DimensionOrientation, ct)`.
|
||||
- `DrawingViewsResult` += `IReadOnlyList<int> ViewNumbers`.
|
||||
- Инструмент `drawing_add_linear_dimension` в `DrawingTools` (orientation строкой → Parse).
|
||||
|
||||
## Валидация (чистые static, unit-тест)
|
||||
|
||||
- `DimensionOrientations.Parse` — horizontal/vertical/parallel (+рус.) → enum; иначе `ArgumentException`.
|
||||
- `DimensionOrientations.ToKompas` — enum → `ksLineDimensionOrientationEnum` (0/1/2).
|
||||
- `DrawingValidation.RequireFiniteCoords(params)` — координаты конечны (NaN/Infinity → ошибка).
|
||||
|
||||
## Реализация
|
||||
|
||||
`AddLinearDimensionCore`: валидация координат + orientation → `RequireActiveDrawing` → найти вид
|
||||
(`viewNumber<=0` → первый с `Number!=0`; иначе по `Number`, ошибка если нет) → `(ISymbols2DContainer)view`
|
||||
→ `LineDimensions.Add()` → задать X1..Y3 + Orientation → `Update()` (FALSE → откат `dim.Delete()` +
|
||||
ошибка) → проверить `dim.Valid` (false → откат + ошибка) → вернуть `AddedDimension { Value =
|
||||
((IDimensionText)dim).NominalValue, ViewNumber = view.Number }`. RCW точечно не освобождаем (v2-2).
|
||||
|
||||
## Тестирование
|
||||
|
||||
### Unit (`DimensionOrientationsTests`)
|
||||
- `Parse` — horizontal/vertical/parallel и рус.-синонимы → enum; бросает на мусоре.
|
||||
- `ToKompas` — каждый → 1/2/0.
|
||||
- `RequireFiniteCoords` — бросает на NaN/Infinity; пропускает конечные.
|
||||
|
||||
### Integration (`DrawingDimensionTests`)
|
||||
Паттерн: построить деталь → сохранить → создать чертёж → стандартные виды → размер → проверить →
|
||||
`finally CloseAsync` (база `IntegrationTestBase`).
|
||||
1. **Горизонтальный** (0,0)-(40,0) → `Value ≈ 40`; `view.ObjectCount` вырос.
|
||||
2. **Вертикальный** (0,0)-(0,20) → `Value ≈ 20`.
|
||||
3. **Адресация вида**: `CreateStandardViewsAsync` вернул `ViewNumbers` (3 шт); размер с конкретным
|
||||
`viewNumber` ставится в этот вид.
|
||||
4. **Нет видов**: чертёж без видов → понятная ошибка.
|
||||
|
||||
(Сценарий 1 = промотированный спайк; спайк-файл удаляется.)
|
||||
|
||||
## Дальнейшее (вне спека)
|
||||
- Диаметральные/радиальные/угловые размеры; привязка к геометрии вида (ассоциативно, `BaseObject`);
|
||||
допуски/обозначения; рамка/формат листа.
|
||||
Reference in New Issue
Block a user