/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Printing/PageLayout.cs
110 строк
5 KB
docNemo
Фундамент продукта: параметрическое построение выкроек, печать, установщик
08 авг 2026, 22:17
08 авг 2026, 22:17
cd47cce
Код
Авторство
О чём код?
using System; using ClothesGraph.Geometry; namespace ClothesGraph.Printing; /// <summary>Размер листа вывода.</summary> public sealed record PageSize(string Name, Length Width, Length Height) { public static readonly PageSize A4 = new("A4", Length.FromMillimetres(210), Length.FromMillimetres(297)); public static readonly PageSize A3 = new("A3", Length.FromMillimetres(297), Length.FromMillimetres(420)); public static readonly PageSize Letter = new("Letter", Length.FromMillimetres(215.9), Length.FromMillimetres(279.4)); /// <summary> /// Рулон плоттера: ширина задана, длина не ограничена. /// </summary> /// <remarks> /// Длина берётся большой, но конечной: разбиение работает с прямоугольной /// сеткой, и бесконечность в ней пришлось бы обрабатывать особым случаем /// ради выигрыша, которого нет — выкройки такой длины не бывает. /// </remarks> public static PageSize Roll(double widthMillimetres) => new( $"Рулон {widthMillimetres:0} мм", Length.FromMillimetres(widthMillimetres), Length.FromMillimetres(10_000)); public static readonly PageSize[] Standard = [A4, A3, Letter]; } public enum PageOrientation { Portrait, Landscape } /// <summary>Способ соединения соседних листов.</summary> public enum SheetJoinMode { /// <summary>Общая полоса изображения на соседних листах и линия обрезки по её границе.</summary> Overlap, /// <summary>Листы обрезаются по краю печатной области и стыкуются без нахлёста.</summary> Butt } /// <summary> /// Параметры разбиения выкройки на листы. /// </summary> /// <remarks> /// Поля отсчитываются от края бумаги: печатать вплотную к краю бытовые принтеры /// не умеют, и попытка это сделать обрежет часть выкройки без предупреждения. /// </remarks> public sealed class PageLayout { public PageLayout( PageSize size, PageOrientation orientation = PageOrientation.Portrait, Length? margin = null, SheetJoinMode joinMode = SheetJoinMode.Overlap, Length? overlap = null) { Size = size; Orientation = orientation; Margin = margin ?? Length.FromMillimetres(8); JoinMode = joinMode; Overlap = overlap ?? Length.FromMillimetres(15); if (PrintableWidth <= Length.Zero || PrintableHeight <= Length.Zero) throw new ArgumentException("Поля не оставляют места для печати"); if (JoinMode == SheetJoinMode.Overlap && (Overlap >= PrintableWidth || Overlap >= PrintableHeight)) throw new ArgumentException("Полоса перекрытия шире печатной области"); } public PageSize Size { get; } public PageOrientation Orientation { get; } public Length Margin { get; } public SheetJoinMode JoinMode { get; } /// <summary>Ширина общей полосы соседних листов. Имеет смысл при склейке с перекрытием.</summary> public Length Overlap { get; } public Length PaperWidth => Orientation == PageOrientation.Portrait ? Size.Width : Size.Height; public Length PaperHeight => Orientation == PageOrientation.Portrait ? Size.Height : Size.Width; /// <summary>Ширина области, куда попадает изображение.</summary> public Length PrintableWidth => PaperWidth - Margin * 2; public Length PrintableHeight => PaperHeight - Margin * 2; /// <summary> /// Шаг сетки листов. При склейке с перекрытием он меньше печатной области /// ровно на ширину общей полосы — за счёт этого она и появляется. /// </summary> public Length StepX => JoinMode == SheetJoinMode.Overlap ? PrintableWidth - Overlap : PrintableWidth; public Length StepY => JoinMode == SheetJoinMode.Overlap ? PrintableHeight - Overlap : PrintableHeight; }