您的位置:首页 > 移动开发 > IOS开发

ios坐标变换

2014-04-03 19:36 337 查看

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 例子分析



CGAffineTransform实际上是一个矩阵
| a,  b,  0 |
| c,  d,  0 |
| tx, ty, 1 |


a={1,1} b={1,2} c={2,1} d={2,2} tx={3,1} ty={3,2}

这个矩阵是用来标记这个View的变化,可以是旋转,缩放,平移。

也就是说,View的坐标为 {x,y},变化后的坐标是{x',y'}
.
| a,  b,  0 |
{x',y',1}={x,y,1} x | c,  d,  0 |
| tx, ty, 1 |




            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));

 
  
  
b72e
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);

}

Copyright ©2014 Delon
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: