using System.Collections.Generic; using OpenNest.Geometry; namespace OpenNest.Breakoffs { /// /// A resolved against a drawing's entities. When is /// set nothing else is meaningful and the breakoff is not applied. /// public sealed class BreakoffLayout { internal BreakoffLayout(string error) => Error = error; internal BreakoffLayout() { } public string Error { get; } public bool IsValid => Error == null; /// The joining line in travel order from its start. public IReadOnlyList BreakLine { get; internal set; } public double Length { get; internal set; } /// The closed outline around part and scrap, with its joints made exact. public IReadOnlyList Outline { get; internal set; } /// The scrap side's closed boundary (part of the outline plus the joining line). public IReadOnlyList Scrap { get; internal set; } /// /// One open cut per section of the joining line between tabs, on the break layer and /// travel-ordered with the scrap to its left, so each is entered from the scrap. /// public IReadOnlyList> Cuts { get; internal set; } /// Tab centers used, as distances along . public IReadOnlyList TabCenters { get; internal set; } public double TabWidth { get; internal set; } /// Entities the outline and cuts replace: the original outline and joining line. internal IReadOnlyList ReplacedEntities { get; set; } public Vector PointAt(double distance) => BreakoffPath.PointAt(BreakLine, distance); /// The distance along the joining line closest to . public double DistanceOf(Vector point) => BreakoffPath.DistanceOf(BreakLine, point); /// /// for tab limited so the tab stays on the /// joining line and keeps a gap from its neighbours. /// public double ClampTabCenter(int index, double center) { var half = TabWidth / 2; var min = index == 0 ? half : TabCenters[index - 1] + TabWidth + MinGap; var max = index == TabCenters.Count - 1 ? Length - half : TabCenters[index + 1] - TabWidth - MinGap; return max < min ? TabCenters[index] : System.Math.Clamp(center, min, max); } // Wider than the builder's overlap tolerance, so a clamped drag always resolves. internal double MinGap => System.Math.Max(TabWidth / 2, 2 * BreakoffBuilder.JoinTolerance); } }