理解Windows坐标系概念及其转换

1. Windows坐标系统

坐标系主要分为两种:

  1. 逻辑坐标系:主要是在“虚拟界面”中绘图,是绘制到设备坐标系的准备阶段。
  2. 设备坐标系:由客户区坐标、窗口坐标、屏幕坐标组成,主要和显示设备有关。

在不同的空间中,各个坐标系及其坐标表示方法稍有不同。世界空间和页面空间的坐标系为平时熟悉的方式,x轴向右为正,y轴向上为正,设备空间中,y轴改为向下为正(要问为什么这么定,emm,自己问MS去)。

illustration showing a rectangle that changes size and position as it appears in the world space, page space, device space, and the device

MS其实对绘制的流程进行了明确的定义,且在不同空间中进行操作时的职能进行了分离,使不同层级下的操作内容更明确。先说逻辑坐标系中的绘制,windows定义的绘图流程如下:

  • 窗口上绘制大小和原点配置(可使用默认值);
  • 世界空间上绘制(允许对图形的缩放、平移、旋转、裁剪、镜像);
  • 页面空间绘制(设置映射模式SetMapMode,确定怎么画到设备空间上);

接下来是设备坐标系的绘制,流程如下:

  • 视口上绘制大小和原点配置(可使用默认值);
  • 设备空间绘制(仅允许进行平移操作);
  • 物理设备显示(最终显示在对应的区域)。

 

注意点:viewPort 和 windowsPort,这两者的翻译是视口,窗口。视口是基于设备坐标(像素的),窗口是基于逻辑坐标的,默认情况下两者重合,但可设置视口坐标系的原点以及窗口坐标系的原点。

  • 要注意区分视口坐标系原点跟视口原点的区别,窗口坐标系原点跟窗口原点的区别。
  • 视口坐标系其实就是设备坐标系,它是固定不变的,因此设备原点永远是(0,0)。
  • 视口原点是可变的,它默认处于设备原点,但是可以更改。
  • 窗口坐标系指定了在窗口绘图时的参考点,参考点就是窗口坐标系的原点。
  • 窗口原点默认等于窗口坐标系原点,但是窗口原点可以改变。
  • 窗口原点永远跟视口原点匹配映射。//这个是最主要的

2. 常见函数及参数

世界空间绘制的常用函数:

函数主要参数作用
SetWorldTransformCONST XFORM *lpXform对图形处理,包括缩放、平移、旋转、裁剪、镜像
SetGraphicsMode

int iMode:

GM_COMPATIBLE(默认)

GM_ADVANCED(可使用SetWorldTransform)

设置特定设备上下文的图形模式

页面空间绘制常用参数:

函数主要参数作用
SetMapMode

int fnMapMode:

MM_ANISORTOPIC:自定义缩放比例

MM_HIENGLISH:0.001inch-->1像素;x正轴向右,y正轴向上

MM_HIMETRIC:0.01毫米-->1像素;x正轴向右,y正轴向上

MM_ISOTROPIC:x和y方向的缩放比例相同

MM_LOENGLISH:0.01inch;x正轴向右,y正轴向上

MM_LOMETRIC:0.1毫米-->1像素;x正轴向右,y正轴向上

MM_TEXT:1:1拷贝;x正轴向右,y正轴向下

MM_TWIPS:1/1440inch-->1像素;x正轴向右,y正轴向上

设置映射模式SetMapMode,确定怎么画到设备空间上
SetWindowExtExint nXExtent, int nYExtent;设置绘制区域大小
SetWindowOrgExint X, int Y;设置绘制的窗口原点

设备空间常用参数:

函数主要参数作用
SetViewportExtExint nXExtent, int nYExtent;设置绘制区域大小
SetViewportOrgExint X, int Y;设置显示的视口原点

 


