几何尺寸与公差论坛

 找回密码
 注册
查看: 3891|回复: 0

Mfc 中的坐标映射方式

[复制链接]
发表于 2007-10-29 13:49:09 | 显示全部楼层 |阅读模式
视口的概念

窗口指的是虚拟存在的一个屏幕,而视口指的是在屏幕上看到的视图客户区域。在Windows中绘制图形时,并不是把图形直接绘制到屏幕上,而是以各种映像方式下的逻辑坐标系将图形绘制到虚拟的窗口中,然后再将这个窗口中的内容映像到视口中。如果是映像到屏幕上就实现了图形的显示;如果是映像到打印机等输出设备上就实现了图形的打印输出。  因此,窗口原点、视口原点和坐标系中的原点3者的概念是不同的。窗口原点和视口原点指的是同一个点在窗口逻辑坐标和视口设备坐标系的坐标值,它决定了图形由窗口映射到视口时的相对位置。

l  Windows函数中指定的所有坐标值必须在-32768到32767之间(这是C语言的int类型数据的域)。

在任何映射方式下,逻辑坐标和设备坐标的缺省原点都为(0,  0),即逻辑坐标的点(0, 0)映射到设备坐标的点(0, 0)。

l  SetViewportOrg函和SetWindowOrg函数可用于改变视区和窗口的原点,但这两个函数不能同时

用,无论怎样改变窗口和视区的原点,Windows都将窗口原点变换到视口原点,并按同样的映射算法(即使用当前给出的映射公式)变换其余的点,例如,如果窗口和视区的X坐标范围分别是2和4,则GDI将逻辑坐标系的X轴的正半轴映射到该设备坐标系统的X轴正半轴且GDI将一个逻辑单位(按X轴计算)映射为两个设备单位;如果窗口和视区的Y坐标范围分别为2和-1,则GDI将逻辑坐标系统的Y轴的正半轴映射到设备坐标系的Y轴的负半轴。

l  对于绘图,常常涉及到逻辑坐标与设备坐标,窗口(Window)和视口(Viewport)。

这里有几点应该明白:窗口中的坐标都是逻辑坐标,视口中的坐标都是设备坐标。我们的绘图语句中用的坐标都是逻辑坐标。

l  在CWnd类中与窗口和视口有关的操作函数如下:

SetWindowOrg函数用来设置一个与设备环境有关的窗口原点。
SetViewportOrg函数用来设置一个与设备环境有关的视口原点。
SetWindowExt函数用来设置与设备环境有关的窗口在x和y方向的幅度。只有在MM_ISOTROPIC映像方式下该函数才有效。
SetViewportExt函数用来设置与设备环境有关的视口在x和y方向的幅度。只有在MM_ISOTROPIC映像方式下该函数才有效。
必须注意,在MM_ISOTROPIC映像方式下,必须先设置窗口幅度,再设置视口幅度。

l  绘制的图形在设备(如显示器)上显示的过程为:

(1)逻辑坐标值减去逻辑坐标原点(SetWindowOrg中设置的值)

(2)上面的结果乘以比例因子变为设备坐标值

(3)上面结果加上设备坐标原点值(SetViewportOrg中设置的值)然后在设备上显示。

例如:

假定一个点在窗口逻辑坐标为(xWindow,  yWindow),在视口设备像素坐标为(xViewport, yViewport),则有如下转换关系:

xViewport = (xWindow  - xWinOrg) * xViewExt / xWinExt + xViewOrg

yViewport = (yWindow -  yWinOrg) * yViewExt / yWinExt +  yViewOrg

SetWindowExt和SetViewportExt用来设置逻辑坐标和设备坐标的比例因子和坐标轴方向,并不限制坐标范围(即逻辑坐标转换为设备坐标超出SetViewportExt设置的范围只要不超出CDC对象相关的区域范围也可以显示出来)。

l  在DC上进行的任何操作都是针对逻辑坐标的,并且是在“窗口”坐标上进行的,而具体哪些内容

被显示到屏幕上,取决于“视口”(Viewport)坐标系。窗口坐标和视口(设备)坐标有一个对应关系,可以看作两个原点重叠,注意,原点不一定是(0,0)点。对于窗口上的坐标值,要转换为视口(设备)坐标值,首先是减去窗口原点值,然后乘以比例因子,然后加上视口原点值得到的。屏幕上显示窗口的左上角始终是视口的(0,0)点,

(1)大多数的CDC类的成员函数要以逻辑坐标作为参数。

(2)CWnd类的成员函数要以设备坐标作为参数。

(3)所有选中测试操作和区域的定义要以设备坐标来表示。

