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);
}
}