# Efficient dynamic drawing

So for example I have this code:

points = {}; k = 0;
Dynamic@k
Dynamic@Graphics[Point@points]

x = .1; y = .3; K = .9;
While[True,
k++;
{x, y} = {FractionalPart[x + K y], FractionalPart[x]};
AppendTo[points, {x, y}];
]


The problem is that the list of points is growing and it slows down with time. What I want is to be able to add a point (or another primitive) directly on the dynamic graph without storing unnecessary chunks of data.

-
AppendTo[] is notoriously slow... –  Ｊ. Ｍ. Oct 1 '12 at 9:08
@J.M. And increasing the number of points to plot ad infinitum doesn't help –  belisarius Oct 1 '12 at 9:18
For systems like Matlab this works because it uses a more PostScript-like approach to rendering (just adding on top)... –  Yves Klett Oct 1 '12 at 12:55

As it was mentioned in the comments: your loop is infinite, which eventually will cause the slowdown of any computation that accumulates data in the memory. The important rule of thumb for Dynamic updating is: only update when necessary and only update what is necessary. Accordingly, you can speed up the performance of the dynamic drawing by wrapping only points and k in Dynamic. By this way, only the list of points is updated (and the label) and Mathematica does not have to redraw the whole Graphics object again and again (which involves a lot of extra computation).

points = {};
Graphics[Point@Dynamic@points, PlotLabel -> Dynamic@k]

x = .1; y = .3; K = .9;
Do[
{x, y} = {FractionalPart[x + K y], FractionalPart[x]};
points = Append[points, {x, y}];
, {k, 20000}]


Starting from @belisarius' comment, I came up with a more economic version (time scales linearly with k). If one does not have to keep all the points we can apply a reasonable resolution to bin the ranges and saving new datapoints in a matrix, overwriting previous data.

resolution = 256;  (* divide the (0,1) range into 256 bins *)
array = Array[0 &, {resolution, resolution}];

Dynamic@ArrayPlot[array, PlotLabel -> Dynamic@k]

x = .1; y = .3; K = .9;
Do[
{x, y} = {FractionalPart[x + K y], FractionalPart[x]};
array = ReplacePart[array, (Min[#, resolution] & /@ (Round[{x, y}*resolution] + 1)) -> 1],
{k, 1000000}]


-
Yes it's much faster but execution still slows down with time. The goal is to get rid off list and just add primitives directly to the existing graph. –  swish Oct 1 '12 at 10:14
@swish: I think that in any case a list must be maintained to store points if you want to build up your graphics by successively introducing points. –  István Zachar Oct 1 '12 at 10:32
How about keeping a rasterized pre-image, and adding a point at a time. It's slow, but O(1) –  belisarius Oct 1 '12 at 12:33
Thanks for the tip @belisarius. See edit. –  István Zachar Oct 1 '12 at 13:39
Thank you all, it is really fast now. I was playing with ArrayPlot too. –  swish Oct 1 '12 at 14:25