Files
kompas3d-mcp/tests/Kompas.Mcp.Tests/Integration/TextAlignmentTests.cs
T
mikhail e127cebb49 Итерация 1: удаление операции, выравнивание надписи, отбор рёбер
По протоколу регресс-прогона (46 вызовов против 90 в прошлом):

feature_delete — ksDocument3D.DeleteObject + RebuildDocument, зависимые уходят каскадом.
Неудачная проба больше не требует пересобирать документ (у субагента таких кругов было три).

align/vAlign у примитива text: сервер строит, замеряет и сдвигает надпись сам. Ловушка,
стоившая двух заходов: ksMoveObj и ksDeleteObj по ссылке от ksConvertTextToCurve возвращают
успех и не делают ничего — двигать надо по ссылке ТЕКСТА, а габарит после сдвига считать
арифметикой (по текстовой ссылке рамка идёт по ячейке). Поймано тестом, который сверяет
заявленный габарит с выдавленной геометрией.

list_edges: отбор по типу и координатному окну + концы рёбер в списке. Так адресуется
нижний контур под фаску, который иначе не выбрать: индексов не отфильтровать, точек не угадать.

Навык: wf меряет пропорцию крупно (1.0→1.25 = +29 %), но квантован ступенями — точную ширину
набирают height; прирост каймы указан НА СТОРОНУ и зависит от начертания, а не от шрифта;
добавлено предупреждение, что primitive(subtract) режет наехавшие буквы.
2026-07-31 17:11:53 +03:00

107 lines
4.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Kompas.Mcp.Core.Documents;
using Kompas.Mcp.Core.Modeling;
using Kompas.Mcp.Core.Query;
using System.Globalization;
using System.Text.RegularExpressions;
namespace Kompas.Mcp.Tests.Integration;
/// <summary>
/// Интеграция: выравнивание надписи. КОМПАС кладёт строку только вправо-вверх от точки вставки
/// (<c>align</c> у <c>ksTextEx</c> её не двигает), поэтому центрирование делает сервер: строит,
/// замеряет, удаляет и кладёт заново со сдвигом.
/// </summary>
[Trait("Category", "Integration")]
[Collection(KompasCollection.Name)]
public sealed class TextAlignmentTests : IntegrationTestBase
{
private readonly DocumentService _docs;
private readonly PartModeler _modeler;
private readonly QueryService _query;
public TextAlignmentTests(KompasFixture fx) : base(fx)
{
_docs = new DocumentService(fx.Session, fx.Dispatcher);
_modeler = new PartModeler(fx.Session, fx.Dispatcher);
_query = new QueryService(fx.Session, fx.Dispatcher);
}
private static SketchEntity Text(string text, double x, double y, TextAlign align, TextVAlign vAlign) => new()
{
Kind = SketchEntityKind.Text,
Points = [(x, y)],
Text = text,
Height = 10,
FontName = "Arial",
Align = align,
VAlign = vAlign,
};
/// <summary>Числа из заметки: minX, maxX, minY, maxY.</summary>
private static (double MinX, double MaxX, double MinY, double MaxY) Box(string note)
{
var n = Regex.Matches(note, @"-?\d+\.\d{2}")
.Select(m => double.Parse(m.Value, CultureInfo.InvariantCulture)).ToList();
Assert.True(n.Count >= 4, $"в заметке нет габарита: {note}");
return (n[0], n[1], n[2], n[3]);
}
[Fact]
public async Task Centered_text_puts_its_middle_on_the_insertion_point()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY, name: "Надпись по центру");
var notes = await _modeler.AddEntitiesAsync(
s, [Text("HHH", 50, 0, TextAlign.Center, TextVAlign.Baseline)], autoClose: true);
var box = Box(notes[0]);
Assert.InRange((box.MinX + box.MaxX) / 2, 49.95, 50.05);
// Надпись осталась ОДНА: первая вставка удалена, а не оставлена рядом.
await _modeler.ExtrudeAsync(s, depth: 2, name: "Рельеф");
await _modeler.RebuildAsync();
var modelBox = await _query.GetBoundingBoxAsync();
var what = $"заметка: {notes[0]}; модель X {modelBox.MinX:F2}…{modelBox.MaxX:F2}";
Assert.True(Math.Abs(modelBox.MinX - box.MinX) < 0.05, what);
Assert.True(Math.Abs(modelBox.MaxX - box.MaxX) < 0.05, what);
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Right_and_middle_anchor_the_box_edges()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY, name: "Надпись по правому краю");
var notes = await _modeler.AddEntitiesAsync(
s, [Text("Hy", 90, 20, TextAlign.Right, TextVAlign.Middle)], autoClose: true);
var box = Box(notes[0]);
Assert.InRange(box.MaxX, 89.95, 90.05); // правый край — на якоре
Assert.InRange((box.MinY + box.MaxY) / 2, 19.95, 20.05); // середина глифов — на якоре
}
finally { await _docs.CloseAsync(save: false); }
}
[Fact]
public async Task Default_alignment_keeps_the_kompas_behaviour()
{
await _docs.CreateAsync(KompasDocumentType.Part);
try
{
var s = await _modeler.OpenSketchAsync(BasePlane.XOY, name: "Надпись от точки");
var notes = await _modeler.AddEntitiesAsync(
s, [Text("HH", 5, 0, TextAlign.Left, TextVAlign.Baseline)], autoClose: true);
var box = Box(notes[0]);
Assert.True(box.MinX >= 5, "по умолчанию строка кладётся вправо от точки вставки");
Assert.InRange(box.MinY, -0.5, 0.5); // базовая линия — на y точки вставки
}
finally { await _docs.CloseAsync(save: false); }
}
}