原作者姓名 汪自军
介绍
Windows绘图映射模式有8种,涉及到逻辑坐标系,设备坐标系,窗口坐标,视口坐标等概念,本文就是作者学习研究之后的一点心得,和大家分享。
读者评分 3 评分次数 1
正文
Windows绘图映射模式
窗口和视口
数据显示和图形绘制并不是直接在屏幕上进行的,而是首先将图形绘制到一个具有逻辑坐标系的虚拟窗口中,然后再根据预先设置好的映射模式,将虚拟窗口中的图形或图像映射到屏幕或打印机等设备中。这个虚拟的窗口被称作窗口(windows),显示图像的设备就是视口(Viewport),对应着实际的屏幕或打印机。
用于设置窗口的函数:SetWindowsOrg和SetWindowExt
用于设置视口的函数:SetViewportOrg和SetViewportExt
逻辑坐标和设备坐标
逻辑坐标指的是窗口下的坐标,设备坐标指的是视口下的坐标,在视口下的设备坐标中的长度单位总是像素,坐标原点是窗口左上角,正方向为向右和向下。通过设置映射方式,可以设置窗口下的逻辑坐标系的长度单位和坐标的正方向,Windows有8种映射方式(详见MSDN)。
窗口原点、视口原点、逻辑原点和设备原点
可以把逻辑坐标原点看作是窗口中的一个固定的点,通过这个点,引出两条坐标线,建立逻辑坐标系,长度单位和正方向通过SetMapMode来设置。窗口原点只是逻辑坐标系中一个可变点,这个点的坐标是通过SetWindowOrg来设置的。
设备坐标原点可以看作是在视口中的一个固定点,对于屏幕而言,它对应于左上角点,通过这个点建立设备坐标系,长度单位是像素,X轴向右为正,Y轴向下为正。视口原点是设备坐标系中的一个可变点,这个点的坐标通过SetViewportOrg来设置。
逻辑坐标系和设备坐标系的联系
逻辑坐标系和设备坐标系是通过窗口原点和视口原点发生联系的,当图像各点从逻辑坐标系向设备坐标系映射时,根据坐标之间的换算关系,换算成图像各点在设备坐标系中相对于视口原点的位置,实现坐标映像。实际视口原点和窗口原点是同一个点,在设备坐标系和逻辑坐标系中有不现的坐标值。
XL-XLO = n*(XD-XDO)
YL-YLO = -n*(YD-YDO)
L为逻辑坐标系,D为设备坐标系,沿X坐标方向一个逻辑单位等于n个设备单位,沿Y方向一个逻辑坐标等于-n个逻辑坐标,LO对对应着DO,分别为窗口原点和视口原点,它们是同一个点。L系中点(XL,YL)在D坐标系中相应点(XD,YD)。如下图1。
逻辑坐标和设备坐标换算的步骤
1, 设置映像模式
2, 设置窗口原点
3, 设置视口原点
4, 坐标换算(由Windows系统内置的程序来完成,我们只须做前3步)
坐标映射模式的有关函数
1,virtual int SetMapMode(int nMapMode):设置映射方式,也就是设置逻辑坐标单位,返回上一次设置的映像码。
2,CPoint SetWindowsOrg(int x, int y):设置窗口原点,返回前一个窗口原点。
3,CPoint SetViewportOrg(int x, int y):设置视口原点,返回前一个视口原点。
4,virtual CSize SetWindowExt(int cx, iny cy):设置窗口在X和Y方向的幅度,返回先前的幅度。
5,virtual CSize SetViewportExt(int cx, int cy):设置视口在X和Y方向的幅度,返回先前的幅度。
4和5两函数只有在模式MM_ANISOTROPI和MM_ISOTROPIC下才有效,且MM_ISOTROPIC时cx和cy设置相同才有效
示例:
void CMyProView::OnDraw(CDC* pDC)
{
pDC->SetMapMode(MM_TEXT);
pDC->SetWindowOrg(CPoint (100, 100));
pDC->Rectangle(CRect(100, 100, 300, 300));
}
在逻辑坐标中以(100,100)为左上角点绘制一矩形,窗口原点就是(100,100),视口原点采用默认值(0,0),它对应屏幕的左上角,而视口原点和窗口原点是同一点,逻辑坐标为(100,100),所以矩形左上角(100,100)就在视口原点。如下图2
pDC->SetMapMode(MM_ISOTROPIC);
CSize size = pDC->GetViewportExt();
pDC->SetWindowExt(size.cx/2, -size.cy/2);
pDC->SetViewportOrg(-100, -100);
pDC->Rectangle(100, -100, 300, -300);
窗口幅度是视口幅度的一半,由上面提及到的方程式:
100-0 = 1/2 * (XDL-(-100)),-100-0 = -1/2*(YDL-(-100)),XDL = 100,YDL = 100
300-0 = 1/2 * (XDR+100),-300-0 = -1/2 * (YDR+100),XDR = 500,YDR = 500
如下图3