using OpenNest.Geometry;
using OpenNest.Math;
namespace OpenNest
{
public partial class Plate
{
///
/// Rotates the plate clockwise or counter-clockwise along with all parts.
///
///
///
public void Rotate90(RotationType rotationDirection, bool keepSameQuadrant = true)
{
const double oneAndHalfPI = System.Math.PI * 1.5;
var turned = Outline?.Rotated90(rotationDirection);
Size = new Size(Size.Length, Size.Width);
Outline = turned;
// After Size swap above, new Size.Width = old Length (old X extent),
// new Size.Length = old Width (old Y extent).
// Convention: Length = X axis, Width = Y axis.
if (rotationDirection == RotationType.CW)
{
Rotate(oneAndHalfPI);
if (keepSameQuadrant)
{
switch (Quadrant)
{
case 1:
Offset(0, Size.Width);
break;
case 2:
Offset(-Size.Length, 0);
break;
case 3:
Offset(0, -Size.Width);
break;
case 4:
Offset(Size.Length, 0);
break;
default:
return;
}
}
else
{
Quadrant = Quadrant < 2 ? 4 : Quadrant - 1;
}
}
else
{
Rotate(Angle.HalfPI);
if (keepSameQuadrant)
{
switch (Quadrant)
{
case 1:
Offset(Size.Length, 0);
break;
case 2:
Offset(0, Size.Width);
break;
case 3:
Offset(-Size.Length, 0);
break;
case 4:
Offset(0, -Size.Width);
break;
default:
return;
}
}
else
{
Quadrant = Quadrant > 3 ? 1 : Quadrant + 1;
}
}
}
///
/// Rotates the plate 180 degrees along with all parts.
///
///
public void Rotate180(bool keepSameQuadrant = true)
{
if (keepSameQuadrant)
{
Vector centerpt;
switch (Quadrant)
{
case 1:
centerpt = new Vector(Size.Length * 0.5, Size.Width * 0.5);
break;
case 2:
centerpt = new Vector(-Size.Length * 0.5, Size.Width * 0.5);
break;
case 3:
centerpt = new Vector(-Size.Length * 0.5, -Size.Width * 0.5);
break;
case 4:
centerpt = new Vector(Size.Length * 0.5, -Size.Width * 0.5);
break;
default:
return;
}
Rotate(System.Math.PI, centerpt);
Outline = Outline?.Rotated180();
}
else
{
Rotate(System.Math.PI);
Outline = Outline?.Rotated180();
Quadrant = (Quadrant + 2) % 4;
if (Quadrant == 0)
Quadrant = 4;
}
}
///
/// Rotates the parts on the plate.
///
///
public void Rotate(double angle)
{
for (var i = Parts.Count - 1; i >= 0; i--)
{
if (Parts[i].BaseDrawing.IsCutOff)
Parts.RemoveAt(i);
}
for (var i = 0; i < Parts.Count; ++i)
{
var part = Parts[i];
part.Rotate(angle);
}
foreach (var cutoff in CutOffs)
cutoff.Position = cutoff.Position.Rotate(angle);
}
///
/// Rotates the parts on the plate around the specified origin.
///
///
///
public void Rotate(double angle, Vector origin)
{
for (var i = Parts.Count - 1; i >= 0; i--)
{
if (Parts[i].BaseDrawing.IsCutOff)
Parts.RemoveAt(i);
}
for (var i = 0; i < Parts.Count; ++i)
{
var part = Parts[i];
part.Rotate(angle, origin);
}
foreach (var cutoff in CutOffs)
{
var pos = cutoff.Position - origin;
pos = pos.Rotate(angle);
cutoff.Position = pos + origin;
}
}
///
/// Offsets the parts on the plate.
///
///
///
public void Offset(double x, double y)
{
// Remove cut-off parts before transforming
for (var i = Parts.Count - 1; i >= 0; i--)
{
if (Parts[i].BaseDrawing.IsCutOff)
Parts.RemoveAt(i);
}
for (var i = 0; i < Parts.Count; ++i)
{
var part = Parts[i];
part.Offset(x, y);
}
// Transform cut-off positions
foreach (var cutoff in CutOffs)
cutoff.Position = new Vector(cutoff.Position.X + x, cutoff.Position.Y + y);
}
///
/// Offsets the parts on the plate.
///
///
public void Offset(Vector voffset)
{
for (var i = Parts.Count - 1; i >= 0; i--)
{
if (Parts[i].BaseDrawing.IsCutOff)
Parts.RemoveAt(i);
}
for (var i = 0; i < Parts.Count; ++i)
{
var part = Parts[i];
part.Offset(voffset);
}
foreach (var cutoff in CutOffs)
cutoff.Position = new Vector(
cutoff.Position.X + voffset.X,
cutoff.Position.Y + voffset.Y
);
}
}
}