Files
kompas3d-mcp/tests/Kompas.Mcp.Tests/SketchEntityInputsTests.cs
T
mikhail a4cc755fb4 Формообразование: надписи в эскизе, тонкая стенка, тела по размерам
Три способа получить форму там, где раньше был только замкнутый контур
из отрезков и дуг.

1. Примитив эскиза type=text: ksTextEx + ksConvertTextToCurve. Пока текст
   остаётся текстом, это оформление, и операция его не видит; после
   конвертации глифы становятся обычным сечением. Ответ возвращает
   фактическую длину строки — иначе ширину шрифта до выдавливания не узнать.

2. extrude(thinThickness, thinSide): контур трактуется как стенка заданной
   толщины. outward по замкнутому контуру даёт кайму-эквидистанту вокруг
   него — так надпись получает подложку без 2D-эквидистанты.
   Толщину при dtReverse КОМПАС читает из reverseThickness: положить её в
   normalThickness значит молча получить СПЛОШНОЕ сечение вместо рамки.

3. Инструмент primitive: элементарные тела API7 (block, cylinder, sphere,
   cone) с result=new|union|subtract|intersect. Карман и паз строятся
   вычитанием тела, без эскиза и выреза. Update() возвращает TRUE даже
   когда вычитание прошло мимо тела, поэтому сервис сверяет объём до и
   после и откатывает операцию, если ничего не изменилось.
2026-07-31 14:50:56 +03:00

158 lines
6.0 KiB
C#

