Jump to content

User:Kghose/ikeda code

From Wikipedia, the free encyclopedia

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;
}