Java 2D - 拖动鼠标以平滑地旋转图像

时间:2010-02-04 08:42:18

标签: java image mouseevent

通过鼠标移动旋转图像的逻辑是什么。我知道如何使用graphics2d.rotate进行旋转......但是使用鼠标作为旋转源很难做到这一点。以下是基本步骤:

  1. 从锚定点获得鼠标x(dx)和鼠标y(dy)的距离(在这种情况下,这将是 我们想要旋转的图像的中心。
  2. 在Math.arcTan2(dy,dx)中使用此点来获取角度或旋转。
  3. 使用步骤中的值来处理Graphics2D.rotate方法。
  4. 根据该策略,每次旋转图像时,图像都会从-pi开始旋转,旋转90度后,图像将返回-pi。我不明白我在这里做错了什么,应该是非常基本的。

    以下是代码的一部分:

    // mouse dragged events get sent here.
    public void mouseDragged( MouseEvent e ) {
        int mx = e.getX( ), my = e.getY( );
        // just checking if it falls within bounds of the image we 
        // want to rotate.
        if( mx > speedKX || mx < speedKX + speedK.getWidth( ) || my > speedKY || my < speedKY + speedK.getHeight( )/2 )
        {
            theta += getTheta( e.getX( ), e.getY( ) ); 
        }
    } 
    

1 个答案:

答案 0 :(得分:4)

据我所知,你应该寻找初始角度(当你点击时,锚点和你的点击之间的线条)和当前角度(当你拖动时,同一条线)。该角度(与当前到锚点的距离无关)将为您提供旋转。

所以你必须:

rotate(anglenow - angle0)

如何找到它:

在这两种情况下(初始点击和鼠标移动事件)你必须找到锚点和鼠标点之间的角度,将锚点视为原点。

我会使用一个方法(getAngle(x1,y1,x2,y2)。该方法(除了相同x或相同y的竞争条件,易于检测)应该计算arctan(dy / dx)。

登录

但是当你划分dy / dx时,它可以是:

+ / + -> +
+ / - -> -
- / + -> -
- / - -> +

有四种可能性给你两种结果。所以,你必须看一些条件来检测它们。

我应该检查arctan doc或source以查看它给出的值(介于0和pi之间,或-pi / 2和+ pi / 2之间),然后检查dx或dy的符号(取决于arctan返回的范围)并使用它来增加/减少pi到当时产生的角度。

然后你会得到一个正确返回360º空间的getAngle方法。

修改

Javadoc说:

Math.atan返回角度的反正切值,范围为-pi / 2到pi / 2.

因此,假设您的角度值0是我假设的X轴,它返回的范围是右半球。所以你必须从右半球中分离右半球。

如果你计算dx = xtarget - xorigin(正如你为分裂所做的那样),如果正确的半球是正确的半球,它将为正,如果不是,则为负。

所以如果dy&lt; 0然后你必须将pi添加到你的结果角度。它将介于-pi / 2和3pi / 2之间。您还可以通过将所有值传递到(-pi,pi)范围或(0,2pi)范围来更正结果。

编辑:伪代码,请仔细检查!

onmousedown {
    startpoint = (x,y);
    startangle = getAngle(origin, startpoint);
}

onmousemove {
    currentpoint = (x,y);
    currentangle = getAngle(origin, currentpoint);
    originalimage.rotate(currentangle - startangle);
}

getAngle(origin, other) {
    dy = other.y - origin.y;
    dx = other.x - origin.x;
    if (dx == 0) // special case
        angle = dy >= 0? PI/2: -PI/2;
    else
    {
        angle = Math.atan(dy/dx);
        if (dx < 0) // hemisphere correction
            angle += PI;
    }
    // all between 0 and 2PI
    if (angle < 0) // between -PI/2 and 0
        angle += 2*PI;
    return angle;
}