坐标系统与坐标变换
win32程序使用坐标系统之间的变换完成图形的缩放、旋转、平移等输出操作。win32下面总共使用四个坐标空间:世界坐标系、页面坐标系、设备坐标系和物理坐标系(包括客户区、桌面或打印纸等)。每个坐标空间都是一个线性空间,用两个相互垂直的坐标轴定位两维的物体。
我们把改变一个物体的大小、方向和形状的算法称作“变换”。一个图形物体从一个坐标空间映射到另一个坐标空间的过程就是一个变换。最终,物体显示在一个物理设备上,通常是屏幕或者打印机。
1、四个坐标系的定义
坐标系 描述 可选,用于图形转换的起始坐标空间。最大尺寸是 2^32单位高世界坐标系 和 2^32 单位宽。支持缩放、平移、旋转、变形、投射等转换操作。 作为世界坐标系之后的第二个坐标系使用,也可以作为变换的起页面坐标系 始坐标系。最大尺寸是 2^32单位高和 2^32 单位宽。可以设置映射模式。 用于页面坐标系之后。仅仅允许平移操作。保证设备坐标系的原设备坐标系 点位于正确的物理设备空间中合适的位置上。最大尺寸是2^27单位高和 2^27单位宽。 图形变换后的最终的输出空间。通常指程序窗口的客户区。也可物理坐标系 以是整个桌面、整个窗口区域或者打印机、绘图仪的某一页,取决于程序获得的DC的句柄。物理设备的尺寸取决于显卡、打印机等的设置。 页面空间和设备空间一起工作,在这两个空间下,程序可以使用设备相关的单位,例如毫米和英寸。但是在世界坐标系和页面坐标系下,都认为是逻辑坐标系,单位是逻辑单位1。
任何程序的绘图代码中使用的坐标都是从世界坐标系开始,直到物理坐标
系,最后得到(看到)输出结果。每两个坐标系之间,系统都采用一种变换方法,从前面的坐标空间复制(或者映射)一个矩形区域到下一个坐标空间。为了便于处理,如果程序调用了SetWorldTransform函数,则这个映射过程从世界坐标系开始,否则从页面坐标系开始。用图形表示如下:
举个例子说,如果我们在DC上面有个画线函数:
MoveTo(hDC, 0, 0); LineTo(hDC, 10,10);
则如果我们没有使用SetWordTransform函数,可以认为我们的画线操作就是在页面坐标系下面,0,10都是页面坐标系下的坐标。如果我们使用了SetWorldTransform函数,则画线操作是在世界坐标系下面。页面坐标系中对应的这个线段是世界坐标系下面的线段(0,0) -> (10,10) 通过两个坐标空间之间的变换矩阵变换得到,结果可能还是(0,0)点到(10,10)点,也可能是(5,9)点到(-20,14)点,这取决于两个坐标系之间的变换矩阵。
同样道理,对于上述四个坐标系,当系统从一个坐标系中复制指定矩形区域内的某个点到下一个坐标系时,它使用这两个坐标系之间的变换算法,根据点的原坐标计算得到点的像坐标。因此,一个图形在不同坐标系下,其尺寸、方向和形状都可能不同。注意一点,虽然这个变换是两个坐标系之间的,是针对物体整体而言的变换,但在系统在操作的时候,是逐点、逐行操作的。
虽然很少用到SetWorldTransform函数,但是应该掌握最基本的坐标系之间的线性变换矩阵,形式如下:
函数采用逻辑单位,缺省的变换矩阵是单位阵:
四个eM参数给出旋转和缩放变换系数,eDx/eDy给出平移变换系数。 注意SetWorldTransform函数要求DC的图形模式是GM_ADVANCED,可以用
SetGraphicsMode设置,仅Windows NT/ 2000下面支持。缺省图形模式是GM_COMPATIBLE,兼容16位windows,这个模式下不能使用该函数。下面简单介绍这两个坐标系之间的变换矩阵。
2、世界坐标系到页面坐标系的变换
(1)平移
物体上每个点进行水平和垂直的移动,eDx和eDy参数分别给出移动的尺寸。具体算法是:
x' = x + Dx y' = y + Dy
其中 x',y' 是新的坐标, x,y 是源坐标。Dx是水平移动距离,Dy是垂直移动距离。平移矩阵是:
(2)缩放
组成物体的每个水平行或者垂直行进行拉伸或者压缩。算法公式是: y' = y * Dy x' = x * Dx
其中Dy,Dx是缩放系数。用矩阵表示为:
(3)旋转
组成物体的每个点都相对于坐标原点旋转一个角度。算法公式是: x' = (x * cos A) - (y * sin A) y' = (x * sin A) + (y * cos A)
A表示绕原点逆时针旋转的角度,用矩阵表示如下: