旋转一组对象坐标

时间:2011-08-18 01:10:44

标签: ruby geometry rotation

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

这些对象都是相对于canvas元素的,所以坐标从(0,0)开始,我希望它们留在那个象限(右下角),如果可能的话。我假设我需要围绕(0,0)进行旋转,然后向下和向右进行平移。

有没有办法可以编写一个可以执行此操作的块?任何帮助表示赞赏。

更新:做了一些修改,以便在一些问题后更清楚。

感谢。

1 个答案:

答案 0 :(得分:9)

  1. 要在原点周围旋转 P R 度的数量:
    P2.x = Px * cos( R ) - Py * sin( R
    P2.y = Px * sin( R )+ Py * cos( R
    [citation]

  2. 您可能希望围绕要保持对象的象限中心的任意点旋转。如果您的象限是200x100单位宽,则需要围绕点<100,50>旋转

    要围绕原点以外的位置 C 旋转点 P ,您需要先将位置转换为原点,然后围绕原点旋转,然后转回C.换句话说,
    P2 = P - C
    P3 =旋转( P2
    P4 = P3 + C

    您可以在http://phrogz.net/SVG/rotations.xhtml处看到此操作 - 单击以设置旋转中心或更改旋转量,并在转换为原点,旋转然后平移的点组上设置变换再回来。

  3. 将所有内容放在一起,并在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>]