旋转一组对象坐标。

6

我有一堆对象(ActiveRecord),它们相对于HTML5画布元素具有x和y坐标。我需要将它们的不同角度(以90度为增量)旋转并再次存储,以进行一次性数据迁移。

这些对象都是相对于画布元素的,因此坐标从(0,0)开始,并希望它们保留在该象限(右下角),如果可能的话。我假设我需要围绕(0,0)旋转,然后向下和向右平移。

有没有办法编写一个代码块来实现这个功能?


我还不确定:您是想加90度还是180度?“保持在该象限内”是什么意思? - mkro
抱歉如果我表达不清楚。我想要将不同的物体集合以不同的度数旋转(通常是90度的倍数)。此外,当我说“象限”时,我指的是HTML5画布的正x和y坐标,即右下角。最后,我假设我们可以围绕原点旋转,然后将它们移回到正的画布象限,但我不确定。 - Chris Butler
1个回答

12
  1. 要将点 P 绕原点旋转 R 度:

    P2.x = P.x * cos(R) - P.y * sin(R)
    P2.y = P.x * sin(R) + P.y * cos(R)
    [来源]
  2. 你可能想围绕存放对象的象限中心的任意点进行旋转。如果你的象限宽度为 200x100,你需要围绕点 <100,50> 进行旋转。

    要将点 P 绕不在原点的位置 C 旋转,首先需要将该位置平移至原点,然后进行旋转再平移回 C。也就是说:
    P2 = P - C
    P3 = rotate(P2)
    P4 = P3 + C

    你可以在http://phrogz.net/SVG/rotations.xhtml查看这个过程——单击来设置旋转中心或更改旋转量,然后会在点组上设置一个变换,该变换将其移动到原点,进行旋转,然后再次平移回来。

总之,要用 Ruby 围绕任意点旋转具有 xy 属性的点,你需要使用以下代码:

Point = Struct.new(:x,:y) do
  def self.to_proc
    lambda{ |x| self.new *x }
  end

  def rotate( degrees, origin=Point.new(0,0) )
    radians = degrees * Math::PI/180
    x2 = x-origin.x; y2 = y-origin.y
    cos = Math.cos(radians); sin = Math.sin(radians)
    self.class.new(
      x2*cos - y2*sin + origin.x, 
      x2*sin + y2*cos + origin.y 
    )
  end

  def inspect
    "<%.1f,%.1f>" % [x,y]
  end
end

points = [ [0,0], [1,2], [3,4], [5,6] ].map(&Point)
p points
#=> [<0.0,0.0>, <1.0,2.0>, <3.0,4.0>, <5.0,6.0>]

p points.map{ |p| p.rotate(90) }
#=> [<0.0,0.0>, <-2.0,1.0>, <-4.0,3.0>, <-6.0,5.0>]

p points.map{ |p| p.rotate(90,Point.new(3,4)) }
#=> [<7.0,1.0>, <5.0,2.0>, <3.0,4.0>, <1.0,6.0>]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接