Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1194527
  • 博文数量: 945
  • 博客积分: 52360
  • 博客等级: 大将
  • 技术积分: 13060
  • 用 户 组: 普通用户
  • 注册时间: 2008-08-07 10:11
文章分类

全部博文(945)

文章存档

2011年(1)

2008年(944)

我的朋友

分类: C/C++

2008-08-07 10:31:37

下载本文示例代码
下载源代码

一、坐标空间和 World space 到 Page space的转换
  坐标空间是一个平面的,在上面图形都是以平面直角坐标定位的。应用程序借助坐标空间可以缩放,平移,剪切,镜像图形的输出。 在Windows GDI中涉及到以下几种坐标空间
        世界坐标空间(world space)

        页面坐标空间(page space)

        设备坐标空间(device space)

        物理坐标空间(physical device space)	  
  通过转换可以改变目标的大小,方向,形状,转换同时能把图形目标从一个坐标空间转化 到另一个坐标空间,最终在物理设备如屏幕、打印机上显示出来。



  我现在介绍的是在编程中相对比较少用到的 World space 到 Page space 的转换。在默认的GDI作图模式下是没有World space 到Page space的转换的,只有在应用程序通过 SetGraphicsMode设置graphics mode到GM_ADVANCED下并且调用SetWorldTransform 设置变换参 数时才会有World space 到Page space的转换。

二、World space 到Page space的转换原理

1、重要结构和函数如下:
     typedef struct  _XFORM { 

           FLOAT eM11; 

           FLOAT eM12; 

           FLOAT eM21; 

           FLOAT eM22; 

           FLOAT eDx; 

           FLOAT eDy; 

     }XFORM, *PXFORM; 	  
用于变换的矩阵数据。
     int SetGraphicsMode(

           HDC hdc,    // handle to device context

           int iMode   // graphics mode

     );	  
设定设备环境上下文(DC)的graphics mode , 当graphics mode设定为GM_ADVANCED才能 支持世界变换。
     BOOL SetWorldTransform(

          HDC hdc,               // handle to device context

          CONST XFORM *lpXform   // transformation data

     );	  
设定设备环境上下文(DC)的世界变换。
     BOOL CombineTransform(

        LPXFORM lpxformResult, // combined transformation

        CONST XFORM *lpxform1, // first transformation

        CONST XFORM *lpxform2 // second transformation

     );     	  
世界变换的组合运算。
     BOOL GetWorldTransform(

        HDC hdc, // handle to device context

        LPXFORM lpXform // transformation

        );	  
得到设备环境上下文(DC)的世界变换。
2、变换原理 假定World space中的坐标为(x,y),变换后坐标为(x'',y''),变换矩阵数据为:
                    FLOAT eM11; 

                    FLOAT eM12; 

                    FLOAT eM21; 

                    FLOAT eM22; 

                    FLOAT eDx; 

                    FLOAT eDy; 	  
则变换计算公式如下:
                                  | eM11 eM12 0 | 

            |x'' y'' 1| = |x y 1| * | eM21 eM22 0 | 

                                  | eDx  eDy  1 | 	  
三、示例 将图形以原点为中心逆时针旋转。



主要代码如下:
01void TransformAndDraw(int iTransform,HWND hWnd)?

