diff --git a/OpenNest.Engine/BestFit/RotationSlideStrategy.cs b/OpenNest.Engine/BestFit/RotationSlideStrategy.cs new file mode 100644 index 0000000..2447213 --- /dev/null +++ b/OpenNest.Engine/BestFit/RotationSlideStrategy.cs @@ -0,0 +1,131 @@ +using System.Collections.Generic; +using OpenNest.Geometry; +using OpenNest.Math; + +namespace OpenNest.Engine.BestFit +{ + public class RotationSlideStrategy : IBestFitStrategy + { + public RotationSlideStrategy(double part2Rotation, int type, string description) + { + Part2Rotation = part2Rotation; + Type = type; + Description = description; + } + + public double Part2Rotation { get; } + public int Type { get; } + public string Description { get; } + + public List GenerateCandidates(Drawing drawing, double spacing, double stepSize) + { + var candidates = new List(); + + // Build part1 at origin + var part1 = new Part(drawing); + var bbox1 = part1.Program.BoundingBox(); + part1.Offset(-bbox1.Location.X, -bbox1.Location.Y); + part1.UpdateBounds(); + + // Build part2 template with rotation, normalized to origin + var part2Template = new Part(drawing); + if (!Part2Rotation.IsEqualTo(0)) + part2Template.Rotate(Part2Rotation); + var bbox2 = part2Template.Program.BoundingBox(); + part2Template.Offset(-bbox2.Location.X, -bbox2.Location.Y); + part2Template.UpdateBounds(); + + var testNumber = 0; + + // Try pushing left (horizontal slide) + GenerateCandidatesForAxis( + part1, part2Template, drawing, spacing, stepSize, + PushDirection.Left, candidates, ref testNumber); + + // Try pushing down (vertical slide) + GenerateCandidatesForAxis( + part1, part2Template, drawing, spacing, stepSize, + PushDirection.Down, candidates, ref testNumber); + + return candidates; + } + + private void GenerateCandidatesForAxis( + Part part1, Part part2Template, Drawing drawing, + double spacing, double stepSize, PushDirection pushDir, + List candidates, ref int testNumber) + { + var bbox1 = part1.BoundingBox; + var bbox2 = part2Template.BoundingBox; + var halfSpacing = spacing / 2; + + var isHorizontalPush = pushDir == PushDirection.Left || pushDir == PushDirection.Right; + + // Perpendicular range: part2 slides across the full extent of part1 + double perpMin, perpMax, pushStartOffset; + + if (isHorizontalPush) + { + perpMin = -(bbox2.Height + spacing); + perpMax = bbox1.Height + bbox2.Height + spacing; + pushStartOffset = bbox1.Width + bbox2.Width + spacing * 2; + } + else + { + perpMin = -(bbox2.Width + spacing); + perpMax = bbox1.Width + bbox2.Width + spacing; + pushStartOffset = bbox1.Height + bbox2.Height + spacing * 2; + } + + // Pre-compute part1's offset lines (half-spacing outward) + var part1Lines = Helper.GetOffsetPartLines(part1, halfSpacing); + + for (var offset = perpMin; offset <= perpMax; offset += stepSize) + { + var part2 = (Part)part2Template.Clone(); + + // Place part2 far away along push axis, at perpendicular offset + if (isHorizontalPush) + part2.Offset(pushStartOffset, offset); + else + part2.Offset(offset, pushStartOffset); + + // Get part2's offset lines (half-spacing outward) + var part2Lines = Helper.GetOffsetPartLines(part2, halfSpacing); + + // Find contact distance + var slideDist = Helper.DirectionalDistance(part2Lines, part1Lines, pushDir); + + if (slideDist >= double.MaxValue || slideDist < 0) + continue; + + // Move part2 to contact position + var pushVector = GetPushVector(pushDir, slideDist); + var finalPosition = part2.Location + pushVector; + + candidates.Add(new PairCandidate + { + Drawing = drawing, + Part1Rotation = 0, + Part2Rotation = Part2Rotation, + Part2Offset = finalPosition, + StrategyType = Type, + TestNumber = testNumber++, + Spacing = spacing + }); + } + } + + private static Vector GetPushVector(PushDirection direction, double distance) + { + switch (direction) + { + case PushDirection.Left: return new Vector(-distance, 0); + case PushDirection.Right: return new Vector(distance, 0); + case PushDirection.Down: return new Vector(0, -distance); + case PushDirection.Up: return new Vector(0, distance); + default: return Vector.Zero; + } + } + } +} diff --git a/OpenNest.Engine/OpenNest.Engine.csproj b/OpenNest.Engine/OpenNest.Engine.csproj index 4345409..6b81169 100644 --- a/OpenNest.Engine/OpenNest.Engine.csproj +++ b/OpenNest.Engine/OpenNest.Engine.csproj @@ -40,6 +40,7 @@ +