// Copyright 2004 by Richard Mansfield Kandarian // This program is licensed under the GPL. The GPL text is available at // http://www.opensource.org/licenses/gpl-license.php import java.awt.*; import java.awt.geom.GeneralPath; import java.awt.event.*; import java.awt.image.*; import java.net.*; import java.applet.*; import java.lang.*; import java.text.*; import java.util.*; class RouteTime extends Object{ double total; double bttotal; double num, den; double dt, btc, nbtc; int bt; public void init(int i){ num = i+1; den = i+2; total = 1 + 2*num/den; bttotal = total; bt=2; if(i > 0){ btc=1; dt = 1/num + 1/den; while(true){ if((nbtc = dt*(bt-1)+1/(double)bt) < btc){ btc = nbtc; bt++; continue; }else{ break; } } bttotal = total - (1 - btc); } } double total(){ return total; } double bttotal(){ return bttotal; } int backTrack(){ return bt-2; } } class GridSpeed extends Component{ Font labelFont; int fontHeight = 10; int lineHeight = fontHeight+2; int lm = 5*fontHeight; int tm = lineHeight; int rm = lm; int bm = 4*lineHeight; int pbm = 3*lineHeight; float lx = fontHeight/2; Graphics2D grid; int Size = 6; boolean initialized = false; int getGSize(){ return Size; } void setGSize(int size){ Size = size; } public void init(){ initialized = true; } final static float MARGIN = 10F/100F; final static float PLOT = 1F/3F; public void drawRoute(Graphics g1){ if(!initialized){ init(); } DecimalFormat lform = new DecimalFormat("#0.00"); RouteTime routeTime = new RouteTime(); Dimension d = getSize(); float side = d.width - lm - rm; if((tm + side + bm + side/4F + pbm) > d.height){ side = (float)(d.height - tm - bm - pbm)/(float)(1+1/4F); } float gw = lm + side + rm; float gh = tm + side + bm; labelFont = new Font("Helvetica", Font.PLAIN, fontHeight); Graphics2D g = (Graphics2D)g1; grid = g; g.setFont(labelFont); /* g.setColor(Color.darkGray); g.setColor(Color.white); */ g.setColor(Color.gray); g.fillRect(0, 0, (int)gw, (int)gh); float dx = side/(Size - 1); boolean noxlabel = false; if(dx < lm/2){ noxlabel = true; } boolean noylabel = false; if(dx < lineHeight){ noylabel = true; } boolean toobig = false; if(dx < 3){ toobig = true; } float xzero = lm; float yzero = tm + side; float plh = side/4F; float pyzero = gh + plh; GeneralPath plscale = new GeneralPath(); plscale.moveTo(xzero, (int)gh); plscale.lineTo(xzero, pyzero); plscale.lineTo(xzero+(int)side, pyzero); GeneralPath s1plot = new GeneralPath(); GeneralPath s2plot = new GeneralPath(); g.setColor(Color.white); g.fillRect(0, (int)gh, (int)gw, (int)(plh) + pbm); g.setColor(Color.black); g.drawString(lform.format(2.0), lx, pyzero + fontHeight/2); g.drawString(lform.format(3.0), lx, pyzero - plh + fontHeight); GeneralPath grid = new GeneralPath(); grid.moveTo(xzero, yzero); grid.lineTo(xzero, yzero-side); grid.lineTo(xzero+side, yzero-side); grid.lineTo(xzero+side, yzero); grid.closePath(); double sum1 = 0; double sum2 = 0; int ybt; GeneralPath route = new GeneralPath(); GeneralPath btroutex = new GeneralPath(); GeneralPath btroutey = new GeneralPath(); route.moveTo(xzero, yzero); s1plot.moveTo(xzero, pyzero); s2plot.moveTo(xzero, pyzero); if(toobig){ btroutex.moveTo(xzero, yzero); btroutey.moveTo(xzero, yzero); } float xinner = 0; float xouter = 0; float yinner = 0; float youter = 0; for(int i=0; i 0){ btroutex.moveTo(xinner, yzero); btroutex.lineTo(xinner, yzero - ybt*dx); btroutex.lineTo(xouter, yzero - ybt*dx); btroutex.lineTo(xouter, yzero); } if(!noylabel){ g.drawString(lform.format(sum1), lx, youter); g.drawString(lform.format(sum2), lx, youter + lineHeight); } }else{ route.lineTo(xzero, youter); route.lineTo(xouter, youter); route.lineTo(xouter, yzero); if((ybt = routeTime.backTrack()) > 0){ btroutey.moveTo(xzero, yinner); btroutey.lineTo(xzero + ybt*dx, yinner); btroutey.lineTo(xzero + ybt*dx, youter); btroutey.lineTo(xzero, youter); } if(!noxlabel){ g.drawString(lform.format(sum1), xouter, yzero+2*lineHeight); g.drawString(lform.format(sum2), xouter, yzero+3*lineHeight); } } }else{ ybt = routeTime.backTrack(); if(i%2 == 0){ btroutex.lineTo(xinner, yzero - ybt*dx); btroutex.lineTo(xouter, yzero - ybt*dx); }else{ btroutey.lineTo(xzero + ybt*dx, yinner); btroutey.lineTo(xzero + ybt*dx, youter); } } g.fillRect((int)xinner, (int)(gh-5), (int)(dx>1?dx+1:1), 3); } if(noylabel){ g.drawString(lform.format(sum1), lx, youter); g.drawString(lform.format(sum2), lx, youter + lineHeight); } BasicStroke gridstroke = new BasicStroke(dx/10, BasicStroke.CAP_BUTT, BasicStroke.JOIN_ROUND); BasicStroke routestroke = new BasicStroke(dx/20, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); BasicStroke btroutestroke = new BasicStroke(dx/40, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); BasicStroke plscalestroke = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); BasicStroke s1plotstroke = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); BasicStroke s2plotstroke = new BasicStroke(1, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND); /* g.setColor(Color.black); */ g.setColor(Color.lightGray); g.setStroke(gridstroke); g.draw(grid); g.setColor(Color.red); g.setStroke(routestroke); g.draw(route); g.setColor(Color.blue); g.setStroke(btroutestroke); g.draw(btroutex); g.draw(btroutey); g.setColor(Color.black); g.setStroke(plscalestroke); g.draw(plscale); g.setColor(Color.blue); g.setStroke(s2plotstroke); g.draw(s2plot); g.setColor(Color.red); g.setStroke(s1plotstroke); g.draw(s1plot); } public void paint(Graphics g1){ drawRoute(g1); } } public class GridSpeedApplet extends Applet implements ActionListener { GridSpeed gridSpeed; TextField sf; public void init(){ String param = getParameter("SIZE"); if(param != null){ gridSpeed.setGSize(Integer.parseInt(param)); sf.setText(param); }else{ gridSpeed.setGSize(6); sf.setText("6"); } sf.selectAll(); } public GridSpeedApplet(){ setLayout(new BorderLayout()); add("Center", gridSpeed = new GridSpeed()); Panel p = new Panel(); p.setLayout(new FlowLayout()); add ("South", p); p.add("West", new Label("Enter grid size, >1 and <=100000:")); sf = new TextField(6); sf.addActionListener(this); p.add("West", sf); } public void itemStateChanged(ItemEvent e){ String item = (String)(e.getItem()); } public void actionPerformed(ActionEvent e){ String sizetext = e.getActionCommand(); int size = gridSpeed.getGSize(); boolean valid = false; try{ size = Integer.parseInt(sizetext); if(size > 1 && size <= 100000){ gridSpeed.setGSize(size); gridSpeed.repaint(); } }catch(NumberFormatException nfe){} sf.selectAll(); } public static void main(String args[]){ Frame f = new Frame("Grid Speed"); GridSpeedApplet gridSpeedApplet = new GridSpeedApplet(); f.add("Center", gridSpeedApplet); f.pack(); f.setVisible(true); gridSpeedApplet.init(); gridSpeedApplet.start(); } }