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

Java 2D-拖动鼠标以平滑地旋转图像,java,image,mouseevent,Java,Image,Mouseevent,通过鼠标移动旋转图像背后的逻辑是什么。我知道如何使用graphics2d进行旋转。旋转…但在使用鼠标作为旋转源时有困难。以下是基本步骤: 获取鼠标x(dx)和鼠标y(dy)距离锚定点的距离(在这种情况下,将是 要旋转的图像的中心) 在Math.arcTan2(dy,dx)中使用该点获得角度或旋转 对于Graphics2D.rotate方法,使用步骤至中的值 使用该策略,每次我旋转图像时,图像从-pi开始旋转,旋转90度后返回到-pi。我不明白我做错了什么,这应该是很基本的 以下是代码的一部分:

通过鼠标移动旋转图像背后的逻辑是什么。我知道如何使用graphics2d进行旋转。旋转…但在使用鼠标作为旋转源时有困难。以下是基本步骤:

  • 获取鼠标x(dx)和鼠标y(dy)距离锚定点的距离(在这种情况下,将是 要旋转的图像的中心)
  • 在Math.arcTan2(dy,dx)中使用该点获得角度或旋转
  • 对于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( ) ); 
        }
    } 
    
    //将鼠标拖动的事件发送到此处。
    公共无效鼠标标记(鼠标事件e){
    intmx=e.getX(),my=e.getY();
    //只是检查它是否在我们看到的图像范围内
    //要旋转。
    如果(mx>speedKX | | mxspeedKY | | my
    据我所知,您应该查找初始角度(单击时,锚点和单击之间的线)和当前角度(拖动时,相同的线)。该角度(与当前到锚定点的距离无关)将为您提供旋转

    因此,你必须:

    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添加/减小到结果角度

    然后您将得到一个getAngle方法,该方法正确返回360º空间

    编辑

    Javadoc说:

    Math.atan重新计算角度的反正切,范围为-pi/2到pi/2

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

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

    因此,如果dy<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;
    }
    
    onmousedown{
    起始点=(x,y);
    startangle=getAngle(原点,起始点);
    }
    移动{
    电流点=(x,y);
    currentangle=getAngle(原点,currentpoint);
    原始图像。旋转(当前角度-星形缠结);
    }
    getAngle(原点,其他){
    dy=其他.y-原点.y;
    dx=其他.x-原点.x;
    if(dx==0)//特殊情况
    角度=dy>=0?π/2:-π/2;
    其他的
    {
    角度=数学常数(dy/dx);
    if(dx<0)//半球校正
    角度+=π;
    }
    //都在0和2PI之间
    如果(角度<0)//介于-PI/2和0之间
    角度+=2*PI;
    返回角;
    }
    
    有可能看到一些代码吗?看起来像是三角问题……是的,当然,这里://鼠标拖动的事件发送到这里。public void mouseDragged(MouseEvent e){int mx=e.getX(),my=e.getY();//只是检查它是否在我们想要旋转的图像的范围内//如果(mx>speedKX | | mxspeedKY | | my