/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Printing/SheetGrid.cs
110 строк
4 KB
docNemo
Фундамент продукта: параметрическое построение выкроек, печать, установщик
08 авг 2026, 22:17
08 авг 2026, 22:17
cd47cce
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using ClothesGraph.Geometry; namespace ClothesGraph.Printing; /// <summary> /// Один лист разбиения. /// </summary> /// <remarks> /// Несёт обозначения соседей: на распечатанной стопке лист должен сам /// рассказывать, откуда он и с чем стыкуется, иначе собрать выкройку /// из полусотни листов невозможно. /// </remarks> public sealed record Sheet( int Column, int Row, string Label, Point2 Origin, string? Left, string? Right, string? Above, string? Below); /// <summary> /// Разбиение области чертежа на листы выбранного формата. /// </summary> /// <remarks> /// Строки обозначаются буквами, столбцы — числами: так принято в выкройках, /// и такое обозначение не путается с номерами размеров. /// </remarks> public sealed class SheetGrid { private readonly List<Sheet> _sheets = []; public SheetGrid(PageLayout layout, Point2 contentMin, Point2 contentMax) { Layout = layout; ContentMin = contentMin; ContentMax = contentMax; var width = contentMax.X - contentMin.X; var height = contentMax.Y - contentMin.Y; Columns = CountSheets(width, layout.StepX, layout.PrintableWidth); Rows = CountSheets(height, layout.StepY, layout.PrintableHeight); Build(); } public PageLayout Layout { get; } public Point2 ContentMin { get; } public Point2 ContentMax { get; } public int Columns { get; } public int Rows { get; } public IReadOnlyList<Sheet> Sheets => _sheets; public int Count => _sheets.Count; private static int CountSheets(Length extent, Length step, Length printable) { if (extent <= printable) return 1; // Первый лист покрывает всю печатную область, каждый следующий // добавляет только шаг: разница между ними и есть перекрытие. var remaining = extent - printable; return 1 + (int)Math.Ceiling(remaining / step); } private void Build() { for (var row = 0; row < Rows; row++) for (var column = 0; column < Columns; column++) { // Строки нумеруются сверху вниз, как читается бумажная стопка, // хотя ось Y чертежа направлена вверх. var originX = ContentMin.X + Layout.StepX * column; var originY = ContentMax.Y - Layout.StepY * row - Layout.PrintableHeight; _sheets.Add(new Sheet( column, row, LabelOf(column, row), new Point2(originX, originY), Left: column > 0 ? LabelOf(column - 1, row) : null, Right: column < Columns - 1 ? LabelOf(column + 1, row) : null, Above: row > 0 ? LabelOf(column, row - 1) : null, Below: row < Rows - 1 ? LabelOf(column, row + 1) : null)); } } public static string LabelOf(int column, int row) { var letters = string.Empty; var value = row; do { letters = (char)('A' + value % 26) + letters; value = value / 26 - 1; } while (value >= 0); return letters + (column + 1).ToString(System.Globalization.CultureInfo.InvariantCulture); } public Sheet this[int column, int row] => _sheets[row * Columns + column]; }