feat: update FindBestRotation to use rotating calipers algorithm
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -231,39 +231,60 @@ namespace OpenNest.Geometry
|
|||||||
|
|
||||||
public static class EntityExtensions
|
public static class EntityExtensions
|
||||||
{
|
{
|
||||||
public static double FindBestRotation(this List<Entity> entities, double stepAngle, double startAngle = 0, double endAngle = Angle.TwoPI)
|
public static BoundingRectangleResult FindBestRotation(this List<Entity> entities, double startAngle = 0, double endAngle = Angle.TwoPI)
|
||||||
{
|
{
|
||||||
startAngle = Angle.NormalizeRad(startAngle);
|
var points = new List<Vector>();
|
||||||
|
|
||||||
if (!endAngle.IsEqualTo(Angle.TwoPI))
|
foreach (var entity in entities)
|
||||||
endAngle = Angle.NormalizeRad(endAngle);
|
|
||||||
|
|
||||||
if (stepAngle.IsEqualTo(0.0))
|
|
||||||
return startAngle;
|
|
||||||
|
|
||||||
entities.ForEach(e => e.Rotate(startAngle));
|
|
||||||
|
|
||||||
var bestAngle = startAngle;
|
|
||||||
var bestArea = entities.GetBoundingBox().Area();
|
|
||||||
|
|
||||||
var steps = startAngle < endAngle
|
|
||||||
? (endAngle - startAngle) / stepAngle
|
|
||||||
: (endAngle + Angle.TwoPI) - startAngle / stepAngle;
|
|
||||||
|
|
||||||
for (int i = 1; i <= steps; ++i)
|
|
||||||
{
|
{
|
||||||
entities.ForEach(e => e.Rotate(stepAngle));
|
switch (entity.Type)
|
||||||
|
|
||||||
var area = entities.GetBoundingBox().Area();
|
|
||||||
|
|
||||||
if (area < bestArea)
|
|
||||||
{
|
{
|
||||||
bestArea = area;
|
case EntityType.Line:
|
||||||
bestAngle = startAngle + stepAngle * i;
|
var line = (Line)entity;
|
||||||
|
points.Add(line.StartPoint);
|
||||||
|
points.Add(line.EndPoint);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntityType.Arc:
|
||||||
|
var arc = (Arc)entity;
|
||||||
|
points.Add(arc.StartPoint());
|
||||||
|
points.Add(arc.EndPoint());
|
||||||
|
points.Add(arc.Center.Offset(arc.Radius, 0));
|
||||||
|
points.Add(arc.Center.Offset(-arc.Radius, 0));
|
||||||
|
points.Add(arc.Center.Offset(0, arc.Radius));
|
||||||
|
points.Add(arc.Center.Offset(0, -arc.Radius));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntityType.Circle:
|
||||||
|
var circle = (Circle)entity;
|
||||||
|
points.Add(circle.Center.Offset(circle.Radius, 0));
|
||||||
|
points.Add(circle.Center.Offset(-circle.Radius, 0));
|
||||||
|
points.Add(circle.Center.Offset(0, circle.Radius));
|
||||||
|
points.Add(circle.Center.Offset(0, -circle.Radius));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntityType.Polygon:
|
||||||
|
var polygon = (Polygon)entity;
|
||||||
|
points.AddRange(polygon.Vertices);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case EntityType.Shape:
|
||||||
|
var shape = (Shape)entity;
|
||||||
|
var subResult = shape.Entities.FindBestRotation(startAngle, endAngle);
|
||||||
|
return subResult;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return bestAngle;
|
if (points.Count == 0)
|
||||||
|
return new BoundingRectangleResult(startAngle, 0, 0);
|
||||||
|
|
||||||
|
var hull = ConvexHull.Compute(points);
|
||||||
|
|
||||||
|
bool constrained = !startAngle.IsEqualTo(0) || !endAngle.IsEqualTo(Angle.TwoPI);
|
||||||
|
|
||||||
|
return constrained
|
||||||
|
? RotatingCalipers.MinimumBoundingRectangle(hull, startAngle, endAngle)
|
||||||
|
: RotatingCalipers.MinimumBoundingRectangle(hull);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -598,16 +598,15 @@ namespace OpenNest.Geometry
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public double FindBestRotation(double stepAngle)
|
public BoundingRectangleResult FindBestRotation()
|
||||||
{
|
{
|
||||||
var entities = new List<Entity>(ToLines());
|
return RotatingCalipers.MinimumBoundingRectangle(Vertices);
|
||||||
return entities.FindBestRotation(stepAngle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public double FindBestRotation(double stepAngle, double startAngle, double endAngle)
|
public BoundingRectangleResult FindBestRotation(double startAngle, double endAngle)
|
||||||
{
|
{
|
||||||
var entities = new List<Entity>(ToLines());
|
var hull = ConvexHull.Compute(Vertices);
|
||||||
return entities.FindBestRotation(stepAngle, startAngle, endAngle);
|
return RotatingCalipers.MinimumBoundingRectangle(hull, startAngle, endAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -599,14 +599,14 @@ namespace OpenNest.Geometry
|
|||||||
get { return EntityType.Shape; }
|
get { return EntityType.Shape; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public double FindBestRotation(double stepAngle)
|
public BoundingRectangleResult FindBestRotation()
|
||||||
{
|
{
|
||||||
return Entities.FindBestRotation(stepAngle);
|
return Entities.FindBestRotation();
|
||||||
}
|
}
|
||||||
|
|
||||||
public double FindBestRotation(double stepAngle, double startAngle, double endAngle)
|
public BoundingRectangleResult FindBestRotation(double startAngle, double endAngle)
|
||||||
{
|
{
|
||||||
return Entities.FindBestRotation(stepAngle, startAngle, endAngle);
|
return Entities.FindBestRotation(startAngle, endAngle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user