fix(ui): place bend lines in the program frame

Drawing.Bends stay in the DXF's source frame while CadImporter moves the
program so its first pierce sits at the origin (Source.Offset). The plate
renderer added part.Location to raw bend points, so every bend and etch
mark was shifted by its drawing's pierce offset, visible on the drawing
library set preview and on plates alike. Remove Source.Offset before
rotating and placing.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
ajandClaude Opus 5.5 committed 2026-10-27 12:57:45 -04:00
1 parent 19be5a5ece
commit eedff85904
2 files changed
+56 -25

No files matched your search

@@ -0,0 +1,40 @@
using OpenNest.Bending;
using OpenNest.Controls;
using OpenNest.Geometry;
using OpenNest.Math;
namespace OpenNest.WinForms.Tests.Controls;
/// <summary>
/// Bends are kept in the drawing's source frame while its program starts at the origin, so a
/// placed part draws them with <c>Source.Offset</c> removed.
/// </summary>
public class BendLinePlacementTests
{
[Fact]
public void BendToWorld_RemovesSourceOffsetBeforePlacing()
{
var drawing = new Drawing("bent", new CNC.Program());
drawing.Source.Offset = new Vector(100, 50);
// In the source frame the bend runs across the part at local x = 5.
var bend = new Bend { StartPoint = new Vector(105, 50), EndPoint = new Vector(105, 60) };
var part = new Part(drawing, new Vector(10, 20));
Assert.Equal(new Vector(15, 20), PlateRenderer.BendToWorld(part, bend.StartPoint));
Assert.Equal(new Vector(15, 30), PlateRenderer.BendToWorld(part, bend.EndPoint));
}
[Fact]
public void BendToWorld_RotatesAboutTheProgramOrigin()
{
var drawing = new Drawing("bent", new CNC.Program());
drawing.Source.Offset = new Vector(100, 50);
var part = new Part(drawing, new Vector(10, 20));
part.Rotate(Angle.HalfPI, part.Location);
var world = PlateRenderer.BendToWorld(part, new Vector(105, 50));
Assert.Equal(10, world.X, 9);
Assert.Equal(25, world.Y, 9);
}
}
+16 -25
View File
@@ -465,25 +465,25 @@ namespace OpenNest.Controls
foreach (var bend in part.BaseDrawing.Bends)
{
var start = bend.StartPoint;
var end = bend.EndPoint;
if (part.Rotation != 0)
{
start = start.Rotate(part.Rotation);
end = end.Rotate(part.Rotation);
}
start = start + part.Location;
end = end + part.Location;
var pt1 = view.PointWorldToGraph(start);
var pt2 = view.PointWorldToGraph(end);
var pt1 = view.PointWorldToGraph(BendToWorld(part, bend.StartPoint));
var pt2 = view.PointWorldToGraph(BendToWorld(part, bend.EndPoint));
g.DrawLine(bendPen, pt1, pt2);
}
}
/// <summary>
/// Maps a bend point to world space. Bends stay in the drawing's source frame while the
/// program is moved by -<c>Source.Offset</c>, so the offset comes off before placing.
/// </summary>
internal static Vector BendToWorld(Part part, Vector point)
{
var local = point - part.BaseDrawing.Source.Offset;
if (part.Rotation != 0)
local = local.Rotate(part.Rotation);
return local + part.Location;
}
private void DrawEtchMarks(Graphics g, Part part, bool muted)
{
if (
@@ -501,17 +501,8 @@ namespace OpenNest.Controls
if (bend.Direction != BendDirection.Up)
continue;
var start = bend.StartPoint;
var end = bend.EndPoint;
if (part.Rotation != 0)
{
start = start.Rotate(part.Rotation);
end = end.Rotate(part.Rotation);
}
start = start + part.Location;
end = end + part.Location;
var start = BendToWorld(part, bend.StartPoint);
var end = BendToWorld(part, bend.EndPoint);
var length = bend.Length;
var angle = bend.StartPoint.AngleTo(bend.EndPoint) + part.Rotation;