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:
@@ -48,4 +48,37 @@ public sealed class FeatureOpsTests
|
||||
}
|
||||
finally { await _docs.CloseAsync(save: false); }
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Rib_adds_material_in_corner_of_L_bracket()
|
||||
{
|
||||
await _docs.CreateAsync(KompasDocumentType.Part);
|
||||
try
|
||||
{
|
||||
// Г-образный уголок: L-профиль на XOZ (замкнутая ломаная), выдавить по Y на 30.
|
||||
// Площадь L = 40×5 + 5×35 = 375 → объём 375·30 = 11250.
|
||||
var sBody = await _modeler.OpenSketchAsync(BasePlane.XOZ);
|
||||
var lprofile = new (double x, double y)[] { (0, 0), (40, 0), (40, 5), (5, 5), (5, 40), (0, 40) };
|
||||
await _modeler.AddPolylineAsync(sBody, lprofile, closed: true);
|
||||
await _modeler.CloseSketchAsync(sBody);
|
||||
await _modeler.ExtrudeAsync(sBody, depth: 30);
|
||||
var before = (await _query.GetPartInfoAsync()).Volume;
|
||||
Assert.True(before > 0);
|
||||
|
||||
// Ребро-косынка: разомкнутый отрезок-диагональ во внутреннем углу, на XOZ (Y=0).
|
||||
// side=up (ортогонально, +Y), несимметрично → растёт от Y=0 вглубь тела на 5 мм.
|
||||
var sRib = await _modeler.OpenSketchAsync(BasePlane.XOZ);
|
||||
await _modeler.AddLineAsync(sRib, 25, 10, 10, 25); // висит в пустом углу, не касаясь полок
|
||||
await _modeler.CloseSketchAsync(sRib);
|
||||
var id = await _modeler.RibAsync(sRib, thickness: 5, side: "left", symmetric: false);
|
||||
Assert.True(id > 0);
|
||||
await _modeler.RebuildAsync();
|
||||
|
||||
// Косынка добавляет материал: объём растёт, но в разумных пределах.
|
||||
var after = (await _query.GetPartInfoAsync()).Volume;
|
||||
Assert.True(after > before, "После ребра жёсткости объём должен увеличиться.");
|
||||
Assert.InRange(after, before, before * 1.3);
|
||||
}
|
||||
finally { await _docs.CloseAsync(save: false); }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,19 @@ public sealed class SketchGeometryTests
|
||||
public void PolygonDescribe_inverts_inscribed(bool inscribed, bool expected)
|
||||
=> Assert.Equal(expected, SketchGeometry.PolygonDescribe(inscribed));
|
||||
|
||||
[Theory]
|
||||
[InlineData("left", 0)]
|
||||
[InlineData("right", 1)]
|
||||
[InlineData("up", 2)]
|
||||
[InlineData("down", 3)]
|
||||
[InlineData("UP", 2)]
|
||||
public void RibSide_maps_known(string side, int expected)
|
||||
=> Assert.Equal(expected, (int)SketchGeometry.RibSide(side));
|
||||
|
||||
[Fact]
|
||||
public void RibSide_throws_on_unknown()
|
||||
=> Assert.Throws<ArgumentException>(() => SketchGeometry.RibSide("diagonal"));
|
||||
|
||||
[Fact]
|
||||
public void RequirePositive_throws_on_zero_or_negative()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user