用鼠标旋转图像

发布于 2024-08-16 10:24:42 字数 858 浏览 2 评论 0原文

我正在编写一个绘图程序 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 它可以适用于任何语言

I am writing a drawing program, Whyteboard -- http://code.google.com/p/whyteboard/

I have implemented image rotating functionality, except that its behaviour is a little odd. I can't figure out the proper logic to make rotating the image in relation to the mouse position

My code is something similar to this:

(these are called from a mouse event handler)

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))

So, basically the angle to rotate the image keeps getting increased when the user moves the mouse. However, this sometimes means you have to "circle" the mouse many times to rotate an image 90 degrees, let alone 360.

But, I need it similar to other programs - how the image is rotated in relation to your mouse's position to the image.

This is the bit I'm having trouble with. I've left the question language-independent, although using Python and wxPython it could be applicable to any language

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

一城柳絮吹成雪 2024-08-23 10:24:42

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

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

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

I'm assuming resize() is called for every mouse movement update. Your problem seems to be the self.angle += 1, which makes you update your angle by 1 degree on each mouse event.

A solution to your problem would be: pick the point on the image where the rotation will be centered (on this case, it's your (0,0) point on self.img.Rotate(), but usually it is the center of the image). The rotation angle should be the angle formed by the line that goes from this point to the mouse cursor minus the angle formed by the line that goes from this point to the mouse position when the user clicked.

To calculate the angle between two points, use math.atan2(y2-y1, x2-x1) which will give you the angle in radians. (you may have to change the order of the subtractions depending on your mouse position axis).

甜柠檬 2024-08-23 10:24:42

fserb 的解决方案也是我进行旋转的方式,但需要额外考虑的是您的使用:

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

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

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

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

然后在旋转模式下使用 display_img 图像。当您结束旋转模式时(可能是onMouseUp),img = display_img

每当您对用户预览进行有损操作时,这种类型的策略就很好。

fserb's solution is the way I would go about the rotation too, but something additional to consider is your use of:

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

If you are performing a bitmap image rotation in response to every mouse drag event, you are going to get a lot of data loss from the combined effect of all the interpolation required for the rotation. For example, rotating by 1 degree 360 times will give you a much blurrier image than the original.

Try having a rotation system something like this:

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

then use the display_img image while you are in rotation mode. When you end rotation mode (onMouseUp maybe), img = display_img.

This type of strategy is good whenever you have a lossy operation with a user preview.

手心的海 2024-08-23 10:24:42

最后的解决方案是这样的

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

Here's the solution in the end,

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文