using System; using System.Collections.Generic; using System.Linq; using OpenNest.Collections; namespace OpenNest { public partial class Plate { /// /// Groups of parts placed one kerf apart to share common-line cuts (see /// docs/common-line-cutting.md). A part removed from leaves its group. /// public ObservableList CommonLines { get; } /// The common-line group holding , or null. public CommonLineGroup CommonLineGroupOf(Part part) => CommonLines.FirstOrDefault(group => group.Contains(part)); /// /// Puts into one common-line group at , /// merging any groups they already belong to. Every part must be on this plate. /// public CommonLineGroup JoinCommonLine(IEnumerable parts, double kerf) { ArgumentNullException.ThrowIfNull(parts); var joined = parts.ToList(); if (joined.Any(part => part == null || !Parts.Contains(part))) throw new ArgumentException("Every part in a common line must be on the plate.", nameof(parts)); var merged = CommonLines.Where(group => joined.Any(group.Contains)).ToList(); var members = merged.SelectMany(group => group.Members).Concat(joined); var result = new CommonLineGroup(members, kerf); foreach (var group in merged) CommonLines.Remove(group); CommonLines.Add(result); return result; } /// /// Cuts every common line twice, as slice 1 did: each member cuts its whole perimeter and /// the second pass runs in kerf the first opened. Off by default: Plan Cutting cuts each /// shared line once and each member's remaining edges after it (see /// docs/common-line-cutting.md). Choose this for a post that cannot write single-pass cuts. /// public bool CutCommonLinesTwice { get; set; } /// /// True when the plate's common lines are cut once: it has groups and does not cut them twice. /// public bool CutsCommonLinesOnce => CommonLines.Count > 0 && !CutCommonLinesTwice; /// Removes the common-line group holding ; true when there was one. public bool RemoveCommonLine(Part part) => CommonLineGroupOf(part) is { } group && CommonLines.Remove(group); } }