- Try all valid best fit pairs instead of only the first when qty=2, picking the best via IsBetterFill comparer (fixes suboptimal plate selection during auto-nesting) - Pre-compute best fits across all plate sizes once via BestFitCache.ComputeForSizes instead of per-size GPU evaluation - Early exit plate optimizer when all items fit (salvage < 100%) - Trim slide offset sweep range to 50% overlap to reduce candidates - Use actual geometry (ray-arc/ray-circle intersection) instead of tessellated polygons for slide distance computation — eliminates the massive line count from circle/arc tessellation - Add RayArcDistance and RayCircleDistance to SpatialQuery - Add PartGeometry.GetOffsetPerimeterEntities for non-tessellated perimeter extraction - Disable GPU slide computer (slower than CPU currently) - Remove dead SelectBestFitPair virtual method and overrides Reduces best fit computation from 7+ minutes to ~4 seconds for a 73x25" part with 30+ holes on a 48x96 plate. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
45 lines
1.6 KiB
C#
45 lines
1.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using OpenNest.Engine;
|
|
using OpenNest.Engine.Fill;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.Math;
|
|
|
|
namespace OpenNest
|
|
{
|
|
/// <summary>
|
|
/// Optimizes for the largest top-side horizontal drop.
|
|
/// Scores by count first, then minimizes Y-extent.
|
|
/// Prefers vertical nest direction and angles that keep parts narrow in Y.
|
|
/// </summary>
|
|
public class HorizontalRemnantEngine : DefaultNestEngine
|
|
{
|
|
public HorizontalRemnantEngine(Plate plate) : base(plate) { }
|
|
|
|
public override string Name => "Horizontal Remnant";
|
|
|
|
public override string Description => "Optimizes for largest top-side horizontal drop";
|
|
|
|
protected override IFillComparer CreateComparer() => new HorizontalRemnantComparer();
|
|
|
|
public override NestDirection? PreferredDirection => NestDirection.Vertical;
|
|
|
|
public override ShrinkAxis TrimAxis => ShrinkAxis.Length;
|
|
|
|
public override List<double> BuildAngles(NestItem item, ClassificationResult classification, Box workArea)
|
|
{
|
|
var baseAngles = new List<double> { classification.PrimaryAngle, classification.PrimaryAngle + Angle.HalfPI };
|
|
baseAngles.Sort((a, b) => RotatedHeight(item, a).CompareTo(RotatedHeight(item, b)));
|
|
return baseAngles;
|
|
}
|
|
|
|
private static double RotatedHeight(NestItem item, double angle)
|
|
{
|
|
var bb = item.Drawing.Program.BoundingBox();
|
|
var cos = System.Math.Abs(System.Math.Cos(angle));
|
|
var sin = System.Math.Abs(System.Math.Sin(angle));
|
|
return bb.Width * cos + bb.Length * sin;
|
|
}
|
|
}
|
|
}
|