VC++图形编程中的坐标映射模式

 前段时间自己在研究Windows的GDI(图形设备接口)编程。刚开始时被其中的坐标映射方式搞得晕头转向,后来经过反复实践终于恍然大悟有所启迪,现总结如下,以避免朋友们遇到此类问题走弯路。
 Windows的GDI支持两种坐标系,即逻辑坐标系和物理设备坐标系。必须明确逻辑坐标系对应于平时所说的窗口(Window),而设备坐标系才对应视口   (Viewport)。Ondraw中的CDC类所有的绘图方法都是基于逻辑坐标而言的,GDI通过映射模式将逻辑窗口中的图形输出到物理设备上来的。
 由逻辑窗口到物理视口的映射过程我们可以这样理解:我们在窗口坐标系(一般是X轴向右递增,Y轴向上递增,即与笛卡尔坐标系一致,而坐标单位是用户自定义的)上绘图,然后要在视口坐标系(一般坐标原点在屏幕视图的左上角,X轴向右递增,Y轴向下为正方向)下显示,坐标映射方式则规定了窗口和视口的范围,各轴的相对方向、原点或缩放比例等。
对这种映射简单打个比方,如图1,假如我们设定某种映射方式后,规定窗口坐标系的Y轴向上为正方向,视口坐标系的Y轴方向相反,视口坐标系的原点位于窗口坐标系中的(x0, y0)处,那么视图区所覆盖的窗口系中的图形部分将会显示在屏幕上,其余图形则不会显示,所以我们可以把视图区看作一个裁剪窗口,只是这个裁剪窗口随不同的映射方式位置不同而已罢了。 
图 1
针对不同的用途,Windows提供三类、共八种标准的映射方式,以便绘图操作:
一 MM_TEXT(默认的坐标映射方式)
图 2
窗口坐标系和视口坐标系完全重合,同为上图,坐标原点对应视图的左上角。此方式下可以把视口系统看作是窗口系统的子区间,并映射为像素单位,即1逻辑单位=1像素,取值范围取决于屏幕的像素分辨率。 
pDC->SetMapMode(MM_TEXT);
pDC->Rectangle(0, 0, 100, 100);
pDC->Rectangle(100, 100, 200, 200);
上面代码输出结果为:
图 3
 再看以下代码:
pDC->SetMapMode(MM_TEXT);
pDC->Rectangle(-100, -100, 100, 100);
pDC->MoveTo(0, 0);
pDC->LineTo(200, 200);
上面代码仅显示图形的右下部分,如下图:
图 4
我们希望看到图形的全部,或者想让逻辑坐标系的原点位于视图区的中央或更精确的如(200, 200)坐标处,则要用到函数SetWindowOrg或SetViewportOrg。
CPoint SetWindowOrg(int x, int y) //平移视口坐标系,使其原点与窗口坐标系中的坐标(x, y)重合
CPoint SetViewportOrg(int x, int y)//平移窗口坐标系,使其原点与视口坐标系的坐标(x, y)重合
pDC->SetMapMode(MM_TEXT);
pDC->SetViewportOrg(200, 200);
// pDC->SetViewportOrg(-200, -200);
pDC->Rectangle(-100, -100, 100, 100);
pDC->MoveTo(0, 0);
pDC->LineTo(200, 200);
绘制效果如下:
图 5
二    MM_HIENGLISH(高精度英制坐标系) 1单位 = 0.001英寸
         MM_LOENGLISH(低精度英制坐标系) 1单位 = 0.01英寸
        MM_HIMETRIC(高精度公制坐标系) 1 单位 = 0.01毫米
         MM_LOMETRIC(低精度公制坐标系) 1 单位 = 0.1毫米
         MM_TWIPS(排版坐标系) 1 单位 = 1缇 = 1/1440英寸
