Математика
Математический подход заключается в представлении этих данных в виде векторов от центра к точкам изображения, переводе этих векторов в начало координат, применении преобразования и перемещении их вокруг центральной точки. Давайте подробно рассмотрим, как это работает.
Представление в виде векторов
Мы можем показать эти векторы в сетке, это даст следующее изображение
![Представление заданных точек в виде векторов вокруг центральной точки](https://i.stack.imgur.com/loIep.png)
Это изображение дает хороший способ взглянуть на эти точки, поэтому мы можем визуально увидеть, как происходят наши действия. Центральная точка отмечена точкой в начале всех стрелок, а конец каждой стрелки — это местонахождение одной из точек, указанных в вопросе.
Вектор можно рассматривать как список значений координат точки, поэтому
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
Полученные точки теперь можно вращать вокруг начала координат и масштабировать относительно начала координат. Новые точки (в виде векторов) выглядят так:
![Те же векторы, что и выше, но смещенные вокруг начала координат](https://i.stack.imgur.com/XK4J8.png)
На этом изображении я намеренно оставил масштаб нетронутым, чтобы было понятно, что это точно такие же векторы (стрелки), по размеру и ориентации, только сдвинутые примерно на (0, 0).
Почему происхождение
Так зачем переводить эти точки в начало координат? Что ж, повороты и действия по масштабированию легко (математически) выполнять вокруг начала координат и не так просто вокруг других точек.
Кроме того, с этого момента я буду включать в эти изображения только 1-ю, 2-ю и 4-ю точки, чтобы сэкономить место.
Масштабирование вокруг начала координат
Операция масштабирования очень проста вокруг начала координат. Просто умножьте координаты точки на коэффициент масштабирования:
scaled_point_x = point[0] * scaling_factor
scaled_point_y = point[1] * scaling_factor
Визуально это выглядит так (увеличение всего на 1,5):
![Масштабированные векторы и оригинальные векторы](https://i.imgur.com/mAgBVCT.png)
Где синие стрелки — исходные векторы, а красные — масштабированные векторы.
вращающийся
Теперь о вращении. Это немного сложнее, потому что вращение чаще всего описывается умножением матрицы на этот вектор.
Матрица для умножения следующая
![матрица вращения](https://i.stack.imgur.com/nofna.png)
(из википедия: Матрица вращения)
Итак, если V является вектором, нам нужно выполнить V_r = R(t) * V
, чтобы получить повернутый вектор V_r
. Это вращение всегда будет против часовой стрелки! Чтобы повернуть по часовой стрелке, нам просто нужно использовать R(-t)
.
Поскольку в вопросе нужны только числа, кратные 90 °, матрица становится почти тривиальной. Для поворота на 90° против часовой стрелки матрица имеет вид:
![Матрица поворота на 90° против часовой стрелки](https://i.stack.imgur.com/SheJc.png)
Что в основном в коде:
rotated_point_x = -point[1] # new x is negative of old y
rotated_point_y = point[0] # new y is old x
Опять же, это можно красиво показать визуально:
![поворот на 90° против часовой стрелки](https://i.stack.imgur.com/cRpec.png)
Где я сопоставил цвета векторов.
Поворот на 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
И все сделано.
Просто резюме
Итак, резюмируя этот длинный пост:
- Вычесть координаты центральной точки из координат точки изображения
- Масштабируйте с коэффициентом, просто умножая координаты
- Используйте идею матричного умножения, чтобы подумать о вращении (вы можете легко найти эти вещи в Google или Википедии).
- Добавьте координаты центральной точки к новым координатам точки изображения
Теперь я понимаю, что мог бы просто дать этот обзор, но теперь в этом посте есть хоть какое-то наглядное пособие и небольшая математическая подоплека, что тоже приятно. Я действительно считаю, что на такие задачи нужно смотреть с математической точки зрения, математическое описание может очень помочь.
person
vikvanderlinden
schedule
04.03.2018