using Kompas.Mcp.Core.Documents; using Kompas.Mcp.Core.Drawings; using Kompas.Mcp.Core.Modeling; namespace Kompas.Mcp.Tests.Integration; /// Интеграция: угловой размер на виде (API7 ISymbols2DContainer.AngleDimensions). [Trait("Category", "Integration")] [Collection(KompasCollection.Name)] public sealed class DrawingAngularTests : IntegrationTestBase { private readonly DocumentService _docs; private readonly PartModeler _modeler; private readonly DrawingService _drawing; public DrawingAngularTests(KompasFixture fx) : base(fx) { _docs = new DocumentService(fx.Session, fx.Dispatcher); _modeler = new PartModeler(fx.Session, fx.Dispatcher); _drawing = new DrawingService(fx.Session, fx.Dispatcher); } private async Task BuildAndSaveBoxAsync() { var path = TestPaths.NewFile(".m3d"); await _docs.CreateAsync(KompasDocumentType.Part); try { 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); await _modeler.RebuildAsync(); await _docs.SaveAsAsync(path); } finally { await _docs.CloseAsync(save: false); } return path; } private async Task NewDrawingWithViewsAsync() { var partFile = await BuildAndSaveBoxAsync(); await _docs.CreateAsync(KompasDocumentType.Drawing); await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150); return partFile; } [Fact] public async Task Angular_measures_right_angle() { await NewDrawingWithViewsAsync(); try { // Вершина (0,0); сторона1 → (10,0); сторона2 → (0,10); дуга в секторе (5,5) → 90°. var r = await _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 0, y2: 10, x3: 5, y3: 5, angleType: AngleDimensionType.Min); Assert.InRange(r.Value, 89.5, 90.5); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Angular_measures_45_degrees() { await NewDrawingWithViewsAsync(); try { // Вершина (0,0); сторона1 → (10,0); сторона2 → (10,10) (45°); дуга (8,4). var r = await _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 10, y2: 10, x3: 8, y3: 4, angleType: AngleDimensionType.Min); Assert.InRange(r.Value, 44.5, 45.5); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Angle_type_max_measures_larger_angle() { await NewDrawingWithViewsAsync(); try { // Лучи 0° и 45°: три типа дают разные углы — min=45 (острый), max=135 (тупой // супплемент 180−45), more=315 (рефлексный). Покрывает маппинг ksADMaxAngle (≠ Min/More). var r = await _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 10, y2: 10, x3: 4, y3: -8, angleType: AngleDimensionType.Max); Assert.InRange(r.Value, 134.0, 136.0); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Targets_specific_view_and_increments_angular_count() { var partFile = await BuildAndSaveBoxAsync(); await _docs.CreateAsync(KompasDocumentType.Drawing); try { var views = await _drawing.CreateStandardViewsAsync(partFile, 1.0, 100, 150); var targetNumber = views.ViewNumbers[1]; var before = await _drawing.GetViewAngularDimensionCountAsync(targetNumber); var r = await _drawing.AddAngularDimensionAsync( targetNumber, xc: 0, yc: 0, x1: 10, y1: 0, x2: 0, y2: 10, x3: 5, y3: 5, angleType: AngleDimensionType.Min); var after = await _drawing.GetViewAngularDimensionCountAsync(targetNumber); Assert.Equal(targetNumber, r.ViewNumber); Assert.Equal(before + 1, after); Assert.InRange(r.Value, 89.5, 90.5); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Angle_type_more_measures_reflex_angle() { await NewDrawingWithViewsAsync(); try { // Та же геометрия 90°, но angleType=more → измеряется рефлексный угол ~270°. // Тип угла (min/max/more) выбирает, какой из секторов измерять; (x3,y3) лишь // позиционирует размерную дугу (её ставим в рефлексный сектор для согласованности). var r = await _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 0, y2: 10, x3: -5, y3: -5, angleType: AngleDimensionType.More); Assert.InRange(r.Value, 269.0, 271.0); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Coincident_vertex_and_side_throws() { await NewDrawingWithViewsAsync(); try { // Вершина совпадает с точкой стороны1 → вырождение до Add. await Assert.ThrowsAsync(() => _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 0, y1: 0, x2: 0, y2: 10, x3: 5, y3: 5, angleType: AngleDimensionType.Min)); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Collinear_rays_rollback_leaves_count_unchanged() { await NewDrawingWithViewsAsync(); try { var before = await _drawing.GetViewAngularDimensionCountAsync(0); // Сонаправленные лучи (0,0)→(10,0) и (0,0)→(20,0): угол ≈0 → пост-проверка → откат. await Assert.ThrowsAsync(() => _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 20, y2: 0, x3: 15, y3: 5, angleType: AngleDimensionType.Min)); var after = await _drawing.GetViewAngularDimensionCountAsync(0); Assert.Equal(before, after); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task No_views_throws() { await _docs.CreateAsync(KompasDocumentType.Drawing); try { await Assert.ThrowsAsync(() => _drawing.AddAngularDimensionAsync( viewNumber: 0, xc: 0, yc: 0, x1: 10, y1: 0, x2: 0, y2: 10, x3: 5, y3: 5, angleType: AngleDimensionType.Min)); } finally { await _docs.CloseAsync(save: false); } } [Fact] public async Task Unknown_view_number_throws() { await NewDrawingWithViewsAsync(); try { await Assert.ThrowsAsync(() => _drawing.AddAngularDimensionAsync( viewNumber: 999, xc: 0, yc: 0, x1: 10, y1: 0, x2: 0, y2: 10, x3: 5, y3: 5, angleType: AngleDimensionType.Min)); } finally { await _docs.CloseAsync(save: false); } } }