mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-14 08:05:07 -05:00
On an enclosed machine a cutout slug that tips once cut free can stand up above the sheet and catch the enclosure door when the pallet changes. The head already keeps off cut cutouts, so this is about clearing the door, not the head. Cutting Settings > Cutouts > "Slice slugs the support grid can't hold level" (CuttingParameters.SliceTippingSlugs, off by default, saved per machine thickness and written only when on) makes Plan Cutting cut each such slug along the bed's contact lines (grid rows and columns, slat center lines) before the cutout, so no piece keeps a contact and the pieces drop between the supports. Each slice stops a kerf short of the cutout, so the pieces stay attached until the cutout's own kerf frees them together. A slug the bed holds level, or one on no contact, is left whole; a cutout holding another part or another of its part's cuts is never sliced. Slices are break cuts emitted right after the drawing's own break cuts, pierced on themselves and led straight back to their start. The released-contour proof now leaves out straight break cuts lying wholly inside one of the part's closed holes, since the grid cells they free are scrap; break cuts in material still take part. The plan fingerprint only changes when the setting is on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
80 lines
4.0 KiB
C#
80 lines
4.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest.Support
|
|
{
|
|
/// <summary>
|
|
/// What a cut part rests on: the machine's support bed, fixed to the machine and measured
|
|
/// from the plate origin into the sheet, so its position on any sheet follows from the
|
|
/// sheet's quadrant alone. A layout only reports where it touches material; the
|
|
/// <see cref="SupportAnalyzer"/> decides from those contacts whether a part stays level.
|
|
/// The laser grid (<see cref="SupportGrid"/>) is the built-in layout; straight or curved
|
|
/// slats imported from a CAD layout can follow as further subclasses.
|
|
/// </summary>
|
|
/// <summary>
|
|
/// A line a support bed's contacts lie on: along X at Y = <see cref="At"/> when
|
|
/// <see cref="AlongX"/>, else along Y at X = <see cref="At"/> (world coordinates).
|
|
/// </summary>
|
|
public readonly record struct ContactLine(bool AlongX, double At);
|
|
|
|
public abstract class SupportBed : IEquatable<SupportBed>
|
|
{
|
|
protected SupportBed(double registrationTolerance, double stabilityMargin)
|
|
{
|
|
if (!double.IsFinite(registrationTolerance) || registrationTolerance < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(registrationTolerance),
|
|
"Registration tolerance must be finite and zero or more.");
|
|
if (!double.IsFinite(stabilityMargin) || stabilityMargin < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(stabilityMargin),
|
|
"Stability margin must be finite and zero or more.");
|
|
RegistrationTolerance = registrationTolerance;
|
|
StabilityMargin = stabilityMargin;
|
|
}
|
|
|
|
/// <summary>
|
|
/// How far a sheet may sit from its nominal place on the bed, along each axis. The
|
|
/// analyzer checks the bed shifted by up to this much and keeps the worst result.
|
|
/// </summary>
|
|
public double RegistrationTolerance { get; }
|
|
|
|
/// <summary>
|
|
/// How far inside its contacts a part's center of gravity must lie for the part to count
|
|
/// as supported; it allows for slag, gas pressure and a contact that is worn low.
|
|
/// </summary>
|
|
public double StabilityMargin { get; }
|
|
|
|
/// <summary>
|
|
/// The contacts under <paramref name="material"/> (world coordinates) on a sheet in
|
|
/// <paramref name="quadrant"/>, with the bed moved by <paramref name="shift"/>. With
|
|
/// <paramref name="extremesOnly"/>, a layout may omit contacts that cannot be corners of
|
|
/// their convex hull; the analyzer needs no others.
|
|
/// </summary>
|
|
public abstract IReadOnlyList<Vector> Contacts(SupportMaterial material, int quadrant, Vector shift,
|
|
bool extremesOnly = false);
|
|
|
|
/// <summary>
|
|
/// The straight lines every contact lies on across <paramref name="region"/> (world
|
|
/// coordinates) on a sheet in <paramref name="quadrant"/>: a grid's rows and columns, a
|
|
/// slat's center line. Material cut along all of them keeps no contact, so it drops
|
|
/// between the supports (see <see cref="SlugSlicer"/>).
|
|
/// </summary>
|
|
public abstract IReadOnlyList<ContactLine> ContactLines(Box region, int quadrant);
|
|
|
|
/// <summary>This layout with every length multiplied by <paramref name="factor"/> (a unit change).</summary>
|
|
public abstract SupportBed Scaled(double factor);
|
|
|
|
public abstract bool Equals(SupportBed other);
|
|
|
|
public override bool Equals(object obj) => obj is SupportBed other && Equals(other);
|
|
|
|
public abstract override int GetHashCode();
|
|
|
|
/// <summary>-1 where a sheet in <paramref name="quadrant"/> lies on the negative side of the origin along X.</summary>
|
|
protected static double SignX(int quadrant) => quadrant is 2 or 3 ? -1 : 1;
|
|
|
|
/// <summary>-1 where a sheet in <paramref name="quadrant"/> lies on the negative side of the origin along Y.</summary>
|
|
protected static double SignY(int quadrant) => quadrant is 3 or 4 ? -1 : 1;
|
|
}
|
|
}
|