代码之家  ›  专栏  ›  技术社区  ›  dave

JAVA 2D-拖动鼠标平滑旋转图像

  •  3
  • dave  · 技术社区  · 15 年前

    通过鼠标移动旋转图像背后的逻辑是什么?我知道如何使用graphics2d.rotate…旋转,但很难用鼠标作为旋转源。以下是基本步骤:

    1. 获取鼠标X(dx)和鼠标Y(dy)到锚定点的距离(在本例中,将是 我们要旋转的图像的中心)。
    2. 使用math.arctan2(dy,dx)中的这个点来获得角度或旋转。
    3. 对graphics2d.rotate方法使用从步骤到的值。

    使用这种策略,每次旋转图像时,图像都从-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 回复  |  直到 10 年前
        1
  •  4
  •   helios    15 年前

    据我所知,您应该查找初始角度(单击时,锚点和单击之间的线)和当前角度(拖动时,相同的线)。这个角度(独立于当前到锚定点的距离)将为您提供旋转。

    所以你必须:

    rotate(anglenow - angle0)
    

    如何找到它:

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

    我将使用一个方法(getangle(x1,y1,x2,y2)。该方法(除了同一个X或同一个Y的比赛条件,很容易检测)应计算arctan(dy/dx)。

    符号

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

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

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

    我应该查看arctan文档或源代码,看看它给出了什么值(在0和pi之间,或者-pi/2和+pi/2之间),然后检查dx或dy的符号(取决于arctan返回的范围),并使用它将pi添加/减少到结果角度。

    然后你会得到一个getAngle方法,可以正确返回360度空间。

    编辑

    Javadoc说:

    math.atan重新运行角度的弧切线,范围为-pi/2到pi/2。

    所以,假设你的值0是x轴的角度,如我假设的,它返回的范围是右半球。所以你必须区分左半球和右半球。

    如果你计算dx=xtarget-xorigin(就像你在除法中所做的那样),如果正确的半球是正确的,它将是正的;如果不正确,它将是负的。

    因此,如果dy<0,则必须将pi添加到生成的角度中。它将介于-pi/2和3pi/2之间。还可以通过将all传递到(-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;
    }