mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-07 13:05:52 -05:00
Holes and radii need sizes on the drawing as well as the overall extents. Select circles or arcs, right-click and choose Add Radius Dimension or Add Diameter Dimension. The value is measured live from the curve, found by its entity ID, so it follows edits; only the leader angle and label offset are saved. A radius on an arc stays on its sweep, and labels are kept clear of the curve and center. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
157 lines
5.8 KiB
C#
157 lines
5.8 KiB
C#
using OpenNest.Dimensions;
|
|
using OpenNest.Geometry;
|
|
using OpenNest.Math;
|
|
|
|
namespace OpenNest.Tests.Dimensions;
|
|
|
|
public class RadialDimensionTests
|
|
{
|
|
private static readonly Layer Cut = new("0") { IsVisible = true };
|
|
|
|
private static Circle Hole(double x = 5, double y = 3, double radius = 1) =>
|
|
new(x, y, radius) { Layer = Cut, Id = Guid.NewGuid() };
|
|
|
|
private static DimensionLayout Layout(Entity curve, DimensionKind kind, double angle, double offset = 0.5) =>
|
|
DimensionBuilder.Layout([curve], new DrawingDimension
|
|
{
|
|
Kind = kind,
|
|
EntityId = curve.Id,
|
|
Angle = angle,
|
|
Offset = offset,
|
|
});
|
|
|
|
[Fact]
|
|
public void Radius_MeasuresTheCircle_WithTheLeaderFromTheCenter()
|
|
{
|
|
var hole = Hole(radius: 1.25);
|
|
|
|
var layout = Layout(hole, DimensionKind.Radius, 0, 0.5);
|
|
|
|
Assert.True(layout.IsValid, layout.Error);
|
|
Assert.Equal(1.25, layout.Value, 9);
|
|
Assert.Equal("R1.250", layout.DisplayText);
|
|
Assert.Equal(0, layout.LineStart.DistanceTo(new Vector(5, 3)), 12);
|
|
Assert.Equal(0, layout.ArrowPoint.DistanceTo(new Vector(6.25, 3)), 12);
|
|
Assert.Equal(0, layout.LineEnd.DistanceTo(new Vector(6.75, 3)), 12);
|
|
}
|
|
|
|
[Fact]
|
|
public void Diameter_MeasuresTwiceTheRadius_WithTheLeaderAcrossTheCircle()
|
|
{
|
|
var hole = Hole(radius: 1.25);
|
|
|
|
var layout = Layout(hole, DimensionKind.Diameter, Angle.HalfPI, 0.5);
|
|
|
|
Assert.True(layout.IsValid, layout.Error);
|
|
Assert.Equal(2.5, layout.Value, 9);
|
|
Assert.Equal("\u00D82.500", layout.DisplayText);
|
|
Assert.Equal(0, layout.LineStart.DistanceTo(new Vector(5, 1.75)), 12);
|
|
Assert.Equal(0, layout.ArrowPoint.DistanceTo(new Vector(5, 4.25)), 12);
|
|
Assert.Equal(0, layout.LineEnd.DistanceTo(new Vector(5, 4.75)), 12);
|
|
}
|
|
|
|
[Fact]
|
|
public void RadiusOnAnArc_StaysOnItsSweep()
|
|
{
|
|
// A quarter arc from 0 to 90 degrees; a leader asked for at 180 degrees snaps to the
|
|
// nearer end, 90 degrees.
|
|
var arc = new Arc(new Vector(0, 0), 2, 0, Angle.HalfPI) { Layer = Cut, Id = Guid.NewGuid() };
|
|
|
|
var layout = Layout(arc, DimensionKind.Radius, System.Math.PI * 0.9);
|
|
|
|
Assert.True(layout.IsValid, layout.Error);
|
|
Assert.Equal(2, layout.Value, 9);
|
|
Assert.Equal(Angle.HalfPI, layout.Angle, 9);
|
|
Assert.Equal(0, layout.ArrowPoint.DistanceTo(new Vector(0, 2)), 9);
|
|
}
|
|
|
|
[Fact]
|
|
public void AMissingCurve_IsNotShown()
|
|
{
|
|
var layout = DimensionBuilder.Layout([Hole()], new DrawingDimension
|
|
{
|
|
Kind = DimensionKind.Radius,
|
|
EntityId = Guid.NewGuid(),
|
|
Angle = 0,
|
|
Offset = 1,
|
|
});
|
|
|
|
Assert.False(layout.IsValid);
|
|
Assert.Contains("not cut", layout.Error);
|
|
}
|
|
|
|
[Fact]
|
|
public void ALine_CannotBeMeasuredAsARadius()
|
|
{
|
|
var line = new Line(0, 0, 4, 0) { Layer = Cut, Id = Guid.NewGuid() };
|
|
|
|
Assert.False(DimensionBuilder.IsRadialTarget(line));
|
|
Assert.Empty(DimensionBuilder.MissingRadial([line], DimensionKind.Radius, [line], []));
|
|
Assert.False(Layout(line, DimensionKind.Radius, 0).IsValid);
|
|
}
|
|
|
|
[Fact]
|
|
public void MissingRadial_AddsOncePerCurveAndKind_OutsideTheCurve()
|
|
{
|
|
var hole = Hole(radius: 1);
|
|
var arc = new Arc(new Vector(0, 0), 2, 0, System.Math.PI) { Layer = Cut, Id = Guid.NewGuid() };
|
|
|
|
var first = DimensionBuilder.MissingRadial([hole, arc], DimensionKind.Radius, [hole, arc], []);
|
|
|
|
Assert.Equal(2, first.Count);
|
|
Assert.All(first, d => Assert.True(d.Offset > 0));
|
|
Assert.Equal(Angle.HalfPI, first[1].Angle, 9); // The middle of the half arc.
|
|
Assert.Empty(DimensionBuilder.MissingRadial([hole, arc], DimensionKind.Radius, [hole, arc], first));
|
|
Assert.Equal(2, DimensionBuilder.MissingRadial([hole, arc], DimensionKind.Diameter, [hole, arc], first).Count);
|
|
}
|
|
|
|
[Fact]
|
|
public void MissingRadial_OnAReversedArc_PointsThroughItsMiddle()
|
|
{
|
|
// Clockwise from 90 down to 0 degrees covers the first quadrant; its middle is 45.
|
|
var arc = new Arc(new Vector(0, 0), 2, Angle.HalfPI, 0, reversed: true) { Layer = Cut, Id = Guid.NewGuid() };
|
|
|
|
var added = Assert.Single(DimensionBuilder.MissingRadial([arc], DimensionKind.Radius, [arc], []));
|
|
|
|
Assert.Equal(Angle.HalfPI / 2, added.Angle, 9);
|
|
}
|
|
|
|
[Theory]
|
|
[InlineData(8, 3, 2, 0)] // Outside to the right: 2 past the curve.
|
|
[InlineData(5, 3.5, -0.5, 0)] // Inside, near the center: kept the minimum clear of it.
|
|
[InlineData(6.02, 3, 0.1, 0)] // Hugging the curve: pushed the minimum out.
|
|
public void Dragging_PutsTheLabelUnderTheCursor_KeptClearOfCurveAndCenter(double x, double y,
|
|
double expectedOffset, double expectedAngle)
|
|
{
|
|
var layout = Layout(Hole(radius: 1), DimensionKind.Radius, 0);
|
|
|
|
var (offset, angle) = layout.RadialPlacementAt(new Vector(x, y), 0.1);
|
|
|
|
Assert.Equal(expectedOffset, offset, 9);
|
|
if (y == 3)
|
|
Assert.Equal(expectedAngle, angle, 9);
|
|
else
|
|
Assert.Equal(Angle.HalfPI, angle, 9);
|
|
}
|
|
|
|
[Fact]
|
|
public void Dragging_ASmallHolesLabelInside_KeepsItOutsideInstead()
|
|
{
|
|
// Radius 0.15 with a 0.1 minimum: no inside spot is clear of both curve and center.
|
|
var layout = Layout(Hole(radius: 0.15), DimensionKind.Diameter, 0);
|
|
|
|
var (offset, _) = layout.RadialPlacementAt(new Vector(5.05, 3), 0.1);
|
|
|
|
Assert.Equal(0.1, offset, 9);
|
|
}
|
|
|
|
[Fact]
|
|
public void Clone_KeepsTheCurveAndAngle()
|
|
{
|
|
var id = Guid.NewGuid();
|
|
var clone = new DrawingDimension { Kind = DimensionKind.Diameter, EntityId = id, Angle = 1.5, Offset = 2 }.Clone();
|
|
|
|
Assert.Equal((DimensionKind.Diameter, id, 1.5, 2.0), (clone.Kind, clone.EntityId, clone.Angle, clone.Offset));
|
|
}
|
|
}
|