agg_clip_liang_barsky.cs 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. //----------------------------------------------------------------------------
  2. // Anti-Grain Geometry - Version 2.4
  3. // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
  4. //
  5. // C# port by: Lars Brubaker
  6. // larsbrubaker@gmail.com
  7. // Copyright (C) 2007
  8. //
  9. // Permission to copy, use, modify, sell and distribute this software
  10. // is granted provided this copyright notice appears in all copies.
  11. // This software is provided "as is" without express or implied
  12. // warranty, and with no claim as to its suitability for any purpose.
  13. //
  14. //----------------------------------------------------------------------------
  15. // Contact: mcseem@antigrain.com
  16. // mcseemagg@yahoo.com
  17. // http://www.antigrain.com
  18. //----------------------------------------------------------------------------
  19. //
  20. // Liang-Barsky clipping
  21. //
  22. //----------------------------------------------------------------------------
  23. namespace MatterHackers.Agg
  24. {
  25. public static class ClipLiangBarsky
  26. {
  27. //------------------------------------------------------------------------
  28. private enum clipping_flags_e
  29. {
  30. clipping_flags_x1_clipped = 4,
  31. clipping_flags_x2_clipped = 1,
  32. clipping_flags_y1_clipped = 8,
  33. clipping_flags_y2_clipped = 2,
  34. clipping_flags_x_clipped = clipping_flags_x1_clipped | clipping_flags_x2_clipped,
  35. clipping_flags_y_clipped = clipping_flags_y1_clipped | clipping_flags_y2_clipped
  36. };
  37. //----------------------------------------------------------clipping_flags
  38. // Determine the clipping code of the vertex according to the
  39. // Cyrus-Beck line clipping algorithm
  40. //
  41. // | |
  42. // 0110 | 0010 | 0011
  43. // | |
  44. // -------+--------+-------- clip_box.y2
  45. // | |
  46. // 0100 | 0000 | 0001
  47. // | |
  48. // -------+--------+-------- clip_box.y1
  49. // | |
  50. // 1100 | 1000 | 1001
  51. // | |
  52. // clip_box.x1 clip_box.x2
  53. //
  54. //
  55. //template<class T>
  56. public static int clipping_flags(int x, int y, RectangleInt clip_box)
  57. {
  58. return ((x > clip_box.Right) ? 1 : 0)
  59. | ((y > clip_box.Top) ? 1 << 1 : 0)
  60. | ((x < clip_box.Left) ? 1 << 2 : 0)
  61. | ((y < clip_box.Bottom) ? 1 << 3 : 0);
  62. }
  63. public static int clipping_flags_x(int x, RectangleInt clip_box)
  64. {
  65. return ((x > clip_box.Right ? 1 : 0) | ((x < clip_box.Left ? 1 : 0) << 2));
  66. }
  67. public static int clipping_flags_y(int y, RectangleInt clip_box)
  68. {
  69. return (((y > clip_box.Top ? 1 : 0) << 1) | ((y < clip_box.Bottom ? 1 : 0) << 3));
  70. }
  71. public static int clip_liang_barsky(int x1, int y1, int x2, int y2,
  72. RectangleInt clip_box,
  73. int[] x, int[] y)
  74. {
  75. int XIndex = 0;
  76. int YIndex = 0;
  77. double nearzero = 1e-30;
  78. double deltax = x2 - x1;
  79. double deltay = y2 - y1;
  80. double xin;
  81. double xout;
  82. double yin;
  83. double yout;
  84. double tinx;
  85. double tiny;
  86. double toutx;
  87. double touty;
  88. double tin1;
  89. double tin2;
  90. double tout1;
  91. int np = 0;
  92. if (deltax == 0.0)
  93. {
  94. // bump off of the vertical
  95. deltax = (x1 > clip_box.Left) ? -nearzero : nearzero;
  96. }
  97. if (deltay == 0.0)
  98. {
  99. // bump off of the horizontal
  100. deltay = (y1 > clip_box.Bottom) ? -nearzero : nearzero;
  101. }
  102. if (deltax > 0.0)
  103. {
  104. // points to right
  105. xin = clip_box.Left;
  106. xout = clip_box.Right;
  107. }
  108. else
  109. {
  110. xin = clip_box.Right;
  111. xout = clip_box.Left;
  112. }
  113. if (deltay > 0.0)
  114. {
  115. // points up
  116. yin = clip_box.Bottom;
  117. yout = clip_box.Top;
  118. }
  119. else
  120. {
  121. yin = clip_box.Top;
  122. yout = clip_box.Bottom;
  123. }
  124. tinx = (xin - x1) / deltax;
  125. tiny = (yin - y1) / deltay;
  126. if (tinx < tiny)
  127. {
  128. // hits x first
  129. tin1 = tinx;
  130. tin2 = tiny;
  131. }
  132. else
  133. {
  134. // hits y first
  135. tin1 = tiny;
  136. tin2 = tinx;
  137. }
  138. if (tin1 <= 1.0)
  139. {
  140. if (0.0 < tin1)
  141. {
  142. x[XIndex++] = (int)xin;
  143. y[YIndex++] = (int)yin;
  144. ++np;
  145. }
  146. if (tin2 <= 1.0)
  147. {
  148. toutx = (xout - x1) / deltax;
  149. touty = (yout - y1) / deltay;
  150. tout1 = (toutx < touty) ? toutx : touty;
  151. if (tin2 > 0.0 || tout1 > 0.0)
  152. {
  153. if (tin2 <= tout1)
  154. {
  155. if (tin2 > 0.0)
  156. {
  157. if (tinx > tiny)
  158. {
  159. x[XIndex++] = (int)xin;
  160. y[YIndex++] = (int)(y1 + tinx * deltay);
  161. }
  162. else
  163. {
  164. x[XIndex++] = (int)(x1 + tiny * deltax);
  165. y[YIndex++] = (int)yin;
  166. }
  167. ++np;
  168. }
  169. if (tout1 < 1.0)
  170. {
  171. if (toutx < touty)
  172. {
  173. x[XIndex++] = (int)xout;
  174. y[YIndex++] = (int)(y1 + toutx * deltay);
  175. }
  176. else
  177. {
  178. x[XIndex++] = (int)(x1 + touty * deltax);
  179. y[YIndex++] = (int)yout;
  180. }
  181. }
  182. else
  183. {
  184. x[XIndex++] = x2;
  185. y[YIndex++] = y2;
  186. }
  187. ++np;
  188. }
  189. else
  190. {
  191. if (tinx > tiny)
  192. {
  193. x[XIndex++] = (int)xin;
  194. y[YIndex++] = (int)yout;
  195. }
  196. else
  197. {
  198. x[XIndex++] = (int)xout;
  199. y[YIndex++] = (int)yin;
  200. }
  201. ++np;
  202. }
  203. }
  204. }
  205. }
  206. return np;
  207. }
  208. public static bool clip_move_point(int x1, int y1, int x2, int y2,
  209. RectangleInt clip_box,
  210. ref int x, ref int y, int flags)
  211. {
  212. int bound;
  213. if ((flags & (int)clipping_flags_e.clipping_flags_x_clipped) != 0)
  214. {
  215. if (x1 == x2)
  216. {
  217. return false;
  218. }
  219. bound = ((flags & (int)clipping_flags_e.clipping_flags_x1_clipped) != 0) ? clip_box.Left : clip_box.Right;
  220. y = (int)((double)(bound - x1) * (y2 - y1) / (x2 - x1) + y1);
  221. x = bound;
  222. }
  223. flags = clipping_flags_y(y, clip_box);
  224. if ((flags & (int)clipping_flags_e.clipping_flags_y_clipped) != 0)
  225. {
  226. if (y1 == y2)
  227. {
  228. return false;
  229. }
  230. bound = ((flags & (int)clipping_flags_e.clipping_flags_y1_clipped) != 0) ? clip_box.Bottom : clip_box.Top;
  231. x = (int)((double)(bound - y1) * (x2 - x1) / (y2 - y1) + x1);
  232. y = bound;
  233. }
  234. return true;
  235. }
  236. //-------------------------------------------------------clip_line_segment
  237. // Returns: ret >= 4 - Fully clipped
  238. // (ret & 1) != 0 - First point has been moved
  239. // (ret & 2) != 0 - Second point has been moved
  240. //
  241. //template<class T>
  242. public static int clip_line_segment(ref int x1, ref int y1, ref int x2, ref int y2,
  243. RectangleInt clip_box)
  244. {
  245. int f1 = clipping_flags(x1, y1, clip_box);
  246. int f2 = clipping_flags(x2, y2, clip_box);
  247. int ret = 0;
  248. if ((f2 | f1) == 0)
  249. {
  250. // Fully visible
  251. return 0;
  252. }
  253. if ((f1 & (int)clipping_flags_e.clipping_flags_x_clipped) != 0 &&
  254. (f1 & (int)clipping_flags_e.clipping_flags_x_clipped) == (f2 & (int)clipping_flags_e.clipping_flags_x_clipped))
  255. {
  256. // Fully clipped
  257. return 4;
  258. }
  259. if ((f1 & (int)clipping_flags_e.clipping_flags_y_clipped) != 0 &&
  260. (f1 & (int)clipping_flags_e.clipping_flags_y_clipped) == (f2 & (int)clipping_flags_e.clipping_flags_y_clipped))
  261. {
  262. // Fully clipped
  263. return 4;
  264. }
  265. int tx1 = x1;
  266. int ty1 = y1;
  267. int tx2 = x2;
  268. int ty2 = y2;
  269. if (f1 != 0)
  270. {
  271. if (!clip_move_point(tx1, ty1, tx2, ty2, clip_box, ref x1, ref y1, f1))
  272. {
  273. return 4;
  274. }
  275. if (x1 == x2 && y1 == y2)
  276. {
  277. return 4;
  278. }
  279. ret |= 1;
  280. }
  281. if (f2 != 0)
  282. {
  283. if (!clip_move_point(tx1, ty1, tx2, ty2, clip_box, ref x2, ref y2, f2))
  284. {
  285. return 4;
  286. }
  287. if (x1 == x2 && y1 == y2)
  288. {
  289. return 4;
  290. }
  291. ret |= 2;
  292. }
  293. return ret;
  294. }
  295. }
  296. }
  297. //#endif