GDI绘图坐标系映射的理解
2013-01-28 15:04
162 查看
GDI绘图坐标系映射的理解
设备坐标和设备单位: 例如屏幕或打印机的单位像素.
通常我们是使用GDI函数绘图, 然后在屏幕上显示. 但是逻辑坐标和设备坐标的单位不同, 逻辑坐标的单位是"猪屎", 而设备的坐标是"像素". 所以需要转换, 怎么转换? 例如2猪屎相当于屏幕的1像素, 那么这两个坐标系的转换当量是 2 猪屎/像素.
那么pDC->MoveTo(100, 200); 如果是在屏幕是绘图, 相当于移动到屏幕 (50像素, 100像素) 这个点的位置.
50像素 = 100猪屎 / 当量 = 100猪屎 / 2 猪屎/像素 = 50像素
100像素 = 200猪屎 / 当量 = 200猪屎 / 2 猪屎/像素 = 100像素
如下图: Windows绘图过程
那么怎么设置这个当量值?
通过CDC的 SetWindowExt和SetViewportExt (看MSDN)
例1. 某屏幕的单位是像素: 10猪屎等于该屏幕的1像素, 那么当量就是10猪屎/1像素 = 10猪屎/像素
可以这么设置pDC->SetWindowExt(10, 10); pDC->SetViewportExt(1, 1);
例2. 某屏幕的单位是像素: 10猪屎等于该屏幕的2像素, 那么当量就是10猪屎/2像素 = 5猪屎/像素
可以这么设置pDC->SetWindowExt(10, 10); pDC->SetViewportExt(2, 2);
为什么要使用两个函数来设置? pDC->SetXXXXXExt(5), 直接把5传给pDC不行吗? 看例3
例3. 某屏幕的单位是像素: 10猪屎等于该屏幕的3像素, 那么当量就是10猪屎/3像素 = 10/3猪屎/像素 = 3.3333...猪屎/像素.
当量是一个浮点数, 我个人了解是为了不影响绘图的速度, 因为绘图时, 两个坐标系频繁的映射也是需要时间的, 使用浮点数会加长这个时间.
例4. 某屏幕的单位是像素: 10猪屎等于该屏幕的3像素, 而且Y轴向下是负方向, 向上才是正方向.
默认方式下, 逻辑坐标系X轴是向右为正方向, Y轴是向下为正方向. 此时可以这么设置
X轴的当量是 10猪屎/3像素 = 10/3猪屎/像素
Y轴的当量是 - 10猪屎/3像素 = -10/3猪屎/像素(因为Y轴与逻辑坐标系的方向是相反的.)
可以这么设置pDC->SetWindowExt(10, -10); pDC->SetViewportExt(3, 3);
或者pDC->SetWindowExt(10, 10); pDC->SetViewportExt(3, -3);
映射方式 逻辑单位 X轴增加 Y轴增加
当量
1. MM_TEXT 像素点 右 下
1 猪屎/猪屎
2. MM_LOMETRIC 0.1mm 右
上 10猪屎/mm
3. MM_HIMETRIC 0.01mm 右
上 100猪屎/mm
4. MM_LOENGLISH 0.254mm 右 上
(1000/254)猪屎/mm
5. MM_HIENGLISH 0.0254mm 右 上
(10000/254)猪屎/mm
6. MM_TWIPS 0.0176mm 右 上
(10000/176)猪屎/mm
7. MM_ISOTROPIC 任意(x=y) 可选
可选 可设
8. MM_ANISOTROPIC 任意(x!=y) 可选 可选
可设
个人理解的映射模式: 默认情况下映射模式是MM_TEXT. 而对于模式2, 3, 4, 5, 6, 7, 8可以说是特殊的MM_TEXT模式. 都可以通过SetWindowExt和SetViewportExt设置实现. 只是某些映射关系使用比较频繁, 所以GDI直接作为一种模式使用例如这里的模式2, 3, 4, 5, 6.
映射模式使用SetMapMode来设置.
MM_LOMETRIC相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(10, 10);
pDC->SetViewportExt(1, -1);
MM_HIMETRIC相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(100, 100);
pDC->SetViewportExt(1, -1);
MM_LOENGLISH相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000, 1000);
pDC->SetViewportExt(254, -254);
如此类推....
所以使用模式MM_ANISOTROPIC是最强大的, 可以任意设置当量和方向.
那么pDC->MoveTo(10, 30); 绘图过程可以这么理解: 在MoveTo内部, 总是会执行10 - XOffset和10 - YOffset.
SetViewportOrg也是一样的理解.
1. 逻辑坐标与设备坐标的当量(EqueX和EqueY).
2. 逻辑坐标的偏移(LogicXOffset, LogicYOffst)和设备坐标的偏移(DeviceXOffset, DeviceYOffst).
例如现在有某一种狗屎设备, 单位是"狗屎", 12猪屎等于该设备的1狗屎. 而且该设备Y轴向上位正方向. 那么在GDI坐标系中点(5猪屎, 6猪屎) 在狗屎设备中的坐标系是哪一点?
DeviceX - DeviceXOffset = (LogicX - LogicXOffset) / EqueX;
DeviceY - DeviceYOffset = (LogicY - LogicYOffset) / EqueY;
其中
EqueX = 12猪屎/1狗屎 = 12猪屎/狗屎
EqueY = - 12猪屎/1狗屎 = -12猪屎/狗屎
这条公式GDI会帮我们自己执行的, 我们只需要调用对应的函数, 把参数设置好.
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(12, 12);
pDC->SetViewportExt(1, -1);
pDC->SetWindowOrg(LogicXOffset, LogicYOffset);
pDC->SetViewportOrg(DeviceXOffset, DeviceYOffset);
一. 坐标单位
Windows的GDI/GDI+的绘图函数绘制图形时使用的是逻辑坐标系, 逻辑坐标系的单位是逻辑单位. 例如: pDC->MoveTo(100, 300); 这里的100和300的单位就是逻辑单位, 我们可以这么说 100逻辑单位, 300逻辑单位, 我觉得"逻辑单位"这4个字又长又臭, 很绕口, 所以我喜欢这么叫 100 猪屎, 300猪屎. 那么pDC->MoveTo(100, 300);的意思就是pDC的在逻辑坐标的当前点移动到(100猪屎, 300猪屎)这个点.设备坐标和设备单位: 例如屏幕或打印机的单位像素.
通常我们是使用GDI函数绘图, 然后在屏幕上显示. 但是逻辑坐标和设备坐标的单位不同, 逻辑坐标的单位是"猪屎", 而设备的坐标是"像素". 所以需要转换, 怎么转换? 例如2猪屎相当于屏幕的1像素, 那么这两个坐标系的转换当量是 2 猪屎/像素.
那么pDC->MoveTo(100, 200); 如果是在屏幕是绘图, 相当于移动到屏幕 (50像素, 100像素) 这个点的位置.
50像素 = 100猪屎 / 当量 = 100猪屎 / 2 猪屎/像素 = 50像素
100像素 = 200猪屎 / 当量 = 200猪屎 / 2 猪屎/像素 = 100像素
如下图: Windows绘图过程
那么怎么设置这个当量值?
通过CDC的 SetWindowExt和SetViewportExt (看MSDN)
例1. 某屏幕的单位是像素: 10猪屎等于该屏幕的1像素, 那么当量就是10猪屎/1像素 = 10猪屎/像素
可以这么设置pDC->SetWindowExt(10, 10); pDC->SetViewportExt(1, 1);
例2. 某屏幕的单位是像素: 10猪屎等于该屏幕的2像素, 那么当量就是10猪屎/2像素 = 5猪屎/像素
可以这么设置pDC->SetWindowExt(10, 10); pDC->SetViewportExt(2, 2);
为什么要使用两个函数来设置? pDC->SetXXXXXExt(5), 直接把5传给pDC不行吗? 看例3
例3. 某屏幕的单位是像素: 10猪屎等于该屏幕的3像素, 那么当量就是10猪屎/3像素 = 10/3猪屎/像素 = 3.3333...猪屎/像素.
当量是一个浮点数, 我个人了解是为了不影响绘图的速度, 因为绘图时, 两个坐标系频繁的映射也是需要时间的, 使用浮点数会加长这个时间.
例4. 某屏幕的单位是像素: 10猪屎等于该屏幕的3像素, 而且Y轴向下是负方向, 向上才是正方向.
默认方式下, 逻辑坐标系X轴是向右为正方向, Y轴是向下为正方向. 此时可以这么设置
X轴的当量是 10猪屎/3像素 = 10/3猪屎/像素
Y轴的当量是 - 10猪屎/3像素 = -10/3猪屎/像素(因为Y轴与逻辑坐标系的方向是相反的.)
可以这么设置pDC->SetWindowExt(10, -10); pDC->SetViewportExt(3, 3);
或者pDC->SetWindowExt(10, 10); pDC->SetViewportExt(3, -3);
二. 坐标系
Windows的GDI/GDI+的逻辑坐标系, 默认是以窗口区域的左上角为原点(0猪屎, 0猪屎)这个点. X轴是向右为正方向, Y轴是向下为正方向. 通常屏幕也是这样, 所以我们一般在屏幕上绘图不需要设置映射关系. Windows提供的映射关系有:映射方式 逻辑单位 X轴增加 Y轴增加
当量
1. MM_TEXT 像素点 右 下
1 猪屎/猪屎
2. MM_LOMETRIC 0.1mm 右
上 10猪屎/mm
3. MM_HIMETRIC 0.01mm 右
上 100猪屎/mm
4. MM_LOENGLISH 0.254mm 右 上
(1000/254)猪屎/mm
5. MM_HIENGLISH 0.0254mm 右 上
(10000/254)猪屎/mm
6. MM_TWIPS 0.0176mm 右 上
(10000/176)猪屎/mm
7. MM_ISOTROPIC 任意(x=y) 可选
可选 可设
8. MM_ANISOTROPIC 任意(x!=y) 可选 可选
可设
个人理解的映射模式: 默认情况下映射模式是MM_TEXT. 而对于模式2, 3, 4, 5, 6, 7, 8可以说是特殊的MM_TEXT模式. 都可以通过SetWindowExt和SetViewportExt设置实现. 只是某些映射关系使用比较频繁, 所以GDI直接作为一种模式使用例如这里的模式2, 3, 4, 5, 6.
映射模式使用SetMapMode来设置.
MM_LOMETRIC相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(10, 10);
pDC->SetViewportExt(1, -1);
MM_HIMETRIC相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(100, 100);
pDC->SetViewportExt(1, -1);
MM_LOENGLISH相当于:
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(1000, 1000);
pDC->SetViewportExt(254, -254);
如此类推....
所以使用模式MM_ANISOTROPIC是最强大的, 可以任意设置当量和方向.
三. 坐标原点
其实所谓的原点都是相对的, 使用SetWindowOrg和SetViewportOrg设置, 我觉得这样理解更简单: 逻辑坐标系默认原点是(0猪屎, 0猪屎), 这是固定的, SetWindowOrg是用来设置偏移量的(或者叫平移量.)(XOffset和YOffset).那么pDC->MoveTo(10, 30); 绘图过程可以这么理解: 在MoveTo内部, 总是会执行10 - XOffset和10 - YOffset.
SetViewportOrg也是一样的理解.
四. 坐标系之间的映射.
现在理解坐标系的映射就非常简单了. 你只需要知道如下的内容.1. 逻辑坐标与设备坐标的当量(EqueX和EqueY).
2. 逻辑坐标的偏移(LogicXOffset, LogicYOffst)和设备坐标的偏移(DeviceXOffset, DeviceYOffst).
例如现在有某一种狗屎设备, 单位是"狗屎", 12猪屎等于该设备的1狗屎. 而且该设备Y轴向上位正方向. 那么在GDI坐标系中点(5猪屎, 6猪屎) 在狗屎设备中的坐标系是哪一点?
DeviceX - DeviceXOffset = (LogicX - LogicXOffset) / EqueX;
DeviceY - DeviceYOffset = (LogicY - LogicYOffset) / EqueY;
其中
EqueX = 12猪屎/1狗屎 = 12猪屎/狗屎
EqueY = - 12猪屎/1狗屎 = -12猪屎/狗屎
这条公式GDI会帮我们自己执行的, 我们只需要调用对应的函数, 把参数设置好.
pDC->SetMapMode(MM_ANISOTROPIC);
pDC->SetWindowExt(12, 12);
pDC->SetViewportExt(1, -1);
pDC->SetWindowOrg(LogicXOffset, LogicYOffset);
pDC->SetViewportOrg(DeviceXOffset, DeviceYOffset);
五. 小结
其实就是坐标缩放和平移. 还没有旋转呢.相关文章推荐
- GDI映射模式理解
- GDI 坐标系 与 映射模式
- Windows GDI 坐标系及坐标映射
- [win32] GDI绘图常用的三种坐标系
- 第五章 绘图基础 ( GDI映射模式 )
- windows程序设计之绘图基础之GDI映射模式
- windows程序设计之绘图基础之GDI映射模式
- 从GDI到GDI+使用的坐标系看微软二维绘图思路的进步
- GDI映射模式理解
- GDI绘图中的映射模式CDC::SetMapMode()
- GDI绘图中的映射模式CDC::SetMapMode()
- 理解映射方式、设备坐标系、逻辑坐标系、设置逻辑坐标原点与设备坐标原点
- GDI绘图中的映射模式CDC::SetMapMode()
- GDI绘图之缩放成像
- MATLAB绘图确定坐标系的显示范围
- Canvas坐标系与绘图坐标系
- Linux内核中ioremap映射的透彻理解
- GDI 字体 设备上下文 绘图
- c# GDI+简单绘图
- 《VC++深入详解》读书笔记——4.MFC消息映射机制和绘图DC的获取