namespace Kompas.Mcp.Core.Drawings;
/// Чистые валидаторы операций чертежа (без COM) — выделены для unit-тестов.
public static class DrawingValidation
{
/// Допустимые расширения файла-источника модели: деталь (.m3d) и сборка (.a3d).
private static readonly HashSet AllowedExtensions =
new(StringComparer.OrdinalIgnoreCase) { ".m3d", ".a3d" };
///
/// Нормализовать путь к файлу 3D-модели: обрезать пробелы, проверить непустоту и расширение
/// (.m3d/.a3d), вернуть абсолютный путь. Существование файла НЕ проверяет (это делает сервис).
///
public static string NormalizeModelPath(string? path)
{
if (string.IsNullOrWhiteSpace(path))
throw new ArgumentException("Путь к файлу модели не задан.", nameof(path));
var trimmed = path.Trim();
var ext = Path.GetExtension(trimmed);
if (!AllowedExtensions.Contains(ext))
throw new ArgumentException(
$"Недопустимое расширение файла модели '{ext}'. Ожидается .m3d (деталь) или .a3d (сборка).",
nameof(path));
return Path.GetFullPath(trimmed);
}
/// Проверить масштаб чертежа: конечный и строго положительный.
public static void RequireScale(double scale)
{
if (!double.IsFinite(scale) || scale <= 0)
throw new ArgumentOutOfRangeException(nameof(scale), "Масштаб должен быть конечным и > 0.");
}
/// Проверить, что все координаты конечны (отсекает NaN/Infinity).
public static void RequireFiniteCoords(params double[] coords)
{
foreach (var c in coords)
if (!double.IsFinite(c))
throw new ArgumentException("Координаты должны быть конечными числами (не NaN/Infinity).");
}
/// Проверить радиус: конечный и строго положительный.
public static void RequirePositiveRadius(double radius)
{
if (!double.IsFinite(radius) || radius <= 0)
throw new ArgumentOutOfRangeException(nameof(radius), "Радиус должен быть конечным и > 0.");
}
/// Проверить, что текст не пустой и не только из пробелов.
public static void RequireNonEmptyText(string? text, string paramName)
{
if (string.IsNullOrWhiteSpace(text))
throw new ArgumentException("Текст не должен быть пустым.", paramName);
}
/// Минимальное расстояние между выносными точками линейного размера (мм).
private const double MinPointDistance = 1e-7;
///
/// Проверить, что выносные точки размера различны (иначе размер вырожден — нулевая длина).
///
public static void RequireDistinctPoints(double x1, double y1, double x2, double y2)
{
var dx = x2 - x1;
var dy = y2 - y1;
if (Math.Sqrt(dx * dx + dy * dy) < MinPointDistance)
throw new ArgumentException("Выносные точки размера совпадают — нельзя поставить размер нулевой длины.");
}
}