home *** CD-ROM | disk | FTP | other *** search
/ Windows Graphics Programming / Feng_Yuan_Win32_GDI_DirectX.iso / Samples / include / curve.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-11  |  7.0 KB  |  324 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   : curve.cpp                                                             //
  10. //  Description: Path, curve transformation, styled curve                            //
  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. #include <assert.h>
  20. #include <tchar.h>
  21.  
  22. #include "curve.h"
  23. #include "pen.h"
  24.  
  25. int KPathData::GetPathData(HDC hDC)
  26. {
  27.     if ( m_pPoint ) delete m_pPoint;
  28.     if ( m_pFlag  ) delete m_pFlag;
  29.  
  30.     m_nCount = ::GetPath(hDC, NULL, NULL, 0);
  31.  
  32.     if ( m_nCount>0 )
  33.     {
  34.         m_pPoint = new POINT[m_nCount];
  35.         m_pFlag  = new  BYTE[m_nCount];
  36.  
  37.         if ( m_pPoint!=NULL && m_pFlag!=NULL )
  38.             m_nCount = ::GetPath(hDC, m_pPoint, m_pFlag, m_nCount);
  39.     }
  40.  
  41.     return m_nCount;
  42. }
  43.  
  44.  
  45. void KPathData::MapPoints(K2DMap & map)
  46. {
  47.     for (int i=0; i<m_nCount; i++)
  48.         map.Map(m_pPoint[i].x, m_pPoint[i].y);
  49. }
  50.  
  51.  
  52. BOOL KTransCurve::MoveTo(HDC hDC, int x, int y)
  53. {
  54.     m_orgx = x;
  55.     m_orgy = y;
  56.  
  57.     x0 = (float) x;
  58.     y0 = (float) y;
  59.  
  60.     Map(x0, y0, m_dstx, m_dsty);
  61.  
  62.     return DrvMoveTo(hDC, (int) (m_dstx+0.5), (int) (m_dsty+0.5));
  63. }
  64.  
  65.  
  66. BOOL KTransCurve::BezierTo(HDC hDC, float x1, float y1, float x2, float y2, float x3, float y3)
  67. {
  68.     float dx3, dy3;
  69.  
  70.     Map(x3, y3, dx3, dy3);
  71.  
  72.     if ( ( fabs(dx3-m_dstx) + fabs(dy3-m_dsty) ) < m_seglen ) // no need to break ?
  73.     {
  74.         float dx1, dy1, dx2, dy2;
  75.         
  76.         Map(x1, y1, dx1, dy1);
  77.         Map(x2, y3, dx2, dy2);
  78.  
  79.         POINT P[3] = {  (int) (dx1+0.5), (int) (dy1+0.5),
  80.                         (int) (dx2+0.5), (int) (dy2+0.5),
  81.                         (int) (dx3+0.5), (int) (dy3+0.5) };
  82.  
  83.         x0 = x3;
  84.         y0 = y3;
  85.         m_dstx = dx3;
  86.         m_dsty = dy3;
  87.  
  88.         return DrvBezierTo(hDC, P);
  89.     }
  90.     else
  91.     {
  92.         BezierTo(hDC, 
  93.             (x0+x1)          /2, (y0+y1)          /2, 
  94.             (x0+x1*2+x2)     /4, (y0+y1*2+y2)     /4, 
  95.             (x0+x1*3+x2*3+x3)/8, (y0+y1*3+y2*3+y3)/8);
  96.  
  97.         return BezierTo(hDC, 
  98.             (x1+x2*2+x3)/4, (y1+y2*2+y3)/4, 
  99.             (x2+x3)     /2, (y2+y3)     /2, 
  100.             x3, y3);
  101.     }
  102. }
  103.     
  104.  
  105. BOOL KPathData::Draw(HDC hDC, KTransCurve & trans, bool bPath)
  106. {
  107.     if ( m_nCount==0 )
  108.         return FALSE;
  109.  
  110.     if ( bPath )
  111.         BeginPath(hDC);
  112.  
  113.     for (int i=0; i<m_nCount; i++)
  114.     {
  115.         switch ( m_pFlag[i] & ~ PT_CLOSEFIGURE )
  116.         {
  117.             case PT_MOVETO:
  118.                 trans.MoveTo(hDC, m_pPoint[i].x, m_pPoint[i].y);
  119.                 break;
  120.  
  121.             case PT_LINETO:
  122.                 trans.LineTo(hDC, m_pPoint[i].x, m_pPoint[i].y);
  123.                 break;
  124.  
  125.             case PT_BEZIERTO:
  126.                 trans.BezierTo(hDC, 
  127.                     m_pPoint[i  ].x, m_pPoint[i  ].y,
  128.                     m_pPoint[i+1].x, m_pPoint[i+1].y,
  129.                     m_pPoint[i+2].x, m_pPoint[i+2].y);
  130.                 i+=2;
  131.                 break;
  132.  
  133.             default:
  134.                 assert(false);
  135.         }
  136.  
  137.         if ( m_pFlag[i] & PT_CLOSEFIGURE )
  138.             trans.CloseFigure(hDC);
  139.     }
  140.  
  141.     if ( bPath )
  142.         EndPath(hDC);
  143.  
  144.     return TRUE;
  145. }
  146.  
  147.  
  148. BOOL KStyleCurve::LineTo(double x, double y)
  149. {
  150.     double x2 = x;
  151.     double y2 = y;
  152.  
  153.     double curlen = sqrt((x2-m_x1)*(x2-m_x1) + 
  154.                          (y2-m_y1)*(y2-m_y1));
  155.  
  156.     double length = m_pDash->GetLength(m_step);
  157.  
  158.     while ( curlen >= length )
  159.     {
  160.         double x1 = m_x1; 
  161.         double y1 = m_y1;
  162.  
  163.         m_x1 += (x2-m_x1) * length / curlen;
  164.         m_y1 += (y2-m_y1) * length / curlen;
  165.  
  166.         if ( ! m_pDash->DrawDash(x1, y1, m_x1, m_y1, m_step) )
  167.             return FALSE;
  168.  
  169.         curlen -= length;
  170.  
  171.         m_step ++;
  172.         length = m_pDash->GetLength(m_step);
  173.     }
  174.  
  175.     return TRUE;
  176. }
  177.  
  178.  
  179. BOOL KStyleCurve::PolyDraw(const POINT *ppt, const BYTE *pbTypes, int nCount)
  180. {
  181.     int lastmovex = 0;
  182.     int lastmovey = 0;
  183.  
  184.     for (int i=0; i<nCount; i++)
  185.     {
  186.         switch ( pbTypes[i] & ~ PT_CLOSEFIGURE )
  187.         {
  188.             case PT_MOVETO:
  189.                 m_x1 = lastmovex = ppt[i].x;
  190.                 m_y1 = lastmovey = ppt[i].y;
  191.                 break;
  192.  
  193.             case PT_LINETO:
  194.                 if ( ! LineTo(ppt[i].x, ppt[i].y) )
  195.                     return FALSE;
  196.                 break;
  197.         }
  198.  
  199.         if ( pbTypes[i] & PT_CLOSEFIGURE )
  200.             if ( ! LineTo(lastmovex, lastmovey) )
  201.                 return FALSE;
  202.     }
  203.  
  204.     return TRUE;
  205. }
  206.  
  207.  
  208. void KPathData::MarkPoints(HDC hDC, bool bShowLine)
  209. {
  210.     if ( bShowLine )
  211.     {
  212.         KPen dot(PS_DOT, 0, RGB(0xFF, 0, 0), hDC);
  213.         
  214.         Polyline(hDC, m_pPoint, m_nCount);
  215.     }
  216.  
  217.     KPen solid(PS_SOLID, 0, RGB(0, 0, 0xFF));
  218.     solid.Select(hDC);
  219.  
  220.     HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0xFF));
  221.  
  222.     for (int i=0; i<m_nCount; i++)
  223.     {
  224. #ifdef _DEBUG
  225.         TCHAR temp[32];
  226.  
  227.         wsprintf(temp, _T("%3d %d (%d,%d)\n"), i, m_pFlag[i], m_pPoint[i].x, m_pPoint[i].y);
  228.         OutputDebugString(temp);
  229. #endif
  230.         
  231.         int x = m_pPoint[i].x;
  232.         int y = m_pPoint[i].y;
  233.  
  234.         if ( m_pFlag[i] & PT_CLOSEFIGURE )
  235.             SelectObject(hDC, hBrush);
  236.         else
  237.             SelectObject(hDC, GetStockObject(WHITE_BRUSH));
  238.  
  239.         switch ( m_pFlag[i] & ~ PT_CLOSEFIGURE )
  240.         {
  241.             case PT_MOVETO:
  242.             {
  243.                     POINT P[] = { x, y-6, x+6, y+4, x-6, y+4, x, y-6 };
  244.  
  245.                     Polygon(hDC, P, 4);
  246.                 }
  247.                 break;
  248.  
  249.             case PT_LINETO:
  250.                 Rectangle(hDC, x-5, y-5, x+5, y+5);
  251.                 break;
  252.  
  253.             case PT_BEZIERTO:
  254.                 Ellipse(hDC, x-5, y-5, x+5, y+5);
  255.                 break;
  256.         }
  257.  
  258.     }
  259.  
  260.     SelectObject(hDC, GetStockObject(WHITE_BRUSH));
  261.     DeleteObject(hBrush);
  262.  
  263.     solid.UnSelect();
  264. }
  265.  
  266.  
  267. BOOL KDashes::DrawDash(double x1, double y1, double x2, double y2, int step)
  268. {
  269.     HBRUSH hBrush = CreateSolidBrush(PALETTEINDEX(step % 20));
  270.     HGDIOBJ hOld  = SelectObject(m_hDC, hBrush);
  271.  
  272.     SelectObject(m_hDC, GetStockObject(NULL_PEN));
  273.     double dy = (x2-x1)/2;
  274.     double dx = (y2-y1)/2;
  275.  
  276.     switch ( m_test & 3 )
  277.     {
  278.         case 0: // diamound
  279.         {
  280.             POINT P[5] = { (int)x1, (int)y1, (int)((x1+x2)/2-dx), (int)((y1+y2)/2+dy),
  281.                            (int)x2, (int)y2, (int)((x1+x2)/2+dx), (int)((y1+y2)/2-dy),
  282.                            (int)x1, (int)y1 };
  283.             Polygon(m_hDC, P, 5);
  284.             break;
  285.         }
  286.  
  287.         case 1: // triangle
  288.         {
  289.             dx /= 0.866; // sqrt(3)/2
  290.             dy /= 0.866;
  291.  
  292.             POINT P[4] = { (int)(x1-dx), (int)(y1+dy), (int)x2, (int)y2,
  293.                            (int)(x1+dx), (int)(y1-dy), (int)(x1-dx), (int)(y1+dy)
  294.         };
  295.         Polygon(m_hDC, P, 4);
  296.         break;
  297.         }
  298.  
  299.         case 2: // circle
  300.         {
  301.             double r = sqrt(dx * dx + dy * dy);
  302.  
  303.             Ellipse(m_hDC, (int)((x1+x2)/2-r), (int)((y1+y2)/2-r),
  304.                            (int)((x1+x2)/2+r), (int)((y1+y2)/2+r));
  305.             break;
  306.         }
  307.  
  308.         case 3: 
  309.         {
  310.             POINT P[5] = { (int)(x1-dx), (int)(y1+dy), (int)(x2-dx), (int)(y2+dy),
  311.                            (int)(x2+dx), (int)(y2-dy), (int)(x1+dx), (int)(y1-dy),
  312.                            (int)(x1-dx), (int)(y1+dy)
  313.             };
  314.             Polygon(m_hDC, P, 5);
  315.             break;
  316.         }
  317.     }
  318.     
  319.     SelectObject(m_hDC, hOld);
  320.     DeleteObject(hBrush);
  321.     return TRUE;
  322. }
  323.  
  324.