Получить новые координаты x, y точки На повернутом изображении
У меня есть значки Google Maps, которые мне нужно повернуть на определенные углы, прежде чем рисовать на карте с помощью MarkerImage. Я делаю вращение на лету в Python с помощью PIL, и полученное изображение имеет тот же размер, что и оригинал - 32x32. Например, со следующим маркером Google Maps по умолчанию: , вращение по часовой стрелке на 30 градусов достигается с помощью следующего кода python:
# full_src is a variable holding the full path to image
# rotated is a variable holding the full path to where the rotated image is saved
image = Image.open(full_src)
png_info = image.info
image = image.copy()
image = image.rotate(30, resample=Image.BICUBIC)
image.save(rotated, **png_info)
полученное изображение
в хитрый бит получает новую точку привязки для использования при создании MarkerImage с использованием нового повернутого изображения. Это должен быть заостренный конец значка. По умолчанию точкой привязки является нижняя середина [определяется как (16,32) в координатах x,y, где (0,0) - верхний левый угол]. Может кто-нибудь объяснить мне, как я могу легко сделать это в JavaScript?
спасибо.
Обновление 22 Июня 2011: Опубликовал неправильное повернутое изображение (оригинал был для 330 градусов против часовой стрелки). Я исправил это. Также добавлена повторная выборка (Image.BICUBIC), что делает повернутый значок более четким.
3 ответов
для вычисления положения повернутой точки вы можете использовать матрица поворота.
преобразованный в JavaScript, это вычисляет повернутую точку:
function rotate(x, y, xm, ym, a) {
var cos = Math.cos,
sin = Math.sin,
a = a * Math.PI / 180, // Convert to radians because that is what
// JavaScript likes
// Subtract midpoints, so that midpoint is translated to origin
// and add it in the end again
xr = (x - xm) * cos(a) - (y - ym) * sin(a) + xm,
yr = (x - xm) * sin(a) + (y - ym) * cos(a) + ym;
return [xr, yr];
}
rotate(16, 32, 16, 16, 30); // [8, 29.856...]
формула для вращений около 0,0:
x1 = cos(theta) x0 - sin(theta) y0
y1 = sin(theta) x0 + cos(theta) y0
но это для регулярных осей и вращения около 0,0. Вращение PIL по часовой стрелке с осями "графиков". Плюс, это вокруг центра изображения. Последняя запутанная вещь заключается в том, что размер изображения может измениться, что необходимо учитывать в конечном результате.
Процедура: Возьмите исходную точку, вычитайте из центра изображения, примените" графические оси " исправленное вращение, найдите новый размер изображения, добавьте задняя центральная позиция нового изображения.
вращение с использованием графических осей:
x1 = cos(theta) x0 + sin(theta) y0
y1 = -sin(theta) x0 + cos(theta) y0
16,32-16,16-0, 16. Поворот на 30 градусов по часовой стрелке вращение (на основе ваших изображений) дает точку cos(-30) * 0 + sin(-30) * 16, - sin (-30)*0+cos(-30)*16 = -8, 13.86. Заключительный шаг-добавление назад центрального положения повернутого положения.
в изображении вниз положителен Y, а вправо-X. Однако, чтобы применить формула вращения, нам нужно вверх как положительный Y. поэтому Шаг 1 должен быть применен f(x,y) = f(x,h-y)
, где ' h ' - высота изображения.
Предположим, что изображение повернуто относительно x0, y0. Затем вам нужно будет преобразовать свое происхождение до этого момента. Поэтому Шаг 2 будет f(x,y) = f(x-x0,y-y0)
. На данном этапе (т. е. после двух шагов), ваши новые координаты будут x-x0
, h-y-y0
. Ты теперь готовы применить формулу вращения
x1 = x*cos(theta) - y*sin(theta)
y1 = xsin(theta) + ycos(theta)
используйте значения x и y, полученные после второго шага. Вы получите
x1 = (x-x0)*cos(theta) - (h-y-y0)*sin(theta)
y1 = (x-x0)*sin(theta) + (h-y-y0)*cos(theta)
теперь отмените преобразования, выполненные на Шаге 2 и шаге 1 (в этом порядке).
после отмены step2:xNew = x1 + x0
и yNew = y1 + y0
после отмены шага 1:xNew = x1 + x0
и yNew = h - (y1 + y0)
это дает вам:
xNew = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) + x0
yNew = -(x-x0)*sin(theta) - (h-y-y0)*cos(theta) + (h-y0)