Files
OpenNest/OpenNest/Controls/CutDirectionArrows.cs
T
aj a368ef0115 refactor(geometry): share cut-direction sampling primitives
Extract the pure world-space position/tangent math from the WinForms
cut-direction arrow renderer into Core (ContourSampler), keeping screen
conversion, arrowheads, and the per-move display policy in the view.
Add a contour-wide arclength scheduler (RingMoves) for measurement use:
distance carries across segment boundaries, short segments are never
omitted, and the closing vertex is not duplicated. Characterization
tests pin the arrow policy (counts, short-move skipping, CW/CCW and
full-circle sweeps, subprogram offsets, suppressed/rapid moves,
incremental mode) and the scheduler's start-vertex invariance.
2026-10-01 01:54:00 -04:00

73 lines
2.3 KiB
C#

using System.Collections.Generic;
using System.Drawing;
using OpenNest.CNC;
using OpenNest.Geometry;
namespace OpenNest.Controls
{
/// <summary>
/// Draws the cut-direction arrows for a CNC program. The position and tangent
/// math lives in <see cref="ContourSampler"/> (OpenNest.Core); this class owns
/// the display side only: screen conversion, arrowheads, and the per-move
/// spacing policy the sampler's arrow schedule implements.
/// </summary>
internal static class CutDirectionArrows
{
public static void DrawProgram(
Graphics g,
DrawControl view,
Program pgm,
ref Vector pos,
Pen pen,
double spacing,
float arrowSize
)
{
DrawProgram(g, view, pgm, pos, ref pos, pen, spacing, arrowSize);
}
private static void DrawProgram(
Graphics g,
DrawControl view,
Program pgm,
Vector basePos,
ref Vector pos,
Pen pen,
double spacing,
float arrowSize
)
{
var samples = new List<ContourSample>();
var end = ContourSampler.ProgramMoves(pgm, basePos, pos, spacing, samples);
foreach (var sample in samples)
{
var screenPt = view.PointWorldToGraph(sample.Position);
// Screen space flips Y, so the screen angle mirrors the world tangent.
var screenAngle = System.Math.Atan2(-sample.Direction.Y, sample.Direction.X);
DrawArrowHead(g, pen, screenPt, screenAngle, arrowSize);
}
pos = end;
}
private static void DrawArrowHead(Graphics g, Pen pen, PointF tip, double angle, float size)
{
var leftAngle = angle + System.Math.PI + 0.5;
var rightAngle = angle + System.Math.PI - 0.5;
var left = new PointF(
tip.X + size * (float)System.Math.Cos(leftAngle),
tip.Y + size * (float)System.Math.Sin(leftAngle)
);
var right = new PointF(
tip.X + size * (float)System.Math.Cos(rightAngle),
tip.Y + size * (float)System.Math.Sin(rightAngle)
);
g.DrawLine(pen, left, tip);
g.DrawLine(pen, right, tip);
}
}
}