IOS中二維座標變換

1.座標變換的數學基礎

      1.1 座標系

          數學中我們使用的是笛卡兒座標系,如下圖所示:                    

                 

            X軸正方向向右,Y軸正方向向上,原點O,座標點A(x,y)。

         1.2 仿射變換

             已知座標點A,變換後新座標系中座標爲B ,則有:

                                               B = AM

                  A爲1*3的矩陣[x,y,1]

                  B爲 1* 3的矩陣[x’,y’,1]

                  M爲3*3仿射矩陣

                             

                  所以AM=B可以寫成:

                            

                 展開後得到:   

                                  

                 以下是常用的變換矩陣:

                     單位矩陣:

                               

                      展開後得:

                              

                      平移矩陣:          

                              

                     展開後得: 

                              

                     縮放矩陣:

                             

                    展開後得:

                             

                            旋轉矩陣:

                            

                   展開後得:       

                                                                                                                                                                    

      1.3 座標變換類型

           模型變換: 座標系固定不動,變換座標系中的模型

           座標軸變換:座標系中模型固定不動, 變換座標系,相對於新座標系構造的變換矩陣和模型變換矩陣是一樣的          

          

          如上圖所示,A爲原座標系C中座標,A'爲新座標系中C'座標,在模型變換中新座標系和原座標系重疊在一起    

          二種變換方式A->A'變換矩陣都是相同的.     

2. IOS中座標系

       2.1 IOS中包含UIKit座標系(X軸正方向向右,Y軸正方向向下)和標準的Quartz 2D繪圖座標系(X軸正方向向右,Y軸正方向向上)

            使用相關API時要仔細閱讀文檔,弄清座標系類型,原點位置等.

      2.2 例子分析

            2.2.1把中心點爲A(50,50)長爲20,寬爲10的矩形以X軸逆時針旋轉45度

  - (void)drawRect:(CGRect)rect{      /**       * UIKit座標系,原點在UIView左上角       */      CGContextRef context =  UIGraphicsGetCurrentContext();      CGContextSaveGState(context);      CGAffineTransform transform;      /**       * 變換後 transform = CBA,顯然不是想要的結果.       * 這是由於CGAffineTransform變換函數構造的矩陣在左邊,如:       * t' = CGAffineTransformTranslate(t,tx,ty)       * 結果爲:t' = [ 1 0 0 1 tx ty ] * t       * 累積變換就會得到上面的結果       */      transform = CGAffineTransformIdentity;      transform = CGAffineTransformTranslate(transform, -50, -50); //A      transform = CGAffineTransformRotate(transform, M_PI_4);      //B      transform = CGAffineTransformTranslate(transform, 50, 50);   //C      /**       * 爲了得到正確結果,調整順序如下:       */      transform = CGAffineTransformIdentity;      transform = CGAffineTransformTranslate(transform, 50, 50);    //C      transform = CGAffineTransformRotate(transform, M_PI_4);       //B      transform = CGAffineTransformTranslate(transform, -50, -50);  //A         /**       * context函數變換       */      //CGContextTranslateCTM(context, 50, 50);    //C      //CGContextRotateCTM(context, M_PI_4);       //B      //CGContextTranslateCTM(context, -50, -50);  //A      CGContextConcatCTM(context, transform);      /**       * 繪製矩形       */      CGContextFillRect(context, CGRectMake(40, 45, 20, 10));      CGContextRestoreGState(context);  }

              

   2.2.2 繪製圖片,下面函數在工作線程裏面很有用

  void drawImage(CGContextRef context, CGImageRef image , CGRect rect){      /**       * 注意變換順序A->B->C->D       */      CGContextSaveGState(context);      /**       * 矩形回到起始位置       */      CGContextTranslateCTM(context, rect.origin.x, rect.origin.y);  //D      /**       * 矩形Y軸正方向平移rect.size.height       */      CGContextTranslateCTM(context, 0, rect.size.height);           //C      /**       * 垂直反轉矩形       */      CGContextScaleCTM(context, 1.0, -1.0);                         //B      /**       * 矩形平移到原點       */      CGContextTranslateCTM(context, -rect.origin.x, -rect.origin.y);//A      /**       * 繪製圖片       */      CGContextDrawImage(context, rect, image);      CGContextRestoreGState(context);  }

       2.2.3 座標軸變換

/** * 原座標系爲Quartz 2D,目標座標系爲UKit,用原座標系中座標繪圖 */- (void)drawRect:(CGRect)rect{    //UKit座標系    CGContextRef context =  UIGraphicsGetCurrentContext();    CGContextSaveGState(context);    CGRect bounds = self.bounds;        /**     * 座標軸變換A->B     */        /**     * 平移座標軸     */    CGContextTranslateCTM(context, 0, bounds.size.height); // B        /**     * 翻轉Y座標軸     */    CGContextScaleCTM(context, 1, -1);                     //A        /**     * 繪製矩形     */    CGContextFillRect(context, CGRectMake(10, 10, 20, 20));        CGContextRestoreGState(context);}

http://www.cnblogs.com/delonchen/archive/2011/08/03/iostransform.html


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章