import java.applet.Applet; import java.awt.*; import java.lang.Math; import java.awt.event.*; /* Stefan Emet 1998. A tool for plotting orbits of 2-dimensional discrete dynamical systems. class two_dim controls the main-frame */ public class two_dim extends Applet implements Runnable, ActionListener{ double X_0=3.0, Y_0=1.5, a=0.5, b=0.4; double[] X_t = new double[3], Y_t = new double[3]; int time=0; Figure Figure_plot; Panel Panel_top, Panel_top_f, Panel_top_input, Panel_right, Panel_bottom; Label Label_Status; TextField TextField_parameter_a, TextField_parameter_b, TextField_X_0, TextField_Y_0; Button Button_Draw, Button_Stop, Button_Continue; Checkbox Checkbox_trace; Thread Thread_RUN=null; // run -controller boolean CLEAR, FIRST, DRAW, NEXT=false, TRACES=true; public void init(){ setLayout(new BorderLayout(5,5)); // sets the main-border Panel_top = new Panel(); Panel_top_f = new Panel(); Panel_top_f.setLayout(new GridLayout(2,1,2,2)); Panel_top_f.add(new Label("X(t+1) = a X(t) + b Y(t)")); Panel_top_f.add(new Label("Y(t+1) = X(t) , t = 0, 1, 2 ...")); Panel_top.add(Panel_top_f); Panel_top_input = new Panel(); Panel_top_input.setLayout(new GridLayout(2,4,2,2)); Panel_top_input.add(new Label(" a:")); Panel_top_input.add(TextField_parameter_a= new TextField(""+a,3)); Panel_top_input.add(new Label(" X(0) :")); Panel_top_input.add(TextField_X_0= new TextField(""+X_0,3)); Panel_top_input.add(new Label(" b:")); Panel_top_input.add(TextField_parameter_b= new TextField(""+b,3)); Panel_top_input.add(new Label(" Y(0) :")); Panel_top_input.add(TextField_Y_0= new TextField(""+Y_0,3)); Panel_top.add(Panel_top_input); add("North",Panel_top); // layout to the top of main border 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")); Button_Draw.addActionListener(this); Button_Stop.addActionListener(this); Button_Continue.addActionListener(this); Panel_right.add(new Label(" ")); Panel_right.add(Checkbox_trace = new Checkbox("Traces",true)); add("East",Panel_right); // layout to the right of main border Panel_bottom = new Panel(); Panel_bottom.add(Label_Status = new Label("Status - label")); add("South",Panel_bottom); // layout to the bottom of main border Figure_plot = new Figure(this); add("Center",Figure_plot); // the plottings/drawings in the middle } public void run() { read_values(); // reads values from input-fields X_t[0]=0; X_t[1]=X_0; // sets the values Y_t[0]=0; Y_t[1]=Y_0; X_t[2]=f(X_0,Y_0)[0]; // calculates: Y_t[2]=f(X_0,Y_0)[1]; // {x(1),y(1)} = f(x(0),y(0)) time=1; while (DRAW){ Figure_plot.repaint(); wait_for_next(); // wait until the drawing is done X_t[0]=X_t[1];X_t[1]=X_t[2];// shifts the previous values Y_t[0]=Y_t[1];Y_t[1]=Y_t[2]; X_t[2]=f(X_t[1],Y_t[1])[0]; // calculates: Y_t[2]=f(X_t[1],Y_t[1])[1]; // {x(t+1),y(t+1)} = f(x(t),y(t)) time++; } } private void wait_for_next(){ while (!NEXT) {;} NEXT=false; } public double[] f(double x, double y){ double[] x_y=new double[2]; x_y[0]=a*x+b*y; x_y[1]=x; return x_y; } public double[] det(){// returns the determinants of a 2*2-matrix double[] determinant=new double[2]; determinant[0]=(double)(a+Math.sqrt(Math.pow(a,2)+4*b))/2; determinant[1]=(double)(a-Math.sqrt(Math.pow(a,2)+4*b))/2; return determinant; } public void read_values(){// reads the input-values a = Double.valueOf(TextField_parameter_a.getText()).doubleValue(); b = Double.valueOf(TextField_parameter_b.getText()).doubleValue(); X_0 = Double.valueOf(TextField_X_0.getText()).doubleValue(); Y_0 = Double.valueOf(TextField_Y_0.getText()).doubleValue(); TRACES=Checkbox_trace.getState();// checks whether checkbox is selected } public void start(){ CLEAR=true; if (Thread_RUN==null){ Thread_RUN=new Thread(this); } Thread_RUN.start(); } public void stop(){ Thread_RUN=null; } public void actionPerformed(ActionEvent e){ Object source=e.getSource(); if (source==Button_Draw){ stop(); FIRST=DRAW=true; NEXT=false; Button_Draw.setEnabled(false); Button_Continue.setEnabled(false); Button_Stop.setEnabled(true); start(); } if (source==Button_Stop){ Button_Draw.setEnabled(true); Button_Continue.setEnabled(true); Button_Stop.setEnabled(false); Thread_RUN.suspend(); } if (source==Button_Continue){ Button_Continue.setEnabled(false); Button_Stop.setEnabled(true); Thread_RUN.resume(); } } public void set_CLEAR(boolean set){ CLEAR=set; } public void set_FIRST(boolean set){ FIRST=set; } public void set_NEXT(boolean set){ NEXT=set; } } // end of class two_dim // class Figure controls the plotting class Figure extends Canvas{ two_dim two_dim_fig; double X_min, X_max, Y_min, Y_max; int FIGURE_WIDTH, FIGURE_HEIGHT, AXES_LEFT, AXES_RIGHT, AXES_TOP, AXES_BOTTOM, AXES_WIDTH, AXES_HEIGHT, X_unit, Y_unit; final static boolean ANIMATION=true, NO_ANIMATION=false; Figure (two_dim f){ super(); two_dim_fig = f; } public void paint(Graphics g){ double x_part=0.8, y_part=0.85; FIGURE_WIDTH=getSize().width; // the width of the Plot-window (Canvas) FIGURE_HEIGHT=getSize().height; // the height of the Plot-window (Canvas) AXES_HEIGHT=(int)(y_part*FIGURE_HEIGHT);// height and width of AXES_WIDTH= (int)(x_part*FIGURE_WIDTH); // the axes in the Plot-window AXES_LEFT= (int)((1-x_part)/2*FIGURE_WIDTH);// the left of the axes AXES_RIGHT= (int)((1+x_part)/2*FIGURE_WIDTH);// the right of the axes AXES_TOP= (int)((1-y_part)/2*FIGURE_HEIGHT);// the top AXES_BOTTOM=(int)((1+y_part)/2*FIGURE_HEIGHT);// the bottom update(g); } public void update(Graphics g){ double[] X_t=two_dim_fig.X_t, // copy the values from Y_t=two_dim_fig.Y_t; // class two_dim if (two_dim_fig.CLEAR){ two_dim_fig.set_CLEAR(false); range(); coordinates(g); } if (two_dim_fig.FIRST){ two_dim_fig.set_FIRST(false); cross(g,X_t[1],Y_t[1]); // puts a cross at the startpoint: (x(0),y(0)) draw(g,X_t[1],Y_t[1],X_t[2],Y_t[2],ANIMATION); // draw a line between the points cross(g,X_t[2],Y_t[2]); // a cross at (x(1),y(1)) two_dim_fig.set_NEXT(true);// indicates that the drawing is done } else if (two_dim_fig.DRAW){ draw(g,X_t[1],Y_t[1],X_t[2],Y_t[2],ANIMATION); // draw a line between the points cross(g,X_t[2],Y_t[2]); // a cross at (x(1),y(1)) two_dim_fig.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); } if (!two_dim_fig.TRACES){ g.setColor(Color.white); 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 pause(boolean animate){ if (animate){ try { Thread.sleep(25);}// slows down the drawings 25 milliseconds catch ( InterruptedException e ) {} } } public void range(){ // determines the range of the axis double det_min, det_min_abs, det_max, det_max_abs; det_min=Math.min(two_dim_fig.det()[0],two_dim_fig.det()[1]); det_max=Math.max(two_dim_fig.det()[0],two_dim_fig.det()[1]); det_min_abs=Math.abs(det_min); // the absolute values det_max_abs=Math.abs(det_max); // of the determinants if (det_max_abs <= 1){ X_max=Math.abs(two_dim_fig.X_0)+1; X_min=-X_max; Y_max=Math.abs(two_dim_fig.Y_0)+1; Y_min=-Y_max; } else if (det_min_abs > 1 || det_max_abs >1){ X_max=1000; X_min=-10; Y_max=1000; Y_min=-10; } //two_dim_fig.showStatus("X: "+X_min+ " : "+X_max+" , Y: "+Y_min+" : "+Y_max); //two_dim_fig.Label_Status.setText("Det: "+roundoff(det_min,2)+" | "+roundoff(det_max,2)); } 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 void coordinates(Graphics g){ double x0=two_dim_fig.X_0, y0=two_dim_fig.Y_0; 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); // draws the frame around the head border g.drawRect(AXES_LEFT,AXES_TOP,AXES_WIDTH,AXES_HEIGHT);// frame around the plot-window g.drawLine(x_pixel(x0),y_pixel(Y_min)+2,x_pixel(x0),y_pixel(Y_min)-2);// tickmark at g.drawString(""+roundoff(x0,2),x_pixel(x0)-10,y_pixel(Y_min)+12); // x(0) g.drawLine(x_pixel(X_min)-2,y_pixel(y0),x_pixel(X_min)+2,y_pixel(y0));// tickmark at g.drawString(""+roundoff(y0,2),x_pixel(X_min)-25,y_pixel(y0)+5); // y(0) g.drawString("Y",x_pixel(X_min)+1,y_pixel(Y_max)-4); // Y-axis label g.drawString("X",x_pixel(X_max)+4,y_pixel(Y_min)+5); // X-axis label } 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 int x_pixel(double x){ int pixvalue=AXES_LEFT; if (x>=X_min && x<=X_max){ pixvalue=(int)(((double)(x-X_min)/(X_max-X_min))*AXES_WIDTH)+AXES_LEFT; } return pixvalue; } public int y_pixel(double y){ int pixvalue=AXES_BOTTOM; if (y>=Y_min && y<=Y_max){ pixvalue=AXES_BOTTOM-(int)(((double)(y-Y_min)/(Y_max-Y_min))*AXES_HEIGHT); } return pixvalue; } } // end of class Figure