Files
mikhail 205a4b02de feat: уклон граней (draft) через API5 — ksInclineDefinition o3d_incline=42
- ВОПРЕКИ прежнему предположению: уклон ЕСТЬ в API5 (операция Incline, не Draft) →
  стандартный паттерн PartModeler, регистрируется в _features (массивы/зеркало применимы)
- DraftAsync: FaceArray().Add(грани) + SetPlane(нейтральная коорд. плоскость) + angle + direction
- ЭМПИРИЧЕСКИ: direction=false=расширение, true=сужение (обратно справке) → маппинг !outward
- инструмент draft (faceIndices, neutralPlane, angle 0..90, outward); валидация угла и индексов
- интеграционный тест: 4 боковые грани коробки → усечённая пирамида (объём ±10%)
- 105 тестов; спек docs/superpowers/specs/2026-05-27-draft-design.md
2026-05-27 10:23:16 +03:00

5.0 KiB
Raw Permalink Blame History

Дизайн: уклон граней (draft / incline) через API5

Дата: 2026-05-27 Статус: реализовано и проверено (тест зелёный); на ревью (ревьюер — Codex)

Цель

Добавить операцию «Уклон» (draft) — наклонить грани на угол относительно нейтральной (опорной) плоскости. Приоритет 1 текущей сессии.

Ключевой факт: уклон ЕСТЬ в API5 (вопреки прежнему предположению)

Память kompas-formative-features-api5 ошибочно считала draft недоступным в API5 — она искала тип со словом Draft, но операция называется «Уклон» = Incline. Рефлексия подтвердила: Obj3dType.o3d_incline=42 + ksInclineDefinition есть в Kompas6API5.dll. Это стандартный API5-паттерн (как shell/rib/fillet) — НЕ нужен API7. Плюс: операция регистрируется в реестре _features, значит массивы/зеркало пакета C к ней применимы.

o3d_DraftFromEdges=644 (API7 IDraftFromEdges) — это ДРУГАЯ операция «уклон от базовой линии» (v22), без нейтральной плоскости. Для обычного уклона граней используем IIncline/ksInclineDefinition.

Сигнатуры (рефлексия interop + справка)

Obj3dType.o3d_incline = 42
ksInclineDefinition:
    double angle              // угол уклона (градусы)
    bool   direction          // ЭМПИРИЧЕСКИ: false=расширение, true=сужение (обратно справке!)
    object FaceArray()        // ksEntityCollection уклоняемых граней (Add по одной)
    bool   SetPlane(object)   // нейтральная (опорная) плоскость — ksEntity
    object GetPlane()

Паттерн: NewEntity(o3d_incline)GetDefinition()FaceArray().Add(face) (по граням) → SetPlane(нейтральная)angledirectionCreate() → регистрация в _features.

Нейтральная плоскость — сечение тела в ней остаётся неизменным; грани уклоняются вокруг линии пересечения с ней. На первом этапе — базовая координатная плоскость (XOY/XOZ/YOZ).

Направление (важно): в interop direction=false даёт расширение, trueсужение (проверено объёмом; обратно тексту справки). Контракт инструмента: outward (true=расширение), маппинг def.direction = !outward.

MCP-инструмент (группа Feature)

Инструмент Параметры Поведение
draft faceIndices: int[], neutralPlane: "XOY"|"XOZ"|"YOZ", angle: double, outward=false Уклон граней faceIndices (из list_faces) на angle° относительно нейтральной координатной плоскости. outward — расширение/сужение. Возвращает id.

Решения (YAGNI): нейтральная плоскость — только координатная (как mirror_operation); уклон от ребра (IDraftFromEdges) — отдельная задача позже. Грани — по стабильному индексу из list_faces.

Реализация

  • Метод DraftAsync(IReadOnlyList<int> faceIndices, BasePlane neutralPlane, double angle, bool outward, ct) в PartModeler.Features.cs. Валидация: angle конечен и в (0; 90); faceIndices не пуст, Distinct; диапазон всех индексов проверяется до мутации (SelectFaceByIndex).
  • Инструмент draft в FeatureTools.cs (neutralPlane парсится BasePlanes.Parse).
  • Транзитные RCW не освобождаем точечно — консистентно (долг v2-2).
  • Create()==FALSEInvalidOperationException (грань не граничит с нейтральной плоскостью?).

Тестирование (Integration, FeatureOpsTests)

Уклон: коробка 40×40×20 (низ на Z=0) → 4 боковые грани (площадь 800) под уклон 10° внутрь (outward=false) относительно XOY → усечённая пирамида: верх ≈ 402·20·tan10°=32.95; V = (20/3)(1600+1085.5+√(1600·1085.5)) ≈ 26689 мм³; InRange(after, ±10%) и after < before. ✓ Боковые грани выбираются из ListFaces по площади 800 (тип plane).