// Use "javac -deprecation glider.java" // NMI's Java Code Viewer 5.1 © 1997-2001 B. Lemaire // http://njcv.htmlplanet.com - info@njcv.htmlplanet.com // Based on: http://www.geocities.com/rengaray/VAPGlider.html which, // in turn, was based on Walter Fendt's original applet at: // http://home.a-city.de/walter.fendt/phe/n2law.htm // Source File Name: glider.java import java.applet.Applet; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Component; import java.awt.Container; import java.awt.Dimension; import java.awt.Font; import java.awt.Graphics; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Image; import java.awt.Insets; import java.awt.Label; import java.awt.List; import java.awt.MediaTracker; import java.awt.Panel; import java.awt.TextComponent; import java.awt.TextField; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionListener; public class glider extends Applet implements Runnable, ActionListener, MouseMotionListener { Graphics g1; Graphics g2; Image offscreen; Image glider_g; Image glide_g; Image ruler_g; Image weight_g; Image laser_g; final Color bgColor; final Color pColor; Thread animatorThread; Font fontH; Font fontC; Font fontCLarge; boolean stopped; boolean execute; Panel p; TextField tf1; TextField tf2; TextField tf3; Button b1; Button b2; Button b3; List li; int width; int height; double M; double m; double my; // Value for the "Coefficient of friction" (mu) final double g = 9.8100000000000005D; final int maxNrExp = 20; int nrExp; boolean completedExp; double T; double t; double s[]; double x; double a; int ls; Dimension dimSize; String text[] = { //".", "Start", "Record Data", "Reset", "Mass of the Wagon:", "Hanging Mass:", "Coefficient of Friction:", "Data:", "LS", "(in s)", ".", "Start", "Record Data", "Reset", "Mass of the Car:", "Hanging Mass:", "mu:", "Data:", "PhotoGate", "(in s)", "(in m)", "Too much friction!" }; int xCR; public void init() { glider_g = getImage(getDocumentBase(), "images/glider.jpg"); glide_g = getImage(getDocumentBase(), "images/glide.jpg"); ruler_g = getImage(getDocumentBase(), "images/meteruler.jpg"); weight_g = getImage(getDocumentBase(), "images/weight.jpg"); laser_g = getImage(getDocumentBase(), "images/laser.jpg"); MediaTracker mediatracker = new MediaTracker(this); mediatracker.addImage(glide_g, 1); mediatracker.addImage(glider_g, 2); mediatracker.addImage(laser_g, 3); mediatracker.addImage(ruler_g, 4); mediatracker.addImage(weight_g, 5); for(int i = 1; i < 6; i++) try { mediatracker.waitForID(i); } catch(InterruptedException _ex) { return; } dimSize = getSize(); width = dimSize.width; height = dimSize.height; g1 = getGraphics(); offscreen = createImage(width, height); g2 = offscreen.getGraphics(); animatorThread = null; fontH = new Font("Helvetica", 1, 12); fontC = new Font("Courier", 0, 12); fontCLarge = new Font("Courier", 1, 16); g2.setFont(fontC); setLayout(new BorderLayout()); s = new double[20]; } public void setPanel() { tf1.setText(doubleToString(M * 1000D, 0)); tf2.setText(doubleToString(m * 1000D, 1)); tf3.setText(doubleToString(my, 3)); } public void start() { xCR = 50; ls = 140; s[0] = (double)(ls - 40) / 200D; //M = 0.10000000000000001D; M = 0.36400000000000001D; // Mass of the glider/car //m = 0.001D; m = 0.020D; // Set the hanging mass higher since mu is higher (below) //my = 0.0D; my = 0.015D; // Set mu to new default value for wood nrExp = 0; completedExp = false; a = ((m - my * M) * 9.8100000000000005D) / (M + m); T = t = x = 0.0D; p = new Panel(); p.setLayout(new GridBagLayout()); p.setBackground(pColor); p.setForeground(Color.green); b1 = new Button(text[1]); b1.addActionListener(this); addComponent(b1, Color.gray, fontH, 0, 0, 3, 5, 10, 5, 10); b2 = new Button(text[2]); addComponent(b2, Color.gray, fontH, 0, 1, 3, 5, 10, 5, 10); b2.setEnabled(false); b2.addActionListener(this); b3 = new Button(text[3]); addComponent(b3, Color.gray, fontH, 0, 2, 3, 5, 10, 0, 10); b3.setEnabled(false); b3.addActionListener(this); addComponent(new Label(text[4]), pColor, fontH, 0, 3, 3, 5, 10, 0, 10); //addComponent(new Label("M = "), pColor, fontC, 0, 4, 1, 0, 10, 5, 0); addComponent(new Label("M1 = "), pColor, fontC, 0, 4, 1, 0, 10, 5, 0); tf1 = new TextField(4); tf1.setForeground(Color.black); tf1.addActionListener(this); addComponent(tf1, Color.white, fontC, 1, 4, 1, 0, 0, 5, 0); addComponent(new Label("g"), pColor, fontC, 2, 4, 1, 0, 5, 0, 10); addComponent(new Label(text[5]), pColor, fontH, 0, 5, 3, 5, 10, 0, 10); //addComponent(new Label("m = "), pColor, fontC, 0, 6, 1, 0, 10, 5, 0); addComponent(new Label("m2 = "), pColor, fontC, 0, 6, 1, 0, 10, 5, 0); tf2 = new TextField(5); tf2.setForeground(Color.black); tf2.addActionListener(this); addComponent(tf2, Color.white, fontC, 1, 6, 1, 0, 0, 5, 0); addComponent(new Label("g"), pColor, fontC, 2, 6, 1, 0, 5, 0, 10); addComponent(new Label(text[6]), pColor, fontH, 0, 7, 3, 5, 10, 0, 10); addComponent(new Label("\265 = "), pColor, fontC, 0, 8, 1, 0, 10, 5, 0); tf3 = new TextField(6); tf3.setForeground(Color.black); tf3.addActionListener(this); addComponent(tf3, Color.white, fontC, 1, 8, 1, 0, 0, 5, 0); addComponent(new Label(text[7]), pColor, fontH, 0, 9, 3, 5, 10, 0, 10); li = new List(3, false); //li.addItem(" s t "); li.addItem(" x t "); li.addItem("-------- -------"); addComponent(li, Color.white, fontC, 0, 10, 3, 0, 5, 5, 5); setPanel(); add("East", p); p.repaint(); animatorThread = new Thread(this); animatorThread.start(); addMouseMotionListener(this); } public void stop() { removeAll(); animatorThread.stop(); animatorThread = null; } public void run() { long l = System.currentTimeMillis(); try { Thread.sleep(200L); } catch(InterruptedException _ex) { } while(execute) { paint(g2); g1.drawImage(offscreen, 0, 0, this); long l1 = System.currentTimeMillis(); if(!stopped) t += (double)(l1 - l) / 1000D; l = l1; } } public void addComponent(Component component, Color color, Font font, int i, int j, int k, int l, int i1, int j1, int k1) { GridBagConstraints gridbagconstraints = new GridBagConstraints(); gridbagconstraints.gridx = i; gridbagconstraints.gridy = j; gridbagconstraints.gridwidth = k; gridbagconstraints.gridheight = 1; gridbagconstraints.fill = 2; gridbagconstraints.anchor = 10; gridbagconstraints.insets = new Insets(l, i1, j1, k1); ((GridBagLayout)p.getLayout()).setConstraints(component, gridbagconstraints); component.setFont(font); component.setBackground(color); p.add(component); } public void clock(Graphics g3) { g3.setColor(Color.gray); g3.fillRect(90, 150, 100, 30); g3.setColor(Color.black); g3.fillRect(100, 155, 80, 20); g3.setColor(Color.red); g3.setFont(fontCLarge); g3.drawString(doubleToString(t >= T ? T : t, 3) + " s", 106, 170); g3.setFont(fontC); g3.setColor(Color.black); } public void wagon(Graphics g3) { x = (a / 2D) * t * t; if(!completedExp && nrExp < 20 && x >= s[nrExp]) { b2.setEnabled(true); completedExp = true; if(nrExp < 20) nrExp++; } if(x > 1.0D) { x = 1.0D; stopped = true; } int i = (int)(x * 200D + 0.5D); int j = (int)(t * 20D + 0.5D); g3.drawImage(glider_g, i, 50, 40, 20, this); g3.setColor(Color.blue); g3.drawLine(40 + i, 58, 250, 58); g3.drawArc(238, 58, 22, 22, 0, 90); g3.drawLine(260, 68, 260, 100 + i); g3.drawImage(weight_g, 258, 100 + i, 5, 6, this); g3.setColor(Color.red); g3.fillOval((310 + j) - 2, 280 - i - 2, 4, 4); g3.fillOval((40 + i) - 2, 56, 4, 4); } public void diagram(Graphics g3, int i, int j) { g3.setColor(Color.black); g3.drawLine(i - 10, j, i + 130, j); g3.drawLine(i + 120, j - 3, i + 130, j); g3.drawLine(i + 120, j + 3, i + 130, j); for(int k = 1; k <= 5; k++) { g3.drawLine(i + k * 20, j - 3, i + k * 20, j + 3); g3.drawString(String.valueOf(k), (i + k * 20) - 3, j + 15); } g3.drawLine(i, j + 10, i, j - 230); g3.drawLine(i - 3, j - 220, i, j - 230); g3.drawLine(i + 3, j - 220, i, j - 230); for(int l = 1; l <= 10; l++) { g3.drawLine(i - 3, j - l * 20, i + 3, j - l * 20); g3.drawString(doubleToString((double)l / 10D, 1), i - 25, (j - l * 20) + 5); } int l2; int j1 = l2 = i; int i3; int i2 = i3 = j; while(l2 < i + 140 && i3 > j - 220) { int k1 = l2; int j2 = i3; l2 = k1 + 2; double d = (double)(l2 - i) / 20D; double d2 = (a / 2D) * d * d; i3 = j - (int)(d2 * 200D + 0.5D); g3.drawLine(k1, j2, l2, i3); } for(int i1 = 0; i1 < nrExp; i1++) { double d3 = s[i1]; double d1 = Math.sqrt((2D * d3) / a); int l1 = i + (int)(d1 * 20D + 0.5D); int k2 = j - (int)(d3 * 200D + 0.5D); g3.fillRect(l1 - 2, k2 - 2, 5, 5); } g3.setFont(fontH); g3.drawString("t", i + 125, j + 15); g3.drawString(text[9], i + 113, j + 30); //g3.drawString("s", i - 20, j - 225); g3.drawString("x", i - 20, j - 225); g3.drawString(text[10], i - 37, j - 210); g3.setFont(fontC); } public String doubleToString(double d, int i) { int l = 0; int k = 1; for(; l < i; l++) k *= 10; int j = (int)(d * (double)k + 0.5D); String s1 = String.valueOf(j / k); if(i > 0) s1 = s1 + text[0]; j %= k; for(int i1 = 0; i1 < i; i1++) { k /= 10; s1 = s1 + j / k; j %= k; } return s1; } public double stringToDouble(String s1) { StringBuffer stringbuffer = new StringBuffer(s1); for(int i = 0; i < stringbuffer.length(); i++) if(stringbuffer.charAt(i) == ',') stringbuffer.setCharAt(i, '.'); double d; try { d = Double.valueOf(stringbuffer.toString()).doubleValue(); } catch(NumberFormatException _ex) { d = 0.0D; } return d; } public void paint(Graphics g3) { g3.setColor(bgColor); g3.fillRect(0, 0, width, height); g3.drawImage(glide_g, 0, 60, 260, 20, this); g3.setColor(Color.red); g3.fillRect(240, 55, 6, 15); g3.drawImage(ruler_g, 40, 85, 200, 20, this); diagram(g3, 310, 280); wagon(g3); clock(g3); g3.setFont(fontH); g3.drawString("a = " + doubleToString(a, 3) + " m/s", 100, 240); g3.drawString("2", 175, 235); if(completedExp || nrExp == 20) //g3.drawString("s = " + doubleToString(s[nrExp - 1], 3) + " m", 100, 260); g3.drawString("x = " + doubleToString(s[nrExp - 1], 3) + " m", 100, 260); else //g3.drawString("s = " + doubleToString(s[nrExp], 3) + " m", 100, 260); g3.drawString("x = " + doubleToString(s[nrExp], 3) + " m", 100, 260); if(completedExp) g3.drawString("t = " + doubleToString(T, 3) + " s", 100, 280); else g3.drawString("t = ", 100, 280); g3.drawString(text[8], ls + 10, 50); g3.setFont(fontC); g3.drawImage(laser_g, ls - 3, 40, 7, 45, this); g3.drawLine(ls - 20, 30, ls + 20, 30); if(ls > 50) { g3.drawLine(ls - 10, 27, ls - 20, 30); g3.drawLine(ls - 10, 33, ls - 20, 30); } if(ls < 240) { g3.drawLine(ls + 10, 27, ls + 20, 30); g3.drawLine(ls + 10, 33, ls + 20, 30); } if(my * M >= m) { g3.setColor(Color.red); g3.setFont(fontH); g3.drawString(text[11], 80, 120); } } public void update(Graphics g3) { paint(g3); } public void newSeries() { t = 0.0D; x = 0.0D; stopped = true; completedExp = false; nrExp = 0; ls = 140; s[nrExp] = (double)(ls - 40) / 200D; b1.setEnabled(true); b2.setEnabled(false); b3.setEnabled(true); setPanel(); } public void changeValues() { double d = stringToDouble(tf1.getText()) / 1000D; double d1 = stringToDouble(tf2.getText()) / 1000D; double d2 = stringToDouble(tf3.getText()); if(d != M || d1 != m || d2 != my) { M = d; m = d1; my = d2; nrExp = 0; setPanel(); } } public void actionPerformed(ActionEvent actionevent) { if(actionevent.getSource() == tf1) { M = stringToDouble(tf1.getText()) / 1000D; if(M < 0.0D) M = 0.0D; if(M > 1.0D) M = 1.0D; newSeries(); } else if(actionevent.getSource() == tf2) { m = stringToDouble(tf2.getText()) / 1000D; if(m < 0.0D) m = 0.0D; if(m > 0.10000000000000001D) m = 0.10000000000000001D; newSeries(); } else if(actionevent.getSource() == tf3) { my = stringToDouble(tf3.getText()); if(my < 0.0D) my = 0.0D; if(my > 1.0D) my = 1.0D; newSeries(); } if(actionevent.getSource() == b1) { b1.setEnabled(false); tf1.setEnabled(false); tf2.setEnabled(false); tf3.setEnabled(false); changeValues(); t = 0.0D; x = 0.0D; stopped = false; completedExp = false; if(nrExp < 20) { s[nrExp] = (double)(ls - 40) / 200D; T = Math.sqrt((2D * s[nrExp]) / a); } } else if(actionevent.getSource() == b2) { b1.setEnabled(true); b2.setEnabled(false); b3.setEnabled(true); t = 0.0D; x = 0.0D; stopped = true; completedExp = false; if(nrExp < 20) { s[nrExp] = (double)(ls - 40) / 200D; T = Math.sqrt((2D * s[nrExp]) / a); } } else if(actionevent.getSource() == b3) { M = 0.10000000000000001D; m = 0.001D; my = 0.0050000000000000001D; changeValues(); newSeries(); tf1.setEnabled(true); tf2.setEnabled(true); tf3.setEnabled(true); } if(M + m > 0.0D) a = ((m - my * M) * 9.8100000000000005D) / (M + m); else a = 0.0D; if(a < 0.0D) { a = 0.0D; tf1.setEnabled(true); tf2.setEnabled(true); tf3.setEnabled(true); } li.clear(); //li.addItem("s t "); li.addItem("x t "); li.addItem("-------- -------"); for(int i = 0; i < nrExp; i++) { double d = Math.sqrt((2D * s[i]) / a); li.addItem(doubleToString(s[i], 3) + " m; " + doubleToString(d, 3) + " s"); } } public void mouseDragged(MouseEvent mouseevent) { int i = mouseevent.getX(); int j = mouseevent.getY(); if(i < ls - 40 || i > ls + 40 || j < 10 || j > 90) execute = true; ls = i; if(ls > 240) ls = 240; if(ls < 50) ls = 50; if(nrExp < 20) s[nrExp] = (double)(ls - 40) / 200D; } public void mouseMoved(MouseEvent mouseevent) { } public glider() { bgColor = Color.white; pColor = Color.black; stopped = true; execute = true; } }