diff --git a/docs/superpowers/specs/2026-05-26-pattern-mirror-design.md b/docs/superpowers/specs/2026-05-26-pattern-mirror-design.md index 3376526..0f2bebd 100644 --- a/docs/superpowers/specs/2026-05-26-pattern-mirror-design.md +++ b/docs/superpowers/specs/2026-05-26-pattern-mirror-design.md @@ -70,11 +70,21 @@ ksMirrorCopyAllDefinition: // зеркало тела( - **Линейный массив — 1D** (одна ось): `SetAxis1` + `SetCopyParamAlongAxis(true,…)`, `count2=1` (второе направление выключено). 2D-сетку добавим позже при необходимости. - `factor=false` (шаг между соседними — интуитивнее для пользователя). -- Круговой `step`: задаём явный угловой шаг (°). Дефолт инструмента не подставляем — пусть - агент передаёт (например 90 для 4 шт). `factor=false`. -- `mirror_body` использует `ksMirrorCopyAllDefinition` без `ChooseBodies` (по умолчанию все тела). +- **Круговой — задаём свойства напрямую** (`SetCopyParamAlongDir` неоднозначен: `dir`/radial vs + annular): `count1=1` (радиально — один «ряд»), `count2=count` (кольцевое — N вокруг оси), + `step2=step` (°), `factor2=false`, `inverce=reverse`. Угловой шаг задаёт агент (например 90). +- `mirror_body` использует `ksMirrorCopyAllDefinition` + `SetPlane`. В API5-interop у определения + **нет** `SaveInitialObjects` (по рефлексии — только `ChooseBodies/Get/SetPlane`); поведение + «оригинал + зеркало» проверяем эмпирически. `ChooseBodies` дорефлексировать в инкременте 3 + (для односложного тела, вероятно, не требуется; если `Create` упадёт — выставить `ksAllBodies`). - `geomArray` дефолт `false` (полное копирование операции — надёжнее для несложных тел). +### Открытые API-тонкости (проверяются интеграционными тестами) +- `count` включает оригинал — подтверждается тестом (count=3 → 3 экз.). Если нет — поправить. +- `count2=1` действительно выключает 2-е направление линейного массива. +- Круговой: `count2=count`/`count1=1` даёт чистый круговой массив (без радиального дубля). +- `mirror_body` оставляет исходное тело (а не заменяет его). + ## Реализация - **Enum** `CoordinateAxis { X, Y, Z }` + `CoordinateAxes.ToObj3dType/Parse` — новый файл @@ -104,11 +114,15 @@ ksMirrorCopyAllDefinition: // зеркало тела( 1. **linear_pattern**: цилиндр R5×H10 в центре (V₁≈785 мм³) → `linear_pattern([cyl], X, 3, 30)` → 3 непересекающихся цилиндра → V≈3·785=2356 (`InRange ±5%`); габарит X≈70 (от −5 до 65). -2. **circular_pattern**: цилиндр R3×H10 со смещением (центр (20,0)) → `circular_pattern([cyl], Z, 4, 90)` → - 4 цилиндра по кругу R20 → V≈4·283=1131 (`±5%`); габарит X≈Y≈46 (от −23 до 23). -3. **mirror_operation**: цилиндр R3×H10 центр (20,0) → `mirror_operation([cyl], YOZ)` → копия в +2. **circular_pattern**: цилиндр R3×H10 со смещением (центр (20,0)) → `circular_pattern([cyl], Z, 3, 90)` → + 3 цилиндра в (20,0),(0,20),(−20,0) (count=3, несимметрично → осмысленный поворот, не «полный + круг») → V≈3·283=849 (`±5%`); габарит X≈46 (от −23 до 23), SizeY≈26 (от −3 до 23). +3. **mirror_operation** (две исходные операции — проверяет заполнение `ksEntityCollection`): + цилиндр R3 центр (20,0) + цилиндр R2 центр (10,0), оба H10 → `mirror_operation([c1,c2], YOZ)` → + копии в (−20,0),(−10,0) → V≈2·(283+125.7)=817 (`±5%`); габарит X≈46. +4. **mirror_body**: цилиндр R3×H10 центр (20,0) → `mirror_body(YOZ)` → оригинал + зеркало в (−20,0) → V≈2·283=565 (`±5%`); габарит X≈46. -4. **mirror_body**: то же тело → `mirror_body(YOZ)` → симметричная пара, габарит X≈46, V≈2·283. -Ожидаемые объёмы считаем аналитически, сверяем `InRange ±5%`. Если `count` НЕ включает -оригинал или направление шага иное — корректируем по факту, сохранив суть проверки. +Ожидаемые объёмы считаем аналитически, сверяем `InRange ±5%`. Открытые тонкости (count вкл. +оригинал; count2=1; круговой count1=1/count2=N; mirror_body оставляет оригинал) — проверяются +этими тестами; при расхождении корректируем по факту, сохранив суть проверки.