/* Copyright F. P. Marin ( Sun June 08 17:15:21 1997 ) E-mail: felix@bloch.ciens.ucv.ve Permission to use, copy, modify and distribute this software and its documentation for NON-COMERCIAL purposes and without fee is hereby granted provided that this copyright notice appears in all copies. F. P. Marin makes no representations or warranties about the suitability of the software, either express or implied, including but no limited to the implied warranties of merchantability, fitness for a particular purpose, or non-infringement. F. P. Marin shall not be liable for any damage suffered by license as a result of using, modifying or distributing this software or its derivatives. HTML code is */ import java.awt.*; public class Lorenz extends java.applet.Applet implements Runnable { final double BETA=2.7,RHO=26.0,SIGMA=10.0; // Lorenz parameters final double X0=0.1,Y0=(-0.1),Z0=0.1; // Initial position final double DT=0.75; boolean clear=false; Color col=Color.yellow.brighter(); double beta=BETA,rho=RHO,sigma=SIGMA; double x0=X0,y0=Y0,z0=Z0; double ax,bx,ay,by,xeq,zeq; Font f=new Font("TimesRoman",Font.BOLD,18); FontMetrics fm=getFontMetrics(f); Graphics grphcs; Image img; int delay=100,xeqtn[]=new int[3],yeqtn,xlast,ylast,xd,yd; NorthPanel np=new NorthPanel(this); SouthPanel sp=new SouthPanel(this); String eqtn[]={"dx/dt = s(y - x)","dy/dt = rx - y - xz", "dz/dt = -bz + xy"}; Thread lrnzthread=null; public void init() { setLayout(new BorderLayout()); add("North",np); add("South",sp); xeqtn[0]=(int)(0.5*(size().width/3.0 - fm.stringWidth(eqtn[0]) + 1)); xeqtn[1]=(int)(0.5*(size().width - fm.stringWidth(eqtn[1]) + 1)); xeqtn[2]=(int)(0.5*(5.0*size().width/3.0 - fm.stringWidth(eqtn[2]) + 1)); yeqtn=(int)(2.5*fm.getAscent() + 0.5); img=createImage(size().width,size().height); grphcs=img.getGraphics(); update(); } public void start() { if ( lrnzthread==null ) { lrnzthread=new Thread(this); lrnzthread.start(); } } public void run() { double dt,sum,temp,vx,vy,vz,x,y,z; int i=0; x=x0; y=y0; z=z0; xlast=(int)(ax*x + bx + 0.5); ylast=(int)(ay*y + by + 0.5); do { vx=sigma*(y - x); dt=Math.abs(vx); vy=rho*x - y - x*z; temp=Math.abs(vy); if ( temp>dt ) dt=temp; vz=x*y - beta*z; temp=Math.abs(vz); if ( temp>dt ) dt=temp; if ( dt>0.0 ) { temp=vx/dt; sum=temp*temp; temp=vy/dt; sum+=temp*temp; temp=vz/dt; sum+=temp*temp; dt*=Math.sqrt(sum); dt=DT/dt; } else break; x+=vx*dt; y+=vy*dt; z+=vz*dt; xd=(int)(ax*x + bx + 0.5); yd=(int)(ay*y + by + 0.5); if ( ++i==1000 ) { col=randColor(); i=0; } repaint(); try { Thread.sleep(delay); } catch ( InterruptedException ie ) {} } while ( true ); } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { if ( !clear ) { grphcs.setColor(Color.white.brighter()); grphcs.setFont(f); grphcs.drawString(eqtn[0],xeqtn[0],yeqtn); grphcs.drawString(eqtn[1],xeqtn[1],yeqtn); grphcs.drawString(eqtn[2],xeqtn[2],yeqtn); grphcs.setColor(col); grphcs.drawLine(xlast,ylast,xd,yd); xlast=xd; ylast=yd; } else { grphcs.setColor(Color.black); grphcs.fillRect(0,0,size().width,size().height); clear=false; } g.drawImage(img,0,0,this); } public void stop() { if ( lrnzthread!=null ) { lrnzthread.stop(); lrnzthread=null; } } public void defaultValues() { beta=BETA; rho=RHO; sigma=SIGMA; x0=X0; y0=Y0; z0=Z0; sp.sl[0].update(rho); sp.sl[1].update(x0); sp.sl[2].update(beta); sp.sl[3].update(y0); sp.sl[4].update(sigma); sp.sl[5].update(z0); } public void drawCircle(Graphics g,int x,int y,int radius) { g.fillOval(x - radius,y - radius,2*radius,2*radius); } public boolean mouseDown(Event e,int x,int y) { if ( lrnzthread!=null ) { lrnzthread.stop(); lrnzthread=null; } else { update(); col=randColor(); lrnzthread=new Thread(this); lrnzthread.start(); } return true; } public Color randColor() { int r,g,b; do { r=(int)(256.0*Math.random()); g=(int)(256.0*Math.random()); b=(int)(256.0*Math.random()); } while ( ( r==0 ) && ( g==0 ) && ( b==0 ) ); return new Color(r,g,b).brighter(); } public void update() { int x=(int)(0.5*(size().width - 3.0)); int y=(int)(0.5*(size().height - 3.0)); grphcs.setColor(Color.black); grphcs.fillRect(0,0,size().width,size().height); grphcs.setColor(col); drawCircle(grphcs,x,y,2); zeq=rho - 1.0; if ( zeq>0.0 ) { xeq=Math.sqrt(beta*zeq); bx=0.5*size().width; ax=0.25*bx/xeq; by=0.5*size().height; ay=(-0.25*by/xeq); x=(int)(ax*xeq + bx + 0.5); y=(int)(ay*xeq + by + 0.5); drawCircle(grphcs,x,y,3); x=(int)(-ax*xeq + bx + 0.5); y=(int)(-ay*xeq + by + 0.5); drawCircle(grphcs,x,y,3); } else zeq=0.0; } } class NorthPanel extends Panel { Button minus=new Button("Delay -10"),plus=new Button("Delay +10"); Label delayval; Lorenz mother; public NorthPanel(Lorenz mother) { super(); setLayout(new GridLayout(1,6)); this.mother=mother; add(new Button("Clear")); add(new Button("Default")); add(new Button("Change Color")); add(minus); add(plus); delayval=new Label("Delay = " + this.mother.delay,Label.CENTER); add(delayval); } public boolean action(Event e,Object o) { if ( e.target instanceof Button ) { String s=(String)o; if ( !s.equals("Change Color") ) { if ( s.equals("Clear") ) { mother.stop(); mother.clear=true; mother.repaint(); } else if ( s.equals("Default") ) { mother.stop(); mother.defaultValues(); mother.col=mother.randColor(); mother.lrnzthread=new Thread(mother); mother.lrnzthread.start(); } else { if ( s.equals(plus.getLabel()) ) mother.delay+=10; else mother.delay-=10; // if ( mother.delay<100 ) mother.delay=100; delayval.setText("Delay = " + mother.delay); } } else mother.col=mother.randColor(); } return true; } } class Slider extends Panel { final static double MIN=0.0,MAX=100.0; double slope,val; int sbmax,sbmin; Label l=new Label(); SouthPanel mother; Scrollbar sb=new Scrollbar(Scrollbar.HORIZONTAL,0,5,0,1000); public Slider(String name,SouthPanel mother) { super(); setLayout(new GridLayout(1,3)); this.mother=mother; setFont(new Font("Helvetic",Font.BOLD + Font.ITALIC,14)); add(new Label(name + " ",Label.RIGHT)); add(sb); add(l); sbmax=sb.getMaximum(); sbmin=sb.getMinimum(); slope=(MAX - MIN)/(sbmax - sbmin); } public boolean handleEvent(Event e) { val=MIN + slope*(sb.getValue() - sbmin); if ( valMAX ) val=MAX; l.setText(" " + String.valueOf(val)); mother.update(this); return true; } public void update(double someval) { if ( somevalMAX ) someval=MAX; val=someval; int sbval=(int)(sbmin + (someval - MIN)/slope + 0.5); if ( sbvalsbmax ) sbval=sbmax; sb.setValue(sbval); l.setText(" " + String.valueOf(someval)); } } class SouthPanel extends Panel { Lorenz mother; Slider sl[]=new Slider[6]; public SouthPanel(Lorenz mother) { super(); setBackground(Color.blue.darker()); setForeground(Color.white.brighter()); setLayout(new GridLayout(3,2)); this.mother=mother; String s[]={"Rho","x0","Beta","y0","Sigma","z0"}; int i; for ( i=0 ; i