3. Examples

  • 修改窗口原点
    • SetWindowOrgEx(dc.m_hDC, 200, 200, NULL);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);

      先在窗口中绘制, 最终转换到视口中显示。

       

       

  • 修改视口原点
    • // viewpoint 
      SetViewportOrgEx(dc.m_hDC, 100, 100, NULL);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);

      在窗口中的坐标点(200,200)绘制文字,而视口中原点坐标变为(100,100),经一定量的偏移,最终绘制在界面坐标(300,300) 处。

  • 窗口和视口同时配置
    • // hybird
      SetWindowOrgEx(dc.m_hDC, 200, 200, NULL);
      SetViewportOrgEx(dc.m_hDC, 100, 100, NULL);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);

      绘制在坐标(100,100)的位置。这里为什么是这样呢?首先在窗口中绘制图形,之后以(200,200)为起点位置,将窗口中的内容复制到视口以(100,100)为起点的位置。

    • 这里,假设本文的绘制位置更改为(250,300),在窗口和视口中绘制的位置又是多少呢?——窗口为(250,300),视口为(150,200),视口中的计算方法:150=(250-200)+100; 200=(300-200)+100;(这里SetMapMode为默认参数MM_TEXT,未配置缩放系数或修改坐标轴方向)。

  • 配置缩放系数为0.5,即从窗口中2个单位的位置,在视口中表示为一个1单位。
    • CRect rect;
      GetClientRect(&rect);
      
      SetMapMode(dc.m_hDC, MM_ANISOTROPIC);
      SetWindowExtEx(dc.m_hDC, rect.Width()*2, rect.Height()*2, NULL);
      SetViewportExtEx(dc.m_hDC, rect.Width(), rect.Height(), NULL);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);
      可以看到,绘制的位置还是(100,100)。因为现在窗口中的(200,200)位置绘制了文本,但转换到视口(即显示设备)时,位置信息缩小了1倍。
    • 从窗口的页面空间转换到设备空间的公式,原文请见此
    • Dx = ((Lx - WOx) * VEx / WEx) + VOx
      
      其中:
      Dx     x value in device units 
      Lx     x value in logical units (also known as page space units) 
      WOx     window x origin 
      VOx     viewport x origin 
      WEx     window x-extent 
      VEx     viewport x-extent

       

      •  
  • 使用世界空间进行转换
    • // world transform
      int nGraphicsMode = SetGraphicsMode(dc.GetSafeHdc(), GM_ADVANCED);
      
      XFORM xForm;
      xForm.eM11 = (FLOAT) 0.5; 
      xForm.eM12 = (FLOAT) 0.0; 
      xForm.eM21 = (FLOAT) 0.0; 
      xForm.eM22 = (FLOAT) 0.5; 
      xForm.eDx  = (FLOAT) 0.0; 
      xForm.eDy  = (FLOAT) 0.0; 		
      SetWorldTransform(dc.GetSafeHdc(), &xForm);
      //Rectangle(dc.GetSafeHdc(), 0, 0, 200, 300);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);

       另一种把图绘制在(100,100)处的方法就是使用世界空间,因为说来说去,图形最开始画的地方就在这里,而且在世界空间中能进行多种的图形操作。这里用到了SetWorldTransform、XFORM和SetGraphicsMode,这是必须使用的函数或者参数,具体使用方法各请看MSDN,那里有非常详细的介绍。

  • 综合使用WindowOrg和ViewPortOrg
    • // using windowpoint & viewpoint
      SetMapMode(dc.m_hDC, MM_TEXT);
      SetViewportOrgEx(dc.GetSafeHdc(), 0, rect.bottom/10, NULL);
      SetWindowOrgEx(dc.GetSafeHdc(), -100, 0, NULL);
      dc.Rectangle(0, 0, 200, 300);
      TextOut(dc.m_hDC, 200, 200, "123456", 6);

       主要明白绘图现在窗口上绘,再是在视口上显示,这个过程即可,转换过程中可能会有一定比例的缩放。

       

       


4. 引用 

 

1. Using SetWorldTransform() to Rotate Basic Shapes by Any Angle

2. MSDN(官方文档,最最权威!)

3. 其他文档

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
绝对坐标系和相对坐标系是两种常用的坐标系,它们之间的转换是非常重要的。下面是它们的概念及坐标变换的原理: 1. 绝对坐标系:绝对坐标系是一个固定的坐标系,通常用来描述物体在绝对位置或绝对方向上的运动状态。例如,笛卡尔坐标系就是一种常见的绝对坐标系。 2. 相对坐标系:相对坐标系是相对于参考物体或参考坐标系而言的坐标系,用来描述物体在相对位置或相对方向上的运动状态。例如,极坐标系就是一种常见的相对坐标系。 坐标变换的原理就是通过一定的数学计算将一个坐标系中的坐标转换为另一个坐标系中的坐标。不同坐标系下的坐标变换可以分为以下两种情况: 1. 绝对坐标系到相对坐标系转换:这种情况下,需要确定参考物体的位置和方向,然后通过一定的数学转换将绝对坐标系下的坐标转换为相对坐标系下的坐标。例如,在极坐标系中,需要确定参考点的位置和方向,然后通过极坐标和笛卡尔坐标之间的转换公式将笛卡尔坐标系下的坐标转换为极坐标系下的坐标。 2. 相对坐标系到绝对坐标系转换:这种情况下,需要确定参考物体的位置和方向,然后通过一定的数学转换将相对坐标系下的坐标转换为绝对坐标系下的坐标。例如,在笛卡尔坐标系中,需要确定参考点的位置和方向,然后通过笛卡尔坐标和极坐标之间的转换公式将极坐标系下的坐标转换为笛卡尔坐标系下的坐标。 总之,坐标系之间的转换是非常重要的,它可以帮助我们更准确地描述物体的运动状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值