勇哥继续谈谈绕任意点的旋转。
绕原点的旋转是二维旋转最基本的情况,当我们需要进行绕任意点旋转时,我们可以把这种情况转换到绕原点的旋转,思路如下:
1. 首先将旋转点移动到原点处
2. 执行如2所描述的绕原点的旋转
3. 再将旋转点移回到原来的位置
(图1)
勇哥根据上述原理写了段演示代码:
/// <summary> /// 点数组绕任意点转30度 /// </summary> /// <param name="ptAry"></param> /// <param name="x1"></param> /// <param name="y1"></param> /// <returns></returns> List<Point> rotateAnyPt30(List<Point> ptAry,int x1,int y1) { double c = 30 * Math.PI / 180.0; ptAry =movePt(ptAry, -x1, -y1); ptAry=ptAryRotate30(ptAry); ptAry = movePt(ptAry, x1, y1); return ptAry; } /// <summary> /// 平移点数组 /// </summary> /// <param name="b"></param> /// <param name="i"></param> /// <param name="j"></param> /// <returns></returns> List<Point> movePt(List<Point> b, int x1, int y1) { for (int i = 0; i < b.Count; i++) { b[i] = new Point(b[i].X + x1,b[i].Y+y1); } return b; } /// <summary> /// 点数组绕原点转30度 /// </summary> /// <param name="a"></param> /// <returns></returns> List<Point> ptAryRotate30(List<Point> a) { double c = 30 * Math.PI / 180.0; for (int i = 0; i < a.Count; i++) { int x = a[i].X; int y = a[i].Y; a[i] = new Point(Convert.ToInt32(x * Math.Cos(c) - y * Math.Sin(c)), Convert.ToInt32(x * Math.Sin(c) + y * Math.Cos(c))); } return a; } Point[] pointa = new Point[3] { new Point(30, 20), new Point(200, 40), new Point(200, 100) }; private void button7_Click(object sender, EventArgs e) { draw(pointa); draw(rotateAnyPt30(pointa.ToList(), 200, 40).ToArray()); }
结果如下图,我们绕三角形的第二个点顺时针转了30度。
(图2)
下面用矩阵方式实现上面的原理。
如图1所示,假设平移的矩阵是T(x,y),也就是说我们需要得到的坐标 v’=T(x,y)*R*T(-x,-y)(我们使用的是列坐标描述点的坐标,因此是左乘,首先执行T(-x,-y))
由于引入了齐次坐标,在描述二维坐标的时候,使用(x,y,w)的方式(一般w=1),于是可以写成下面矩阵的形式
从平移和旋转的矩阵可以看出,3x3矩阵的前2x2部分是和旋转相关的,第三列与平移相关。有了上面的基础之后,我们很容易得出二维中绕任意点旋转的旋转矩阵了,只需要把三个矩阵乘起来即可:
按上面的公式,编写程序如下:
private void button8_Click(object sender, EventArgs e) { //绕任意点旋转30度(矩阵) draw(pointa); var angel = 30; double sinA = Math.Sin(angel * Math.PI / 180); double cosA = Math.Cos(angel * Math.PI / 180); // angel为正数即说明相对原点顺时针 double[] Rdata = new double[] { cosA, -sinA, 0, sinA, cosA, 0, 0, 0, 1 }; Matrix R = new Matrix(3, Rdata); // 3*3 矩阵 double mx = 200, my = 40; double[] mData1 = new double[] { 1,0,mx, 0,1,my, 0,0,1 }; Matrix M1 = new Matrix(3, mData1); double[] mData2 = new double[] { 1,0,-mx, 0,1,-my, 0,0,1 }; Matrix M2 = new Matrix(3, mData2); for(int i=0;i<pointa.Length;i++) { try { double[] Pdata = new double[] { pointa[i].X, pointa[i].Y, 1 }; Matrix P = new Matrix(3, 1, Pdata); P = M1 * R * M2 * P; int x = Round_Int(P.GetElement(0, 0)); int y = Round_Int(P.GetElement(1, 0)); pointa[i] = new Point(x, y); } catch(Exception ex) { MessageBox.Show(ex.Message); } } draw(pointa); }
(图3)
友情提醒: 上面代码中用到的类Matrix是类库netMarketing v1.3.1版中的矩阵类。
---------------------
作者:hackpig
来源:www.skcircle.com
版权声明:本文为博主原创文章,转载请附上博文链接!

