/* * fhmr.java - revised 8 Apr 05 - width 451, height 271 * latest revision plots trajectories with and without air resistance and * cleans up choice between finding range and showing motion * on replot, the motion is shown in real time * @author jackord@kw.igs.net */ import java.applet.Applet; import java.awt.*; import java.awt.event.ActionListener; import java.awt.event.ActionEvent; public class fhmr extends Applet implements ActionListener { int phi; int kk=0; int rr=0; int show=0; // Declarations double gr, vi, k, ax, ay, t, cf, cmph; double dt=.01; String b1s="Range"; Button b1=new Button(b1s); String b2s="Motion"; Button b2=new Button(b2s); Image aim, bim; Graphics agr, bgr; public void init() { setLayout(new FlowLayout(FlowLayout.LEFT)); add(b1); add(b2); b1.addActionListener(this); b2.addActionListener(this); setBackground(new Color(211, 211, 211)); // Light Gray Background } double hit(Graphics g) { // Feynman Algorithm int x1, y1, x2, y2, xx1, yy1, xx2, yy2, r; long tt=0; double x, y, q, vx, vy, dvx, dvy, xx, yy, vxx, vyy; x=0; y=0; q=phi*Math.PI/18000; x1=0; y1=270; xx1=x1; yy1=225; r=5; vx=vi*Math.cos(q); vy=vi*Math.sin(q); t=0; vxx=vx; vyy=vy; acc(vx, vy); dvx=ax*dt; dvy=ay*dt; vx=vx+dvx/2; vy=vy+dvy/2; if (kk==2) { tt=System.currentTimeMillis(); } do { t=t+dt; x=x+vx*dt; y=y+vy*dt; x2=(int)(cf*x); y2=(int)(270-cf*y); if (show==1) { // Find initial v g.drawLine(x1, y1, x2, y2); x1=x2; y1=y2; } if (kk==2) { // Plot trajectories bgr.drawLine(x1, y1-45, x2, y2-45); x1=x2; y1=y2; xx=vxx*t; yy=vyy*t-gr*t*t/2; // Without air xx2=(int)(cf*xx); yy2=(int)(225-cf*yy); if (xx2<=450) { bgr.drawLine(xx1, yy1,xx2, yy2); xx1=xx2; yy1=yy2; } agr.drawImage(bim, 0, 0, null); agr.fillArc(x2-r, y2-r-45, 2*r, 2*r, 0, 360); if (xx2<=450) { agr.fillArc(xx2-r, yy2-r, 2*r, 2*r, 0, 360); } g.drawImage(aim, 0, 45, null); } acc(vx+dvx/2, vy+dvy/2); dvx=ax*dt; dvy=ay*dt; vx=vx+dvx; vy=vy+dvy; } while (y>0); if (kk==2) { // Set dt for real time dt=dt*(System.currentTimeMillis()-tt)/5500; } return x-vx*y/vy; } double ang(Graphics g) { // Find optimum angle double x, xo; long tt; int dph; tt=System.currentTimeMillis(); dph=256; show=0; x=hit(g); do { phi=phi+dph; xo=x; x=hit(g); if (x2); do { } while ((System.currentTimeMillis()-tt)<1500); phi=phi+2*dph; show=1; x=hit(g); show=0; g.clearRect(50, 5, 400, 20); g.drawString("Vinit "+((int)(10*vi*cmph+.5))/10.+" mph at " +phi/100.+" deg Range "+((int)(10*cf*x+.5))/10.+" ft", 135, 20); return x; } public void acc(double ux, double uy) { // Newton's Law double u; u = Math.sqrt(ux*ux+uy*uy); ax=-k*u*ux; ay=-k*u*uy-gr; } public void paint(Graphics g) { // Paint double m, r, va, vb, vim, dvi, range, range2, rx; aim=createImage(451, 226); // Animation buffers agr=aim.getGraphics(); bim=createImage(451, 226); bgr=bim.getGraphics(); agr.setColor(Color.red); bgr.setColor(Color.black); for (int i=0; i<=10; i=i+1) { bgr.drawLine(45*i, 0, 45*i, 225); } for (int i=0; i<=5; i=i+1) { bgr.drawLine(0, 45*i, 450, 45*i); } g.drawImage(bim, 0, 45, null); g.setColor(Color.blue); bgr.setColor(Color.blue); cf=100/2.54/12; cmph=3600/.0254/12/5280; rx=0; if (kk==1) { m=5.125/16/2.2; r=9.125*.0254/2/Math.PI; gr=9.8; k=.87*r*r/m; range=450/cf; dvi=Math.sqrt(gr*range); vi=0; phi=3000; do { // Bracket the Range vi=vi+dvi; } while (ang(g)range) { vb=vi; } else { va=vi; } } while (vb-va>.02); vi=(va+vb)/2; g.setColor(Color.red); show=1; rx=hit(g); rr=1; } if (kk==2) { // Plot trajectories rx=hit(g); } vim=vi*cmph; rx=((int)(10*cf*rx+.5))/10.; range2=vi*vi*Math.sin(2*phi*Math.PI/18000)/gr*cf; if (kk==2) { g.drawString("Flight time "+((int)(100*t+.5))/100.+ " sec Range "+(int)range2+" ft without air", 135, 35); } if (kk>0) { g.clearRect(50, 5, 400, 20); g.drawString("Vinit "+((int)(10*vim+.5))/10.+" mph at " +phi/100.+" deg Range "+rx+" ft", 135, 20); kk=0; } } public void actionPerformed(ActionEvent e) { // Buttons String tst; tst=e.getActionCommand(); if (b1s.equals(tst)) { // Find the Range kk=1; repaint(); } if ((b2s.equals(tst))&&(rr==1)) { // Plot the Motion kk=2; repaint(); } } }