using Kompas.Mcp.Core.Modeling;
namespace Kompas.Mcp.Tests;
/// <summary>
/// Разбор пакета примитивов эскиза. Схема слитого инструмента не может запретить неверную
/// комбинацию полей — её ловит этот разбор, и сообщение должно называть недостающий параметр
/// и позицию в списке, иначе агент не исправится с первой попытки.
/// </summary>
[Trait("Category", "Unit")]
public sealed class SketchEntityInputsTests
{
private static SketchEntityInput Circle() => new()
{
Type = "circle", CenterX = 0, CenterY = 0, Radius = 5,
};
[Fact]
public void Empty_input_gives_empty_list()
{
Assert.Empty(SketchEntityInputs.Parse(null));
Assert.Empty(SketchEntityInputs.Parse([]));
}
[Theory]
[InlineData("line", SketchEntityKind.Line)]
[InlineData("LINE", SketchEntityKind.Line)]
[InlineData(" rect ", SketchEntityKind.Rectangle)]
[InlineData("rectangle", SketchEntityKind.Rectangle)]
[InlineData("arc3", SketchEntityKind.Arc3Points)]
[InlineData("arc3points", SketchEntityKind.Arc3Points)]
[InlineData("axis", SketchEntityKind.Axis)]
public void Type_names_and_aliases_are_recognized(string type, SketchEntityKind expected)
{
var e = new SketchEntityInput
{
Type = type,
Points = [new SketchPoint(0, 0), new SketchPoint(10, 10), new SketchPoint(20, 0)],
};
Assert.Equal(expected, SketchEntityInputs.Parse([e])[0].Kind);
}
[Fact]
public void Unknown_type_lists_the_allowed_ones()
{
var e = new SketchEntityInput { Type = "spiral" };
var ex = Assert.Throws<ArgumentException>(() => SketchEntityInputs.Parse([e]));
Assert.Contains("spiral", ex.Message, StringComparison.Ordinal);
Assert.Contains("polyline", ex.Message, StringComparison.Ordinal);
}
[Fact]
public void Error_names_the_position_in_the_batch()
{
var bad = new SketchEntityInput { Type = "circle", CenterX = 0, CenterY = 0 }; // без radius
var ex = Assert.Throws<ArgumentException>(() => SketchEntityInputs.Parse([Circle(), Circle(), bad]));
Assert.Contains("entities[2]", ex.Message, StringComparison.Ordinal);
Assert.Contains("radius", ex.Message, StringComparison.Ordinal);
}
[Fact]
public void Line_requires_two_points()
{
var e = new SketchEntityInput { Type = "line", Points = [new SketchPoint(0, 0)] };
var ex = Assert.Throws<ArgumentException>(() => SketchEntityInputs.Parse([e]));
Assert.Contains("points", ex.Message, StringComparison.Ordinal);
Assert.Contains("минимум 2", ex.Message, StringComparison.Ordinal);
}
[Fact]
public void Arc_requires_center_radius_and_angles()
{
var e = new SketchEntityInput { Type = "arc", CenterX = 0, CenterY = 0, Radius = 10, StartAngle = 0 };
var ex = Assert.Throws<ArgumentException>(() => SketchEntityInputs.Parse([e]));
Assert.Contains("endAngle", ex.Message, StringComparison.Ordinal);
}
[Fact]
public void Polygon_requires_vertex_count()
{
var e = new SketchEntityInput { Type = "polygon", CenterX = 0, CenterY = 0, Radius = 10 };
var ex = Assert.Throws<ArgumentException>(() => SketchEntityInputs.Parse([e]));
Assert.Contains("vertexCount", ex.Message, StringComparison.Ordinal);
}
[Fact]
public void Defaults_are_applied_for_omitted_flags()
{
var e = new SketchEntityInput { Type = "arc", CenterX = 1, CenterY = 2, Radius = 3, StartAngle = 0, EndAngle = 90 };
var parsed = SketchEntityInputs.Parse([e])[0];
Assert.True(parsed.CounterClockwise); // умолчание — против часовой
Assert.True(parsed.Inscribed);
Assert.False(parsed.Closed);
Assert.Equal(0, parsed.Angle);
}
[Fact]
public void Text_requires_insertion_point_string_and_height()
{
var noPoint = new SketchEntityInput { Type = "text", Text = "OldMan", Height = 10 };
Assert.Contains("points", Assert.Throws<ArgumentException>(
() => SketchEntityInputs.Parse([noPoint])).Message, StringComparison.Ordinal);
var noText = new SketchEntityInput { Type = "text", Points = [new SketchPoint(0, 0)], Height = 10 };
Assert.Contains("text", Assert.Throws<ArgumentException>(
() => SketchEntityInputs.Parse([noText])).Message, StringComparison.Ordinal);
var noHeight = new SketchEntityInput { Type = "text", Points = [new SketchPoint(0, 0)], Text = "OldMan" };
Assert.Contains("height", Assert.Throws<ArgumentException>(
() => SketchEntityInputs.Parse([noHeight])).Message, StringComparison.Ordinal);
}
[Fact]
public void Text_defaults_keep_normal_width_and_upright_face()
{
var e = new SketchEntityInput
{
Type = "text", Points = [new SketchPoint(4, 12)], Text = "EDITION", Height = 6, FontName = "Zilla Slab",
};
var parsed = SketchEntityInputs.Parse([e])[0];
Assert.Equal(SketchEntityKind.Text, parsed.Kind);
Assert.Equal("EDITION", parsed.Text);
Assert.Equal("Zilla Slab", parsed.FontName);
Assert.Equal(6, parsed.Height);
Assert.Equal(1.0, parsed.WidthFactor);
Assert.False(parsed.Bold);
Assert.False(parsed.Italic);
Assert.Equal((4.0, 12.0), parsed.Points[0]);
}
[Fact]
public void Points_keep_their_order()
{
var e = new SketchEntityInput
{
Type = "polyline",
Points = [new SketchPoint(0, 0), new SketchPoint(10, 0), new SketchPoint(10, 5)],
Closed = true,
};
var parsed = SketchEntityInputs.Parse([e])[0];
Assert.True(parsed.Closed);
Assert.Equal(3, parsed.Points.Count);
Assert.Equal((10.0, 5.0), parsed.Points[2]);
}
}