775128484e
Флаг associate у drawing_add_diametral_dimension/drawing_add_radial_dimension: - associate=false (по умолчанию) — прежний свободный размер (без изменений); - associate=true — (xc,yc,radius) как ключ поиска спроецированной окружности (IDrawingContainer.Circles), привязка через BaseObject; значение Ø/R читается из геометрии и обновляется с моделью. - CircularObjectMatch.SelectMatchIndex (чистый отбор по центру+радиусу, допуск 1 мм; бросает при отсутствии/неоднозначности; концентрические разделяются радиусом) - RequireViewContainers (вид → ISymbols2DContainer + IDrawingContainer), CollectCircles, FindBaseCircle - 5 unit + 6 интеграционных тестов (всего 278 зелёных), сборка Release чистая Спайк подтвердил: BaseObject=circle без задания Xc/Yc/Radius → Valid, NominalValue из геометрии (Ø=20/R=10 для R10). Объём — только окружности (Circles); дуги/угловой/линейный — далее. Ревью Codex спека учтено (оба контейнера, guard вокруг блока, доказательство ассоциативности тестом radius=10.3→Ø20, регресс обоих свободных путей). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
54 lines
2.1 KiB
C#
54 lines
2.1 KiB
C#
using Kompas.Mcp.Core.Drawings;
|
|
|
|
namespace Kompas.Mcp.Tests;
|
|
|
|
[Trait("Category", "Unit")]
|
|
public sealed class CircularObjectMatchTests
|
|
{
|
|
private const double Tol = 1.0;
|
|
|
|
private static IReadOnlyList<CircleCandidate> Candidates(params (double x, double y, double r)[] items)
|
|
=> items.Select(i => new CircleCandidate(i.x, i.y, i.r)).ToList();
|
|
|
|
[Fact]
|
|
public void SelectMatchIndex_returns_unique_match()
|
|
{
|
|
var c = Candidates((0, 0, 10), (50, 20, 5));
|
|
// ключ с допустимым отклонением центра и радиуса
|
|
Assert.Equal(0, CircularObjectMatch.SelectMatchIndex(c, 0.3, -0.2, 10.3, Tol));
|
|
Assert.Equal(1, CircularObjectMatch.SelectMatchIndex(c, 50, 20, 5, Tol));
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectMatchIndex_concentric_disambiguated_by_radius()
|
|
{
|
|
// концентрические R5 и R10 (цековка): ключ R10 выбирает внешнюю, не неоднозначно
|
|
var c = Candidates((0, 0, 5), (0, 0, 10));
|
|
Assert.Equal(1, CircularObjectMatch.SelectMatchIndex(c, 0, 0, 10, Tol));
|
|
Assert.Equal(0, CircularObjectMatch.SelectMatchIndex(c, 0, 0, 5, Tol));
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectMatchIndex_throws_when_none_in_tolerance()
|
|
{
|
|
var c = Candidates((0, 0, 10));
|
|
// центр далеко
|
|
Assert.Throws<InvalidOperationException>(() => CircularObjectMatch.SelectMatchIndex(c, 100, 100, 10, Tol));
|
|
// радиус далеко
|
|
Assert.Throws<InvalidOperationException>(() => CircularObjectMatch.SelectMatchIndex(c, 0, 0, 25, Tol));
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectMatchIndex_throws_when_ambiguous()
|
|
{
|
|
// две почти совпадающие окружности в допуске
|
|
var c = Candidates((0, 0, 10), (0.2, 0.2, 10.2));
|
|
Assert.Throws<InvalidOperationException>(() => CircularObjectMatch.SelectMatchIndex(c, 0, 0, 10, Tol));
|
|
}
|
|
|
|
[Fact]
|
|
public void SelectMatchIndex_throws_on_empty()
|
|
=> Assert.Throws<InvalidOperationException>(
|
|
() => CircularObjectMatch.SelectMatchIndex(Candidates(), 0, 0, 10, Tol));
|
|
}
|