如何将二维数组旋转到任意程度?

时间:2011-06-01 20:49:21

标签: c# arrays math

说我有一个bool [] [],我想将它旋转37度。我知道转型并不总是完美的,那没关系。我已经准备好了很多类似于我的问题的答案,但我发现的唯一解决方案只能解决90度增量的问题。

4 个答案:

答案 0 :(得分:6)

最好的方法是遍历目标位置,并为每个位置读取正确的源位置。如果你尝试相反的方式(即在源上循环并在目的地上书写),你最终会有差距。

旋转公式很简单......

source_x = dest_x * c + dest_y * s + x0
source_y = dest_x * -s + dest_y * c + y0

其中c是角度的余弦值,s是角度的正弦值,x0, y0用于正确平移旋转的图像。在psedudocode

for y = 0, 1, ... dest_height
    for x = 0, 1, ... dest_width
        src_x = c*x + s*y + x0
        src_y = -s*x + c*y + y0
        copy from source[src_y][src_x] to dest[y][x]
可以计算

x0, y0,以便源中心通过

结束目的地中心
 x0 = src_width/2 - c*dest_width/2 - s*dest_height/2
 y0 = src_height/2 - c*dest_height/2 + s*dest_width/2

如果不是仅使用c = cos(angle)s = sin(angle),而是使用因子k缩放它们,则生成的图像将在中心周围旋转和缩放。

另请注意,公式在xy中是双线性的;这意味着您可以使用完整公式获取行的第一个像素的完整值,然后对同一行的每个元素执行src_x += csrc_y -= s,因为这是从移动时发生的情况xx+1

另请注意,根据源和目标大小,计算的源元素可能不可用,因为图像外。在这种情况下,有几个常用的选项

  1. 写一个固定值(例如false
  2. 不要写那个目标单元格
  3. 执行“夹紧”操作,将坐标限制在阅读前允许的最大值
  4. 通过使用模运算符
  5. 对坐标进行标准化来进行“平铺”

答案 1 :(得分:4)

其中x,y是笛卡尔坐标,R是旋转角度:

newx = x * cos(R) - y * sin(R)
newy = x * sin(R) + y * cos(R)

答案 2 :(得分:1)

假设您正在旋转位图,我首先考虑使用成像框架(例如System.Drawing)来实现您想要的效果。说,拿你的bool,把它变成一个1-bpp的位图,把它旋转,然后把它读出来。

如果那不是您想要的,您可以使用wberry提供的旋转并应用于每个bool,或者如果性能非常高,请编写自己的纹理化矩形光栅化器。要做到后者,请查看一些关于如何纹理映射任意2D多边形的旧图形编程教科书。

答案 3 :(得分:0)

除非你真的想要自己这样做,否则请考虑使用类似AForge的内容 - 更具体地说AForge.Imaging.Filters.RotateBicubic。此例程处理24bpp和8bpp图像,因此您需要将Alpha内容(作为24bpp图像)与Alpha通道分开旋转(作为8bpp图像)。