CSE423 · Computer Graphics

DDA Line Drawing Simulator

Step through slope, increment and rounding to see which pixel DDA lights up next.

dx = 15, dy = 9. steps = max(|dx|, |dy|) = 15, so x increments by 1.000 and y by 0.600 each step.

step 1 of 18
pixel plotted this stepalready plottedexact position before roundingideal line

DDA

Steps the longer axis by 1 and adds a fractional increment to the other, rounding each time. Simple, but every step costs a floating-point add and a round.

Pixels plotted
0

Endpoints

Range -12 to 12. Try a steep line (slope > 1) or one going right to left to see which axis drives.

Working

#exactxy

← → to step, or use the buttons above.

How DDA Line Drawing Simulator works

The digital differential analyser draws a line by sampling it at unit intervals along whichever axis it moves fastest on. Start from dx = x₂ − x₁ and dy = y₂ − y₁ and take steps = max(|dx|, |dy|). Dividing both deltas by that count gives the per-step increments xInc and yInc, and one of them is always exactly ±1 — the driving axis — while the other is the fractional slope. From the starting point you then repeatedly add the increments to a pair of floating-point accumulators and round each result to the nearest integer to get a pixel. Because the driving axis advances by a full pixel every step, the line never leaves gaps, and because the other axis creeps along by the true slope, the rounded values track the ideal line closely. The cost is arithmetic: DDA needs floating-point addition and a rounding operation per pixel, which is exactly what Bresenham was invented to remove.

Pseudocode

DDA(x1, y1, x2, y2):
    dx = x2 - x1
    dy = y2 - y1

    // drive along the axis with the larger span, so no gaps appear
    steps = max(abs(dx), abs(dy))
    if steps == 0:
        plot(round(x1), round(y1)); return    // degenerate: single point

    xInc = dx / steps          // one of xInc, yInc is exactly +1 or -1
    yInc = dy / steps

    x = x1
    y = y1
    plot(round(x), round(y))

    repeat steps times:
        x = x + xInc
        y = y + yInc
        plot(round(x), round(y))

Time and space complexity

Time
O(max(|dx|, |dy|)) — one iteration per pixel plotted
Space
O(1)

The work is linear in the length of the longer axis because exactly one pixel is emitted per step; the per-step cost is two floating-point additions and two roundings.

Worked example

Draw from (2, 3) to (7, 6). dx = 5, dy = 3, so steps = max(5, 3) = 5, xInc = 1.0, yInc = 0.6.

  1. k = 0x = 2.0, y = 3.0 → plot (2, 3).
  2. k = 1x = 3.0, y = 3.6 → round → plot (3, 4).
  3. k = 2x = 4.0, y = 4.2 → round → plot (4, 4).
  4. k = 3x = 5.0, y = 4.8 → round → plot (5, 5).
  5. k = 4x = 6.0, y = 5.4 → round → plot (6, 5).
  6. k = 5x = 7.0, y = 6.0 → plot (7, 6). Endpoint reached.

Six pixels: (2,3), (3,4), (4,4), (5,5), (6,5), (7,6). Note y advances irregularly — 3,4,4,5,5,6 — which is the slope 0.6 showing up in the rounding.

Common exam mistakes

  • Using steps = |dx| always. That leaves gaps whenever |dy| > |dx|; the whole point of max() is to drive along the steeper axis.
  • Truncating instead of rounding. floor() biases every pixel downward and visibly shifts the line; round() is required.
  • Rounding the accumulator itself rather than a copy. Feed the un-rounded x and y forward, or the error compounds and the line bends.
  • Forgetting the starting pixel. The loop runs `steps` times but the line has steps + 1 pixels.
  • Not handling dx = dy = 0. Both increments become 0/0; guard the degenerate case before dividing.

Frequently asked questions

What is the difference between DDA and Bresenham's line algorithm?

They plot nearly the same pixels but DDA uses floating-point accumulators and rounding, while Bresenham (midpoint) uses an integer decision parameter and only additions. Bresenham is faster and free of floating-point drift, which is why hardware uses it.

Why does DDA use max(|dx|, |dy|) as the step count?

So the faster-changing axis moves exactly one pixel per iteration. If you stepped along the slower axis, the faster one would jump by more than a pixel each time and the line would come out dotted.

Is DDA accurate for steep lines?

Yes — for |dy| > |dx| the roles simply swap, y becomes the driving axis with yInc = ±1 and xInc holds the reciprocal slope. The algorithm is symmetric.

Why is DDA considered slow?

Every pixel costs a floating-point add and a round on both axes. On long lines the accumulated floating-point error can also drift, so integer methods are preferred in practice.

Related simulators