这五种映射方式都规定窗口坐标系的X轴向右,Y轴向上为正方向,区别在于1逻辑单位与1设备单位的换算关系不同。此时仍然可以把视图区看作是逻辑坐标系的一个子区间,只是它位于逻辑坐标系的第四象限。
图 6
如果想显示图3的类似绘制效果,那么须修改代码如下:
pDC->SetMapMode(MM_LOENGLISH);
pDC->Rectangle(0, 0, 100, -100);
pDC->Rectangle(100, -100, 200, -200);
三      MM_ISOTROPIC(各向同性坐标系,x与y单位相等)
   MM_ANISOTROPIC(各向异性坐标系,x与y单位不等)
在以上两种方式下,还需要额外设置窗口和视口的范围、,各轴的相对方向、原点及缩放比例。                                              
SetWindowExt(int Lwidth, int Lheight) //参数的单位为逻辑单位(Logical);
SetViewportExt(int Pwidth, int Pheight) //参数的单位为像素(Pixel);
虽然这两个函数是设置窗口和视口范围的函数,但真正意义是设定两坐标单位刻度比。即
pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(10240,7680);
       pDC->SetViewportExt(1024,768);
       pDC->Rectangle(0,0,100,100);                                                                                       和下面代码
pDC->SetMapMode(MM_ISOTROPIC);
       pDC->SetWindowExt(102400,76800);
       pDC->SetViewportExt(10240,7680);
       pDC->Rectangle(0,0,100,100);                                                                                       绘制效果完全相同。
SetWindowExt和SetViewportExt还确定了两坐标系中X轴和Y轴相对方向。如果Lwidth与Pwidth同号,逻辑坐标的x轴方向与设备坐标系中的x轴方向相同,否则相反。需要说明的是设备坐标系保持X轴向右,Y轴向下为正方向。
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(10240,-7680);//逻辑坐标Y轴的方向与设备坐标系Y轴方向相反,即向上为正方向,
pDC->SetViewportExt(1024,768);//1逻辑单位=0.1设备单位
      此外,当使用MM_ISOTROPIC模式时,如果通过计算window与viewport范围的比值得到两个方向的单位刻度比值不同时,那么将会以较小的那个为准。即
pDC->SetMapMode(MM_ISOTROPIC);
pDC->SetWindowExt(10240,7680);
// pDC->SetWindowExt(1024,7680);
// pDC->SetWindowExt(10240,768);
pDC->SetViewportExt(1024,768);
pDC->Rectangle(0,0,100,100);
绘制效果完全相同。
下面是一段完整的绘制代码,输出如图7
    CRect cRect; // 客户区矩形
    int i, j;
    pDC->SetMapMode(MM_ISOTROPIC); // 设定映射方式
    pDC->SetWindowExt(4000, 3000);
    AfxGetMainWnd()->GetClientRect(cRect); // 获取主窗口客户区矩形
    pDC->SetViewportExt(cRect.Width(), -cRect.Height()); // 将整个客户区作为视图区,同时改变窗口坐标系Y轴方向,即向上为正方向
    pDC->SetViewportOrg(cRect.Width() / 2, cRect.Height() / 2); // 将窗口坐标系的原点平移到视图区的中央
    pDC->TextOut(-850, 1400, "The first Windows Application"); // 输出黑色标题文字
    // 画坐标轴
    pDC->MoveTo(-4000, 0);
    pDC->LineTo(4000, 0);
    pDC->MoveTo(0, -3000);
    pDC->LineTo(0, 3000);
    // 绘制图形
    for (i = 10; i > 0; i --)
    {
       j = 20 - (2 * i);
       pDC->Ellipse(j, j, 100 * i, 100 * i);
       pDC->Rectangle(-j, -j, -100 * i, -100 * i);
    }
图 7
 
总结
       第一、二类映射模式MM_TEXT, MM_LOENGLISH、MM_HIENGLISH、MM_ANISOTROPIC、MM_HIMETRIC, MM_ISOTROPIC、 MM_LOMETRIC, MM_TWIPS属于固定映射模式,该类映射模式已经固定了坐标轴的方向和坐标单位长度,如MM_TEXT规定Y轴向下,后面五种规定Y轴方向向上。第三类映射模式则允许用户自定义坐标系统,包括坐标轴方向和单位刻度值,也更加灵活。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值