二维点的旋转(C#演示代码)

勇哥先来谈谈点绕原点旋转


如下图, 在2维坐标上,有一点p(x, y) , 直线opの长度为r, 直线op和x轴的正向的夹角为a。 直线op围绕原点做逆时针方向b度的旋转,到达p’ (s,t) 

image.png


s = r cos(a + b) = r cos(a)cos(b) – r sin(a)sin(b)   (1.1)
t = r sin(a + b) = r sin(a)cos(b) + r cos(a) sin(b)  (1.2)
其中 x = r cos(a)  , y = r sin(a)
代入(1.1), (1.2) ,
s = x cos(b) – y sin(b)    (1.3)
t = x sin(b) + y cos(b)    (1.4)

用行列式表达如下:

image.png


由于勇哥数学底子差,不知道式1是怎么来的,它其实是cos(a+b)的展开式:

cos(a+b)=cosacosb-sinasinb
顺便附上所有形式
sin(A+B) = sinAcosB+cosAsinB 
sin(A-B) = sinAcosB-cosAsinB
cos(A+B) = cosAcosB-sinAsinB 
cos(A-B) = cosAcosB+sinAsinB


下面应用上面的旋转公式写个C#例子:

 private void button4_Click(object sender, EventArgs e)
        {
            for(int i=0;i<pointa.Length;i++)
            {
                pointa[i] = rotate30(pointa[i]);
            }
            draw(pointa);
        }
  Point rotate30(Point a)                  //旋转30度
        {
            double c = 30 * Math.PI / 180.0;
            int x = a.X;
            int y = a.Y;
            a.X = Convert.ToInt32(x * Math.Cos(c) - y * Math.Sin(c));
            a.Y = Convert.ToInt32(x * Math.Sin(c) + y * Math.Cos(c));
            return a;
        }
    void draw(Point[] pointm)                             
        {
            //原点移动到215,215
            g = this.pictureBox1.CreateGraphics();
            g.Clear(this.pictureBox1.BackColor);
            g.TranslateTransform(265, 245);

            g.DrawLine(new Pen(new SolidBrush(Color.Black)), new Point(-300, 0), new Point(300, 0));
            g.DrawLine(new Pen(new SolidBrush(Color.Black)), new Point(0, -300), new Point(0, 300));
           
            g.DrawPolygon(new Pen(new SolidBrush(Color.Blue)), pointm);
            g.Dispose();

        }


以上程序,每按一次旋转,多边形从当前位置转30度。

image.png


下面勇哥谈谈利用矩阵来旋转点


把上面的行列式写成矩阵的方式是这样的:

image.png

但这是一个2*2矩阵,无法表示平移操作。

在计算机图形学中,为了统一将平移、旋转、缩放等用矩阵表示,需要引入齐次坐标。(假设使用2x2的矩阵,是没有办法描述平移操作的,只有引入3x3矩阵形式,才能统一描述二维中的平移、旋转、缩放操作。同理必须使用4x4的矩阵才能统一描述三维的变换)。

由于引入了齐次坐标,在描述二维坐标的时候,使用(x,y,w)的方式(一般w=1),于是可以写成下面矩阵的形式。

于是我们可以把上面的2*2旋转矩阵扩展成下面这样的3*3矩阵。

image.png

勇哥写了一段C#代码测试一下这个旋转矩阵:

public static List<Point> RotateTrans(List<Point> points, double angel)
        {
            /*
             * 旋转的变换矩阵
             * 
             * cos  sin 0 
             * -sin  cos 0
             *  0    0  1
             *  
             * 点
             * 
             *   X
             *   Y
             *   1
             *   
             * **/
            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 矩阵
                                             // 输出当前变换矩阵
            Console.WriteLine("旋转的变换矩阵为: \n" + R.ToString());
            // 变换

            points = Trans(points, R);
            return points;
        }

        public static List<Point> Trans(List<Point> points, Matrix trans)
        {
            // 遍历List<Point> 对每一个点都变换
            for (int i = 0; i < points.Count; ++i)
            {
                double[] Pdata = new double[] { points[i].X, points[i].Y, 1 };
                Matrix P = new Matrix(3, 1, Pdata);

                Console.WriteLine("之前P: \n" + P.ToString());
                // 矩阵的乘法 (即变换)
                P = trans * P;
                Console.WriteLine("之后P: \n" + P.ToString());

                // 将当前更新后的点替换原先的点
                // 四舍五入
                int x = Round_Int(P.GetElement(0, 0));
                int y = Round_Int(P.GetElement(1, 0));
                points[i] = new Point(x, y);
            }
            return points;
        }

        private void button5_Click(object sender, EventArgs e)
        {
            draw(RotateTrans(pointa.ToList(), 30).ToArray());
        }

如果想顺时针转动,则修改矩阵为:

 cosA, -sinA, 0,
 sinA, cosA, 0

或者把旋转角度写成-30度。

image.png

程序中的类Matrix不是微软的类库,它是netMarketing类库v1.3.1中的一个类。

你也可以网上搜索一下矩阵的类库。


--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!


本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864