我有一堆对象(ActiveRecord),它们相对于HTML5画布元素具有x和y坐标。我需要将它们的不同角度(以90度为增量)旋转并再次存储,以进行一次性数据迁移。
这些对象都是相对于画布元素的,因此坐标从(0,0)开始,并希望它们保留在该象限(右下角),如果可能的话。我假设我需要围绕(0,0)旋转,然后向下和向右平移。
有没有办法编写一个代码块来实现这个功能?
我有一堆对象(ActiveRecord),它们相对于HTML5画布元素具有x和y坐标。我需要将它们的不同角度(以90度为增量)旋转并再次存储,以进行一次性数据迁移。
这些对象都是相对于画布元素的,因此坐标从(0,0)开始,并希望它们保留在该象限(右下角),如果可能的话。我假设我需要围绕(0,0)旋转,然后向下和向右平移。
有没有办法编写一个代码块来实现这个功能?
要将点 P 绕原点旋转 R 度:
P2.x = P.x * cos(R) - P.y * sin(R)你可能想围绕存放对象的象限中心的任意点进行旋转。如果你的象限宽度为 200x100,你需要围绕点 <100,50>
进行旋转。
要将点 P 绕不在原点的位置 C 旋转,首先需要将该位置平移至原点,然后进行旋转再平移回 C。也就是说:
P2 = P - C
P3 = rotate(P2)
P4 = P3 + C
你可以在http://phrogz.net/SVG/rotations.xhtml查看这个过程——单击来设置旋转中心或更改旋转量,然后会在点组上设置一个变换,该变换将其移动到原点,进行旋转,然后再次平移回来。
总之,要用 Ruby 围绕任意点旋转具有 x
和 y
属性的点,你需要使用以下代码:
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>]