javascript 获取旋转图像中某个点的新 x,y 坐标
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6428192/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get new x,y coordinates of a point in a rotated image
提问by Simon Kagwi
I have Google Maps icons which I need to rotate by certain angles before drawing on the map using MarkerImage. I do the rotation on-the-fly in Python using PIL, and the resulting image is of the same size as the original - 32x32. For example, with the following default Google Maps marker:
, a 30 degrees conter-clockwise rotation is achieved using the following python code:
我有谷歌地图图标,在使用MarkerImage在地图上绘制之前,我需要将其旋转特定角度。我使用 PIL 在 Python 中即时进行旋转,生成的图像与原始图像大小相同 - 32x32。例如,使用以下默认的 Google Maps 标记:
,使用以下 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)
The resulting image is
结果图像是
The tricky bit is getting the new anchor point to use when creating the MarkerImage using the new rotated image. This needs to be the pointy end of the icon. By default, the anchor point is the bottom middle [defined as (16,32) in x,y coordinates where (0,0) is the top left corner]. Can someone please explain to me how I can easily go about this in JavaScript?
棘手的一点是在使用新旋转图像创建 MarkerImage 时获取要使用的新锚点。这需要是图标的尖头。默认情况下,锚点是底部中间 [在 x,y 坐标中定义为 (16,32),其中 (0,0) 是左上角]。有人可以向我解释如何在 JavaScript 中轻松解决这个问题吗?
Thanks.
谢谢。
Update 22 Jun 2011:Had posted the wrong rotated image (original one was for 330 degrees counter-clockwise). I've corrected that. Also added resampling (Image.BICUBIC) which makes the rotated icon clearer.
2011 年 6 月 22 日更新:发布了错误的旋转图像(原始图像是逆时针旋转 330 度)。我已经更正了。还添加了重采样(Image.BICUBIC),使旋转的图标更清晰。
回答by pimvdb
To calculate the position of a rotated point you can use a rotation matrix.
要计算旋转点的位置,您可以使用旋转矩阵。
Converted into JavaScript, this calculates the rotated point:
转换成 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...]
回答by Nathan Whitehead
The formula for rotations about 0,0 is:
关于 0,0 的旋转公式是:
x1 = cos(theta) x0 - sin(theta) y0
y1 = sin(theta) x0 + cos(theta) y0
But that's for regular axes, and rotation about 0,0. The PIL rotation is clockwise with "graphics" axes. Plus, it's around the center of the image. The final confusing thing is that the size of the image can change, which needs to be accounted for in the final result.
但那是针对常规轴和旋转约 0,0。PIL 旋转以“图形”轴顺时针旋转。另外,它位于图像的中心附近。最后令人困惑的是图像的大小可以改变,这需要在最终结果中考虑。
Procedure: take original point, subtract off center of image, apply "graphics axes" corrected rotation, find new size of image, add back center position of new image.
过程:取原点,减去图像中心,应用“图形轴”校正旋转,找到新的图像大小,添加新图像的中心位置。
Rotation using graphics axes is:
使用图形轴的旋转是:
x1 = cos(theta) x0 + sin(theta) y0
y1 = -sin(theta) x0 + cos(theta) y0
16,32 - 16,16 is 0, 16. Rotate 30 degrees clockwise rotation (based on your images) gives a point cos(-30)*0+sin(-30)*16, -sin(-30)*0+cos(-30)*16 = -8, 13.86. The final step is adding back the center position of the rotated position.
16,32 - 16,16 是 0, 16. 顺时针旋转 30 度(根据您的图像)给出一个点 cos(-30)*0+sin(-30)*16, -sin(-30)*0 +cos(-30)*16 = -8, 13.86。最后一步是重新添加旋转位置的中心位置。
回答by Nikhil Sharma
In an image, downwards is positive Y and rightwards is positive X. However, to apply the rotation formula, we need upwards as positive Y. Therefore, step 1 would be to apply f(x,y) = f(x,h-y)
, where 'h' is the height of the image.
Let's say the image is rotated with respect to x0,y0. You'd then need to transform your origin to this point. Therefore, step 2 would be f(x,y) = f(x-x0,y-y0)
. At this stage (i.e. after the two steps), your new co-ordinates would be x-x0
, h-y-y0
. You're now ready to apply the rotation formula
在图像中,向下是正 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)
Use the values of x and y obtained after step two. You'd get
使用在第二步之后获得的 x 和 y 的值。你会得到
x1 = (x-x0)*cos(theta) - (h-y-y0)*sin(theta)
y1 = (x-x0)*sin(theta) + (h-y-y0)*cos(theta)
Now, undo transformations done in step 2 and step 1 (in that order).
现在,撤消在第 2 步和第 1 步中完成的转换(按此顺序)。
After undoing step2: xNew = x1 + x0
and yNew = y1 + y0
撤消 step2 后:xNew = x1 + x0
和yNew = y1 + y0
After undoing step1: xNew = x1 + x0
and yNew = h - (y1 + y0)
撤消 step1 后:xNew = x1 + x0
和yNew = h - (y1 + y0)
This gives you:
这给你:
xNew = (x-x0)*cos(theta) - (h-y-y0)*sin(theta) + x0
yNew = -(x-x0)*sin(theta) - (h-y-y0)*cos(theta) + (h-y0)