mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-10-30 11:51:08 -04:00
fix(ui): scale part label search precision to material width
The plate view searched for each part's label point with PolyLabel's fixed 0.5" precision, a third of a 1.5" part, so the search stopped on the first interior cell and put labels near edges instead of in the thickest spot. Precision is now 5% of the part's mean material width (2 x net area over total outline length), so small, slender or heavily cut-out parts refine further while large solid ones stay cheap. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
add94dff6c
commit
3d1270a860
3 files changed
+76
-1
No files matched your search
@@ -24,6 +24,43 @@ namespace OpenNest.Geometry
|
||||
public static Vector Find(Polygon outer, IList<Polygon> holes, double precision, int maxCells) =>
|
||||
Find(outer, holes, precision, maxCells, out _);
|
||||
|
||||
/// <summary>
|
||||
/// A precision proportional to the shape's mean material width (twice the net area over
|
||||
/// the total outline length, holes included), so small or slender shapes refine further
|
||||
/// than large solid ones. A fixed precision near the shape's size stops at the first
|
||||
/// interior cell.
|
||||
/// </summary>
|
||||
public static double ThicknessPrecision(Polygon outer, IList<Polygon> holes = null, double fraction = 0.05)
|
||||
{
|
||||
var area = outer.Area();
|
||||
var length = ClosedLength(outer);
|
||||
|
||||
if (holes != null)
|
||||
{
|
||||
for (var i = 0; i < holes.Count; i++)
|
||||
{
|
||||
area -= holes[i].Area();
|
||||
length += ClosedLength(holes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!(area > 0) || !(length > 0))
|
||||
return 1e-9;
|
||||
|
||||
return System.Math.Max(fraction * 2 * area / length, 1e-9);
|
||||
}
|
||||
|
||||
private static double ClosedLength(Polygon polygon)
|
||||
{
|
||||
var verts = polygon.Vertices;
|
||||
var sum = 0.0;
|
||||
|
||||
for (int i = 0, j = verts.Count - 1; i < verts.Count; j = i++)
|
||||
sum += verts[j].DistanceTo(verts[i]);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
internal static Vector Find(
|
||||
Polygon outer,
|
||||
IList<Polygon> holes,
|
||||
|
||||
@@ -115,6 +115,44 @@ public class PolyLabelTests
|
||||
Assert.True(result.X < 20, $"Expected label in left bar, got X={result.X}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThicknessPrecision_FindsThickBarOfSmallPart()
|
||||
{
|
||||
// 1.5-unit C-shape: left bar 0.6 wide, arms 0.15 tall. A fixed 0.5 precision is a
|
||||
// third of the part and stops on the first interior cell.
|
||||
var p = new Polygon();
|
||||
p.Vertices.Add(new Vector(0, 0));
|
||||
p.Vertices.Add(new Vector(1.5, 0));
|
||||
p.Vertices.Add(new Vector(1.5, 0.15));
|
||||
p.Vertices.Add(new Vector(0.6, 0.15));
|
||||
p.Vertices.Add(new Vector(0.6, 1.35));
|
||||
p.Vertices.Add(new Vector(1.5, 1.35));
|
||||
p.Vertices.Add(new Vector(1.5, 1.5));
|
||||
p.Vertices.Add(new Vector(0, 1.5));
|
||||
|
||||
var result = PolyLabel.Find(p, null, PolyLabel.ThicknessPrecision(p));
|
||||
|
||||
// Any height along the bar is equally clear; its centreline is not.
|
||||
Assert.Equal(0.3, result.X, 0.02);
|
||||
Assert.InRange(result.Y, 0.3, 1.2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ThicknessPrecision_ScalesWithMaterialWidth()
|
||||
{
|
||||
var hole = new Polygon();
|
||||
hole.Vertices.Add(new Vector(20, 20));
|
||||
hole.Vertices.Add(new Vector(80, 20));
|
||||
hole.Vertices.Add(new Vector(80, 80));
|
||||
hole.Vertices.Add(new Vector(20, 80));
|
||||
|
||||
// Square side s: 2 * s^2 / 4s = s / 2.
|
||||
Assert.Equal(0.05 * 50, PolyLabel.ThicknessPrecision(Square(100)), 9);
|
||||
Assert.Equal(0.05 * 0.5, PolyLabel.ThicknessPrecision(Square(1)), 9);
|
||||
// A 20-wide frame is thinner than the solid square, so it refines further.
|
||||
Assert.True(PolyLabel.ThicknessPrecision(Square(100), new[] { hole }) < PolyLabel.ThicknessPrecision(Square(100)));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void DegeneratePolygon_ReturnsFallback()
|
||||
{
|
||||
|
||||
@@ -237,7 +237,7 @@ namespace OpenNest
|
||||
holes.Add(cutout.ToPolygonWithTolerance(0.1));
|
||||
}
|
||||
|
||||
return PolyLabel.Find(outer, holes);
|
||||
return PolyLabel.Find(outer, holes, PolyLabel.ThicknessPrecision(outer, holes));
|
||||
}
|
||||
|
||||
public void Update(DrawControl plateView)
|
||||
|
||||
Reference in new issue
Block a user