18

我有谷歌地图图标,在使用MarkerImage在地图上绘制之前,我需要将其旋转一定角度。我使用 PIL 在 Python 中即时进行旋转,生成的图像与原始图像大小相同 - 32x32。例如,使用以下默认谷歌地图标记: 旋转前的图标 ,使用以下 python 代码实现逆时针旋转 30 度:

# 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)

结果图像是图标逆时针旋转 30 度

棘手的一点是在使用新的旋转图像创建 MarkerImage 时使用新的锚点。这需要是图标的尖端。默认情况下,锚点位于底部中间[在 x,y 坐标中定义为 (16,32),其中 (0,0) 是左上角]。有人可以向我解释一下如何在 JavaScript 中轻松解决这个问题吗?

谢谢。

2011 年 6 月 22 日更新: 发布了错误的旋转图像(原始图像是逆时针旋转 330 度)。我已经纠正了。还添加了重采样 (Image.BICUBIC),使旋转的图标更清晰。

4

3 回答 3

25

要计算旋转点的位置,您可以使用旋转矩阵

转换为 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...]
于 2011-06-21T16:17:09.190 回答
8

旋转大约 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。最后一步是添加回旋转位置的中心位置。

于 2011-06-21T16:04:02.737 回答
2

在图像中,向下是正 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 步中完成的转换(按此顺序)。

撤消步骤2后:xNew = x1 + x0yNew = y1 + y0

撤消步骤1后:xNew = x1 + x0yNew = 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)
于 2016-03-16T11:59:54.700 回答