Как пересчитать координаты точки после масштабирования и поворота?

У меня есть координаты 6 точек на изображении

(170.01954650878906, 216.98866271972656)
(201.3812255859375, 109.42137145996094)
(115.70114135742188, 210.4272918701172)
(45.42426300048828, 97.89037322998047)
(167.0367889404297, 208.9329833984375)
(70.13690185546875, 140.90538024902344)

У меня точка как центр [89.2458, 121.0896]. Я пытаюсь пересчитать положение точек в питоне, используя 4 градуса вращения (от 0,90 до 90,180) и 6 коэффициентов масштабирования (0,5,0,75,1,1,10,1,25,1,35,1,5).
Мой вопрос в том, как я могу повернуть и масштабировать вышеупомянутые точки относительно центральной точки и получить новые координаты этих 6 точек?

Ваша помощь очень ценится.


person S.EB    schedule 04.03.2018    source источник


Ответы (1)


Математика

Математический подход заключается в представлении этих данных в виде векторов от центра к точкам изображения, переводе этих векторов в начало координат, применении преобразования и перемещении их вокруг центральной точки. Давайте подробно рассмотрим, как это работает.

Представление в виде векторов

Мы можем показать эти векторы в сетке, это даст следующее изображение

Представление заданных точек в виде векторов вокруг центральной точки

Это изображение дает хороший способ взглянуть на эти точки, поэтому мы можем визуально увидеть, как происходят наши действия. Центральная точка отмечена точкой в ​​начале всех стрелок, а конец каждой стрелки — это местонахождение одной из точек, указанных в вопросе.

Вектор можно рассматривать как список значений координат точки, поэтому

my_vector = [point[0], point[1]]

может быть представлением вектора в python, оно просто содержит координаты точки, поэтому формат вопроса можно использовать как есть! Обратите внимание, что во всем ответе я буду использовать позицию 0 для координаты x и 1 для координаты y.

Я добавил это представление только в качестве наглядного пособия, мы можем рассматривать любой набор из двух точек как вектор, никаких вычислений не требуется, это просто другой способ взглянуть на эти точки.

Перевод в оригинал

Здесь происходят первые расчеты. Нам нужно перевести все эти векторы в начало координат. Мы можем очень легко сделать это, например, вычитая местоположение центральной точки из всех других точек (можно сделать в простом цикле):

point_origin_x = point[0] - center_point[0] # Xvalue point - Xvalue center
point_origin_y = point[1] - center_point[1] # Yvalue point - Yvalue center

Полученные точки теперь можно вращать вокруг начала координат и масштабировать относительно начала координат. Новые точки (в виде векторов) выглядят так:

Те же векторы, что и выше, но смещенные вокруг начала координат

На этом изображении я намеренно оставил масштаб нетронутым, чтобы было понятно, что это точно такие же векторы (стрелки), по размеру и ориентации, только сдвинутые примерно на (0, 0).

Почему происхождение

Так зачем переводить эти точки в начало координат? Что ж, повороты и действия по масштабированию легко (математически) выполнять вокруг начала координат и не так просто вокруг других точек.

Кроме того, с этого момента я буду включать в эти изображения только 1-ю, 2-ю и 4-ю точки, чтобы сэкономить место.

Масштабирование вокруг начала координат

Операция масштабирования очень проста вокруг начала координат. Просто умножьте координаты точки на коэффициент масштабирования:

scaled_point_x = point[0] * scaling_factor
scaled_point_y = point[1] * scaling_factor

Визуально это выглядит так (увеличение всего на 1,5):

Масштабированные векторы и  оригинальные векторы

Где синие стрелки — исходные векторы, а красные — масштабированные векторы.

вращающийся

Теперь о вращении. Это немного сложнее, потому что вращение чаще всего описывается умножением матрицы на этот вектор.

Матрица для умножения следующая

матрица вращения

(из википедия: Матрица вращения)

Итак, если V является вектором, нам нужно выполнить V_r = R(t) * V, чтобы получить повернутый вектор V_r. Это вращение всегда будет против часовой стрелки! Чтобы повернуть по часовой стрелке, нам просто нужно использовать R(-t).

Поскольку в вопросе нужны только числа, кратные 90 °, матрица становится почти тривиальной. Для поворота на 90° против часовой стрелки матрица имеет вид:

Матрица поворота на 90° против часовой стрелки

Что в основном в коде:

rotated_point_x = -point[1]    # new x is negative of old y
rotated_point_y = point[0]     # new y is old x

Опять же, это можно красиво показать визуально:

поворот на 90° против часовой стрелки

Где я сопоставил цвета векторов.

Поворот на 90° по часовой стрелке будет

rotated_counter_point_x = point[1]    # x is old y
rotated_counter_point_y = -point[0]   # y is negative of old x

Поворот на 180° будет просто принимать отрицательные координаты, или вы можете просто масштабировать с коэффициентом -1, что по сути то же самое.

В качестве последнего пункта этих операций, могу ли я добавить, что вы можете масштабировать и/или вращать столько, сколько хотите в последовательности, чтобы получить желаемый результат.

Перевод обратно в центральную точку

После действий по масштабированию и/или вращению остается только повторно перевести векторы в центральную точку.

retranslated_point_x = new_point[0] + center_point_x
retranslated_point_y = new_point[1] + center_point_y

И все сделано.

Просто резюме

Итак, резюмируя этот длинный пост:

  1. Вычесть координаты центральной точки из координат точки изображения
  2. Масштабируйте с коэффициентом, просто умножая координаты
  3. Используйте идею матричного умножения, чтобы подумать о вращении (вы можете легко найти эти вещи в Google или Википедии).
  4. Добавьте координаты центральной точки к новым координатам точки изображения

Теперь я понимаю, что мог бы просто дать этот обзор, но теперь в этом посте есть хоть какое-то наглядное пособие и небольшая математическая подоплека, что тоже приятно. Я действительно считаю, что на такие задачи нужно смотреть с математической точки зрения, математическое описание может очень помочь.

person vikvanderlinden    schedule 04.03.2018
comment
Вау... Большое спасибо за исчерпывающий ответ, я очень ценю вашу помощь. - person S.EB; 04.03.2018