fc99739e1e
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>
85 lines
4.2 KiB
C#
85 lines
4.2 KiB
C#
using Kompas.Mcp.Core.Documents;
|
||
using Kompas.Mcp.Core.Modeling;
|
||
using Kompas.Mcp.Core.Query;
|
||
|
||
namespace Kompas.Mcp.Tests.Integration;
|
||
|
||
/// <summary>Интеграция: формообразующие операции пакета B.</summary>
|
||
[Trait("Category", "Integration")]
|
||
[Collection(KompasCollection.Name)]
|
||
public sealed class FeatureOpsTests
|
||
{
|
||
private readonly DocumentService _docs;
|
||
private readonly PartModeler _modeler;
|
||
private readonly QueryService _query;
|
||
|
||
public FeatureOpsTests(KompasFixture fx)
|
||
{
|
||
_docs = new DocumentService(fx.Session, fx.Dispatcher);
|
||
_modeler = new PartModeler(fx.Session, fx.Dispatcher);
|
||
_query = new QueryService(fx.Session, fx.Dispatcher);
|
||
}
|
||
|
||
[Fact]
|
||
public async Task Shell_box_hollows_with_open_cap()
|
||
{
|
||
await _docs.CreateAsync(KompasDocumentType.Part);
|
||
try
|
||
{
|
||
// Коробка 40×30×20.
|
||
var s = await _modeler.OpenSketchAsync(BasePlane.XOY);
|
||
await _modeler.AddRectangleAsync(s, 0, 0, 40, 30);
|
||
await _modeler.CloseSketchAsync(s);
|
||
await _modeler.ExtrudeAsync(s, depth: 20);
|
||
var before = (await _query.GetPartInfoAsync()).Volume; // 24000
|
||
|
||
// Удаляем один из двух плоских торцов (площадь 40×30=1200) → открытая оболочка.
|
||
// Какой именно торец (верх/низ) — для объёма не важно: результат симметричен.
|
||
var faces = await _query.ListFacesAsync();
|
||
var cap = faces.First(f => f.Type == "plane" && Math.Abs(f.Area - 1200) < 1);
|
||
var id = await _modeler.ShellAsync(new[] { cap.Index }, thickness: 2, outward: false);
|
||
Assert.True(id > 0);
|
||
await _modeler.RebuildAsync();
|
||
|
||
// Оболочка 2 мм с открытым торцом: 24000 − 36×26×18 = 7152 мм³.
|
||
var after = (await _query.GetPartInfoAsync()).Volume;
|
||
Assert.True(after < before, "После оболочки объём должен уменьшиться.");
|
||
Assert.InRange(after, 7152 * 0.95, 7152 * 1.05);
|
||
}
|
||
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); }
|
||
}
|
||
}
|