02{ 

03      HDC hDC; 

04      XFORM xForm; 

05      RECT rect;  

06      ::GetClientRect(hWnd, (LPRECT) &rect);     

07      hDC = ::GetDC(hWnd);  

08      ::MoveToEx(hDC ,rect.right / 2 , 0 , NULL  ) ; 

09      ::LineTo(hDC , rect.right / 2 , rect.bottom ) ; 

10      ::MoveToEx(hDC , 0 , rect.bottom / 2 , NULL )  ; 

11      ::LineTo(hDC ,  rect.right , rect.bottom / 2) ; 

12      ::SetGraphicsMode(hDC, GM_ADVANCED); 

13      switch (iTransform) 

14      { 

15      case 0:

16          AfxGetMainWnd()->SetWindowText("原始图像") ;

17             break; 

18          case 1:        // Scale to 1/2 of the original size. 

19              xForm.eM11 = (FLOAT) 0.5; 

20              xForm.eM12 = (FLOAT) 0.0; 

21              xForm.eM21 = (FLOAT) 0.0; 

22              xForm.eM22 = (FLOAT) 0.5; 

23              xForm.eDx  = (FLOAT) 0.0; 

24              xForm.eDy  = (FLOAT) 0.0; 

25              ::SetWorldTransform(hDC, &xForm); 

26              AfxGetMainWnd()->SetWindowText("缩小到一半") ;            

27              break; 

28   

29          case 2:   // Translate right by 3/4 inch. 

30              xForm.eM11 = (FLOAT) 1.0; 

31              xForm.eM12 = (FLOAT) 0.0; 

32              xForm.eM21 = (FLOAT) 0.0; 

33              xForm.eM22 = (FLOAT) 1.0; 

34              xForm.eDx  = (FLOAT) 75.0; 

35              xForm.eDy  = (FLOAT) 0.0; 

36              ::SetWorldTransform(hDC, &xForm); 

37          AfxGetMainWnd()->SetWindowText("平移") ;

38              break; 

39   

40          case 3:      // Rotate 30 degrees counterclockwise. 

41              xForm.eM11 = (FLOAT) 0.8660; 

42              xForm.eM12 = (FLOAT) 0.5000; 

43              xForm.eM21 = (FLOAT) -0.5000; 

44              xForm.eM22 = (FLOAT) 0.8660; 

45              xForm.eDx  = (FLOAT) 0.0; 

46              xForm.eDy  = (FLOAT) 0.0; 

47              ::SetWorldTransform(hDC, &xForm); 

48          AfxGetMainWnd()->SetWindowText("旋转") ;

49              break; 

50   

51          case 4:       // Shear along the x-axis with a 

52                            // proportionality constant of 1.0. 

53              xForm.eM11 = (FLOAT) 1.0; 

54              xForm.eM12 = (FLOAT) 1.0; 

55              xForm.eM21 = (FLOAT) 0.0; 

56              xForm.eM22 = (FLOAT) 1.0; 

57              xForm.eDx  = (FLOAT) 0.0; 

58              xForm.eDy  = (FLOAT) 0.0; 

59              ::SetWorldTransform(hDC, &xForm); 

60          AfxGetMainWnd()->SetWindowText("剪切") ;

61              break; 

62   

63          case 5:     // Reflect about a horizontal axis. 

64              xForm.eM11 = (FLOAT) 1.0; 

65              xForm.eM12 = (FLOAT) 0.0; 

66              xForm.eM21 = (FLOAT) 0.0; 

67              xForm.eM22 = (FLOAT) -1.0; 

68              xForm.eDx  = (FLOAT) 0.0; 

69              xForm.eDy  = (FLOAT) 0.0; 

70              ::SetWorldTransform(hDC, &xForm); 

71              AfxGetMainWnd()->SetWindowText("水平镜像") ;

72              break;  

73        

74      case 6:     // Reflect about a Vertical axis. 

75              xForm.eM11 = (FLOAT) -1.0; 

76              xForm.eM12 = (FLOAT) 0.0; 

77              xForm.eM21 = (FLOAT) 0.0; 

78              xForm.eM22 = (FLOAT) 1.0; 

79              xForm.eDx  = (FLOAT) 0.0; 

80              xForm.eDy  = (FLOAT) 0.0; 

81              ::SetWorldTransform(hDC, &xForm);

82          AfxGetMainWnd()->SetWindowText("垂直镜像") ;            

83              break; 

84   

85      }      

86      ::DtoLP(hDC, (LPPOINT) &rect, 2); 

87      HBITMAP hBMP1;

88      hBMP1 = ::LoadBitmap(AfxGetResourceHandle() ,  MAKEINTRESOURCE(IDB_BITMAP1)) ;

89      HDC hImageDC = ::CreateCompatibleDC((HDC)hDC);

90      HBITMAP hOldImageBMP = (HBITMAP)::SelectObject( hImageDC , hBMP1 );

91      ::BitBlt((HDC)hDC,(rect.right/2 -40),(rect.bottom / 2 -40),

                 80,80,hImageDC,0,0,SRCCOPY );        

92      ::SelectObject((HDC)hDC , hOldImageBMP);      

93      ::DeleteObject(hBMP1) ; 

94      ::DeleteDC(hImageDC) ; 

95      ::ReleaseDC(hWnd, hDC); 

96  } 	  
四、结束语
  错误之处希望大家批评指正!关于坐标变换的详细信息请参阅msdn中 Coordinate Spaces and Transformations一节。源代码见附件。
 

下载本文示例代码
阅读(304) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~