日期:2014-05-18  浏览次数:20993 次

集思广益 关于在GDI+中使用笛卡尔坐标系
windows的坐标系是左上角(0,0)x轴向右增长 y轴向下增长 可以平时数学公式往往使用的是笛卡尔坐标系 也就是原点在客户区中央 x向右增加 左负右正 y值向上增加 下负上正 大家一般用的时候是怎样设计的?

------解决方案--------------------
换算到计算机的显示形式对应坐标
------解决方案--------------------
世界坐标空间到页面坐标空间的变换(二维affine(注三)变换):
   此过程中涉及到的各种变换,比如:相等、平移、缩放、映像、旋转、剪切、合并等都是通过为affine矩阵的各个成员指定适当的值来实现的。
  这个矩阵所对应的结构如下:
   typedef struct _XFORM { 
   FLOAT eM11; 
   FLOAT eM12; 
   FLOAT eM21; 
   FLOAT eM22; 
   FLOAT eDx; 
   FLOAT eDy; 
   } XFORM, *PXFORM; 
  一个世界坐标空间的点转换为页面坐标空间的点的公式为:
  xpage=xworld*eM11+yworld*eM21+eDx;
  ypage=xworld*eM12+yworld*eM22+eDy;(公式一)
  其中xworld、yworld为世界坐标空间的点。xpage、ypage为上述点在页面坐标空间中对应的位置。至于与affine变换的数学属性及如何才能实现页面的相等、平移、缩放、映像、旋转、剪切、合并此处不进行详细说明,因为那样将使这篇文章的规模膨胀许多(注四)。
  页面坐标空间到设备坐标空间的转换:
  这个过程涉及到几个概念,他们分别是:
  视口原点:当前页面坐标空间所认为的设备坐标空间的原点位置。用SetViewportOrgEx、GetViewportOrgEx分别进行设置和读取。用这两个函数进行操作时,所涉及的坐标为设备空间的坐标。
  视口范围: 视口范围并不是一个绝对的用于表示设备坐标空间大小的值。而是一个相对值,它同窗口范围的比例最终决定页面坐标空间到设备坐标空间是一种缩小还是放大的转换。用SetViewportExtEx、GetViewportExtEx对视口范围进行存取。
  窗口原点:页面坐标空间的原点。用SetWindowOrgEx、GetWindowOrgEx对窗口原点进行存取,所涉及的坐标为逻辑坐标。
  窗口范围:见视口范围的说明。用SetWindowExtEx、GetWindowExtEx进行存取。
  由了两个坐标空间的原点值和范围的比例值,在这两个坐标空间间进行坐标转换也就不是什么太难的事了。比较容易的可以得出下面的公式:
  页面坐标空间到设备坐标空间:
  xdevice=(xpage-WOrgx)*VExtx /WExtx+VOrgx;
  ydevice=(ypage-WOrgy)*VExty /WExty+VOrgy;(公式二)
  其中(WOrgx,WOrgy)为窗口原点。(VOrgx VOrgy,)为视口原点。(WExtx, WExty)为窗口范围。(VExtx,VExty)为视口范围。
  设备坐标空间到页面坐标空间的转换大家可以自己推导。
  为了更好的理解坐标空间的转换,我们将利用上述两组公式,动手来实现自己的LPtoDP。我们的这个函数将只适合nt类的平台。(9x没有世界坐标空间,会更简单)具体实现见源码2。实现MyLPtoDP的过程比较简单,此处仅对要用到的几个主要函数做些说明。
  
  int GetGraphicsMode(
   HDC hdc // handle to device context
  );
  这个函数用来得到指定DC的图形模式。图形模式有两种GM_COMPATIBLE和GM_ADVANCED
  只有在GM_ADVANCED才可能使用世界坐标空间。可以用SetGraphicsMode在两者间切换。
  BOOL GetWorldTransform(
   HDC hdc, // handle to device context
   LPXFORM lpXform // transformation
  );
  此函数用来得到与当前DC相关联的affine矩阵。通过公式一,
  应该可以知道缺省的affine矩阵具有{1.0,0,0,1.0,0,0}的形式。
  MyLPtoDP虽然有返回值但此值无意义,并且实现过程中也并没有进行任何出错处理。
请参考坐标系代码:http://www.wangchao.net.cn/bbsdetail_31587.html
------解决方案--------------------
取得界面的长和宽,然后通过转换来转换坐标位置

如果窗体大小修改,在重新获取窗体打小,在重新转换