WPF中使用AxisAngleRotation3D实现CAD的2D旋转功能

2021-07-04 19:07

阅读:641

????? 对于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工具里面,这里不做说明。


评论


亲,登录后才可以留言!