merge: resolve .gitignore conflict, keep both entries

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-13 07:22:45 -04:00
70 changed files with 4008 additions and 795 deletions

View File

@@ -155,6 +155,28 @@ namespace OpenNest.Geometry
Center.Y + Radius * System.Math.Sin(EndAngle));
}
/// <summary>
/// Splits the arc at the given point, returning two sub-arcs.
/// Either half may be null if the split point coincides with an endpoint.
/// </summary>
/// <param name="point">The point at which to split the arc.</param>
/// <returns>A tuple of (first, second) sub-arcs.</returns>
public (Arc first, Arc second) SplitAt(Vector point)
{
if (point.DistanceTo(StartPoint()) < Tolerance.Epsilon)
return (null, new Arc(Center, Radius, StartAngle, EndAngle, IsReversed));
if (point.DistanceTo(EndPoint()) < Tolerance.Epsilon)
return (new Arc(Center, Radius, StartAngle, EndAngle, IsReversed), null);
var splitAngle = Angle.NormalizeRad(Center.AngleTo(point));
var firstArc = new Arc(Center, Radius, StartAngle, splitAngle, IsReversed);
var secondArc = new Arc(Center, Radius, splitAngle, EndAngle, IsReversed);
return (firstArc, secondArc);
}
/// <summary>
/// Returns true if the given arc has the same center point and radius as this.
/// </summary>
@@ -388,7 +410,7 @@ namespace OpenNest.Geometry
boundingBox.X = minX;
boundingBox.Y = minY;
boundingBox.Width = maxX - minX;
boundingBox.Height = maxY - minY;
boundingBox.Length = maxY - minY;
}
public override Entity OffsetEntity(double distance, OffsetSide side)

View File

@@ -13,7 +13,7 @@ namespace OpenNest.Geometry
double minX = boxes[0].X;
double minY = boxes[0].Y;
double maxX = boxes[0].X + boxes[0].Width;
double maxY = boxes[0].Y + boxes[0].Height;
double maxY = boxes[0].Y + boxes[0].Length;
foreach (var box in boxes)
{

View File

@@ -15,14 +15,14 @@ namespace OpenNest.Geometry
{
Location = new Vector(x, y);
Width = w;
Height = h;
Length = h;
}
public Vector Location;
public Vector Center
{
get { return new Vector(X + Width * 0.5, Y + Height * 0.5); }
get { return new Vector(X + Width * 0.5, Y + Length * 0.5); }
}
public Size Size;
@@ -45,10 +45,10 @@ namespace OpenNest.Geometry
set { Size.Width = value; }
}
public double Height
public double Length
{
get { return Size.Height; }
set { Size.Height = value; }
get { return Size.Length; }
set { Size.Length = value; }
}
public void MoveTo(double x, double y)
@@ -86,7 +86,7 @@ namespace OpenNest.Geometry
public double Top
{
get { return Y + Height; }
get { return Y + Length; }
}
public double Bottom
@@ -96,12 +96,12 @@ namespace OpenNest.Geometry
public double Area()
{
return Width * Height;
return Width * Length;
}
public double Perimeter()
{
return Width * 2 + Height * 2;
return Width * 2 + Length * 2;
}
public bool Intersects(Box box)
@@ -197,12 +197,12 @@ namespace OpenNest.Geometry
public Box Offset(double d)
{
return new Box(X - d, Y - d, Width + d * 2, Height + d * 2);
return new Box(X - d, Y - d, Width + d * 2, Length + d * 2);
}
public override string ToString()
{
return string.Format("[Box: X={0}, Y={1}, Width={2}, Height={3}]", X, Y, Width, Height);
return string.Format("[Box: X={0}, Y={1}, Width={2}, Length={3}]", X, Y, Width, Length);
}
}
}

View File

@@ -23,7 +23,7 @@
var x = large.Left;
var y = large.Bottom;
var w = small.Left - x;
var h = large.Height;
var h = large.Length;
return new Box(x, y, w, h);
}
@@ -49,7 +49,7 @@
var x = small.Right;
var y = large.Bottom;
var w = large.Right - x;
var h = large.Height;
var h = large.Length;
return new Box(x, y, w, h);
}

View File

@@ -263,7 +263,7 @@ namespace OpenNest.Geometry
boundingBox.X = Center.X - Radius;
boundingBox.Y = Center.Y - Radius;
boundingBox.Width = Diameter;
boundingBox.Height = Diameter;
boundingBox.Length = Diameter;
}
public override Entity OffsetEntity(double distance, OffsetSide side)

View File

