Quartz 2D编程指南(5)变换(Transforms)

来源:互联网 发布:网络信息安全测评认证 编辑:程序博客网 时间:2024/05/21 06:36
    Quartz2D绘制模型定义了两种完全独立的坐标空间:用户空间(用于表现文档页)和设备空间(用于表现设备的原生分辨率)。用户坐标空间用浮点数表示坐标,与设备空间的像素分辨率没有关系。当我们想要打印和显示文档时, Quartz会将用户空间坐标系统映射到设备空间坐标系统。因此,我们不需要重写应用程序或添加额外的代码来调整应用程序的输出以适应不同的设备。

       我们可以通过操作CTM(current transformation matrix当前变换矩阵)来修改默认的用户空间。在创建图形上下文后,CTM是单位矩阵,我们可以使用 Quartz的变换函数来修改CTM,从而修改用户空间中的绘制操作。

这一章节主要内容:

1:变换操作函数概览
2:怎样修改CTM
3:怎样创建一个仿射变换
4:怎样确定两个变换是否相同
5:怎样获取user-to-device-space变换
6:在affine transforms之后讨论数学(he Math Behind the Matrices)

Quartz变换函数(About Quartz Transformation Functions)

      我们可能使用Quartz内置的变换函数方便的平移、旋转和缩放我们的绘图。只需要短短几行代码,我们便可以按顺序应用变换或组合变换。图5-1显示了缩放和旋转一幅图片的效果。我们使用的每个变换操作都更新了CTMCTM总是用于表示用户空间和设备空间的当前映射关系。这种映射确保了应用程序的输出在任何显示器或打印机上看上去都很棒。

                       Figure 5-1  Applying scaling and rotation
  
                       Applying scaling and rotation

   Quartz2D API提供了5个函数,以允许我们获取和修改CTM。我们可以旋转、平移、缩放CTM。而且我们还可以联结一个仿射变换矩阵。更多信息可以看:Modifying the Current Transformation Matrix.

   Quartz允许我们创建应用的仿射矩阵但是不操作我们的用户空间一直到我们决定使用变换到CTM时。我们同样可以使用另外一组函数来创建仿射变换,这些变换可以与CTM联结在一起。更多信息可以看: Creating Affine Transforms.

      我们可以不需要了解矩阵的数学含义而使用这些函数。如果我们想了解当调用变换函数的时候,Quartz做了什么事情,我们可以看The Math Behind the Matrices.

修改CTM(Current Transformation Matrix)

      我们可以在绘制图像前操作CTM来旋转、缩放或平移page,从而变换我们将要绘制的对象。以变换CTM之前,我们需要保存图形状态,以便绘制后能恢复。我们同样能用仿射矩阵来联结CTM。在本节中,我们将介绍与CTM函数相关的四种操作平移、旋转、缩放和联结。

      假设我们提供了一个可用的图形上下文、一个指向可绘制图像的矩形的指针和一个可用的CGImage对象,则下面一行代码绘制了一个图像。该行代码可以绘制如图5-2所示的图片。在阅读了本节余下的部分后,我们将看到图像的改变由于使用了变换。
CGContextDrawImage (myContext, rect, myImage);

                       Figure 5-2  An image that is not transformed
  
                 An image that is not transformed

       平移变换根据我们指定的x, y轴的值移动坐标系统的原点。我们通过调用CGContextTranslateCTM函数来修改每个点的x, y坐标值。如图5-3显示了一幅图片沿x轴移动了100个单位,沿y轴移动了50个单位。具体代码如下:
CGContextTranslateCTM (myContext, 100, 50);

                              Figure 5-3  A translated image

                 A translated image

      旋转变换根据指定的角度来移动坐标空间。我们调用CGContextRotateCTM函数来指定旋转角度(以弧度为单位)。图5-4显示了图片以原点(左下角)为中心旋转45度,代码所下所示:
CGContextRotateCTM (myContext, radians(–45.));

      由于旋转操作使图片的部分区域置于上下文之外,所以区域外的部分被裁减。我们用弧度来指定旋转角度。如果需要进行旋转操作,下面的代码将会很有用。
#include <math.h>staticinlinedouble radians (double degrees) {return degrees * M_PI/180;}
                       
                           Figure 5-4  A rotated image

                  A rotated image

      缩放操作根据指定的x, y因子来改变坐标空间的大小,从而放大或缩小图像。x, y因子的大小决定了新的坐标空间是否比原始坐标空间大或者小。另外,通过指定x因子为负数,可以倒转x轴,同样可以指定y因子为负数来倒转y轴。通过调用CGContextScaleCTM函数来指定x, y缩放因子。图5-5显示了指定x因子为0.5y因子为0.75后的缩放效果。代码如下:
CGContextScaleCTM (myContext, .5, .75);

                          Figure 5-5  A scaled image

                    A scaled image

      联合变换将两个矩阵相乘来联接现价变换操作。我们可以联接多个矩阵来得到一个包含所有矩阵累积效果矩阵。我们也可以通过调用CGContextConcatCTM来联接CTM和仿射矩阵。另外一种得到累积效果的方式是执行两个或多个变换操作而不恢复图形状态。图5-6显示了先平移后旋转一幅图片的效果,代码如下:
