LINE.CPP
上传用户:whjcdz88
上传日期:2011-09-07
资源大小:121k
文件大小:6k
源码类别:

图形图象

开发平台:

WINDOWS

  1. // Line.cpp : Defines the class behaviors for CDashLine
  2. //
  3. // The Bresenham function in this file is derived from code from 
  4. // Jean-Claude Lanz mailto:Jclanz@bluewin.ch
  5. // and he presumably shares copyright to it
  6. // Otherwise the copyright belongs to Llew S. Goodstadt 
  7. // http://www.lg.ndirect.co.uk    mailto:lg@ndirect.co.uk
  8. // who hereby grants you fair use and distribution rights of the code 
  9. // in both commercial and non-commercial applications.
  10. #include "stdafx.h"
  11. #include "Line.h"
  12. #include "bezier.h"
  13. #ifdef _DEBUG
  14. #define new DEBUG_NEW
  15. #undef THIS_FILE
  16. static char THIS_FILE[] = __FILE__;
  17. #endif
  18. // define _TIMING to null out the GDI calls.
  19. // i.e. you can find out what is the cost of the calculations
  20. //#define _TIMING 1
  21. /////////////////////////////////////////////////////////////////////////////
  22. // helper
  23. /////////////////////////////////////////////////////////////////////////////
  24. // CDashLine
  25. CDashLine::CDashLine(CDC& dc, unsigned* pattern, unsigned count)
  26. :m_DC(dc), m_Pattern(0)
  27. {
  28. SetPattern(pattern, count);
  29. }
  30. CDashLine::~CDashLine()
  31. {
  32. // destroy GDI objects
  33. delete[] m_Pattern;
  34. }
  35. void CDashLine::SetPattern(unsigned* pattern, unsigned count)
  36. {
  37. // Must be an even number of dash and gaps
  38. ASSERT(m_Count >=0);
  39. ASSERT(!(m_Count % 2));
  40. m_Count = count;
  41. delete[] m_Pattern;
  42. if (m_Count)
  43. {
  44. m_Pattern = new UINT[count];
  45. memcpy(m_Pattern, pattern, count * sizeof(UINT));
  46. }
  47. else
  48. m_Pattern = 0;
  49. Reset();
  50. }
  51. void CDashLine::Reset()
  52. {
  53. m_CurPat = 0;
  54. if (m_Count)
  55. m_CurStretch = m_Pattern[0];
  56. }
  57. // use linear interpolation to compute next position
  58. void CDashLine::Bresenham(LONG x, LONG y)
  59. {
  60. // Setup Bresenham
  61. LONG dx = x - m_CurPos.x;
  62. LONG dy = y - m_CurPos.y;
  63. LONG *p1, *p2, *pd1, *pd2;
  64. if (abs(dx) >= abs(dy))
  65. {
  66. p1 = &m_CurPos.x; 
  67. p2 = &m_CurPos.y; 
  68. pd1 = &dx; 
  69. pd2 = &dy; 
  70. }
  71. else
  72. {
  73. p1 = &m_CurPos.y; 
  74. p2 = &m_CurPos.x; 
  75. pd1 = &dy; 
  76. pd2 = &dx;
  77. }
  78. int max = abs(*pd1);
  79. int dec = abs(*pd2);
  80. int s1 = (*pd1 >= 0) ? 1: -1;
  81. int s2 = (*pd2 >= 0) ? 1: -1;
  82. int val = max;
  83. // count past correct number of pixels in current segment
  84. //  or until end of this line
  85. for (int i = 0; i < max; i++)
  86. {
  87. val -= dec;
  88. if (val <= 0) 
  89. {
  90. *p2 += s2; 
  91. val += max; 
  92. }
  93. *p1 += s1;
  94. --m_CurStretch;
  95. if (!m_CurStretch)
  96. {
  97. // use next pattern for next segment
  98. m_CurPat = (m_CurPat + 1) % m_Count;
  99. m_CurStretch = m_Pattern[m_CurPat];
  100. // draw segment or skip gap
  101. #ifndef _TIMING
  102. if (m_CurPat % 2)
  103. m_DC.LineTo(m_CurPos);
  104. else
  105. m_DC.MoveTo(m_CurPos);
  106. #endif _TIMING
  107. // if last point, return
  108. if (i == max - 1) 
  109. return;
  110. }
  111. }
  112. // draw to last point if necessary
  113. #ifndef _TIMING
  114. if (!(m_CurPat % 2))
  115. m_DC.LineTo(m_CurPos);
  116. #endif _TIMING
  117. }
  118. void CDashLine::MoveTo(int x, int y)
  119. {
  120. // with MoveTo, reset parameters
  121. Reset();
  122. // save current position
  123. m_CurPos.x = x; 
  124. m_CurPos.y = y;
  125. // move to position
  126. m_DC.MoveTo(m_CurPos);
  127. }
  128. void CDashLine::LineTo(int x, int y)
  129. {
  130. // line type and color
  131. if (!m_Count)
  132. {
  133. m_DC.LineTo(x, y);
  134. m_CurPos.x = x; m_CurPos.y = y;
  135. return;
  136. }
  137. #ifdef _TIMING
  138. m_DC.LineTo(x, y);
  139. #endif _TIMING
  140. // calculate and draw next points
  141. Bresenham(x, y);
  142. }
  143. // use linear interpolation to compute next position
  144. void CDashLine::BezierTo(POINT* dest)
  145. {
  146. #ifdef _TIMING
  147. m_DC.PolyBezierTo(dest, 3);
  148. #endif _TIMING
  149. if (!m_Count)
  150. {
  151. m_DC.PolyBezierTo(dest, 3);
  152. m_CurPos = dest[2];
  153. return;
  154. }
  155. // Setup Bezier representing curve
  156. LBezier currentBez;
  157. currentBez.p[0] = m_CurPos;
  158. for (int i = 0; i < 3; ++i)
  159. currentBez.p[i+1] = dest[i];
  160. LBezier drawBezier;
  161. CPoint Output[4];
  162. //for (int ii = 0; ii < 100; ++ii)
  163. while(1)
  164. {
  165. // split off segment corresponding to current stretch, ie drawBezier
  166. currentBez.TSplit(drawBezier, currentBez.TAtLength(m_CurStretch));
  167. drawBezier.GetCPoint(Output);
  168. m_CurPos = Output[3];
  169. #ifndef _TIMING
  170. if (m_CurPat % 2)
  171. m_DC.MoveTo(m_CurPos);
  172. else
  173. m_DC.PolyBezierTo(Output+1, 3);
  174. #endif _TIMING
  175. // break if some part of segment did not fit on bezier
  176. if (!m_CurStretch)
  177. {
  178. // use next pattern for next segment
  179. m_CurPat = (m_CurPat + 1) % m_Count;
  180. m_CurStretch = m_Pattern[m_CurPat];
  181. }
  182. else
  183. break;
  184. }
  185. }
  186. // Returns count of elements (dash/dot and gaps)
  187. // You must be careful to pass in enough memory for pattern
  188. // It is probably safest to always have an array of [8]
  189. unsigned CDashLine::GetPattern(unsigned* pattern, bool round, unsigned penSize, unsigned style)
  190. {
  191. ASSERT(style <= DL_DASHDOTDOTDOT_GAP);
  192. int gapLen = round ? penSize * 2 : penSize;
  193. int dotLen = round ? 1 : penSize;
  194. int dashLen = round ? penSize * 2 : penSize * 3;
  195. if (style >= DL_DASH_GAP)
  196. gapLen *= 2;
  197. if (style == DL_SOLID)
  198. return(0);
  199. switch (style)
  200. {
  201. case DL_DASH:
  202. case DL_DASH_GAP:
  203. pattern[0] = dashLen;
  204. pattern[1] = gapLen;
  205. return 2;
  206. case DL_DOT:
  207. case DL_DOT_GAP:
  208. pattern[0] = dotLen;
  209. pattern[1] = gapLen;
  210. return 2;
  211. case DL_DASHDOT:
  212. case DL_DASHDOT_GAP:
  213. pattern[0] = dashLen;
  214. pattern[2] = dotLen;
  215. pattern[1] = 
  216. pattern[3] = gapLen;
  217. return 4;
  218. case DL_DASHDOTDOT:
  219. case DL_DASHDOTDOT_GAP:
  220. pattern[0] = dashLen;
  221. pattern[2] =
  222. pattern[4] = dotLen;
  223. pattern[1] =
  224. pattern[3] =
  225. pattern[5] = gapLen;
  226. return 6;
  227. case DL_DASHDOTDOTDOT:
  228. case DL_DASHDOTDOTDOT_GAP:
  229. default:
  230. pattern[0] = dashLen;
  231. pattern[2] =
  232. pattern[4] = 
  233. pattern[6] = dotLen;
  234. pattern[1] =
  235. pattern[3] =
  236. pattern[5] = 
  237. pattern[7] = gapLen;
  238. return 8;
  239. }
  240. }