Не совсем корректный подсчет координат треугольника
Есть такая задача:
Описать класс, представляющий треугольник. Предусмотреть методы для создания объектов, перемещения на плоскости, изменения размеров и вращения на заданный угол. Описать свойства для получения состояния объекта. При невозможности построения треугольника должны "выбрасываться" исключения. Написать программу, демонстрирующую все разработанные элементы класса.
У меня почти все готово. Класс описан, все методы готовы, за исключением последнего. Он тоже описан, но работает не совсем корректно
В структуре программы имеется два класса: Point и Triangle. Triangle описывается тремя точками(класс Point)
Ниже предоставляю кусок кода, этого самого метода вращения треугольника. В математике я не силен, нашел в интернете как это сделать(умножение каждой точки треугольника на матрицу поворота) и нашел пример кода, поэтому мог допустить ошибки.
public void Rotate(double rad, Point a, Point b, Point c)
{
a = new Point((int)((double)a.point_X * Math.Cos(rad) - (double)a.point_Y * Math.Sin(rad)), (int)((double)a.point_X * Math.Sin(rad) + (double)a.point_Y * Math.Cos(rad)));
b = new Point((int)((double)b.point_X * Math.Cos(rad) - (double)b.point_Y * Math.Sin(rad)), (int)((double)b.point_X * Math.Sin(rad) + (double)b.point_Y * Math.Cos(rad)));
c = new Point((int)((double)c.point_X * Math.Cos(rad) - (double)c.point_Y * Math.Sin(rad)), (int)((double)c.point_X * Math.Sin(rad) + (double)c.point_Y * Math.Cos(rad)));
A = a;
B = b;
C = c;
}
Этот код частично выполняет свою задачу, выглядит это примерно так:
На фото видно, что треугольник повернулся на те самые 90 градусов, но сам треугольник изменил свои координаты и размеры.
Если вопрос проблема описана плохо или требуется весь код работы, сообщите пожалуйста в комментариях предоставлю его на pastebin. Заранее спасибо:)
Ответы (1 шт):
У вас некорректная архитектура: вам нужен не треугольник, а полигон. Все алгоритмы такие же, только вместо обработки 3-х координат - цикл. Вот классы:
public enum AngleUnit
{
Degree, // 360°
Radian, // 2*π
Grad, // 400ᵍ
Turn // 1 turn
}
public readonly struct Angle : IEquitable<Angle>
{
public double Value { get; }
public AngleUnit Unit { get; }
// ...
public double ToRadians() { /*...*/ }
// ...
}
public struct Matrix : IEquitable<Matrix>
{
public double M11 { get; set; }
public double M12 { get; set; }
public double M21 { get; set; }
public double M22 { get; set; }
public double OffsetX { get; set; }
public double OffsetY { get; set; }
// ...
}
public readonly struct Vector2 : IEquitable<Vector2>
{
public static readonly Vector2 Zero = new Vector2();
public double X { get; }
public double Y { get; }
public double Magnitude => Math.Sqrt(X * X + Y * Y);
public double PhaseInRadians => Math.Atan2(Y, X);
public Angle Phase => Angle.FromRadians(PhaseInRadians);
// ...
public Vector2 Transform(ref Matrix matrix) =>
(X * matrix.M11 + Y * matrix.M21 + matrix.OffsetX,
X * matrix.M12 + Y * matrix.M22 + matrix.OffsetY);
public Vecto2 RotateAt(Vector2 origin, Angle angle) =>
new Vertor2(Magnitude, Phase + angle); // возможно, не самый лучший алгоритм
public Vector2 Rotate(Angle angle) => RotateAt(Zero, angle);
// ...
public static implicit operator (double X, double Y)(Vector2 vector)
{
vector.Deconstruct(out var x, out var y);
return (x, y);
}
}
public readonly struct Rect : IEquitable<Rect>
{
// ...
}
public class Polygon
{
public Memory<Vector2> Points { get; }
public int SideCount => Points.Length;
public Rect Bounds => ComputeBounds(Points.Span);
public Vector2 Center => Bounds.Center;
public Polygon(Memory<Vector2> points)
{
if (points.Length < 3) throw /*...*/;
Points = points;
}
static Rect ComputeBounds(ReadOnlySpan<Vector2> points)
{
var l = points[0].X;
var t = points[0].Y;
var r = l;
var b = t;
foreach (var point in points)
{
if (point.X < l)
l = point.X;
else if (point.X > r)
r = point.X;
if (point.Y < t)
t = point.Y;
else if (point.Y > b)
b = point.Y;
}
return Rect.FromLtrb(l, t, r, b);
}
public void Transform(ref Matrix matrix)
{
for (var i = 0; i < SideCount; i++)
points[i] = points[i].Transform(ref matrix);
}
public void RotateAt(Vector2 origin, Angle angle)
{
var matrix = new Matrix();
matrix.Translate(origin);
matrix.Rotate(origin);
Transform(ref matrix);
}
public void Rotate(Angle angle) => RotateAt(Center, angle);
}
void Run()
{
var points = new Vector2[]
{
(0.0, 0.0),
(4.0, 0.0),
(2.0, 2.0)
};
var triangle = new Polygon(points.AsMemory());
PrintPoints(points.AsSpan());
triangle.RotateAt(Vector2.Zero, Angle.FromDegree(-90.0));
PrintPoints(points.AsSpan()); // т. к. мы используем `Memory`, то можно и так
}
void PrintPoints(ReadOnlySpan<Vector2> points)
{
Console.WriteLine("Points: ");
foreach (var point in points)
Console.WriteLine($" {point}"); // тут лучше использовать 'ValueModel' (ссылка #1, ссылка #2)
}