CGContextTranslateCTM (myContext, w,h);CGContextRotateCTM (myContext, radians(-180.));

                 Figure 5-6  An image that is translated and rotated

                     An image that is translated and rotated

5-7显示了平移、缩放和旋转一幅图片,代码如下:
CGContextTranslateCTM (myContext, w/4, 0);CGContextScaleCTM (myContext, .25,  .5);CGContextRotateCTM (myContext, radians ( 22.));

               Figure 5-7  An image that is translated, scaled, and then rotated

          An image that is translated, scaled, and then rotated

变换操作的顺序会影响到最终的效果。如果调换顺序,将得到不同的结果。调换上面代码的顺序将得到如图5-8所示的效果,代码如下:
CGContextRotateCTM (myContext, radians ( 22.));CGContextScaleCTM (myContext, .25,  .5);CGContextTranslateCTM (myContext, w/4, 0);

                Figure 5-8  An image that is rotated, scaled, and then translated

           An image that is rotated, scaled, and then translated

创建仿射变换(Creating Affine Transforms)

      仿射变换操作在矩阵上,而不是在CTM上。我们可以使用这些函数来构造一个之后用于CTM(调用函数CGContextConcatCTM)的矩阵。仿射变换函数使用或者返回一个CGAffineTransform数据对象。我们可以构建简单或复杂的仿射变换。

      仿射变换函数能实现与CTM函数相同的操作平移、旋转、缩放、联合。表5-1列出了仿射变换函数及其用途。注意每种变换都有两个函数

                              Table 5-1  Affine transform functions for translation, rotation, and scaling

Function

Use

CGAffineTransformMakeTranslation

To construct a new translation matrix from x and y values that specify how much to move the origin.

CGAffineTransformTranslate

To apply a translation operation to an existing affine transform. 

CGAffineTransformMakeRotation

To construct a new rotation matrix from a value that specifies in radians how much to rotate the coordinate system.

CGAffineTransformRotate

To apply a rotation operation to an existing affine transform. 

CGAffineTransformMakeScale

To construct a new scaling matrix from x and y values that specify how much to stretch or shrink coordinates.

CGAffineTransformScale

To apply a scaling operation to an existing affine transform.


   Quartz同样提供了一个仿射变换函数(CGAffineTransformInvert)来倒置矩阵。倒置操作通常用于在变换对象中提供点的倒置变换。当我们需要恢复一个被矩阵变换的值时,可以使用倒置操作。将值与倒置矩阵相乘,就可得到原先的值。我们通常不需要倒置操作,因为我们可以通过保存和恢复图形状态来倒置CTM的效果。

      在一些情况下,我们可能不需要变换整修空间,而只是一个点或一个大小。
      我们通过调用CGPointApplyAffineTransformCGPoint结构上执行变换操作。
      调用CGSizeApplyAffineTransformCGSize结构上执行变换操作。
      调用CGRectApplyAffineTransformCGRect结构上执行变换操作。
   CGRectApplyAffineTransform返回一个最小的矩形,该矩形包含了被传递给CGRectApplyAffineTransform的矩形对象的角点。如果矩形上的仿射变换操作只有缩放和平移操作,则返回的矩形与四个变换后的角组成的矩形是一致的。

    可以通过调用函数CGAffineTransformMake来创建一个新的仿射变换,但与其它函数不同的是,它需要提供一个矩阵实体。

评价仿射变换(Evaluating Affine Transforms)

     我们可以通过调用CGAffineTransformEqualToTransform函数来决定一个仿射变换是否与另一个相同。如果两个变换相同,则返回true;否则返回false

     函数CGAffineTransformIsIdentity用于确认一个变换是否是单位变换。单位变换没有平移、缩放和旋转操作。Quartz常量CGAffineTransformIdentity表示一个单位变换。

获取用户空间到设备空间的变换(Getting the User to Device Space Transform)

     当使用Quartz2D时,我们只是在用户空间下工作。Quartz为我们处理用户空间和设备空间的转换。如果我们的应用程序需要获取Quartz转换用户空间和设备空间的仿射变换,我们可以调用函数CGContextGetUserSpaceToDeviceSpaceTransform.

   Quartz提供了一系列的函数来转换用户空间和设备空间的几何体。我们会发现这些函数使用赶来比使用CGContextGetUserSpaceToDeviceSpaceTransform函数返回的仿射变换更好用。

点:函数 CGContextConvertPointToDeviceSpace CGContextConvertPointToUserSpace 将一个CGPoint数据结构从一个空间变换到另一个空间。
大小:函数 CGContextConvertSizeToDeviceSpaceCGContextConvertSizeToUserSpace 将一个CGSize数据结构从一个空间变换到另一个空间。
矩形:函数CGContextConvertRectToDeviceSpace  CGContextConvertRectToUserSpace 将一个CGPoint数据结构从一个空间变换到另一个空间。

0 0
原创粉丝点击