@@ -381,12 +381,12 @@ namespace OpenNest.Geometry
if (StartPoint.Y < EndPoint.Y)
{
boundingBox.Y = StartPoint.Y;
boundingBox.Height = EndPoint.Y - StartPoint.Y;
boundingBox.Length = EndPoint.Y - StartPoint.Y;
}
else
{
boundingBox.Y = EndPoint.Y;
boundingBox.Height = StartPoint.Y - EndPoint.Y;
boundingBox.Length = StartPoint.Y - EndPoint.Y;
}
}
@@ -414,6 +414,25 @@ namespace OpenNest.Geometry
return OffsetEntity(distance, side);
}
/// <summary>
/// Splits the line at the given point, returning two sub-lines.
/// Either half may be null if the split point coincides with an endpoint.
/// </summary>
/// <param name="point">The point at which to split the line.</param>
/// <returns>A tuple of (first, second) sub-lines.</returns>
public (Line first, Line second) SplitAt(Vector point)
{
var first = point.DistanceTo(StartPoint) < Tolerance.Epsilon
? null
: new Line(StartPoint, point);
var second = point.DistanceTo(EndPoint) < Tolerance.Epsilon
? null
: new Line(point, EndPoint);
return (first, second);
}
/// <summary>
/// Gets the closest point on the line to the given point.
/// </summary>

View File

@@ -312,7 +312,7 @@ namespace OpenNest.Geometry
boundingBox.X = minX;
boundingBox.Y = minY;
boundingBox.Width = maxX - minX;
boundingBox.Height = maxY - minY;
boundingBox.Length = maxY - minY;
}
public override Entity OffsetEntity(double distance, OffsetSide side)

View File

@@ -201,6 +201,68 @@ namespace OpenNest.Geometry
return closestPt;
}
/// <summary>
/// Returns a new shape with entities reordered so that the given point on
/// the given entity becomes the new start point of the contour.
/// </summary>
/// <param name="point">The point on the entity to reindex at.</param>
/// <param name="entity">The entity containing the point.</param>
/// <returns>A new reindexed shape.</returns>
public Shape ReindexAt(Vector point, Entity entity)
{
// Circle case: return a new shape with just the circle
if (entity is Circle)
{
var result = new Shape();
result.Entities.Add(entity);
return result;
}
var i = Entities.IndexOf(entity);
if (i < 0)
throw new ArgumentException("Entity not found in shape", nameof(entity));
// Split the entity at the point
Entity firstHalf = null;
Entity secondHalf = null;
if (entity is Line line)
{
var (f, s) = line.SplitAt(point);
firstHalf = f;
secondHalf = s;
}
else if (entity is Arc arc)
{
var (f, s) = arc.SplitAt(point);
firstHalf = f;
secondHalf = s;
}
// Build reindexed entity list
var entities = new List<Entity>();
// secondHalf of split entity (if not null)
if (secondHalf != null)
entities.Add(secondHalf);
// Entities after the split index (wrapping)
for (var j = i + 1; j < Entities.Count; j++)
entities.Add(Entities[j]);
// Entities before the split index (wrapping)
for (var j = 0; j < i; j++)
entities.Add(Entities[j]);
// firstHalf of split entity (if not null)
if (firstHalf != null)
entities.Add(firstHalf);
var reindexed = new Shape();
reindexed.Entities.AddRange(entities);
return reindexed;
}
/// <summary>
/// Converts the shape to a polygon.
/// </summary>
@@ -399,7 +461,7 @@ namespace OpenNest.Geometry
public override Entity OffsetEntity(double distance, OffsetSide side)
{
var offsetShape = new Shape();
var definedShape = new DefinedShape(this);
var definedShape = new ShapeProfile(this);
Entity lastEntity = null;
Entity lastOffsetEntity = null;

View File

@@ -2,14 +2,14 @@
namespace OpenNest.Geometry
{
public class DefinedShape
public class ShapeProfile
{
public DefinedShape(Shape shape)
public ShapeProfile(Shape shape)
{
Update(shape.Entities);
}
public DefinedShape(List<Entity> entities)
public ShapeProfile(List<Entity> entities)
{
Update(entities);
}

View File

@@ -1,16 +1,16 @@
using System;
using System;
namespace OpenNest.Geometry
{
public struct Size
{
public Size(double width, double height)
public Size(double width, double length)
{
Height = height;
Length = length;
Width = width;
}
public double Height;
public double Length;
public double Width;
@@ -21,10 +21,10 @@ namespace OpenNest.Geometry
if (a.Length > 2)
throw new FormatException("Invalid size format.");
var height = double.Parse(a[0]);
var length = double.Parse(a[0]);
var width = double.Parse(a[1]);
return new Size(width, height);
return new Size(width, length);
}
public static bool TryParse(string s, out Size size)
@@ -44,12 +44,12 @@ namespace OpenNest.Geometry
public override string ToString()
{
return string.Format("{0} x {1}", Height, Width);
return string.Format("{0} x {1}", Length, Width);
}
public string ToString(int decimalPlaces)
{
return string.Format("{0} x {1}", System.Math.Round(Height, decimalPlaces), System.Math.Round(Width, decimalPlaces));
return string.Format("{0} x {1}", System.Math.Round(Length, decimalPlaces), System.Math.Round(Width, decimalPlaces));
}
}
}