Windows GDI+坐标系统详解

GDI+中的坐标系

1 什么是坐标系

坐标系就是确定一组数据位置的标尺。按按照维数分为2维平面坐标系和3维空间坐标系。其实2维坐标系也是z=03维坐标系的特例。

坐标系有三要素,一是原点,二是方向,三是单位大小。如果两个坐标系这三点完全一样,那么这两个坐标系就完全相同。关于坐标系和点的关系,我们可以这么理解:点本身是固定的,但在不同坐标系下的表示是不同的。那么为什么要定义那么多的坐标系呢,答案是为了描述方便。比如描述一个圆,如果把坐标系原点放到圆心,那么对圆的描述就是 x2+y2=r2。而如果原点不在圆心,那么圆描述就成了:(x-x0)2+(y-y0)2=r2

 

 

2 坐标系变换与矩阵运算

既然可以找到描述形状方便的坐标系,那么问题也来了。比如要同时描述两个形状,如两个圆,而且这两个圆是有相对位置的,比如是自行车的两个轮子。

 

尽管两个圆各自在自己的坐标系里都能很方便的描述,但是要建立两者之间的关系时,却遇到了麻烦。因为要计算两个圆的位置关系,必须把两个圆放到同一个坐标系下描述才行。所以就引出了坐标系变换的概念。在此例中,可以把第二个圆也放到第一个坐标系下描述,方法就是把第二个坐标系放到第一个坐标系中合适的位置(两个坐标系的关系),然后根据两个坐标系的关系,推算出第二个圆在第一个坐标系中的描述。

这种方式对于CAD中的任务分隔特别重要,比如做汽车设计的公司,可以把不同的部件分配给不同的人来做。设计人员接到任务后,自由选择合适的坐标系来描述负责的部件。等所有部件设计完成以后,再把所有的部件转换的整车坐标系上。坐标系间的转换(2维和3维)是非常有规律的,有数学基础的人可以自己推导公式,没有数学基础的也没有关系,各种图形库都已经把坐标系变换公式做成了函数API供程序调用。比如OpenGL提供了三维坐标系间的各种变换APIGDI+则提供了2维坐标的变换API。需要了解的是,坐标系间的变换,一般是通过矩阵运算完成的,感兴趣的读者可以参考任何讲解OpenGL坐标变换算法的书籍,重要的是矩阵运算可以通过硬件流水线完成,这就是图形显示中的显卡硬件加速的一部分。当然矩阵运算不光应用于坐标系转换,还广泛运用于其他计算领域,因此有人提出了用GPU代替CPU来进行大规模科学计算的方案。

3 GDI+中的三种坐标系

作为Windows中图形显示的关键部件,GDI+代表了Windows2维图形API。三维则是D3D的领域了。图形API要提供的函数大概是两类,一是绘图函数,二是坐标系转换函数。GDI+提供了很多绘图函数,如DrawRectangle,DrawEclipse,DrawString等等。所有这些函数中都需要位置或大小参数,对于这些参数含义的理解是很重要的。

3.1 调用者自定义坐标系(world

一是参数的单位是什么?位置参数的坐标系是什么?答案很有意思:不确定。因为这些东西有调用者自由确定。那么GDI+怎么根据这些不确定的参数绘制图形呢?答案是调用者要提供自己定义的坐标系和PAGE坐标系的关系。

3.2 Page坐标系

Page坐标系附属在某一个窗口或控件上,是一个固定的坐标系,原点位于窗口的左上角,x轴方向向右,y轴方向向下。单位为cminchpixel,根据实际情况设定。GDI+提供了Page坐标系和World坐标系间的转换API。含义是把world坐标系放到Page坐标系合适的位置。回到前面讲过的汽车分部件设计的例子,此处Page坐标系就是最后的整车坐标系,GID+提供的就是把各个部件(GDI+绘制函数绘制的图形)连同其坐标系一起放到整车(Page)坐标系里。

 

这是很合理的方式。在利用GDI+作图时也要按照这种思路来做。具体说来,先把整个图形分解成各个小的图形,在画某一个小的图形时不要考虑它最终在Page坐标系的位置,只要按照你自己设想的坐标系来调用GDI+

  • 3
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
控件继承QWidget, 实现了左右上下四种形式的坐标轴控件。 可以设置固定间隔或自动选择间隔 可以设置最小间隔 开放一个槽来动态调整坐标轴的范围 处理了边缘刻度的显示 /************************************************************************ * 版权所有 (C) 2012-2015, liang1057@yahoo.com.cn 类声明: 坐标轴控件 ************************************************************************/ /** @brief 坐标轴控件 * * @details 坐标轴控件 只有刻度和数字,数字可以隐藏(用来显示其他需要显示的刻度值) */ class uiAxis : public QWidget { Q_OBJECT public: /** @brief 坐标轴类型 * * @details 坐标轴类型 */ enum AXISTYPE{ LEFT_AXIS = 0, TOP_AXIS, RIGHT_AXIS, BOTTOM_AXIS }; /** @brief 构造函数 */ uiAxis(AXISTYPE type = BOTTOM_AXIS, QWidget *parent = 0); /** @brief 析构函数 */ ~uiAxis(void); /** @brief 设置坐标轴的范围 */ void setScop(double minValue, double maxValue); /** @brief 获取坐标轴的范围 */ void getScop(double& minValue,double& maxValue); /** @brief 获取坐标轴的范围 */ double getMinValue(); double getMaxValue(); /** @brief 设置坐标轴的类型 */ void setAxisType(AXISTYPE type); /** @brief 坐标轴的类型 */ AXISTYPE getAxisType(); /** @brief 设置最小刻度(小刻度的最小间隔) */ void setMinInterval(double value); /** @brief 设置自动间隔 */ void setAutoScale(bool val=true); /** @brief 设置固定间隔 */ void setSettedScale(bool val=true); /** @brief 设置坐标轴的绘制范围, 像素值 */ void setBoundary(int left, int right, int top, int bottom); void getBoundary(int& left, int& right, int& top, int& bottom);

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值