GDI绘图坐标系映射的理解

本文详细介绍了GDI绘图中的坐标单位、坐标系、坐标原点、坐标系之间的映射关系,以及如何设置和理解这些概念。通过实例解析了逻辑坐标系与设备坐标的转换,强调了坐标系的映射对于绘图的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

GDI绘图坐标系映射的理解


一. 坐标单位


        Windows的GDI/GDI+绘图函数绘制图形时使用的是逻辑坐标系, 逻辑坐标系的单位是逻辑单位. 例如: pDC->MoveTo(100, 300); 这里的100300的单位就是逻辑单位我们可以这么说 100逻辑单位, 300逻辑单位我觉得"逻辑单位"4个字又长又臭很绕口所以我喜欢这么叫 100 猪屎, 300猪屎那么pDC->MoveTo(100, 300);的意思就是pDC的在逻辑坐标的当前点移动到(100猪屎, 300猪屎)这个点.

       设备坐标和设备单位例如屏幕或打印机的单位像素

通常我们是使用GDI函数绘图然后在屏幕上显示但是逻辑坐标和设备坐标的单位不同逻辑坐标的单位是"猪屎", 而设备的坐标是"像素". 所以需要转换怎么转换例如2猪屎相当于屏幕的1像素那么这两个坐标系的转换当量是 猪屎/像素.

那么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                 像素点                       右                                   下                                 猪屎/猪屎

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是用来设置偏移量的(或者叫平移量.)(XOffsetYOffset).

        那么pDC->MoveTo(10, 30); 绘图过程可以这么理解MoveTo内部总是会执行10 - XOffset10 - YOffset.

SetViewportOrg也是一样的理解.

四. 坐标系之间的映射.


现在理解坐标系的映射就非常简单了你只需要知道如下的内容.

1. 逻辑坐标与设备坐标的当量(EqueXEqueY).

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


五. 小结


其实就是坐标缩放和平移还没有旋转呢.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值