Страницы

Поиск по вопросам

вторник, 28 января 2020 г.

Как повернуть треугольник?

#математика #android #java #геометрия


Рисую на Canvas равнобедренный треугольник посередине экрана. Рисую от центра треугольника
(места пересечения медиан). Соответственно, известны экранные координаты центра треугольника
и размер треугольника. Нужно иметь возможность поворачивать треугольник на произвольный
(рандомный) угол по часовой стрелке. Делаю так:
// Исходные данные
float angle = 90; // Угол на который будем поворачивать треугольник
final float height = 60; // Высота треугольника
final float width = 36; // Ширина треугольника
float centerX = 540; // Координаты центра треугольника на экране
float centerY = 960;

// Вычисляем экранные координаты всех вершин до поворота
// l1, l2, l3 - это расстояние от центра треугольника до вершины
// это расстояние вычисляю по формуле √ ((X2-X1)²+(Y2-Y1)²)
float x1 = centerX;
float y1 = centerY - height / 2;
float l1 = (float) Math.sqrt(Math.pow(centerX - x1, 2) + Math.pow(centerY - y1, 2));
float x2 = centerX + width / 2;
float y2 = centerY + height / 2;
float l2 = (float) Math.sqrt(Math.pow(centerX - x2, 2) + Math.pow(centerY - y2, 2));
float x3 = centerX - width / 2;
float y3 = y2;
float l3 = l2;

// Вычисляем координаты вершин с учетом поворота треугольника
float alpha1 = (float) (Math.atan(y1 / x1) - angle);
x1 = (float) (centerX + l1 * Math.cos(alpha1));
y1 = (float) (centerY + l1 * Math.sin(alpha1));

float alpha2 = (float) (Math.atan(y2 / x2) - angle);
x2 = (float) (centerX + l2 * Math.cos(alpha2));
y2 = (float) (centerY + l2 * Math.sin(alpha2));

float alpha3 = (float) (Math.atan(y3 / x3) - angle);
x3 = (float) (centerX + l3 * Math.cos(alpha3));
y3 = (float) (centerY + l3 * Math.sin(alpha3));

Код сделал развернутым, чтобы было понятнее, в релизе оптимизирую.
Проблема в том, что координаты после поворота вычисляются неверно. Что я делаю не
так? Как вычислить новые координаты после поворота треугольника?    


Ответы

Ответ 1



Поворот вокруг начальной точки на угол A, описываемый формулой: Xn = Xc * cos(A) - Yc * sin(A) Yn = Xc * sin(A) + Yc * cos(A) где Xc, Yc - координаты относительно центра поворота; Xn, Yn - новые координаты. Все что остается перейти к новой системе координат с нулевой точкой в центре треугольника выполнить поворот и потом вернуться к старой системе координат. Переход к новой системе координат выполняет по формуле: Xn = X - Ox Yn = Y - Oy Т.е. для Вашего случая получаем для каждой точки нужно сделать преобразования: x1 = (x1 - centerX) * cos(angle) - (y1 - centerY) * sin(angle) + centerX; y1 = (x1 - centerX) * sin(angle) + (y1 - centerY) * cos(angle) + centerY; Для больших подробностей откуда такие формулы и т.д. погуглите тему аффинные преобразования.

Ответ 2



Вы неверно вычисляете координаты поворота. Посмотрите на формулу (19) поворота осей здесь Ну и кроме того как верно сказал @Nofate ♦ - у вас неверно заданы углы. Надо задавать в радианах: angle*Math.PI/180

Ответ 3



Вы учитываете, что тригонометрические функции в java.lang.Math оперируют радианами, а не градусами? Чтобы не мучиться - задавайте исходные координаты относительно нуля. Затем поворачивайте: xNew = x*cos(angle) - y*sin(angle) yNew = x*sin(angle) + x*cos(angle) И потом позиционируйте относительно центра экрана.

Комментариев нет:

Отправить комментарий