docs: спек drawing_add_diametral_dimension — диаметральный размер (API7)

Веха 2D-ЧЕРТЁЖ, инкремент 4. Спайк: (ISymbols2DContainer)view.DiametralDimensions.
Add → Xc/Yc/Radius/Angle(рад) → Update; NominalValue == диаметр (2R, проверено 30).
Angle экспонируется в градусах. Та же модель, что линейный размер.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 18:17:15 +03:00
parent cd76abd652
commit b6cd92b95c
@@ -0,0 +1,81 @@
# Дизайн: диаметральный размер на виде чертежа (drawing_add_diametral_dimension) через API7
**Дата:** 2026-05-27
**Статус:** спайк зелёный (значение=диаметр подтверждено); спроектировано; на ревью (Codex)
## Цель
Веха 2D-ЧЕРТЁЖ, инкремент 4. После линейного размера — **диаметральный** размер окружности на виде
(Ø для отверстий/цилиндров — частый случай конструкторского чертежа). Радиальный (с ветвями) и
угловой — следующие инкременты.
## Спайк: механизм подтверждён (НЕ разучивать)
Та же модель, что у линейного размера (`ISymbols2DContainer` QI от вида). Спайк
(`DrawingDiametralSpikeTests`, зелёный):
```
ISymbols2DContainer symbols = (ISymbols2DContainer)view; // QI от конкретного IView
IDiametralDimension dim = symbols.DiametralDimensions.Add();
dim.Xc = xc; dim.Yc = yc; // центр окружности (ЛОКАЛЬНАЯ СК вида, мм)
dim.Radius = radius; // радиус окружности (мм)
dim.Angle = angleRad; // направление выноски (РАДИАНЫ)
bool ok = dim.Update();
double value = ((IDimensionText)dim).NominalValue; // = ДИАМЕТР (2·Radius)
```
**Проверено:** `Xc=10,Yc=10,Radius=15,Angle=0.785``Update=True`, `Valid=True`,
`NominalValue == 30` (= диаметр = 2·Radius). `Angle` — в **радианах** (конвенция 2D-API КОМПАС;
для размера задаёт лишь направление выноски, на значение не влияет).
**Координаты** — локальная СК вида (как у линейного). Размер «свободный» (по Xc/Yc/Radius), без
ассоциативной привязки к геометрии (`BaseObject` не задаём — будущее).
## MCP-инструмент
| Инструмент | Параметры | Поведение |
|---|---|---|
| `drawing_add_diametral_dimension` | `xc,yc` (центр), `radius`, `angle=0` (°), `viewNumber=0` | Поставить диаметральный размер (Ø) окружности с центром (xc,yc) и радиусом `radius` (ЛОКАЛЬНАЯ СК вида, мм) на виде. `angle` — направление выноски в ГРАДУСАХ (внутри → радианы). `viewNumber`: 0 = первый/главный вид. Значение (диаметр = 2·radius) измеряется автоматически. Возвращает диаметр и номер вида. |
`angle` экспонируется в **градусах** (LLM-дружелюбно), внутри умножается на π/180.
## Архитектура
В существующем `DrawingService` (рядом с `AddLinearDimensionAsync`); переиспользуем `FindView`,
`DrawingDimensionResult`, паттерн отката.
- `DrawingService.AddDiametralDimensionAsync(viewNumber, xc, yc, radius, angleDeg, ct)`.
- Инструмент `drawing_add_diametral_dimension` в `DrawingTools`.
- Helper `GetViewDiametralDimensionCountAsync` (для теста — попадание в вид; размеры в
`ISymbols2DContainer`, не в `ObjectCount` — как выяснено для линейных).
## Валидация (чистые static, unit-тест)
- `DrawingValidation.RequireFiniteCoords(xc, yc, angleDeg)` (уже есть).
- `DrawingValidation.RequirePositiveRadius(double radius)` (новый) — конечный и `> 0`.
## Реализация
`AddDiametralDimensionCore`: валидация (coords + radius>0) → `FindView``(ISymbols2DContainer)view`
`DiametralDimensions.Add()` (null-check) → `Xc/Yc/Radius`, `Angle = angleDeg·π/180``Update()`
(FALSE → откат `dim.Delete` + ошибка) → `Valid` (false → откат) → `value = ((IDimensionText)dim).
NominalValue` (диаметр); если `≤ 0` → откат + ошибка → вернуть `DrawingDimensionResult { Value, ViewNumber }`.
RCW точечно не освобождаем (v2-2).
## Тестирование
### Unit (`DrawingValidationTests`)
- `RequirePositiveRadius` — бросает на 0/отрицательном/NaN/Infinity; пропускает положительный.
### Integration (`DrawingDiametralTests`)
1. **Значение = диаметр**: Radius=15 → `Value ≈ 30`.
2. **Попадание в вид**: `*DiametralDimensions.Count` целевого вида +1 (адресация по `viewNumber` из
`ViewNumbers`).
3. **Радиус ≤ 0**`ArgumentOutOfRangeException` (откат не нужен — до `Add`).
4. **Нет видов** → понятная ошибка.
(Сценарий 1 = промотированный спайк; спайк-файл удаляется.)
## Дальнейшее (вне спека)
- Радиальный размер (`RadialDimensions`, ветви), угловой; ассоциативная привязка к окружности вида
(`BaseObject`); рамка/формат листа.