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>
45 lines
2.3 KiB
C#
45 lines
2.3 KiB
C#
namespace Kompas.Mcp.Core.Drawings;
|
||
|
||
/// <summary>Геометрия окружности-кандидата вида (центр + радиус, локальная СК вида, мм).</summary>
|
||
public sealed record CircleCandidate(double Xc, double Yc, double Radius);
|
||
|
||
/// <summary>
|
||
/// Чистый отбор окружности проекционного вида по ключу (центр + радиус) для ассоциативной привязки
|
||
/// размера. Выделен из COM-перечисления ради unit-тестов.
|
||
/// </summary>
|
||
public static class CircularObjectMatch
|
||
{
|
||
/// <summary>
|
||
/// Индекс единственной окружности из <paramref name="candidates"/>, чей центр и радиус совпадают с
|
||
/// ключом (<paramref name="keyX"/>,<paramref name="keyY"/>,<paramref name="keyR"/>) в пределах
|
||
/// <paramref name="tol"/> (мм): <c>dist(центр,ключ) ≤ tol</c> И <c>|R − keyR| ≤ tol</c>.
|
||
/// </summary>
|
||
/// <exception cref="InvalidOperationException">Нет подходящих (0) или неоднозначно (>1).</exception>
|
||
public static int SelectMatchIndex(IReadOnlyList<CircleCandidate> candidates,
|
||
double keyX, double keyY, double keyR, double tol)
|
||
{
|
||
ArgumentNullException.ThrowIfNull(candidates);
|
||
|
||
var matches = new List<int>();
|
||
for (var i = 0; i < candidates.Count; i++)
|
||
{
|
||
var c = candidates[i];
|
||
var dx = c.Xc - keyX;
|
||
var dy = c.Yc - keyY;
|
||
if (Math.Sqrt(dx * dx + dy * dy) <= tol && Math.Abs(c.Radius - keyR) <= tol)
|
||
matches.Add(i);
|
||
}
|
||
|
||
return matches.Count switch
|
||
{
|
||
1 => matches[0],
|
||
0 => throw new InvalidOperationException(
|
||
$"Окружность не найдена рядом с ({keyX},{keyY}) R≈{keyR} (допуск {tol} мм). " +
|
||
"Проверьте координаты/радиус и наличие окружности на этом виде."),
|
||
_ => throw new InvalidOperationException(
|
||
$"Неоднозначный выбор окружности у ({keyX},{keyY}) R≈{keyR}: подходит {matches.Count}. " +
|
||
"Уточните координаты/радиус."),
|
||
};
|
||
}
|
||
}
|