5272066bef
drawing_add_rough (знак шероховатости: ISymbols2DContainer.Roughs + IRoughParams, SignType ksRoughSignEnum, значение Ra/Rz через RoughParamText.Str), drawing_add_text (свободная надпись: IDrawingContainer.DrawingTexts + IText.Str), drawing_set_technical_requirements (блок тех. требований уровня документа: IDrawingDocument.TechnicalDemand.Text). - DrawingService: AddRoughAsync/AddTextAsync/SetTechnicalRequirementsAsync + ReadTechnicalRequirementsAsync + счётчики; RequireDrawingContainer/RequireTechnicalDemand - RoughSignType (enum + Parse/ToKompas), DrawingAnnotationResult (Value read-back из COM) - RequireNonEmptyText в DrawingValidation - 13 unit + 13 интеграционных тестов (всего 267 зелёных), сборка Release чистая Спайк подтвердил: значение шероховатости через IRoughParams.RoughParamText.Str (round-trip); текст НЕ в IView.ObjectCount (счёт по DrawingTexts.Count); тех. требования IsCreated False→True при первом Text.Str+Update, многострочно через \n. Ревью Codex спека учтено (height убран — это высота блока, не шрифт; guards; read-back возврат). Спек — docs/superpowers/specs/. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
72 lines
3.8 KiB
C#
72 lines
3.8 KiB
C#
namespace Kompas.Mcp.Core.Drawings;
|
|
|
|
/// <summary>Чистые валидаторы операций чертежа (без COM) — выделены для unit-тестов.</summary>
|
|
public static class DrawingValidation
|
|
{
|
|
/// <summary>Допустимые расширения файла-источника модели: деталь (.m3d) и сборка (.a3d).</summary>
|
|
private static readonly HashSet<string> AllowedExtensions =
|
|
new(StringComparer.OrdinalIgnoreCase) { ".m3d", ".a3d" };
|
|
|
|
/// <summary>
|
|
/// Нормализовать путь к файлу 3D-модели: обрезать пробелы, проверить непустоту и расширение
|
|
/// (.m3d/.a3d), вернуть абсолютный путь. Существование файла НЕ проверяет (это делает сервис).
|
|
/// </summary>
|
|
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);
|
|
}
|
|
|
|
/// <summary>Проверить масштаб чертежа: конечный и строго положительный.</summary>
|
|
public static void RequireScale(double scale)
|
|
{
|
|
if (!double.IsFinite(scale) || scale <= 0)
|
|
throw new ArgumentOutOfRangeException(nameof(scale), "Масштаб должен быть конечным и > 0.");
|
|
}
|
|
|
|
/// <summary>Проверить, что все координаты конечны (отсекает NaN/Infinity).</summary>
|
|
public static void RequireFiniteCoords(params double[] coords)
|
|
{
|
|
foreach (var c in coords)
|
|
if (!double.IsFinite(c))
|
|
throw new ArgumentException("Координаты должны быть конечными числами (не NaN/Infinity).");
|
|
}
|
|
|
|
/// <summary>Проверить радиус: конечный и строго положительный.</summary>
|
|
public static void RequirePositiveRadius(double radius)
|
|
{
|
|
if (!double.IsFinite(radius) || radius <= 0)
|
|
throw new ArgumentOutOfRangeException(nameof(radius), "Радиус должен быть конечным и > 0.");
|
|
}
|
|
|
|
/// <summary>Проверить, что текст не пустой и не только из пробелов.</summary>
|
|
public static void RequireNonEmptyText(string? text, string paramName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(text))
|
|
throw new ArgumentException("Текст не должен быть пустым.", paramName);
|
|
}
|
|
|
|
/// <summary>Минимальное расстояние между выносными точками линейного размера (мм).</summary>
|
|
private const double MinPointDistance = 1e-7;
|
|
|
|
/// <summary>
|
|
/// Проверить, что выносные точки размера различны (иначе размер вырожден — нулевая длина).
|
|
/// </summary>
|
|
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("Выносные точки размера совпадают — нельзя поставить размер нулевой длины.");
|
|
}
|
|
}
|