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


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值