feat(feature): кинематическая операция (sweep)
SweepAsync (o3d_baseEvolution): SetSketch(профиль) + PathPartArray(траектория) + sketchShiftType=0 + SetThinParam(false). Инструмент sweep в FeatureTools. Integration: окружность R5 по вертикали 50 → цилиндр ~3927 мм³. loft отложен — требует offset-плоскости (пакет E) для параллельных сечений. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,55 @@
|
||||
# Дизайн: пакет B (шаг 3) — кинематическая операция (sweep)
|
||||
|
||||
**Дата:** 2026-05-26
|
||||
**Статус:** на ревью (автономный режим; ревьюер — Codex)
|
||||
|
||||
## Цель
|
||||
|
||||
Добавить формообразующую **кинематическую операцию** (sweep) — переместить профиль вдоль
|
||||
траектории, образуя тело. Третий шаг пакета B. Один MCP-инструмент `sweep`. В отличие от
|
||||
loft (требует параллельные сечения → offset-плоскость, пакет E), sweep естественно работает с
|
||||
базовыми плоскостями: профиль на одной, траектория на перпендикулярной.
|
||||
|
||||
## Сигнатуры COM (рефлексия interop)
|
||||
|
||||
```
|
||||
Obj3dType.o3d_baseEvolution = 45
|
||||
ksBaseEvolutionDefinition:
|
||||
short sketchShiftType // тип переноса сечения вдоль пути
|
||||
bool SetSketch(object) // профиль (сечение)
|
||||
object PathPartArray() // ksEntityCollection сегментов траектории
|
||||
bool SetThinParam(bool thin, short thinType, double normal, double reverse)
|
||||
```
|
||||
|
||||
**Паттерн:** `NewEntity(o3d_baseEvolution)` → `GetDefinition()` → `SetSketch(профиль)` →
|
||||
`PathPartArray().Add(траектория)` → `sketchShiftType` → `SetThinParam(false,…)` (сплошное) →
|
||||
`Create()`.
|
||||
|
||||
## Новый MCP-инструмент (группа Feature)
|
||||
|
||||
| Инструмент | Параметры | Поведение |
|
||||
|---|---|---|
|
||||
| `sweep` | `profileSketchId: int`, `pathSketchId: int` | Кинематическая операция: переместить замкнутый профиль `profileSketchId` вдоль траектории `pathSketchId`, образуя сплошное тело. Профиль и траектория — на разных (обычно перпендикулярных) плоскостях; начало траектории совпадает с плоскостью профиля. Возвращает id операции. |
|
||||
|
||||
**Решения (YAGNI):** тонкостенный режим (`thin`) и `sketchShiftType` наружу не выставляем —
|
||||
сплошное тело, `sketchShiftType=0` (перенос с сохранением угла). Можно расширить позже.
|
||||
|
||||
## Реализация
|
||||
|
||||
- **Метод** `SweepAsync(int profileSketchId, int pathSketchId, CancellationToken)` в
|
||||
`PartModeler.Features.cs`. Оба эскиза закрываются перед операцией (`CloseSketchCore`);
|
||||
берутся `sketch.Entity` из реестра. `profileSketchId == pathSketchId` → `ArgumentException`.
|
||||
Возвращает id операции.
|
||||
- **Инструмент** `sweep` в `FeatureTools.cs`.
|
||||
- `PathPartArray()` проверяется на null (`as ksEntityCollection ?? throw`).
|
||||
- Транзитный `ksBaseEvolutionDefinition` не освобождается — консистентно (долг v2-2).
|
||||
- `Create()==FALSE` → `InvalidOperationException` (профиль/траектория несовместимы: начало пути
|
||||
не на плоскости профиля, самопересечение?).
|
||||
|
||||
## Тестирование
|
||||
|
||||
**Integration** (`FeatureOpsTests`): профиль — окружность R5 на XOY (центр 0,0); траектория —
|
||||
вертикальный отрезок на XOZ `(0,0)→(0,50)` (начинается в центре профиля, идёт по +Z) →
|
||||
`SweepAsync(profile, path)` → цилиндр R5×H50, объём `π·25·50 ≈ 3927 мм³`. Проверка
|
||||
`InRange(volume, 3927·0.95, 3927·1.05)`. Если `sketchShiftType=0` не строит — перебрать тип
|
||||
(0/1) по факту, сохранив проверку объёма.
|
||||
Reference in New Issue
Block a user