agg_line_aa_basics.cs 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. //----------------------------------------------------------------------------
  2. // Anti-Grain Geometry - Version 2.4
  3. // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
  4. //
  5. // Permission to copy, use, modify, sell and distribute this software
  6. // is granted provided this copyright notice appears in all copies.
  7. // This software is provided "as is" without express or implied
  8. // warranty, and with no claim as to its suitability for any purpose.
  9. //
  10. //----------------------------------------------------------------------------
  11. // Contact: mcseem@antigrain.com
  12. // mcseemagg@yahoo.com
  13. // http://www.antigrain.com
  14. //----------------------------------------------------------------------------
  15. using System;
  16. namespace MatterHackers.Agg
  17. {
  18. //---------------------------------------------------------------line_coord
  19. public struct line_coord
  20. {
  21. public static int conv(double x)
  22. {
  23. return (int)Math.Round(x * LineAABasics.line_subpixel_scale);
  24. }
  25. };
  26. //-----------------------------------------------------------line_coord_sat
  27. public struct line_coord_sat
  28. {
  29. public static int conv(double x)
  30. {
  31. return Util.iround(x * LineAABasics.line_subpixel_scale, LineAABasics.line_max_coord);
  32. }
  33. };
  34. //==========================================================line_parameters
  35. public struct line_parameters
  36. {
  37. //---------------------------------------------------------------------
  38. public int x1, y1, x2, y2, dx, dy, sx, sy;
  39. public bool vertical;
  40. public int inc;
  41. public int len;
  42. public int octant;
  43. // The number of the octant is determined as a 3-bit value as follows:
  44. // bit 0 = vertical flag
  45. // bit 1 = sx < 0
  46. // bit 2 = sy < 0
  47. //
  48. // [N] shows the number of the orthogonal quadrant
  49. // <M> shows the number of the diagonal quadrant
  50. // <1>
  51. // [1] | [0]
  52. // . (3)011 | 001(1) .
  53. // . | .
  54. // . | .
  55. // . | .
  56. // (2)010 .|. 000(0)
  57. // <2> ----------.+.----------- <0>
  58. // (6)110 . | . 100(4)
  59. // . | .
  60. // . | .
  61. // . | .
  62. // (7)111 | 101(5)
  63. // [2] | [3]
  64. // <3>
  65. // 0,1,2,3,4,5,6,7
  66. public static readonly byte[] s_orthogonal_quadrant = { 0, 0, 1, 1, 3, 3, 2, 2 };
  67. public static readonly byte[] s_diagonal_quadrant = { 0, 1, 2, 1, 0, 3, 2, 3 };
  68. //---------------------------------------------------------------------
  69. public line_parameters(int x1_, int y1_, int x2_, int y2_, int len_)
  70. {
  71. x1 = (x1_);
  72. y1 = (y1_);
  73. x2 = (x2_);
  74. y2 = (y2_);
  75. dx = (Math.Abs(x2_ - x1_));
  76. dy = (Math.Abs(y2_ - y1_));
  77. sx = ((x2_ > x1_) ? 1 : -1);
  78. sy = ((y2_ > y1_) ? 1 : -1);
  79. vertical = (dy >= dx);
  80. inc = (vertical ? sy : sx);
  81. len = (len_);
  82. octant = ((sy & 4) | (sx & 2) | (vertical ? 1 : 0));
  83. }
  84. //---------------------------------------------------------------------
  85. public uint orthogonal_quadrant()
  86. {
  87. return s_orthogonal_quadrant[octant];
  88. }
  89. public uint diagonal_quadrant()
  90. {
  91. return s_diagonal_quadrant[octant];
  92. }
  93. //---------------------------------------------------------------------
  94. public bool same_orthogonal_quadrant(line_parameters lp)
  95. {
  96. return s_orthogonal_quadrant[octant] == s_orthogonal_quadrant[lp.octant];
  97. }
  98. //---------------------------------------------------------------------
  99. public bool same_diagonal_quadrant(line_parameters lp)
  100. {
  101. return s_diagonal_quadrant[octant] == s_diagonal_quadrant[lp.octant];
  102. }
  103. //---------------------------------------------------------------------
  104. public void divide(out line_parameters lp1, out line_parameters lp2)
  105. {
  106. int xmid = (x1 + x2) >> 1;
  107. int ymid = (y1 + y2) >> 1;
  108. int len2 = len >> 1;
  109. lp1 = this; // it is a struct so this is a copy
  110. lp2 = this; // it is a struct so this is a copy
  111. lp1.x2 = xmid;
  112. lp1.y2 = ymid;
  113. lp1.len = len2;
  114. lp1.dx = Math.Abs(lp1.x2 - lp1.x1);
  115. lp1.dy = Math.Abs(lp1.y2 - lp1.y1);
  116. lp2.x1 = xmid;
  117. lp2.y1 = ymid;
  118. lp2.len = len2;
  119. lp2.dx = Math.Abs(lp2.x2 - lp2.x1);
  120. lp2.dy = Math.Abs(lp2.y2 - lp2.y1);
  121. }
  122. };
  123. public static class LineAABasics
  124. {
  125. public const int line_subpixel_shift = 8; //----line_subpixel_shift
  126. public const int line_subpixel_scale = 1 << line_subpixel_shift; //----line_subpixel_scale
  127. public const int line_subpixel_mask = line_subpixel_scale - 1; //----line_subpixel_mask
  128. public const int line_max_coord = (1 << 28) - 1; //----line_max_coord
  129. public const int line_max_length = 1 << (line_subpixel_shift + 10); //----line_max_length
  130. public const int line_mr_subpixel_shift = 4; //----line_mr_subpixel_shift
  131. public const int line_mr_subpixel_scale = 1 << line_mr_subpixel_shift; //----line_mr_subpixel_scale
  132. public const int line_mr_subpixel_mask = line_mr_subpixel_scale - 1; //----line_mr_subpixel_mask
  133. public static int line_mr(int x)
  134. {
  135. return x >> (line_subpixel_shift - line_mr_subpixel_shift);
  136. }
  137. public static int line_hr(int x)
  138. {
  139. return x << (line_subpixel_shift - line_mr_subpixel_shift);
  140. }
  141. public static int line_dbl_hr(int x)
  142. {
  143. return x << line_subpixel_shift;
  144. }
  145. public static void bisectrix(line_parameters l1,
  146. line_parameters l2,
  147. out int x, out int y)
  148. {
  149. double k = (double)(l2.len) / (double)(l1.len);
  150. double tx = l2.x2 - (l2.x1 - l1.x1) * k;
  151. double ty = l2.y2 - (l2.y1 - l1.y1) * k;
  152. //All bisectrices must be on the right of the line
  153. //If the next point is on the left (l1 => l2.2)
  154. //then the bisectix should be rotated by 180 degrees.
  155. if ((double)(l2.x2 - l2.x1) * (double)(l2.y1 - l1.y1) <
  156. (double)(l2.y2 - l2.y1) * (double)(l2.x1 - l1.x1) + 100.0)
  157. {
  158. tx -= (tx - l2.x1) * 2.0;
  159. ty -= (ty - l2.y1) * 2.0;
  160. }
  161. // Check if the bisectrix is too short
  162. double dx = tx - l2.x1;
  163. double dy = ty - l2.y1;
  164. if ((int)Math.Sqrt(dx * dx + dy * dy) < line_subpixel_scale)
  165. {
  166. x = (l2.x1 + l2.x1 + (l2.y1 - l1.y1) + (l2.y2 - l2.y1)) >> 1;
  167. y = (l2.y1 + l2.y1 - (l2.x1 - l1.x1) - (l2.x2 - l2.x1)) >> 1;
  168. return;
  169. }
  170. x = Util.iround(tx);
  171. y = Util.iround(ty);
  172. }
  173. public static void fix_degenerate_bisectrix_start(line_parameters lp,
  174. ref int x, ref int y)
  175. {
  176. int d = Util.iround(((double)(x - lp.x2) * (double)(lp.y2 - lp.y1) -
  177. (double)(y - lp.y2) * (double)(lp.x2 - lp.x1)) / lp.len);
  178. if (d < line_subpixel_scale / 2)
  179. {
  180. x = lp.x1 + (lp.y2 - lp.y1);
  181. y = lp.y1 - (lp.x2 - lp.x1);
  182. }
  183. }
  184. public static void fix_degenerate_bisectrix_end(line_parameters lp,
  185. ref int x, ref int y)
  186. {
  187. int d = Util.iround(((double)(x - lp.x2) * (double)(lp.y2 - lp.y1) -
  188. (double)(y - lp.y2) * (double)(lp.x2 - lp.x1)) / lp.len);
  189. if (d < line_subpixel_scale / 2)
  190. {
  191. x = lp.x2 + (lp.y2 - lp.y1);
  192. y = lp.y2 - (lp.x2 - lp.x1);
  193. }
  194. }
  195. };
  196. }