代码之家  ›  专栏  ›  技术社区  ›  Steven Sproat

用鼠标旋转图像

  •  4
  • Steven Sproat  · 技术社区  · 14 年前

    我正在写一个绘图程序,whyteboard-- http://code.google.com/p/whyteboard/

    我已经实现了图像旋转功能,只是它的行为有点奇怪。我想不出正确的逻辑来使图像相对于鼠标位置旋转

    我的代码与此类似:

    (这些是从鼠标事件处理程序调用的)

    def resize(self, x, y, direction=None):
        """Rotate the image"""
        self.angle += 1
        if self.angle > 360:
            self.angle = 0
        self.rotate()
    
    
    def rotate(self, angle=None):
        """Rotate the image (in radians), turn it back into a bitmap"""
        rad = (2 * math.pi * self.angle) / 360
        if angle:
            rad = (2 * math.pi * angle) / 360
        img = self.img.Rotate(rad, (0, 0))
    

    所以,基本上,当用户移动鼠标时,旋转图像的角度会不断增加。然而,这有时意味着你必须“圈”鼠标多次旋转图像90度,更不用说360度。

    但是,我需要它类似于其他程序——图像是如何相对于鼠标相对于图像的位置旋转的。

    这就是我遇到的麻烦。尽管使用python和wxpython,它可以应用于任何语言,但我还是让问题语言独立。

    3 回复  |  直到 14 年前
        1
  •  6
  •   orip    14 年前

    我假设 resize() 每次鼠标移动更新都会调用。你的问题似乎是 self.angle += 1 ,使您在每次鼠标事件中更新角度1度。

    解决问题的方法是:在图像上选择旋转中心的点(在本例中,它是 (0,0) 点上 self.img.Rotate() ,但通常是图像的中心)。旋转角度应该是从该点到鼠标光标的线形成的角度减去用户单击时从该点到鼠标位置的线形成的角度。

    要计算两点之间的角度,请使用 math.atan2(y2-y1, x2-x1) 它会给你以弧度表示的角度。(可能需要根据鼠标位置轴更改减法顺序)。

        2
  •  1
  •   tkerwin    14 年前

    fserb的解决方案也是我进行轮换的方式,但需要考虑的是您使用:

    img = self.img.Rotate(rad, (0, 0))
    

    如果您在响应每个鼠标拖动事件时执行位图图像旋转,您将从旋转所需的所有插值的组合效果中获得大量数据丢失。例如,旋转360度会使图像比原始图像模糊得多。

    尝试使用这样的旋转系统:

    display_img = self.img.Rotate(rad, pos)
    

    然后使用 display_img 图像在旋转模式下。当您结束旋转模式时( onMouseUp 也许, img = display_img .

    这种策略在用户预览有损操作时是很好的。

        3
  •  0
  •   Steven Sproat    14 年前

    这是最终的解决方案,

    def rotate(self, position, origin):
        """ position: mouse x/y position, origin: x/y to rotate around"""
        origin_angle = self.find_angle(origin, self.center)
        mouse_angle = self.find_angle(position, self.center)
    
        angle = mouse_angle - origin_angle 
        # do the rotation here
    
    
    def find_angle(self, a, b):
        try:
            answer = math.atan2((a[0] - b[0]) , (a[1] - b[1]))
        except:
            answer = 0
        return answer