mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-15 02:31:54 -04:00
Plates the engine built from stock (DrawingJobMapper.CreatePlate, used by the public result materializer, the layout check and the placement fillers) stored placement-frame zones, while live plates store them relative to the sheet's lower-left corner. The same Plate.ClampZones therefore meant two frames: the new clamp cut checks double-translated materialized plates in quadrants 2-4, and interactive fill and push on live plates read sheet-frame zones as placement coordinates, so they could put parts on clamps there. Plates built from stock now keep the stock's input zones (sheet frame, no lossy translate-and-back), and the layout check and interactive clamp obstacles map through ClampZoneFrame.ToPlacement, which reproduces the stock's placement zones bit for bit, so engine placements and validation are unchanged. Project Memory: opennest 14f93b26-2e41-41f1-b09f-87dc895bb4da
55 lines
2.6 KiB
C#
55 lines
2.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using OpenNest.Geometry;
|
|
|
|
namespace OpenNest;
|
|
|
|
/// <summary>
|
|
/// Maps a plate's <see cref="Plate.ClampZones"/>, stored in the sheet's lower-left frame
|
|
/// (<see cref="ClampRail.ResolveFor"/>), into the signed placement frame of its parts,
|
|
/// cut-offs and motions. The translation matches the sheet itself and the engine stock:
|
|
/// -Length on X in quadrants 2 and 3, -Width on Y in quadrants 3 and 4. Whole footprints are
|
|
/// kept, never clipped. Every plate uses the sheet frame, including plates the engine builds
|
|
/// from a <c>NestPlateStock</c>, so this is the only translation any consumer applies.
|
|
/// </summary>
|
|
public static class ClampZoneFrame
|
|
{
|
|
/// <summary>
|
|
/// Detached placement-frame copies in the plate's zone order; empty when there are none.
|
|
/// Throws <see cref="ArgumentException"/> for a missing or malformed zone: zone bounds stay
|
|
/// publicly mutable, so construction-time validation is not proof of current geometry.
|
|
/// </summary>
|
|
public static IReadOnlyList<ClampZone> ToPlacement(Plate plate)
|
|
{
|
|
ArgumentNullException.ThrowIfNull(plate);
|
|
var zones = plate.ClampZones;
|
|
if (zones == null || zones.Count == 0)
|
|
return Array.Empty<ClampZone>();
|
|
if (plate.Quadrant is < 1 or > 4)
|
|
throw new ArgumentException("Quadrant must be 1 through 4.", nameof(plate));
|
|
var left = plate.Quadrant is 2 or 3 ? -plate.Size.Length : 0;
|
|
var bottom = plate.Quadrant is 3 or 4 ? -plate.Size.Width : 0;
|
|
if (!double.IsFinite(left) || !double.IsFinite(bottom))
|
|
throw new ArgumentException("Sheet size must be finite.", nameof(plate));
|
|
|
|
var mapped = new ClampZone[zones.Count];
|
|
for (var i = 0; i < mapped.Length; i++)
|
|
{
|
|
var zone = zones[i];
|
|
if (zone?.Bounds == null)
|
|
throw new ArgumentException($"Clamp zone {i + 1} is missing.", nameof(plate));
|
|
var box = zone.Bounds;
|
|
var x = box.X + left;
|
|
var y = box.Y + bottom;
|
|
if (!(box.Length > 0) || !(box.Width > 0) || !double.IsFinite(box.Length)
|
|
|| !double.IsFinite(box.Width) || !double.IsFinite(box.X) || !double.IsFinite(box.Y)
|
|
|| !double.IsFinite(x) || !double.IsFinite(y)
|
|
|| !double.IsFinite(x + box.Length) || !double.IsFinite(y + box.Width))
|
|
throw new ArgumentException(
|
|
$"Clamp zone '{zone.Id}' must have finite bounds and a positive size.", nameof(plate));
|
|
mapped[i] = new ClampZone(zone.Id, new Box(x, y, box.Length, box.Width));
|
|
}
|
|
return mapped;
|
|
}
|
|
}
|