feat(feature): операция Ребро жёсткости (rib)

RibAsync (o3d_ribOperation): SetSketch + index/angle/side + SetThinParam.
SketchGeometry.RibSide маппинг (left/right/up/down). Инструмент rib в FeatureTools.
Эмпирически: контур ребра висит в зазоре (не касается тела), side=left для косынки.
Integration: L-уголок + ребро в углу → объём растёт.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-26 22:51:58 +03:00
parent 7a9964b6f1
commit fc99739e1e
6 changed files with 171 additions and 0 deletions
@@ -230,6 +230,41 @@ public sealed partial class PartModeler
return id;
}, ct);
/// <summary>Построить ребро жёсткости от разомкнутого контура эскиза до тела.
/// thickness — толщина стенки (мм); side — направление достройки (left|right|up|down);
/// symmetric — толщина симметрична плоскости эскиза; angle — уклон стенок (градусы).
/// Возвращает id операции.</summary>
public Task<int> RibAsync(int sketchId, double thickness, string side = "up", bool symmetric = true, double angle = 0, CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() =>
{
if (thickness <= 0) throw new ArgumentOutOfRangeException(nameof(thickness), "Толщина должна быть > 0.");
var sideCode = SketchGeometry.RibSide(side);
var sketch = RequireSketch(sketchId);
CloseSketchCore(sketch); // эскиз должен быть закрыт перед операцией
var part = GetTopPart();
var entity = part.NewEntity((short)Obj3dType.o3d_ribOperation) as ksEntity
?? throw new InvalidOperationException("NewEntity(o3d_ribOperation) вернул null.");
var def = entity.GetDefinition() as ksRibDefinition
?? throw new InvalidOperationException("GetDefinition() ребра вернул не ksRibDefinition.");
def.SetSketch(sketch.Entity);
def.index = 0; // первый сегмент контура задаёт уклон
def.angle = angle;
def.side = sideCode;
if (symmetric)
def.SetThinParam((short)Direction_Type.dtBoth, thickness / 2, thickness / 2);
else
def.SetThinParam((short)Direction_Type.dtNormal, thickness, 0);
if (!entity.Create())
throw new InvalidOperationException(
"Create() ребра вернул FALSE (контур не пересекает тело или неверное направление side?).");
var id = _nextId++;
_features[id] = entity;
return id;
}, ct);
/// <summary>Перестроить документ.</summary>
public Task RebuildAsync(CancellationToken ct = default)
=> _dispatcher.InvokeAsync(() =>