home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / Affine.cpp next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  5.0 KB  |  216 lines

  1. //-----------------------------------------------------------------------------------//
  2. //              Windows Graphics Programming: Win32 GDI and DirectDraw               //
  3. //                             ISBN  0-13-086985-6                                   //
  4. //                                                                                   //
  5. //  Written            by  Yuan, Feng                             www.fengyuan.com   //
  6. //  Copyright (c) 2000 by  Hewlett-Packard Company                www.hp.com         //
  7. //  Published          by  Prentice Hall PTR, Prentice-Hall, Inc. www.phptr.com      //
  8. //                                                                                   //
  9. //  FileName   : affine.cpp                                                             //
  10. //  Description: Affine transformation                                               //
  11. //  Version    : 1.00.000, May 31, 2000                                              //
  12. //-----------------------------------------------------------------------------------//
  13.  
  14. #define STRICT
  15. #define WIN32_LEAN_AND_MEAN
  16.  
  17. #include <windows.h>
  18. #include <math.h>
  19.  
  20. #include "Affine.h"
  21.  
  22.  
  23. // Reset to identity transform
  24. void KAffine::Reset()
  25. {
  26.     m_xm.eM11 = 1;
  27.     m_xm.eM12 = 0;
  28.     m_xm.eM21 = 0;
  29.     m_xm.eM22 = 1;
  30.     m_xm.eDx  = 0;
  31.     m_xm.eDy  = 0;
  32. }
  33.  
  34.  
  35. // Copy transform if valid
  36. BOOL KAffine::SetTransform(const XFORM & xm)
  37. {
  38.     if ( xm.eM11 * xm.eM22 == xm.eM12 * xm.eM21 )
  39.         return FALSE;
  40.  
  41.     m_xm = xm;    
  42.     return TRUE;
  43. }
  44.  
  45.  
  46. // transform = transform * b
  47. BOOL KAffine::Combine(const XFORM & b)
  48. {
  49.     if ( b.eM11 * b.eM22 == b.eM12 * b.eM21 )
  50.         return FALSE;
  51.  
  52.     XFORM a = m_xm;
  53.  
  54.     // 11 12   11 12
  55.     // 21 22   21 22
  56.     m_xm.eM11 = a.eM11 * b.eM11 + a.eM12 * b.eM21;
  57.     m_xm.eM12 = a.eM11 * b.eM12 + a.eM12 * b.eM22;
  58.     m_xm.eM21 = a.eM21 * b.eM11 + a.eM22 * b.eM21;
  59.     m_xm.eM22 = a.eM21 * b.eM12 + a.eM22 * b.eM22;
  60.     m_xm.eDx  = a.eDx  * b.eM11 + a.eDy  * b.eM21 + b.eDx;
  61.     m_xm.eDy  = a.eDx  * b.eM12 + a.eDy  * b.eM22 + b.eDy;
  62.  
  63.     return TRUE;
  64. }
  65.  
  66.  
  67. // transform = 1 / transform
  68. //  M = A * x + B 
  69. //  Inv(M) = Inv(A) * x - Inv(A) * B
  70. BOOL KAffine::Invert(void)
  71. {
  72.     FLOAT det = m_xm.eM11 * m_xm.eM22 - m_xm.eM21 * m_xm.eM12;
  73.  
  74.     if ( det==0 )
  75.         return FALSE;
  76.  
  77.     XFORM old = m_xm;
  78.  
  79.     m_xm.eM11 =   old.eM22 / det;
  80.     m_xm.eM12 = - old.eM12 / det;
  81.     m_xm.eM21 = - old.eM21 / det;
  82.     m_xm.eM22 =   old.eM11 / det;
  83.     
  84.     m_xm.eDx  = - ( m_xm.eM11 * old.eDx + m_xm.eM21 * old.eDy );
  85.     m_xm.eDy  = - ( m_xm.eM12 * old.eDx + m_xm.eM22 * old.eDy );
  86.  
  87.     return TRUE;
  88. }
  89.  
  90.  
  91. BOOL KAffine::Translate(FLOAT dx, FLOAT dy)
  92. {
  93.     m_xm.eDx += dx;
  94.     m_xm.eDy += dy;
  95.  
  96.     return TRUE;
  97. }
  98.  
  99.  
  100. BOOL KAffine::Scale(FLOAT sx, FLOAT sy)
  101. {
  102.     if ( (sx==0) || (sy==0) )
  103.         return FALSE;
  104.  
  105.     m_xm.eM11 *= sx;
  106.     m_xm.eM12 *= sx;
  107.     m_xm.eM21 *= sy;
  108.     m_xm.eM22 *= sy;
  109.     m_xm.eDx  *= sx;
  110.     m_xm.eDy  *= sy;
  111.  
  112.     return TRUE;
  113. }
  114.  
  115.  
  116. BOOL KAffine::Rotate(FLOAT angle, FLOAT x0, FLOAT y0)
  117. {
  118.     XFORM xm;
  119.  
  120.     Translate(-x0, -y0);    // make (x0,y0) the origin
  121.     
  122.     double rad = angle * (3.14159265359 / 180); 
  123.  
  124.     xm.eM11 =   (FLOAT) cos(rad);
  125.     xm.eM12 =   (FLOAT) sin(rad);
  126.     xm.eM21 = -         xm.eM12;
  127.     xm.eM22 =           xm.eM11;
  128.     xm.eDx  = 0;
  129.     xm.eDy  = 0;
  130.  
  131.     Combine(xm);            // rotate
  132.     Translate(x0, y0);        // move origin back
  133.  
  134.     return TRUE;
  135. }
  136.  
  137.  
  138. // Find a transform which maps (0,0) (1,0) (0,1) to p, q, and r respectively
  139. BOOL KAffine::MapTri(FLOAT px0, FLOAT py0, FLOAT qx0, FLOAT qy0, FLOAT rx0, FLOAT ry0)
  140. {
  141.     // px0 = dx, qx0 = m11 + dx, rx0 = m21 + dx
  142.     // py0 = dy, qy0 = m12 + dy, ry0 = m22 + dy
  143.     m_xm.eM11 = qx0 - px0;
  144.     m_xm.eM12 = qy0 - py0;
  145.     m_xm.eM21 = rx0 - px0;
  146.     m_xm.eM22 = ry0 - py0;
  147.     m_xm.eDx  = px0;
  148.     m_xm.eDy  = py0;
  149.  
  150.     return m_xm.eM11 * m_xm.eM22 != m_xm.eM12 * m_xm.eM21;
  151. }
  152.  
  153.  
  154. // Find a transform which maps p0, q0, and r0 to p1, p1 and r1 respectively
  155. BOOL KAffine::MapTri(FLOAT px0, FLOAT py0, FLOAT qx0, FLOAT qy0, FLOAT rx0, FLOAT ry0,
  156.                        FLOAT px1, FLOAT py1, FLOAT qx1, FLOAT qy1, FLOAT rx1, FLOAT ry1)
  157. {
  158.     if ( ! MapTri(px0, py0, qx0, qy0, rx0, ry0) )
  159.         return FALSE;
  160.  
  161.     Invert();        // transform p0, q0, and r0 back to (0,0),(1,0),(0,1)
  162.  
  163.     KAffine map1;
  164.  
  165.     if (! map1.MapTri(px1, py1, qx1, qy1, rx1, ry1) )
  166.         return FALSE;
  167.  
  168.     return Combine(map1.m_xm);    // then to p1,r1,q1
  169. }
  170.  
  171.  
  172. // get the combined world to device coordinate space mapping
  173. BOOL KAffine::GetDPtoLP(HDC hDC)
  174. {
  175.     if ( ! GetWorldTransform(hDC, & m_xm) )
  176.         return FALSE;
  177.  
  178.     POINT origin;
  179.     GetWindowOrgEx(hDC, & origin);
  180.     Translate( - (FLOAT) origin.x, - (FLOAT) origin.y);
  181.  
  182.     SIZE  sizew, sizev;
  183.     GetWindowExtEx  (hDC, & sizew);
  184.     GetViewportExtEx(hDC, & sizev);
  185.     
  186.     Scale( (FLOAT) sizew.cx/sizev.cx, (FLOAT) sizew.cy/sizev.cy);
  187.  
  188.     GetViewportOrgEx(hDC, & origin);
  189.     Translate( (FLOAT) origin.x, (FLOAT) origin.y);
  190.  
  191.     return TRUE;
  192. }
  193.  
  194.  
  195. void minmax(int x0, int x1, int x2, int x3, int & minx, int & maxx)
  196. {
  197.     if ( x0<x1 )
  198.     {    
  199.         minx = x0; maxx = x1;    
  200.     }
  201.     else
  202.     {    
  203.         minx = x1; maxx = x0;
  204.     }
  205.  
  206.     if ( x2<minx) 
  207.         minx = x2; 
  208.     else if ( x2>maxx) 
  209.         maxx = x2;
  210.  
  211.     if ( x3<minx) 
  212.         minx = x3; 
  213.     else if ( x3>maxx) 
  214.         maxx = x3;
  215. }
  216.