docs: спек assembly_add_mate — сопряжения компонентов (API7), спайк зелёный
Веха СБОРКИ, инкремент 2. Механизм подтверждён спайком: mates.Add(type) + BaseObject1/2 (грани через FindObjectsByPoint FirstLevel=false) + Update + RebuildModel. Coincidence (ширина 120→40), Distance(30) (→70). Свой enum MateType. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,105 @@
|
||||
# Дизайн: сопряжение компонентов сборки (assembly_add_mate) через API7
|
||||
|
||||
**Дата:** 2026-05-27
|
||||
**Статус:** спайк зелёный (механизм подтверждён вживую); спроектировано; на ревью (Codex)
|
||||
|
||||
## Цель
|
||||
|
||||
Веха СБОРКИ, инкремент 2. После вставки компонентов (`assembly_add_component`, инкремент 1) —
|
||||
**сопряжения**: наложить связь между гранями двух компонентов (совпадение / на расстоянии),
|
||||
чтобы решатель сборки спозиционировал компоненты относительно друг друга. Это вторая
|
||||
половина минимально полезного цикла сборки (вставить → связать).
|
||||
|
||||
## Спайк: механизм подтверждён вживую (НЕ разучивать)
|
||||
|
||||
Спайк (`AssemblyMateSpikeTests`, оба теста зелёные) подтвердил полный путь API7:
|
||||
|
||||
```
|
||||
IPart7 top = (IPart7)doc3d.TopPart; // активная сборка
|
||||
IMateConstraints3D mates = top.MateConstraints; // COM-свойство (не QI)
|
||||
IMateConstraint3D mate = mates.Add(MateConstraintType); // напр. mc_Coincidence=0 / mc_Distance=5
|
||||
mate.BaseObject1 = (IModelObject)face1; // грань компонента 1
|
||||
mate.BaseObject2 = (IModelObject)face2; // грань компонента 2
|
||||
if (distance|angle) mate.ParamValue = value; // зазор (мм) / угол (°)
|
||||
bool ok = mate.Update(); // наложить сопряжение
|
||||
top.RebuildModel(true); // применить к геометрии
|
||||
```
|
||||
|
||||
**Выбор граней компонентов:** `top.FindObjectsByPoint(x, y, z, FirstLevel=false)` — `FirstLevel=false`
|
||||
заставляет спуститься В компоненты и вернуть их грань в **контексте сборки** (мировые координаты с
|
||||
учётом placement компонента). Это именно тот `IModelObject`, который нужен решателю сопряжений.
|
||||
|
||||
**Проверенные результаты (2 куба 20³, A в нуле x[0,20], B со сдвигом +100 x[100,120]):**
|
||||
- **Совпадение** (`mc_Coincidence`) +X грани A (20,10,10) с −X гранью B (100,10,10): `Update=True`,
|
||||
`Valid=True`, `Alignment=ksMCAlignmentClosest` (дефолт). Грани сошлись заподлицо → ширина сборки
|
||||
по X **120 → 40** (кубы соприкасаются). Решатель подвинул A (к B), не B.
|
||||
- **Расстояние** (`mc_Distance`, `ParamValue=30`) тех же граней: `Update=True`, `Valid=True`. Грани
|
||||
встали в 30 мм → ширина сборки по X **120 → 70** (20+30+20).
|
||||
|
||||
**Тонкости (эмпирика):**
|
||||
- `Alignment` НЕ выставляем — дефолт работает (`ksMCAlignmentClosest` для совпадения,
|
||||
`ksMCAlignmentUnknown` для расстояния). Параметр выравнивания — расширение позже (YAGNI).
|
||||
- Решатель может двигать **любой** компонент (в т.ч. первый, «зафиксированный»). Поэтому результат
|
||||
проверяем по **ширине габарита** (грани сблизились), а не по тому, какой компонент сдвинулся.
|
||||
- `mates.Add` возвращает `IMateConstraint3D`; результат `Update()` проверяем (FALSE = не наложилось).
|
||||
После — `RebuildModel(true)` (результат проверяем, как в инкременте 1).
|
||||
|
||||
## Архитектура
|
||||
|
||||
Метод в существующем `AssemblyService` (он уже про сборки). Свой enum `MateType` (паттерн
|
||||
`BasePlane`/`CoordinateAxis`) маппится на КОМПАС `MateConstraintType` — COM-константы не текут в
|
||||
Host/тесты.
|
||||
|
||||
- `src/Kompas.Mcp.Core/Assemblies/MateType.cs` — enum `MateType` + static `Mates`
|
||||
(`ToConstraintType`, `Parse(string)` англ./рус., `RequiresValue`).
|
||||
- `AssemblyService.AddMateAsync(MateType, x1,y1,z1, x2,y2,z2, value, ct)` — реализация.
|
||||
- Инструмент `assembly_add_mate` в `AssemblyTools` (тип сопряжения строкой → `Mates.Parse`).
|
||||
|
||||
## MCP-инструмент
|
||||
|
||||
| Инструмент | Параметры | Поведение |
|
||||
|---|---|---|
|
||||
| `assembly_add_mate` | `mateType: string`, `x1,y1,z1`, `x2,y2,z2`, `value=0` | Наложить сопряжение между гранями двух компонентов активной сборки, выбранными по мировым точкам (x1..z1) и (x2..z2). `mateType`: coincidence / distance / parallel / perpendicular / concentric / angle / tangency. Для distance — `value` зазор (мм), для angle — `value` угол (°). |
|
||||
|
||||
Контракт: активный документ — сборка (`RequireActiveAssembly`, уже есть); обе точки должны попасть
|
||||
на грани компонентов. **Гарантированно валидированы геометрией: coincidence, distance.** Остальные
|
||||
типы маппятся и вызываемы через тот же путь Add+BaseObject+Update, но не покрыты регрессионным
|
||||
тестом по габариту (требуют иной геометрии/проверки) — помечены в описании инструмента.
|
||||
|
||||
## Валидация (чистые static, unit-тест)
|
||||
|
||||
`Mates`:
|
||||
- `Parse(string)` — англ./рус. → `MateType`; иначе `ArgumentException` со списком допустимых.
|
||||
- `ToConstraintType(MateType)` — → `MateConstraintType`.
|
||||
- `RequiresValue(MateType)` — true для Distance/Angle.
|
||||
|
||||
В сервисе: `RequireFinitePosition` для обеих точек (уже есть в `AssemblyValidation`); если
|
||||
`RequiresValue` — проверить `double.IsFinite(value)` (новый чистый валидатор
|
||||
`AssemblyValidation.RequireFiniteValue`).
|
||||
|
||||
## Реализация
|
||||
|
||||
`AddMateCore`: валидация точек (и value, если нужен) → `RequireActiveAssembly` →
|
||||
`FindFaceInAssembly` (FirstLevel=false) для обеих точек (понятная ошибка, если грань не найдена) →
|
||||
`mates.Add(Mates.ToConstraintType(type))` → `BaseObject1/2` → `ParamValue` (если нужен) →
|
||||
`Update()` (FALSE → откат сопряжения через `IFeature7.Delete` + ошибка) → `RebuildModel(true)`
|
||||
(FALSE → ошибка). Транзитные RCW не освобождаем точечно (долг v2-2, как везде).
|
||||
|
||||
## Тестирование
|
||||
|
||||
### Unit (`MateTests` или в `AssemblyValidationTests`)
|
||||
- `Mates.Parse` — англ. и рус. синонимы → верный `MateType`; бросает на мусоре.
|
||||
- `Mates.ToConstraintType` — каждый `MateType` → ожидаемый `MateConstraintType`.
|
||||
- `Mates.RequiresValue` — true для Distance/Angle, false для прочих.
|
||||
- `AssemblyValidation.RequireFiniteValue` — бросает на NaN/Infinity.
|
||||
|
||||
### Integration (`AssemblyMateTests`)
|
||||
Паттерн: построить куб 20³ → сохранить → создать сборку → вставить 2 компонента (A в нуле, B +100)
|
||||
→ сопряжение → проверить ширину габарита → `finally CloseAsync`.
|
||||
1. **Совпадение** граней A(+X)/B(−X): ширина по X **120 → ~40** (соприкосновение).
|
||||
2. **Расстояние 30**: ширина по X **120 → ~70** (зазор 30).
|
||||
(Эти два сценария = промотированный спайк; спайк-файл удаляется.)
|
||||
|
||||
## Дальнейшее (вне спека)
|
||||
- Выравнивание (`Alignment`), типы concentric/angle/parallel с геометрической проверкой.
|
||||
- Перемещение/фиксация/массив компонентов.
|
||||
Reference in New Issue
Block a user