Files
kompas3d-mcp/docs/superpowers/specs/2026-05-27-drawing-diametral-dimension-design.md
T
mikhail 910d120c8a feat: drawing_add_diametral_dimension — диаметральный размер на виде (API7)
Веха 2D-ЧЕРТЁЖ, инкремент 4. DrawingService.AddDiametralDimensionAsync:
(ISymbols2DContainer)view.DiametralDimensions.Add → Xc/Yc/Radius/Angle(рад) +
AutoNominalValue → Update → Valid → NominalValue (= диаметр 2R). angle в градусах
(DimensionAngles.ToRadians). Новый инструмент drawing_add_diametral_dimension.

Рефактор по ревью Codex: извлечён RequireSymbols2DContainer(viewNumber) (общий для
линейных/диаметральных размеров); AutoNominalValue выставляется явно (как у линейного);
DimensionType — COM-дефолт; ToRadians — чистый helper с unit-тестом.

Валидаторы: RequirePositiveRadius (новый). Тесты: +10 unit (ToRadians,
RequirePositiveRadius), +4 integration (DrawingDiametralTests: диаметр=2R, адресация
вида, radius<=0, нет видов). Итого 141 unit + 76 integration = 217.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 18:30:04 +03:00

7.1 KiB
Raw Blame History

Дизайн: диаметральный размер на виде чертежа (drawing_add_diametral_dimension) через API7

Дата: 2026-05-27 Статус: реализовано и проверено (4 интеграционных + unit, всего 217); ревью Codex спека учтено

Правки по ревью Codex

  • #5 ((IDimensionText)dim).AutoNominalValue = true выставляем явно (консистентно с линейным).
  • #7 извлечь RequireSymbols2DContainer(viewNumber) (= (ISymbols2DContainer)FindView(...)) — переиспользуют диаметральный путь и счётчики (радиальный — следующий, тот же паттерн).
  • #4 конверсия °→рад вынесена в чистый DimensionAngles.ToRadians(deg) + unit-тест (значение от угла не зависит → математику проверяем отдельно).
  • #2 DimensionType НЕ задаём — принимаем COM-дефолт (стандартный стиль; полярность bool не подтверждена, спайк с дефолтом дал Valid + верное значение). Зафиксировано комментарием.
  • #1 размер «свободный» (по Xc/Yc/Radius, без BaseObject) — как у линейного; LLM задаёт верные параметры окружности. Ассоциативная привязка — будущее. Отражено в описании инструмента.
  • #3 angle — любой конечный (направление выноски, КОМПАС нормализует); валидируем лишь конечность. #6 откат после Add() для диаметрального не форсируется (radius>0 → всегда Valid, value=2R>0); код отката идентичен протестированному линейному (zero-projection тест).

Цель

Веха 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.785Update=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)viewDiametralDimensions.Add() (null-check) → Xc/Yc/Radius, Angle = angleDeg·π/180Update() (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. Радиус ≤ 0ArgumentOutOfRangeException (откат не нужен — до Add).
  4. Нет видов → понятная ошибка.

(Сценарий 1 = промотированный спайк; спайк-файл удаляется.)

Дальнейшее (вне спека)

  • Радиальный размер (RadialDimensions, ветви), угловой; ассоциативная привязка к окружности вида (BaseObject); рамка/формат листа.