import java.applet.Applet; import java.awt.*; import java.lang.Math; /* Stefan Emet 1998. class logistic_map controls the main-frame */ public class logistic_map extends Applet implements Runnable { figure figure_plot; // class figure controls the plotting double a=2.5, X_0=0.2; double[] X_t = new double[3]; TextField TextField_parameter_a,TextField_X_0; Button Button_Draw, Button_Stop, Button_Continue; Thread Thread_RUN=null; // run -controller Panel Panel_top, Panel_right, Panel_bottom; Label Label_Status; boolean CLEAR, FIRST, DRAW, NEXT=false; public void init(){ setLayout(new BorderLayout(5,5)); // sets the main-border Panel_top = new Panel(); Panel_top.add(new Label("X(t+1) = a X(t) ( 1-X(t) ) , t=0, 1, 2...")); Panel_top.add(new Label(" a:")); Panel_top.add(TextField_parameter_a= new TextField(""+a,3)); Panel_top.add(new Label("X(0) :")); Panel_top.add(TextField_X_0= new TextField(""+X_0,3)); add("North",Panel_top); // add to Logistic map Panel_right = new Panel(); Panel_right.setLayout(new GridLayout(0,1,5,5)); Panel_right.add(Button_Draw = new Button("Draw")); Panel_right.add(Button_Continue = new Button("Continue")); Panel_right.add(Button_Stop = new Button("Stop")); Panel_right.add(new Label(" ")); Panel_right.add(new Label(" ")); add("East",Panel_right); Panel_bottom = new Panel(); Panel_bottom.add(Label_Status = new Label("Status - label")); add("South",Panel_bottom); figure_plot = new figure(this); add("Center",figure_plot); } public void run() {// run() is called after start of the Thread_RUN // take value from button a = Double.valueOf(TextField_parameter_a.getText()).doubleValue(); X_0 = Double.valueOf(TextField_X_0.getText()).doubleValue(); NEXT=false; X_t[0]=0; X_t[1]=X_0; X_t[2]= f(X_0); while (DRAW){ figure_plot.repaint(); wait_for_next(); // wait until the animation is done X_t[0]=X_t[1]; X_t[1]=X_t[2]; X_t[2]= f(X_t[2]); // calculate: x(t+1)=f(x(t)) DRAW=(DRAW)? DRAW_CHECK():DRAW; NEXT=false; } Button_Draw.enable(); } private void wait_for_next(){ while (!NEXT){;} NEXT=false; } public boolean DRAW_CHECK(){ if (X_t[2]<0){ Label_Status.setText("X(t) tends to -infinity"); return false; } if (Thread_RUN==null) return false; return true; } public double f(double x){ return a*x*(1-x); } public void start(){ CLEAR=true; if (Thread_RUN==null){ Thread_RUN=new Thread(this); } Thread_RUN.start(); // calls the run -method } public void stop(){ Thread_RUN=null; // the thread to null } public boolean action(Event e, Object arg){ if (e.target.equals(Button_Draw)){ stop(); FIRST = DRAW = true; Button_Draw.disable(); Button_Continue.disable(); Button_Stop.enable(); Label_Status.setText(""); start(); } if (e.target.equals(Button_Stop)){ Button_Draw.enable(); Button_Continue.enable(); Button_Stop.disable(); Thread_RUN.suspend(); } if (e.target.equals(Button_Continue)){ Button_Continue.disable(); Button_Stop.enable(); Thread_RUN.resume(); } return false; } public void set_CLEAR(boolean set){ CLEAR=set; } public void set_FIRST(boolean set){ FIRST=set; } public void set_NEXT(boolean set){ NEXT=set; } } // class logistic_map // class figure controls the plotting class figure extends Canvas{ logistic_map logistic; double X_min, X_max, Y_min, Y_max; int FIGURE_WIDTH, FIGURE_HEIGHT, AXES_WIDTH, AXES_HEIGHT, UNIT, AXES_LEFT, AXES_RIGHT, AXES_TOP, AXES_BOTTOM, AXES_X_0, AXES_X_1, AXES_Y_0, AXES_Y_1; final static boolean ANIMATION=true, NO_ANIMATION=false; figure (logistic_map initialize_map){ super(); logistic = initialize_map; } public void paint(Graphics g){ FIGURE_WIDTH=size().width; // the width of the Plot-window FIGURE_HEIGHT=size().height; // the height of the Plot-window AXES_HEIGHT= (int)(0.85*FIGURE_HEIGHT); // height and width of AXES_WIDTH = (int)(0.80*FIGURE_WIDTH); // the axes in the Plot-window AXES_LEFT = (int)(0.1*FIGURE_WIDTH); // left and right of AXES_RIGHT = AXES_LEFT+AXES_WIDTH; // the Plot-window AXES_TOP = (int)(0.075*FIGURE_WIDTH); // top and bottom of AXES_BOTTOM= AXES_TOP + AXES_HEIGHT; // Plot-window AXES_Y_1=(int)(0.2*FIGURE_HEIGHT); // the pixel for y=1 AXES_X_0=(int)(0.25*FIGURE_WIDTH); // the pixel for x=0 UNIT=(int)(0.6*FIGURE_HEIGHT); // the pixel for y in [0,1] AXES_Y_0=AXES_Y_1+UNIT; // the pixel for y=0 AXES_X_1=AXES_X_0 + UNIT; // the pixel for x=1 X_min=-((double)(AXES_BOTTOM-AXES_Y_0)/UNIT); // min(x) X_max=1+((double)(AXES_Y_1-AXES_TOP)/UNIT); // max(x) Y_min=-((double)(AXES_BOTTOM-AXES_Y_0)/UNIT); // min(y) Y_max=1+((double)(AXES_Y_1-AXES_TOP)/UNIT); // max(y) update(g); } public void update(Graphics g){ double X_t_0=logistic.X_t[0],X_t_1=logistic.X_t[1],X_t_2=logistic.X_t[2]; if (logistic.CLEAR){ // clears the plot-window logistic.set_CLEAR(false); coordinates(g); // draw coordinates plot_function(g); // draw the function } if (logistic.FIRST){ logistic.set_FIRST(false); cross(g,X_t_1,X_t_0); // put a cross at the startpoint draw(g,X_t_1,X_t_0,X_t_1,X_t_2,true); cross(g,X_t_1,X_t_2); logistic.set_NEXT(true); } else if (logistic.DRAW){ draw(g, X_t_0, X_t_1, X_t_1, X_t_1,ANIMATION); draw(g, X_t_1, X_t_1, X_t_1, X_t_2,ANIMATION); cross(g,X_t_1,X_t_2); logistic.set_NEXT(true); } } public void draw(Graphics g, double x0, double y0, double x1, double y1, boolean animate){ double dy; int x0_pix=x_pixel(x0), x1_pix=x_pixel(x1), y0_pix=y_pixel(y0), y1_pix=y_pixel(y1), dx,istep,i; if (x0_pix == x1_pix && y0_pix == y1_pix){ return; } else if (x0_pix != x1_pix){ istep=Math.abs(x0_pix-x1_pix); // total x-pix-step dy=(double)(y1_pix-y0_pix)/istep; dx=(x0_pix > x1_pix)? -1: 1; } else { istep=Math.abs(y0_pix-y1_pix); // total y-pix-step dx=0; dy=(y0_pix > y1_pix)? -1: 1; } g.setColor(Color.magenta); for (i=1; i<= istep; i++){ g.drawLine( (int)(x0_pix+(i-1)*dx),(int)(y0_pix+(i-1)*dy), (int)(x0_pix+i*dx),(int)(y0_pix+i*dy)); pause(animate); } g.setColor(Color.black); } public void plot_function(Graphics g){ double x1,y1,x2,y2,dx, interval_length=X_max-X_min; int interval_xpix_length=AXES_RIGHT-AXES_LEFT; dx=(double)interval_length/interval_xpix_length; for (int i=1; i<=interval_xpix_length; i++){ x1=X_min+(i-1)*dx; y1=logistic.f(x1); x2=x1+dx; y2=logistic.f(x2); if (y1>=Y_min && y2>=Y_min) draw(g,x1,y1,x2,y2,NO_ANIMATION); } } public void pause(boolean animate){ if (animate){ try { Thread.sleep(25);} // slows down the drawings with a tupplur catch ( InterruptedException e ) {} } } public void cross(Graphics g, double x, double y){ int x_pix=x_pixel(x),y_pix=y_pixel(y); g.setColor(Color.blue); g.drawLine(x_pix-1,y_pix-1,x_pix+1,y_pix+1); g.drawLine(x_pix-1,y_pix+1,x_pix+1,y_pix-1); g.setColor(Color.black); } public int x_pixel(double x){ int pixvalue=AXES_X_0+(int)((X_min%1)*UNIT); if (x>=X_min){ pixvalue=AXES_X_0 + (int)(x*UNIT); } return pixvalue; } public int y_pixel(double y){ int pixvalue=AXES_BOTTOM; if (y >= Y_min){ pixvalue=AXES_Y_0 - (int)(y*UNIT); } return pixvalue; } public double roundoff(double x, int n){ // returns the double x with n decmals return (double)(Math.round(x*Math.pow(10,n)))/Math.pow(10,n); } public void coordinates(Graphics g){ g.setColor(Color.white); g.fillRect(0,0,FIGURE_WIDTH,FIGURE_HEIGHT); g.setColor(Color.black); g.drawRect(0,0,FIGURE_WIDTH-1,FIGURE_HEIGHT-1); g.drawRect(AXES_X_0, AXES_Y_1, UNIT, UNIT); g.drawLine(AXES_LEFT,AXES_Y_0,AXES_RIGHT,AXES_Y_0); // draws the x-axes g.drawLine(AXES_X_0,AXES_TOP,AXES_X_0,AXES_BOTTOM); // draws the y-axes g.drawLine(x_pixel(X_min),y_pixel(Y_min),x_pixel(X_max),y_pixel(Y_max));// the diagonal x=y g.drawLine(x_pixel(X_min),AXES_Y_0-2,x_pixel(X_min),AXES_Y_0+2);// g.drawLine(x_pixel(X_max),AXES_Y_0-2,x_pixel(X_max),AXES_Y_0+2);// g.drawString(""+roundoff(X_min,2), (x_pixel(X_min)-12),AXES_Y_0+12); g.drawString(""+roundoff(X_max,2), x_pixel(X_max)-8, AXES_Y_0+12); g.drawString("X(t+1)",AXES_X_0+2,AXES_TOP-4); g.drawString("X(t)",AXES_RIGHT+2,AXES_Y_0+12); g.drawString("0",AXES_X_0+2,AXES_Y_0+12); g.drawString("1",AXES_X_0-8,AXES_Y_1+2); g.drawString("1",AXES_X_1-3,AXES_Y_0+12); } } // class figure