/
docNemo
/
clothes-graph
Обзор
Документация
Войти
/
docNemo
/
clothes-graph
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
main
src/ClothesGraph.Model/PatternDocument.cs
164 строки
8 KB
docNemo
Запрос на слияние 'interface-to-spec' (
#1
) из interface-to-spec в main
09 авг 2026, 20:28
Верифицирован
09 авг 2026, 20:28
1bbc436
Код
Авторство
О чём код?
using System; using System.Collections.Generic; using System.Linq; using ClothesGraph.Geometry; using ClothesGraph.Model.Drafting; using ClothesGraph.Model.Editing; using ClothesGraph.Model.Formulas; using ClothesGraph.Model.Grading; using ClothesGraph.Model.Measurements; using ClothesGraph.Model.Pieces; using ClothesGraph.Model.Seams; using ClothesGraph.Model.Underlay; namespace ClothesGraph.Model; /// <summary> /// Документ выкройки — корень модели, к которому привязано всё остальное. /// </summary> /// <remarks> /// По мере появления деталей и швов они добавляются сюда же: документ должен /// оставаться единственной точкой входа к состоянию, которое сохраняется в файл. /// </remarks> public sealed class PatternDocument : IFormulaScope { public PatternDocument(string baseSize = "Базовый", LengthUnit formulaUnit = LengthUnit.Centimetre) { Measurements = new MeasurementSet(); Sizes = new SizeChart(baseSize); Draft = new DraftGraph(); Undo = new UndoStack(); FormulaUnit = formulaUnit; DisplayUnit = formulaUnit; // Правки чертежа проходят через журнал отмены, поэтому отмечаются // отсюда. Всё остальное — мерки, швы, подложки, раскладка — журнала // не касается и сообщает о правке само. Undo.Changed += (_, _) => MarkModified(); } /// <summary> /// Есть ли правки, не записанные в файл. /// </summary> /// <remarks> /// Признак живёт в документе, а не в окне: потерять несохранённую работу /// можно не только закрытием окна, и знать об этом обязан тот, кто держит /// само состояние. /// </remarks> public bool IsModified { get; private set; } /// <summary>Признак несохранённых правок изменился.</summary> public event EventHandler? ModifiedChanged; /// <summary>Отмечает документ изменённым.</summary> public void MarkModified() => SetModified(true); /// <summary>Сбрасывает признак правок: документ записан в файл.</summary> public void MarkSaved() => SetModified(false); private void SetModified(bool value) { if (IsModified == value) return; IsModified = value; ModifiedChanged?.Invoke(this, EventArgs.Empty); } public MeasurementSet Measurements { get; } public SizeChart Sizes { get; } public DraftGraph Draft { get; } /// <summary>Детали выкройки, собранные из линий чертежа.</summary> public IList<PatternPiece> Pieces { get; } = new List<PatternPiece>(); /// <summary> /// Швы изделия: какие участки контуров сшиваются друг с другом. /// </summary> public SeamGraph Seams { get; } = new(); public UndoStack Undo { get; } /// <summary>Настройки вывода на листы; сохраняются вместе с документом.</summary> public PrintSettings Print { get; } = new(); /// <summary> /// Ручные поправки к отдельным размерам поверх пересчёта по меркам. /// </summary> public SizeAdjustments Adjustments { get; } = new(); /// <summary>Изображения, подложенные под чертёж для работы от образца.</summary> public IList<UnderlayImage> Underlays { get; } = new List<UnderlayImage>(); /// <summary> /// Обведённые кривые, не привязанные к каркасу. /// </summary> /// <remarks> /// Такие кривые не участвуют в градации: при пересчёте на другой размер /// они остаются на месте, пока конструкция расходится. Перечисляются перед /// выводом размерного ряда, чтобы это не обнаружилось уже на бумаге. /// </remarks> public IReadOnlyList<DraftNode> UngradedTracings() => Draft.Nodes .OfType<TracedCurveNode>() .Where(node => !node.IsAnchored || node.Dependencies.Any(anchor => !Draft.Contains(anchor))) .Cast<DraftNode>() .ToArray(); /// <summary> /// Единица, в которой пишутся числа в формулах. /// </summary> /// <remarks> /// Задаётся при создании документа и дальше не меняется. Если бы она /// следовала за единицей отображения, формула «Ог/4 + 2» меняла бы смысл /// при переключении сантиметров на миллиметры: прибавка «2» означала бы /// то два сантиметра, то два миллиметра. /// </remarks> public LengthUnit FormulaUnit { get; } /// <summary> /// Единица, в которой величины показываются пользователю. На хранение /// не влияет и на смысл формул тоже. /// </summary> public LengthUnit DisplayUnit { get; set; } /// <summary>Значения мерок для указанного размера.</summary> public IReadOnlyDictionary<MeasurementId, Length> ResolveMeasurements(string? size = null) => Sizes.Resolve(size ?? Sizes.BaseSize, Measurements).Values; /// <summary> /// Пересчитывает чертёж в указанном размере вместе с источником значений /// для формул деталей. /// </summary> public (DraftEvaluation Evaluation, EvaluationValues Values) Evaluate(string? size = null) { var measurements = ResolveMeasurements(size); var evaluation = new DraftEvaluator(Draft).Evaluate(measurements, FormulaUnit); return (evaluation, new EvaluationValues(evaluation, measurements, FormulaUnit)); } public MeasurementId? FindMeasurement(string name) => Measurements.FindByName(name)?.Id; public NodeId? FindNode(string name) => Draft.FindByName(name)?.Id; public string? GetMeasurementName(MeasurementId id) => Measurements.TryGet(id, out var measurement) ? measurement!.DisplayName : null; public string? GetNodeName(NodeId id) => Draft.TryGet(id, out var node) ? node!.Name : null; /// <summary>Разбирает формулу в области имён этого документа.</summary> public Formula ParseFormula(string text) => Formula.Parse(text, this); /// <summary> /// Помечает построения, зависящие от изменённой мерки, требующими пересчёта. /// </summary> public void MeasurementChanged(MeasurementId id) => Draft.InvalidateMeasurement(id); /// <summary>Мерки, на которые ссылается хотя бы одно построение.</summary> public IReadOnlyCollection<MeasurementId> UsedMeasurements => Draft.Nodes.SelectMany(node => node.MeasurementDependencies).Distinct().ToArray(); }