using Kompas.Mcp.Core.Documents; using Kompas.Mcp.Core.Modeling; using Kompas.Mcp.Core.Query; namespace Kompas.Mcp.Tests.Integration; /// Интеграция: формообразующие операции пакета B. [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); } } }