Получить новые координаты x, y точки На повернутом изображении

У меня есть значки Google Maps, которые мне нужно повернуть на определенные углы, прежде чем рисовать на карте с помощью MarkerImage. Я делаю вращение на лету в Python с помощью PIL, и полученное изображение имеет тот же размер, что и оригинал - 32x32. Например, со следующим маркером Google Maps по умолчанию: icon before rotation , вращение по часовой стрелке на 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)

полученное изображение icon rotated 30 degrees counter-clockwise

в хитрый бит получает новую точку привязки для использования при создании 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)