//Mike Piff, CICS, University of Sheffield (1997) import java.applet.*; import java.awt.*; public class RungeKutta extends Applet implements Runnable { private static final int fieldWidth=8;//width of numeric fields private Cartesian lowPoint=new Cartesian(-1.1,-1.1), highPoint=new Cartesian(1.1,1.1); public Cartesian initPoint=new Cartesian(-1.0,0.0,1.0); private long steps=1000; private double h; int order=2; private Choice rkChoice,orderSelector; private Panel panf; private Panel controlPanel; private Panel graphPanel; private Panel panLowX,panHighX; private Label labLowX,labHighX; private TextField textLowX,textHighX; private Panel panLowY,panHighY; private Label labLowY,labHighY; private TextField textLowY,textHighY,textSteps;; private TextField textFunction; private Panel panInitX,panInitY,panInitdydx,panSteps; private Label labInitX,labInitY,labInitdydx,labSteps; public TextField textInitX,textInitY,textInitdydx; private Button clearButton,drawButton; private Panel navPanel; private Button upButton,downButton,leftButton,rightButton, magButton,redButton; private Graph graph;//Where graph is drawn private Scrollbar hScrollbar,vScrollbar; public Dimension graphDim; public int graphBorder=20; private Thread runner; private FunctionParse fn; private String independentvariable="x",dependentvariable="y", firstderivativealias="z"; public void init() { independentvariable=processStringParameter("X",independentvariable); dependentvariable=processStringParameter("Y",dependentvariable); firstderivativealias=processStringParameter("D",firstderivativealias); initPoint.x=processParameter("INITX",initPoint.x); initPoint.y=processParameter("INITY",initPoint.y); initPoint.z=processParameter("INITD",initPoint.z); lowPoint.y=processParameter("LOWY",lowPoint.y); highPoint.y=processParameter("HIGHY",highPoint.y); highPoint.x=processParameter("HIGHX",highPoint.x); lowPoint.x=processParameter("LOWX",lowPoint.x); steps=(long)(processParameter("STEPS",steps)); controlPanel=new Panel(); controlPanel.setLayout(new GridLayout(0,1)); graphPanel=new Panel(); graphPanel.setLayout(new BorderLayout()); setLayout(new BorderLayout()); initButtons(); initGraph(); initPanX(); initPanY(); initPanInit(); add("West",controlPanel); } public void start() { reStart(); } private double processParameter(String s,double dflt){ String tmp; double tmpFloat=dflt; tmp=getParameter(s); if (tmp != null) { try {tmpFloat=interpret(tmp);} catch(NumberFormatException e) {tmpFloat=dflt;} } return tmpFloat; } private String processStringParameter(String s,String dflt){ String tmp=getParameter(s); if (tmp==null) return dflt; else return tmp; } public synchronized void drawGraph(){ reInitialise(); System.gc(); if (runner!=null) runner.stop(); runner=new Thread(this); runner.start(); } public synchronized void reStart(){ if (runner!=null) runner.stop(); reInitialise(); System.gc(); graph.drawAxes(); drawGraph(); } boolean firstIteration=true; public void run(){ Graphics g=graph.getGraphics(); g.clipRect(graphBorder,graphBorder,graphDim.width-2*graphBorder,graphDim.height-2*graphBorder); int rkOrder=rkChoice.getSelectedIndex(); order=orderSelector.getSelectedIndex(); Cartesian currPoint=new Cartesian(initPoint); Cartesian oldPoint=new Cartesian(initPoint); //System.out.println(initPoint.toString()); firstIteration=true; while (currPoint.x10){ while (temp>10) { temp/=10; step*=10; } } else { while (temp<=1){ temp*=10; step/=10; } } return step; } private String shorten(double x){ String tmp=new Double(x).toString(); if ((tmp.indexOf('E')<0)&&(tmp.length()>8)){ tmp=new String(new Double(tmp.substring(0,7)).toString()); } return tmp; } public String curtail(String s){ if (s.length()>fieldWidth) return s.substring(0,8); else return s; } private void drawXLine(Graphics g,double xx,boolean labelIt){ int x=screenX(xx); if ((x>=graphBorder)&&(x<=graphDim.width-graphBorder)){ g.drawLine(x,graphBorder,x,graphDim.height-graphBorder); if (labelIt) { String tmp=shorten(xx); g.drawString(tmp,x,graphDim.height); } } } private void drawXLine(Graphics g,double xx){ drawXLine(g,xx,true); } private void drawYLine(Graphics g,double yy,boolean labelIt){ int y=screenY(yy); if ((y>=graphBorder)&&(y<=graphDim.height-graphBorder)){ g.drawLine(graphBorder,y,graphDim.width-graphBorder,y); if (labelIt){ String tmp=shorten(yy); g.drawString(tmp,0,y); } } } private void drawYLine(Graphics g,double yy){ drawYLine(g,yy,true); } private void whiten(Graphics g){ //System.out.println("whiten()"); Color c=g.getColor(); g.setColor(Color.orange); g.clipRect(0,0,graphDim.width,graphDim.height); g.fillRect(0,0,graphDim.width,graphDim.height); g.setColor(c); } private int screenX(double x){ return graphBorder+(int)((graphDim.width-2*graphBorder)*(x-lowPoint.x)/(highPoint.x-lowPoint.x)); } public double graphX(int x){ return (float)lowPoint.x+x*(highPoint.x-lowPoint.x)/(graphDim.width-2*graphBorder); } private int screenY(double y){ return graphBorder+(int)((graphDim.height-2*graphBorder)*(1.0-(double)(y-lowPoint.y)/(highPoint.y-lowPoint.y))); } public double graphY(int y){ return (double)highPoint.y+y*(lowPoint.y-highPoint.y)/(graphDim.height-2*graphBorder); } private synchronized double f(double x,double y,double z){ return fn.evaluate(x,y,z); } private synchronized double f(double x,double y){ return fn.evaluate(x,y); } private synchronized double f(double x){ return fn.evaluate(x); } public void checkScroll(){ int i; if ((i=hScrollbar.getValue())!=50) shift(new Cartesian((highPoint.x-lowPoint.x)*(-0.5+i/100.0),0)); if ((i=vScrollbar.getValue())!=50) shift(new Cartesian(0,(highPoint.y-lowPoint.y)*(0.5-i/100.0))); } public boolean action(Event e,Object o){ if (e.target == drawButton){ drawGraph(); return true; } else if (e.target==clearButton){ if (runner!=null) runner.stop(); //reInitialise(); checkScroll(); reCenter(); graph.drawAxes(); return true; } else if (e.target==magButton) { Cartesian lPoint =new Cartesian(lowPoint,highPoint,7,1); Cartesian hPoint =new Cartesian(lowPoint,highPoint,1,7); lowPoint=lPoint; highPoint=hPoint; reCenter(); graph.repaint(); return true; } else if (e.target==redButton) { Cartesian lPoint =new Cartesian(lowPoint,highPoint,7,-1); Cartesian hPoint =new Cartesian(lowPoint,highPoint,-1,7); lowPoint=lPoint; highPoint=hPoint; reCenter(); graph.repaint(); return true; } else if (e.target==downButton) { shift(new Cartesian(0,-0.25*(highPoint.y-lowPoint.y))); reCenter(); graph.repaint(); return true; } else if (e.target==upButton) { shift(new Cartesian(0,0.25*(highPoint.y-lowPoint.y))); reCenter(); graph.repaint(); return true; } else if (e.target==leftButton) { shift(new Cartesian(-0.25*(highPoint.x-lowPoint.x),0)); reCenter(); graph.repaint(); return true; } else if (e.target==rightButton) { shift(new Cartesian(0.25*(highPoint.x-lowPoint.x),0)); reCenter(); graph.repaint(); return true; } else if (e.target==orderSelector){ order=orderSelector.getSelectedIndex(); switch (order) { case 0: textInitY.disable(); textInitdydx.disable(); rkChoice.disable(); break; case 1: textInitY.enable(); textInitdydx.disable(); rkChoice.enable(); break; case 2: textInitY.enable(); textInitdydx.enable(); rkChoice.enable(); break; } } return false; } private void shift(Cartesian c){ lowPoint.x+=c.x; lowPoint.y+=c.y; highPoint.x+=c.x; highPoint.y+=c.y; reCenter(); } private void reCenter(){ textLowX.setText(curtail(String.valueOf(lowPoint.x))); textLowY.setText(curtail(String.valueOf(lowPoint.y))); textHighX.setText(curtail(String.valueOf(highPoint.x))); textHighY.setText(curtail(String.valueOf(highPoint.y))); } private void reInitialise(){ fn=new FunctionParse(textFunction.getText().trim(),independentvariable,dependentvariable,firstderivativealias); highPoint.x=interpret(textHighX.getText()); highPoint.y=interpret(textHighY.getText()); initPoint.x=interpret(textInitX.getText()); order=orderSelector.getSelectedIndex(); switch (order){ case 0: initPoint.y=f(initPoint.x); textInitY.setText(curtail(String.valueOf(initPoint.y))); break; case 1: initPoint.y=interpret(textInitY.getText()); break; case 2: initPoint.y=interpret(textInitY.getText()); initPoint.z=interpret(textInitdydx.getText()); break; } lowPoint.x=interpret(textLowX.getText()); lowPoint.y=interpret(textLowY.getText()); steps=(long)interpret(textSteps.getText()); h=(highPoint.x-lowPoint.x)/steps; int scrollSize=50; hScrollbar.setValue(scrollSize); vScrollbar.setValue(scrollSize); validate(); graphDim=new Dimension(graph.size()); } private double interpret(String s){ FunctionParse f=new FunctionParse(s,independentvariable,dependentvariable,firstderivativealias); return f.evaluate(); } private double convert(String s){ Double d=new Double(s); return d.doubleValue(); } private void initGraph(){ graph=new Graph(this,independentvariable,dependentvariable); graphPanel.add("Center",graph); hScrollbar=new Scrollbar(Scrollbar.HORIZONTAL,50,1,0,100); vScrollbar=new Scrollbar(Scrollbar.VERTICAL,50,1,0,100); graphPanel.add("South",hScrollbar); graphPanel.add("East",vScrollbar); graphPanel.add("North",navPanel); add("Center",graphPanel); panf=new Panel(); panf.add(new Label("The graph of ")); orderSelector=new Choice(); orderSelector.addItem(dependentvariable); orderSelector.addItem("d"+dependentvariable+"/d"+independentvariable); orderSelector.addItem("d^2"+dependentvariable+"/d"+independentvariable+"^2"); panf.add(orderSelector); order=(int)processParameter("ORDER",1); order=Math.max(order,0); order=Math.min(order,2); orderSelector.select(order); panf.add(new Label("=")); textFunction=new TextField(getParameter("FUNCTION"),40); panf.add(textFunction); rkChoice=new Choice(); rkChoice.addItem("RungeKutta of order 2"); rkChoice.addItem("RungeKutta of order 4"); panf.add(rkChoice); add("North",panf); } private void initPanY(){ panLowY=new Panel(); labLowY=new Label(" Low "+dependentvariable+"="); panLowY.add(labLowY); textLowY=new TextField(fieldWidth); textLowY.setText(curtail(String.valueOf(lowPoint.y))); panLowY.add(textLowY); controlPanel.add(panLowY); panHighY=new Panel(); labHighY=new Label(" High "+dependentvariable+"="); panHighY.add(labHighY); textHighY=new TextField(fieldWidth); textHighY.setText(curtail(String.valueOf(highPoint.y))); panHighY.add(textHighY); controlPanel.add(panHighY); } private void initPanX(){ panLowX=new Panel(); labLowX=new Label(" Low "+independentvariable+"="); panLowX.add(labLowX); textLowX=new TextField(fieldWidth); textLowX.setText(curtail(String.valueOf(lowPoint.x))); panLowX.add(textLowX); controlPanel.add(panLowX); panHighX=new Panel(); labHighX=new Label(" High "+independentvariable+"="); panHighX.add(labHighX); textHighX=new TextField(fieldWidth); textHighX.setText(curtail(String.valueOf(highPoint.x))); panHighX.add(textHighX); controlPanel.add(panHighX); } private void initPanInit(){ panInitX=new Panel(); labInitX=new Label(" Init "+independentvariable+"="); panInitX.add(labInitX); textInitX=new TextField(fieldWidth); textInitX.setText(curtail(String.valueOf(initPoint.x))); panInitX.add(textInitX); controlPanel.add(panInitX); panInitY=new Panel(); labInitY=new Label(" Init "+dependentvariable+"="); panInitY.add(labInitY); textInitY=new TextField(fieldWidth); textInitY.setText(curtail(String.valueOf(initPoint.y))); panInitY.add(textInitY); controlPanel.add(panInitY); panInitdydx=new Panel(); labInitdydx=new Label(" Init d"+dependentvariable+"/d"+independentvariable+"="); panInitdydx.add(labInitdydx); textInitdydx=new TextField(fieldWidth); textInitdydx.setText(curtail(String.valueOf(initPoint.z))); panInitdydx.add(textInitdydx); controlPanel.add(panInitdydx); panSteps=new Panel(); labSteps=new Label(" Steps="); panSteps.add(labSteps); textSteps=new TextField(fieldWidth); textSteps.setText(String.valueOf(steps)); panSteps.add(textSteps); controlPanel.add(panSteps); } private void initButtons(){ navPanel=new Panel(); upButton=new Button("Up"); downButton=new Button("Down"); leftButton=new Button("Left"); rightButton=new Button("Right"); magButton=new Button("Magnify"); redButton=new Button("Reduce"); drawButton=new Button("Draw"); drawButton.setForeground(Color.red); clearButton=new Button("Clear"); clearButton.setForeground(Color.red); navPanel.add(upButton); navPanel.add(downButton); navPanel.add(leftButton); navPanel.add(rightButton); navPanel.add(magButton); navPanel.add(redButton); navPanel.add(drawButton); navPanel.add(clearButton); } }