LINE.C 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. /*
  2. THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
  3. SOFTWARE CORPORATION ("PARALLAX"). PARALLAX, IN DISTRIBUTING THE CODE TO
  4. END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
  5. ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
  6. IN USING, DISPLAYING, AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
  7. SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
  8. FREE PURPOSES. IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
  9. CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES. THE END-USER UNDERSTANDS
  10. AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
  11. COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION. ALL RIGHTS RESERVED.
  12. */
  13. /*
  14. * $Source: f:/miner/source/2d/rcs/line.c $
  15. * $Revision: 1.10 $
  16. * $Author: john $
  17. * $Date: 1994/11/18 22:50:02 $
  18. *
  19. * Graphical routines for drawing lines.
  20. *
  21. * $Log: line.c $
  22. * Revision 1.10 1994/11/18 22:50:02 john
  23. * Changed shorts to ints in parameters.
  24. *
  25. * Revision 1.9 1994/07/13 12:03:04 john
  26. * Added assembly modex line-drawer.
  27. *
  28. * Revision 1.8 1993/12/06 18:18:03 john
  29. * took out aaline.
  30. *
  31. * Revision 1.7 1993/12/03 12:11:17 john
  32. * ,
  33. *
  34. * Revision 1.6 1993/11/18 09:40:22 john
  35. * Added laser-line
  36. *
  37. * Revision 1.5 1993/10/15 16:23:36 john
  38. * y
  39. *
  40. * Revision 1.4 1993/09/29 16:13:58 john
  41. * optimized
  42. *
  43. * Revision 1.3 1993/09/26 18:44:12 matt
  44. * Added gr_uline(), which just calls gr_line(), and made both take
  45. * fixes, and shift down themselves.
  46. *
  47. * Revision 1.2 1993/09/11 19:50:15 matt
  48. * In gr_vline() & gr_hline(), check for start > end, and EXCHG if so
  49. *
  50. * Revision 1.1 1993/09/08 11:43:54 john
  51. * Initial revision
  52. *
  53. *
  54. */
  55. #include <stdlib.h>
  56. #include "mem.h"
  57. #include "gr.h"
  58. #include "grdef.h"
  59. #include "fix.h"
  60. #include "clip.h"
  61. extern void gr_modex_line();
  62. int modex_line_vertincr;
  63. int modex_line_incr1;
  64. int modex_line_incr2;
  65. int modex_line_x1;
  66. int modex_line_y1;
  67. int modex_line_x2;
  68. int modex_line_y2;
  69. ubyte modex_line_Color;
  70. /*
  71. Symmetric Double Step Line Algorithm
  72. by Brian Wyvill
  73. from "Graphics Gems", Academic Press, 1990
  74. */
  75. /* non-zero flag indicates the pixels needing EXCHG back. */
  76. void plot(int x,int y,int flag)
  77. { if (flag)
  78. gr_upixel(y, x);
  79. else
  80. gr_upixel(x, y);
  81. }
  82. int gr_hline(int x1, int x2, int y)
  83. { int i;
  84. if (x1 > x2) EXCHG(x1,x2);
  85. for (i=x1; i<=x2; i++ )
  86. gr_upixel( i, y );
  87. return 0;
  88. }
  89. int gr_vline(int y1, int y2, int x)
  90. { int i;
  91. if (y1 > y2) EXCHG(y1,y2);
  92. for (i=y1; i<=y2; i++ )
  93. gr_upixel( x, i );
  94. return 0;
  95. }
  96. void gr_universal_uline(int a1, int b1, int a2, int b2)
  97. {
  98. int dx, dy, incr1, incr2, D, x, y, xend, c, pixels_left;
  99. int x1, y1;
  100. int sign_x = 1, sign_y = 1, step, reverse, i;
  101. if (a1==a2) {
  102. gr_vline(b1,b2,a1);
  103. return;
  104. }
  105. if (b1==b2) {
  106. gr_hline(a1,a2,b1);
  107. return;
  108. }
  109. dx = a2 - a1;
  110. dy = b2 - b1;
  111. if (dx < 0) {
  112. sign_x = -1;
  113. dx *= -1;
  114. }
  115. if (dy < 0) {
  116. sign_y = -1;
  117. dy *= -1;
  118. }
  119. /* decide increment sign by the slope sign */
  120. if (sign_x == sign_y)
  121. step = 1;
  122. else
  123. step = -1;
  124. if (dy > dx) { /* chooses axis of greatest movement (make * dx) */
  125. EXCHG(a1, b1);
  126. EXCHG(a2, b2);
  127. EXCHG(dx, dy);
  128. reverse = 1;
  129. } else
  130. reverse = 0;
  131. /* note error check for dx==0 should be included here */
  132. if (a1 > a2) { /* start from the smaller coordinate */
  133. x = a2;
  134. y = b2;
  135. x1 = a1;
  136. y1 = b1;
  137. } else {
  138. x = a1;
  139. y = b1;
  140. x1 = a2;
  141. y1 = b2;
  142. }
  143. /* Note dx=n implies 0 - n or (dx+1) pixels to be set */
  144. /* Go round loop dx/4 times then plot last 0,1,2 or 3 pixels */
  145. /* In fact (dx-1)/4 as 2 pixels are already plottted */
  146. xend = (dx - 1) / 4;
  147. pixels_left = (dx - 1) % 4; /* number of pixels left over at the
  148. * end */
  149. plot(x, y, reverse);
  150. plot(x1, y1, reverse); /* plot first two points */
  151. incr2 = 4 * dy - 2 * dx;
  152. if (incr2 < 0) { /* slope less than 1/2 */
  153. c = 2 * dy;
  154. incr1 = 2 * c;
  155. D = incr1 - dx;
  156. for (i = 0; i < xend; i++) { /* plotting loop */
  157. ++x;
  158. --x1;
  159. if (D < 0) {
  160. /* pattern 1 forwards */
  161. plot(x, y, reverse);
  162. plot(++x, y, reverse);
  163. /* pattern 1 backwards */
  164. plot(x1, y1, reverse);
  165. plot(--x1, y1, reverse);
  166. D += incr1;
  167. } else {
  168. if (D < c) {
  169. /* pattern 2 forwards */
  170. plot(x, y, reverse);
  171. plot(++x, y += step, reverse);
  172. /* pattern 2 backwards */
  173. plot(x1, y1, reverse);
  174. plot(--x1, y1 -= step, reverse);
  175. } else {
  176. /* pattern 3 forwards */
  177. plot(x, y += step, reverse);
  178. plot(++x, y, reverse);
  179. /* pattern 3 backwards */
  180. plot(x1, y1 -= step, reverse);
  181. plot(--x1, y1, reverse);
  182. }
  183. D += incr2;
  184. }
  185. } /* end for */
  186. /* plot last pattern */
  187. if (pixels_left) {
  188. if (D < 0) {
  189. plot(++x, y, reverse); /* pattern 1 */
  190. if (pixels_left > 1)
  191. plot(++x, y, reverse);
  192. if (pixels_left > 2)
  193. plot(--x1, y1, reverse);
  194. } else {
  195. if (D < c) {
  196. plot(++x, y, reverse); /* pattern 2 */
  197. if (pixels_left > 1)
  198. plot(++x, y += step, reverse);
  199. if (pixels_left > 2)
  200. plot(--x1, y1, reverse);
  201. } else {
  202. /* pattern 3 */
  203. plot(++x, y += step, reverse);
  204. if (pixels_left > 1)
  205. plot(++x, y, reverse);
  206. if (pixels_left > 2)
  207. plot(--x1, y1 -= step, reverse);
  208. }
  209. }
  210. } /* end if pixels_left */
  211. }
  212. /* end slope < 1/2 */
  213. else { /* slope greater than 1/2 */
  214. c = 2 * (dy - dx);
  215. incr1 = 2 * c;
  216. D = incr1 + dx;
  217. for (i = 0; i < xend; i++) {
  218. ++x;
  219. --x1;
  220. if (D > 0) {
  221. /* pattern 4 forwards */
  222. plot(x, y += step, reverse);
  223. plot(++x, y += step, reverse);
  224. /* pattern 4 backwards */
  225. plot(x1, y1 -= step, reverse);
  226. plot(--x1, y1 -= step, reverse);
  227. D += incr1;
  228. } else {
  229. if (D < c) {
  230. /* pattern 2 forwards */
  231. plot(x, y, reverse);
  232. plot(++x, y += step, reverse);
  233. /* pattern 2 backwards */
  234. plot(x1, y1, reverse);
  235. plot(--x1, y1 -= step, reverse);
  236. } else {
  237. /* pattern 3 forwards */
  238. plot(x, y += step, reverse);
  239. plot(++x, y, reverse);
  240. /* pattern 3 backwards */
  241. plot(x1, y1 -= step, reverse);
  242. plot(--x1, y1, reverse);
  243. }
  244. D += incr2;
  245. }
  246. } /* end for */
  247. /* plot last pattern */
  248. if (pixels_left) {
  249. if (D > 0) {
  250. plot(++x, y += step, reverse); /* pattern 4 */
  251. if (pixels_left > 1)
  252. plot(++x, y += step, reverse);
  253. if (pixels_left > 2)
  254. plot(--x1, y1 -= step, reverse);
  255. } else {
  256. if (D < c) {
  257. plot(++x, y, reverse); /* pattern 2 */
  258. if (pixels_left > 1)
  259. plot(++x, y += step, reverse);
  260. if (pixels_left > 2)
  261. plot(--x1, y1, reverse);
  262. } else {
  263. /* pattern 3 */
  264. plot(++x, y += step, reverse);
  265. if (pixels_left > 1)
  266. plot(++x, y, reverse);
  267. if (pixels_left > 2) {
  268. if (D > c) /* step 3 */
  269. plot(--x1, y1 -= step, reverse);
  270. else /* step 2 */
  271. plot(--x1, y1, reverse);
  272. }
  273. }
  274. }
  275. }
  276. }
  277. }
  278. //unclipped version just calls clipping version for now
  279. int gr_uline(fix _a1, fix _b1, fix _a2, fix _b2)
  280. {
  281. int a1,b1,a2,b2;
  282. a1 = f2i(_a1); b1 = f2i(_b1); a2 = f2i(_a2); b2 = f2i(_b2);
  283. switch(TYPE)
  284. {
  285. case BM_LINEAR:
  286. gr_linear_line( a1, b1, a2, b2 );
  287. return 0;
  288. case BM_MODEX:
  289. modex_line_x1 = a1+XOFFSET;
  290. modex_line_y1 = b1+YOFFSET;
  291. modex_line_x2 = a2+XOFFSET;
  292. modex_line_y2 = b2+YOFFSET;
  293. modex_line_Color = grd_curcanv->cv_color;
  294. gr_modex_line();
  295. return 0;
  296. default:
  297. gr_universal_uline( a1, b1, a2, b2 );
  298. return 0;
  299. }
  300. }
  301. // Returns 0 if drawn with no clipping, 1 if drawn but clipped, and
  302. // 2 if not drawn at all.
  303. int gr_line(fix a1, fix b1, fix a2, fix b2)
  304. {
  305. int x1, y1, x2, y2;
  306. int clipped=0;
  307. x1 = i2f(MINX);
  308. y1 = i2f(MINY);
  309. x2 = i2f(MAXX);
  310. y2 = i2f(MAXY);
  311. CLIPLINE(a1,b1,a2,b2,x1,y1,x2,y2,return 2,clipped=1, FSCALE );
  312. gr_uline( a1, b1, a2, b2 );
  313. return clipped;
  314. }
  315.