I used the following code on a linux box to generate the Ikeda map attractor plots and animations.

Movie Script edit

Use the following script to create the animation and plots. It requires ImageMagick and mencoder from mplayer.

#Notes:
#For hint about depth 8 see http://lists.mplayerhq.hu/pipermail/mencoder-users/2006-August/003817.html
#For hint about adding text using ImageMagick see http://www-128.ibm.com/developerworks/library/l-graf/?ca=dnt-428
#For bash scripting see http://linuxgazette.net/issue18/bash.html
#For mencoder options see http://www.mplayerhq.hu/DOCS/HTML/en/menc-feat-enc-images.html

#run calculations
./ikeda  

#annotate and convert to depth 8
for img in `ls ikeda0*.png`
do
  theend=${img#*0}
  caption="u = 0.${theend%.png}"
  echo $caption
  convert -font helvetica -fill black -pointsize 12 -draw "text 10,20 \"$caption\"" $img -depth 8 $img
done

#Now run mencoder on the depth 8 files
mencoder mf://ikeda0*.png -mf w=400:h=400 -ovc lavc -lavcopts vcodec=xvid -of avi -o ikeda_map.avi

Makefile edit

Compile the c++ code with the following makefile:

CC=g++
CFLAGS= -c -Wall -O4 -DNO_FREETYPE
LDFLAGS= -lfreetype -lm -lpng -lpngwriter -lz -DNO_FREETYPE -O4
EXECUTABLE = ikeda 

all: $(HEADERS) $(SOURCES) $(EXECUTABLE)
	
ikeda: main.cpp
	$(CC) $(LDFLAGS) main.cpp pngwriter.o -oikeda 

clean:
	rm -f *.o ikeda 

C++ Code edit

The c++ program requires pngwriter, libpng and zlib.

#include <stdlib.h>
#include <iostream>
#include <pngwriter.h>

using namespace std;

//N is the number of trajectory points
//X,Y are arrays (pre assigned) of length N that contain the trajectory
//bb_XXXX contains the bounding box of the plot
struct IkedaTrajectory
{
      int N; 
      double *X, *Y, bb_xmin, bb_xmax, bb_ymin, bb_ymax ;
};

//a convenience structure for the plot bounding box
struct Scale
{
      double bb_xmin, bb_xmax, bb_ymin, bb_ymax ;
};

//convenience structure to carry the simulation params
struct Params
{
    double u;
    int N,          // simulation steps
        N_start_points, //points in trajectory
        Nx, Ny,     //size of image
        last_N_points; //for attractor plot, how many points from a trajectory do we plot
};

struct ImageData
{
    char filename[80];
    int *X, *Y;
};

//u is the Ikeda parameter
//x,y is the initial point
//it is the ikeda trajectory structure we return our answer in
//remember to initialise it
void ikeda_trajectory(double u, double x, double y, IkedaTrajectory &it)
{
     it.X[0] = x ;
     it.Y[0] = y ;
     double t, x1 = x, y1 = y;
     for(int n = 1 ; n < it.N ; n++)
     {   
         /*
         if( it.bb_xmin > x1 ) it.bb_xmin = x1 ;
         if( it.bb_xmax < x1 ) it.bb_xmax = x1 ;
         if( it.bb_ymin > y1 ) it.bb_ymin = y1 ;
         if( it.bb_ymax < y1 ) it.bb_ymax = y1 ;
         */
                     
         t = 0.4 - 6.0/(1.0 + x1*x1 + y1*y1);
         it.X[n] = 1.0 + u*(x1*cos(t) - y1*sin(t)) ;
         it.Y[n] = u*(x1*sin(t) + y1*cos(t)) ;
         x1 = it.X[n];
         y1 = it.Y[n];
     }
}

//scale the plot data to the canvas
//Pre allocate X and Y
void scale_plot(IkedaTrajectory &it, Scale &sc, int Nx, int Ny, int *X, int *Y)
{          
     double scaleX, translateX, scaleY, translateY ;
     scaleX = (double)Nx / (sc.bb_xmax - sc.bb_xmin) ;
     translateX = sc.bb_xmin ;
     scaleY = (double)Ny / (sc.bb_ymax - sc.bb_ymin) ;
     translateY = sc.bb_ymin ;                
                                
     for(int n = 0 ; n < it.N ; n++)
     {
             X[n] = (int)( (it.X[n] - translateX) * scaleX );
             Y[n] = (int)( (it.Y[n] - translateY) * scaleY );
     }
}


void save_plot(Params p, IkedaTrajectory &it, Scale &it_scale, ImageData &imagedata)
{
    pngwriter png(p.Nx, p.Ny, 1.0, imagedata.filename);
    double r, b, x, y ; 
            
    cout << "Computing u = " << p.u << flush ;
    for(int n = 0 ; n < p.N_start_points ; n++)
    {
        r = rand()/((double)RAND_MAX + 1);
        b = rand()/((double)RAND_MAX + 1);    
        x = ( r - 0.5 ) * 20.0;
        y = ( r - 0.5 ) * 20.0;    
               
        ikeda_trajectory(p.u, x, y, it) ;
        scale_plot(it, it_scale, p.Nx, p.Ny, imagedata.X, imagedata.Y) ;
                
        for(int m = it.N - p.last_N_points ; m < it.N ; m++)
        {
                png.filledcircle_blend( imagedata.X[m], imagedata.Y[m], 2.0, 0.6, r, 0.5, b);
                png.plot( imagedata.X[m], imagedata.Y[m], r, 0.5, b );
	}
    }    
  
    cout << " --- Saving " << flush ;
    //png.setcompressionlevel(1); //messing with this does not speed up the process
    png.close();
    cout << " --- Done ! " << endl ;
}

int main(int argc, char *argv[])
{    
    Params p ;
    ImageData imagedata ;
    
    p.N = 500 ;
    p.N_start_points = 20000 ;
    p.Nx = 400 ;
    p.Ny = 400 ;
    p.last_N_points = 20 ;
                
    IkedaTrajectory it ;
    Scale it_scale ;
    
    it_scale.bb_xmax = 5;
    it_scale.bb_ymax = 4.5;
    it_scale.bb_xmin = -1;
    it_scale.bb_ymin = -1.5;
    
    
    it.N = p.N ;
    it.X = new double [it.N];
    it.Y = new double [it.N];
    imagedata.X = new int [it.N];
    imagedata.Y = new int [it.N];        
 
    for(double u = 0.0 ; u < 1.0 ; u += 0.001) 
    {
        p.u = u;
        sprintf(imagedata.filename, "ikeda%04d.png", (int)(p.u * 1000 +.5)); 
	save_plot(p, it, it_scale, imagedata);
    }
    
    delete[] it.X ;
    delete[] it.Y ;
    
    delete[] imagedata.X ;
    delete[] imagedata.Y ;
    
    return EXIT_SUCCESS;
}