确定顺时针或逆时针旋转

3

我需要确定用户是进行顺时针旋转手势还是逆时针。我有起始向量位置以及当前和上一个触摸点。虽然我认为起始向量可能没有太大用处,因为用户还可以在旋转过程中更改旋转方向。就像旋转x-box的d-pad一样。 为了像Dead Trigger 2开发人员那样实时演示想法,屏幕上没有按钮,只需使用手势在屏幕上旋转即可。 我该如何确定它?

1个回答

3
为了确定一个二维输入是顺时针旋转还是逆时针旋转,需要计算从旋转中心到两个向量的叉积,并判断其正负性。其中一个向量来自前一次输入,另一个向量来自当前输入。
伪代码如下:
centerX = screenCenterX;  // point user is rotating around
centerY = screenCenterY;
inputX = getUserX();   // gets X and Y input coords
inputY = getUserY();   //
lastVecX = inputX - centerX;  // the previous user input vector x,y
lastVecY = inputY - centerY;  //      

while(true){ // loop 
    inputX = getUserX();  // gets X and Y input coords
    inputY = getUserY();  //

    vecInX = inputX - centerX;  // get the vector from center to input
    vecInY = inputY - centerY;  // 

    // now get the cross product
    cross = lastVecX * vecInY - lastVecY * vecInX;

    if(cross > 0) then rotation is clockwise
    if(cross < 0) then rotation is anticlockwise
    if(cross == 0) then there is no rotation

    lastVecX = vecInX;  // save the current input vector
    lastVecY = vecInY;  // 
} // Loop until the cows come home.

您需要对向量进行归一化,然后叉乘是角度变化的正弦值。

以下是伪代码:

vecInX = inputX - centerX;  // get the vector from center to input
vecInY = inputY - centerY;  // 

// normalized input Vector by getting its length
length = sqrt(vecInX * vecInX + vecInY * vecInY);

// divide the vector by its length
vecInX /= length;
vecInY /= length;

// input vector is now normalised. IE it has a unit length

// now get the cross product
cross = lastVecX * vecInY - lastVecY * vecInX;

// Because the vectors are normalised the cross product will be in a range
// of -1 to 1 with < 0 anticlockwise and > 0 clockwise

changeInAngle = asin(cross);  // get the change in angle since last input
absoluteAngle += changeInAngle; // track the absolute angle

lastVecX = vecInX;  // save the current normalised input vector
lastVecY = vecInY;  //       
// loop

此代码仅适用于旋转角度在-90到+90度之间的情况。如果旋转角度为120度,它将无法返回正确的角度。 - FMaz008
1
使用两个向量的点积 dot = lastVecX * vecInX + lastVecY * vecInY;。如果 dot < 0,则角度在第二或第三象限。 - Blindman67
你是在暗示我们需要假设弧/旋转始于右上象限吗?(因为当我发表评论时,我的旋转始于圆的最左侧,并以逆时针120度结束于以轴为中心的虚拟象限的右上方。除非我实现代码有误,否则它对于该用例无效。) - FMaz008
1
@FMaz008 答案是旋转方向(顺时针或逆时针)。然而,在画布上,第1、2、3、4象限从弧度0到PI/2(第1象限)开始,然后沿顺时针方向到第4象限。叉积和点积的符号唯一地标识了所有4个象限,然后您可以调整计算得出的角度,例如ang = Math.asin(Math.min(1, Math.max(-1, x2 * y1 - y2 * x1))); return x2 * x1 + y2 * y1 < 0 ? ( ang < 0 ? -Math.PI - ang : Math.PI - ang ) : ang; 其中 x1,y1x2,y2 是归一化向量。 - Blindman67
我不得不慢慢地、多次地阅读你的最后一条评论,但它对于理解它的工作原理非常有帮助。谢谢! - FMaz008

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接