As we stated before, the center of a pixel is at (x+1/2, y+1/2)
At an arbitrary step i, we have just plotted the
point (xi, yi)
Which means that the line is within yi+/- 1/2
We need to be able to choose between yi+1 = yi and yi+1
To do this, we compute the distance between the actual y value and
the two pixel based y values.
y = m(xi+1)+b
d1 = y - yi
= m(xi+1)+b -yi
d2 = yi +1 - y
= yi +1 -(m(xi+1)+b)
remember xi+1 = xi+1
We form a predictor, Pi for step i
Pi = d1 - d2
if Pi is positive, d1 is larger and the actual
point is closer to (xi+1, yi+1).
if Pi is negative, d2 is larger and the actual
point is closer to ((xi+1, yi),
so d1 - d2 = m(xi+1)+b -yi - [yi +1 -(m(x+1)+b)]
= 2(m(xi + 1) + b) - 2yi -1
= 2m(xi + 1) - 2yi + 2b - 1
= 2mxi - 2yi + 2b + 2m -1
Remember m = Δy/Δx
This has a floating point computation hidden in m so let
pi = Δx Pi
The sign of pi and Pi are the same, which
is what we are interested in.
pi = Δx(d1 - d2)
pi = 2Δyxi - 2Δx yi + Δx(2b +2m -1)
let c = Δx(2b +2m -1)
pi = 2Δyxi - 2Δx yi + c
Notice that this is an integer computation.
so we can compute pi and look at the sign to determine
the value of yi+1
We don't want to recompute pi every
iteration of the loop, it involves two multiples and two adds.
Frequently this is solved by computing the amount pi
changes each step.
pi = 2Δy xi - 2Δx yi + c
pi+1= 2Δy xi+1 - 2Δx yi+1 + c
Δp = pi+1 -pi
= 2Δy xi+1 - 2Δx yi+1 + c -[2Δy xi - 2Δx yi + c]
= 2Δy(xi+1-xi)
- 2Δx (yi+1- yi) +c - c
And we know that xi+1 = xi + 1 so,
Δp= 2Δy(xi+1-xi)
- 2Δx (yi+1- yi) +c - c
= 2Δy - 2Δx (yi+1- yi)
Finally, if y did not change (ie pi < < 0) then
pi+1 = pi
so Δp = 2Δy - 2Δx(yi-yi)
= 2Δy
If y did change pi+1 = pi +1
and Δp = 2Δy - 2Δx(yi + 1 -yi)
= 2Δy - 2Δx
To save computation, we can let
A = 2Δy
B = - 2Δx
And have the following code:
dx = this.x2 - this.x1;
dy = this.y2 - this.y1;
d = 0;
y = this.y1;
A = -2*dx;
B = 2*dy;
for(x = this.x1; x <= this.x2; x++) {
this.PlotPoint(x,y);
if (d >= 0) {
d += B;
y++;
}
d += A;
}