Task

Implement the   Xiaolin Wu's line algorithm   described in Wikipedia.



This algorithm draws anti-aliased lines.



Related task

   See   Bresenham's line algorithm   for aliased lines.


INCLUDE "H6:REALMATH.ACT"
 
REAL one
 
PROC PutBigPixel(INT x,y,col)
  IF x>=0 AND x<=79 AND y>=0 AND y<=47 THEN
    y==LSH 2
    IF col<0 THEN col=0
    ELSEIF col>15 THEN col=15 FI
    Color=col
    Plot(x,y)
    DrawTo(x,y+3)
  FI
RETURN
 
INT FUNC Abs(INT x)
  IF x<0 THEN RETURN (-x) FI
RETURN (x)
 
PROC Swap(INT POINTER a,b)
  INT tmp
 
  tmp=a^ a^=b^ b^=tmp
RETURN
 
PROC Line(INT x1,y1,x2,y2,col)
  INT x,y,dx,dy,c
  INT POINTER px,py
  REAL rx,ry,grad,rcol,tmp1,tmp2
 
  dx=Abs(x2-x1)
  dy=Abs(y2-y1)
  IF dy>dx THEN
    Swap(@x1,@y1)
    Swap(@x2,@y2)
    px=@y py=@x
  ELSE
    px=@x py=@y
  FI
 
  IF x1>x2 THEN
    Swap(@x1,@x2)
    Swap(@y1,@y2)
  FI
 
  x=x2-x1
  IF x=0 THEN x=1 FI
  IntToRealForNeg(x,rx)
  IntToRealForNeg(y2-y1,ry)
  RealDiv(ry,rx,grad)
 
  IntToRealForNeg(y1,ry)
  IntToReal(col,rcol)
  FOR x=x1 TO x2
  DO
    Frac(ry,tmp1)
    IF IsNegative(tmp1) THEN
      RealAdd(one,tmp1,tmp2)
      RealAssign(tmp2,tmp1)
    FI
    RealMult(rcol,tmp1,tmp2)
    c=Round(tmp2)
    y=Floor(ry)
    PutBigPixel(px^,py^,col-c)
    y==+1
    PutBigPixel(px^,py^,c)
    RealAdd(ry,grad,tmp1)
    RealAssign(tmp1,ry)
  OD
RETURN
 
PROC Main()
  BYTE CH=$02FC ;Internal hardware value for last key pressed
  REAL tmp,c
  BYTE i,x1,y1,x2,y2
 
  MathInit()
  IntToReal(1,one)
 
  Graphics(9)
  FOR i=0 TO 11
  DO
    Line(0,i*4,38,1+i*5,15)
    Line(40+i*4,0,41+i*6,47,15)
  OD
 
  DO UNTIL CH#$FF OD
  CH=$FF
RETURN