原文:
WPF中使用AxisAngleRotation3D實作CAD的2D旋轉功能對于CAD圖形來說,3D旋轉比較常用,具體實作方法在上篇文章《
WPF中3D旋轉的實作》中做了講解,可以參考Daniel。
今天說一下CAD的2D旋轉,2D旋轉雖然不如3D那麼常用,但也是CAD操作的基本功能需要實作。剛開始的做法是覺得用AxisAngleRotation3D沒法實作2D旋轉,是以用RotateTransform去實作。但是用它遇到的問題是旋轉的transform沒有考慮在旋轉矩陣裡面,旋轉矩陣是Daniel的3D Tool裡面的代碼,隻考慮了3D的一些transform,說實話裡面的矩陣轉換一直沒有看懂,根本就不可能進行修改的。就因為這個問題2D旋轉一直放着沒做。
前幾天CAD的基本操作實作差不多了,又回頭看看CAD,仔細看了看《Rotating the Camera with the Mouse》中3D旋轉的原理,突然恍然大悟,找到了2D旋轉的方法,已經成功實作,就在這裡整理一下。
原理:
2D旋轉是相對于目前螢幕的旋轉,是以旋轉軸是Z軸,旋轉角度是滑鼠點的變化角度。
代碼:
(1)幾個變量
private Transform3DGroup _transform = new Transform3DGroup();
private AxisAngleRotation3D _axisAngleRotation3D = new AxisAngleRotation3D(new Vector3D(0, 1, 0), -5.0);
private RotateTransform3D _rotateTransform3D = null;
private Point3D _rotCenter3D = new Point3D(0.0, 0.0, 0.0);
private Point _previousPosition2D = new Point(0.0, 0.0);
(2)互相關系,定義在構造函數裡面
_rotateTransform3D = new RotateTransform3D(_axisAngleRotation3D);
_transform.Children.Add(_rotateTransform3D);
_camera.Transform = _transform;
這個transform是作用在camera上的。
(3)Move函數
private void OnMouseMove(object sender, MouseEventArgs e)
{
Point currentPositonTrans = e.GetPosition(EventSource);
Rotate2DCad(currentPositonTrans);
_previousPosition2D = currentPositonTrans;
}
(4)2D旋轉CAD
private void Rotate2DCad(Point newPosition)
//将旋轉中心轉換成2D坐标點。
bool success = false;
Point rotateCenterPt = Convert3DPointTo2D(_rotCenter3D, out success);
if (success == false)
rotateCenterPt = new Point();
//計算旋轉角度
Double currentAngle = 0;
Double angle1 = Math.Atan2(_previousPosition2D.Y - rotateCenterPt.Y, _previousPosition2D.X - rotateCenterPt.X);
Double angle2 = Math.Atan2(newPosition.Y - rotateCenterPt.Y, newPosition.X - rotateCenterPt.X);
if (newPosition.Y > 0 && _previousPosition2D.Y > 0)
{
currentAngle = (angle1 - angle2) * 180.0 / Math.PI;
}
Rotate2D(currentAngle);
}
private void Rotate2D(Double angle)
//應用新的旋轉變換到目前的變換。
Quaternion delta = new Quaternion(new Vector3D(0, 0, 1), -angle);
Quaternion q = new Quaternion(_axisAngleRotation3D.Axis, _axisAngleRotation3D.Angle);
q *= delta;
Vector3D zeorVec = new Vector3D(0.0, 0.0, 0.0);
if (Vector3D.Equals(q.Axis, zeorVec))
return;
_axisAngleRotation3D.Axis = q.Axis;
_axisAngleRotation3D.Angle = q.Angle;
注:
(1)旋轉中心是CAD的原點,或者可以修改3D旋轉中心(代碼中的旋轉中心為CAD原點(0,0,0))。
(2)Convert3DPointTo2D()函數是來自于3D Tools工具裡面,這裡不做說明。