xiaolin_wu_s_line_algorithm.sf 1.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. #!/usr/bin/ruby
  2. func plot(x, y, c) {
  3. c && printf("plot %d %d %.1f\n", x, y, c);
  4. }
  5. func fpart(x) {
  6. x - int(x);
  7. }
  8. func rfpart(x) {
  9. 1 - fpart(x);
  10. }
  11. func drawLine(x0, y0, x1, y1) {
  12. var p = plot;
  13. if (abs(y1 - y0) > abs(x1 - x0)) {
  14. p = {|arg| plot(arg[1, 0, 2]) };
  15. (x0, y0, x1, y1) = (y0, x0, y1, x1);
  16. }
  17. if (x0 > x1) {
  18. (x0, x1, y0, y1) = (x1, x0, y1, y0);
  19. }
  20. var dx = (x1 - x0);
  21. var dy = (y1 - y0);
  22. var gradient = (dy / dx);
  23. var xends = [];
  24. var intery;
  25. # handle the endpoints
  26. [[x0, y0], [x1, y1]].each { |xy|
  27. var (x, y) = xy...;
  28. var xend = int(x + 0.5);
  29. var yend = (y + gradient*(xend-x));
  30. var xgap = rfpart(x + 0.5);
  31. var x_pixel = xend;
  32. var y_pixel = yend.int;
  33. xends << x_pixel;
  34. p.call(x_pixel, y_pixel , rfpart(yend) * xgap);
  35. p.call(x_pixel, y_pixel+1, fpart(yend) * xgap);
  36. defined(intery) && next;
  37. # first y-intersection for the main loop
  38. intery = (yend + gradient);
  39. }
  40. # main loop
  41. range(xends[0]+1, xends[1]-1).each { |x|
  42. p.call(x, intery.int, rfpart(intery));
  43. p.call(x, intery.int+1, fpart(intery));
  44. intery += gradient;
  45. }
  46. }
  47. drawLine(0, 1, 10, 2);