## 器材旋转。
鼠标按下,获取器材内部鼠标按下的位置(不动点)。
鼠标移动,旋转器材,使得旋转之后,不动点仍然在鼠标下方。
之前都是记住上一次的旋转角度,计算出旋转了多少度(可以用全局坐标系),然后加上去。这里我们换一种方法。
假设器材不缩放。
假设一个点的坐标是(x,y),旋转角度θ,旋转之后的坐标是(x',y'),有:
$$
\begin{bmatrix}
cos(θ) & -sin(θ) \\\\
sin(θ) & cos(θ)
\end{bmatrix}
\begin{bmatrix}
x\\\\
y
\end{bmatrix}=
\begin{bmatrix}
x^{\prime}\\\\
y^{\prime}
\end{bmatrix}\tag{1}
$$
假设不动点是$x_0、y_0$,不动点对应的器材外部的坐标为$x_1、y_1$,器材旋转角度为$θ_1$,有:
$$
\begin{bmatrix}
c_1 & -s_1\\\\
s_1 & c_1
\end{bmatrix}
\begin{bmatrix}
x_0\\\\
y_0
\end{bmatrix}=
\begin{bmatrix}
x_1\\\\
y_1
\end{bmatrix}\tag{1}
$$
其中$c_1=cos(θ_1),s_1=sin(θ_1)$。
$x_0、y_0$是已知的,就是鼠标按下时,鼠标位置对应的器材内部点的坐标,$θ_0$是已知的,就是器材当前的旋转角度,$x_1、y_1$也是已知的,就是鼠标按下的位置对应的器材外部的坐标。
转转之后,假设器材旋转角度为$θ_2$,有:
$$
\begin{bmatrix}
c_2 & -s_2\\\\
s_2 & c_2
\end{bmatrix}
\begin{bmatrix}
x_0\\\\
y_0
\end{bmatrix}=
\begin{bmatrix}
x_2\\\\
y_2
\end{bmatrix}\tag{2}
$$
其中$c_2=cos(θ_2),s_2=sin(θ_2)$。
我们的目标是求出$θ_2$。
$x_0、y_0$是已知的,$x_1、y_1$也是已知的,同上。
联立(1)、(2),得到方程组:
$$
\begin{cases}
x_1=c_1x_0 - s_1y_0 \\\\
y_1=s_1x_0 + c_1y_0 \\\\
x_2=c_2x_0 - s_2y_0 \\\\
y_2=s_2x_0 + c_2y_0 \\\\
\end{cases} \tag{3}
$$
可以求出:
$$
\begin{cases}
c_2=\displaystyle{\frac{x_0x_2+y_0y_2}{x_0x_0+y_0y_0}} \\\\
s_2=\displaystyle{\frac{x_0y_2-x_2y_0}{x_0x_0+y_0y_0}} \\\\
\end{cases} \tag{4}
$$
可以得到:
$$
t_2=\frac{s_2}{c_2}=\displaystyle{\frac{x_0y_2-x_2y_0}{x_0x_2+y_0y_2}}
$$
其中$t_2=tan(θ_2)$。
求得了$t_2$,也就得到了$θ_2$。
以下是ActionScript代码,实现,点击拖动TouchRotItem,旋转TouchRotItem的parent。
```ActionScript
package
{
import flash.display.MovieClip;
import flash.display.Sprite;
import flash.events.MouseEvent;
import flash.geom.Point;
/**
* ...
* @author hanyeah
*/
public class TouchRotItem extends MovieClip
{
protected var localP: Point;
public function TouchRotItem()
{
addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
}
private function mouseDownHandler(e:MouseEvent):void
{
e.stopPropagation();
localP = parent.globalToLocal(new Point(e.stageX, e.stageY));
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.addEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
private function mouseMoveHandler(e:MouseEvent):void
{
var x0: Number = localP.x;
var y0: Number = localP.y;
var p2: Point = parent.parent.globalToLocal(new Point(e.stageX, e.stageY));
// 相对于parent原点的坐标
p2.x -= parent.x;
p2.y -= parent.y;
var x2: Number = p2.x;
var y2: Number = p2.y;
var s2: Number = x0 * y2 - x2 * y0;
var c2: Number = x0 * x2 + y0 * y2;
var t2: Number = s2 / c2;
var dir: Number = c2 > 0 ? 1: -1;
var rot = Math.atan2(t2 * dir, dir) * 180 / Math.PI;
parent.rotation = rot;
}
private function mouseUpHandler(e:MouseEvent):void
{
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
stage.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMoveHandler);
}
}
}
```05
2023
05
器材拖动旋转
发布:hanyeah | 分类:算法 | 评论:0 | 浏览:
相关文章:
器材拖动旋转2 (2023-5-5 17:38:19)
沿任意轨迹拖动 (2019-12-11 9:40:45)
安卓原生控件做时钟 (2017-3-3 16:48:11)
按下拖动双击编辑 (2016-4-21 9:31:28)
tree组件拖动改变节点顺序 (2016-4-21 8:52:5)
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。