(4)将一些长期使用的坐标值用逻辑坐标来保存。
详析VC中坐标系的建立
bull77


  建立一个合适的坐标系可以为我们的绘图带来很大的方便  。下面介绍一下如何在VC中建立我们想要的坐标系。

  一 设备坐标和逻辑坐标

  设备坐标(Device  Coordinate)又称为物理坐标(Physical  Coordinate),是指输出设备上的坐标。通常将屏幕上的设备坐标称为屏幕坐标。设备坐标用对象距离窗口左上角的水平距离和垂直距离来指定对象的位置,是以像素为单位来表示的,设备坐标的X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。

  逻辑坐标(Logical  Coordinate)是系统用作记录的坐标。在缺省的模式(MM_TEXT)下,逻辑坐标的方向和单位与设备坐标的方向和单位相同,也是以像素为单位来表示的,X轴向右为正,Y轴向下为正,坐标原点位于窗口的左上角。逻辑坐标和设备坐标即使在缺省模式下其数值也未必一致,除了在以下两种情况下:

  1.  窗口为非滚动窗口

  2.  窗口为滚动窗口,但垂直滚动条位于滚动边框的最上端,水平滚动条位于最左端,但如果移动了滚动条这两种坐标就不一致了。

  在VC中鼠标坐标的坐标位置用设备坐标表示,但所有GDI绘图都用逻

  坐标表示,所以用鼠标绘图时,那么必须将设备坐标转换为逻辑坐标,可以使用CDC  函数DptoLP()将设备坐标转化为逻辑坐标,同样可以用LptoDP()将逻辑坐标转化为设备坐标。

  二  坐标模式


  为了在不同的领域使用逻辑坐标,Windows提供了以下8种坐标模式:

  分别为MM_TEXT、MM_HIENGLISH、MM_LOENGLISH、MM_HIMETRIC、MM_LOMETRIC、MM_TWIPS、MM_ANISOTROPIC和MM_ISOTROPIC。  



  三 实例解析

  (一)  建立以左上角为原点,X轴和Y轴为1000的坐标,如下图




  我们可以用以下代码:

  void  CTtView::OnDraw(CDC* pDC)
   {
    CTtDoc* pDoc =  GetDocument();
    ASSERT_VALID(pDoc);
    CRect  rect;
    GetClientRect(&rect);

    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetViewportOrg(0,0);
    pDC->SetViewportExt(rect.right,rect.bottom);

    pDC->SetWindowOrg(0,0);
    pDC->SetWindowExt(1000,1000);

    pDC->MoveTo(50,50);
    pDC->LineTo(50,950);
    pDC->LineTo(950,950);
    pDC->LineTo(50,50);
   }

  代码分析:

  1.  GetClientRect(&rect); 取得客户区矩形区域,将其存放在rect中

  2.  用pDC->SetMapMode(MM_ANISOTROPIC); 设置映射模式

  3.  通过pDC->SetViewportOrg(0,0);设置逻辑坐标的原点

  4.  通过pDC->SetViewportExt(rect.right,rect.bottom);和  

   pDC->SetWindowExt(1000,1000);来确定逻辑坐标下和设备坐标下的尺寸对应关系

  5.  在MM_ANISOTROPIC模式下,X轴单位和Y轴单位可以不相同

  6.  坐标方向的确定方法是如果逻辑窗范围和视口范围符号相同,则逻辑坐标的方向和视口的方向相同,即X轴向右为正,Y轴向下为正。

  7.  如果将显示模式改为MM_ISOTROPIC,那么X轴单位和Y轴单位一定相同,感兴趣的读者可以自己使一下。

  (二)  建立以视窗中心为原点的坐标,如下图




  用如下代码:

  void CTtView::OnDraw(CDC*  pDC)
   {
    CTtDoc* pDoc =  GetDocument();
    ASSERT_VALID(pDoc);
    CRect  rect;
    GetClientRect(&rect);

    pDC->SetMapMode(MM_ANISOTROPIC);
    pDC->SetViewportOrg(rect.right/2,rect.bottom/2);
    pDC->SetViewportExt(rect.right,rect.bottom);

    pDC->SetWindowOrg(0,0);
    pDC->SetWindowExt(1000,-1000);

    pDC->MoveTo(150,150);
    pDC->LineTo(-150,-200);
    pDC->LineTo(150,-150);
    pDC->LineTo(150,150);
   }

  代码分析:

  1.  用 pDC->SetViewportOrg(rect.right/2,rect.bottom/2); 设置视口的原点。

  2.  用pDC->SetViewportExt(rect.right,rect.bottom);和pDC->SetWindowExt(1000,-1000);来确定设备坐标和逻辑坐标的单位对应关系。

  3.  因为逻辑窗范围和视口范围的符号不一致,纵坐标取反,所以Y轴向上为正。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

QQ|Archiver|小黑屋|几何尺寸与公差论坛

GMT+8, 2024-4-27 03:27 , Processed in 0.034344 second(s), 19 queries .

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表