import java.awt.*; import java.awt.event.*; import java.lang.*; import java.lang.Math; public class RelVa extends java.applet.Applet implements Runnable { Canvas oscillators; Label riverSpeedLabel, boatSpeedLabel, boatAngleLabel, riverSpeedS, boatSpeedS, boatAngleS; Button Start; Thread runner; Scrollbar riverSpeedscroll, boatSpeedscroll, boatAnglescroll; int riverSpeed, boatSpeed, ballDiameter; int[] xpos = new int[5]; double[] x = new double[5]; int[] ypos = new int[5]; double[] y = new double[5]; int[] vectorX = new int[6]; double vectorXpos = new double[6]; int[] vectorY = new int[6]; double vectorYpos = new double[6]; double riverV, boatV, boatA, vRSX, vRSY, vBRX, vBRY, vBSX, vBSY, crossTime, xDistance; double pi = 3.141592653589793238468; Image offscreenImg; Graphics offscreenG; boolean startFlag; void buildConstraints(GridBagConstraints gbc, int gx, int gy, int gw, int gh, int wx, int wy) { gbc.gridx = gx; gbc.gridy = gy; gbc.gridwidth = gw; gbc.gridheight = gh; gbc.weightx = wx; gbc.weighty = wy; } public void init() { GridBagLayout gridbag = new GridBagLayout(); GridBagConstraints constraints = new GridBagConstraints(); setLayout(gridbag); // River speed text buildConstraints(constraints, 0, 0, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label riverSpeedLabel = new Label("Speed of the river (m/s):", Label.CENTER); gridbag.setConstraints (riverSpeedLabel, constraints); add(riverSpeedLabel); // River speed scrollbar label buildConstraints(constraints, 2, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; riverSpeedS = new Label("2", Label.LEFT); riverSpeed = 2; gridbag.setConstraints (riverSpeedS, constraints); add(riverSpeedS); // River speed scrollbar buildConstraints(constraints, 1, 0, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; riverSpeedscroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 0, 5); riverSpeedscroll.setValue (riverSpeed); gridbag.setConstraints (riverSpeedscroll, constraints); add(riverSpeedscroll); // boat speed text buildConstraints(constraints, 0, 1, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label boatSpeedLabel = new Label("Speed of the boat (m/s):", Label.CENTER); gridbag.setConstraints (boatSpeedLabel, constraints); add(boatSpeedLabel); // boat speed scrollbar label buildConstraints(constraints, 2, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; boatSpeedS = new Label("5", Label.LEFT); boatSpeed = 5; gridbag.setConstraints (boatSpeedS, constraints); add(boatSpeedS); // boat speed scrollbar buildConstraints(constraints, 1, 2, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; boatSpeedscroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, 1, 12); boatSpeedscroll.setValue (boatSpeed); gridbag.setConstraints (boatSpeedscroll, constraints); add(boatSpeedscroll); // boat angle text buildConstraints(constraints, 0, 2, 1, 1, 20, 5); constraints.fill = GridBagConstraints.NONE; constraints.anchor = GridBagConstraints.EAST; Label boatAngleLabel = new Label("Boat angle (degrees):", Label.CENTER); gridbag.setConstraints (boatAngleLabel, constraints); add(boatAngleLabel); // boat angle scrollbar label buildConstraints(constraints, 2, 2, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; boatAngleS = new Label("0", Label.LEFT); boatAngle = 0; gridbag.setConstraints (boatAngleS, constraints); add(boatAngleS); // boat angle scrollbar buildConstraints(constraints, 1, 2, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; boatAnglescroll = new Scrollbar(Scrollbar.HORIZONTAL, 0, 0, -30, 30); boatAnglescroll.setValue (boatAngle); gridbag.setConstraints (boatAnglescroll, constraints); add(boatAnglescroll); // Start button buildConstraints(constraints, 1, 3 , 1, 1, 0, 10); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; Start = new Button("Start"); gridbag.setConstraints (Start, constraints); add(Start); // canvas buildConstraints(constraints, 0, 4, 3, 1, 0, 80); constraints.fill = GridBagConstraints.HORIZONTAL; oscillators = new Canvas(); gridbag.setConstraints (oscillators, constraints); add(oscillators); offscreenImg = createImage(this.size().width, this.size().height); offscreenG = offscreenImg.getGraphics(); } public void start() { if (runner == null); { runner = new Thread(this); runner.start(); } } public void stop() { if (runner != null) { runner.stop(); runner = null; } } public void run() { double xOrigin, yOrigin, kAngle, scale; ballDiameter = 16; kAngle = pi/180.0; yOrigin = 380.0; xOrigin = 100.0; while (true) { startFlag = false; index = 0; currentX = 0.0; currentY = 0.0; dropTime = 0.0; riverV = riverSpeed; boatV = boatSpeed; boatA = kAngle*boatAngle; x[0] = xOrigin-ballDiameter; xpos[0] = (int)(x[0]); y[0] = yOrigin; ypos[0] = (int)(y[0]); vRSX = riverV; vRSY = 0.0; vBRX = boatV*Math.sin(boatA); vBRY = boatV*Math.cos(boatA); vBSX = vBRX + vRSX; vBSY = vBRY + vRSY; crossTime = 50.0/vBSY; xDistance = vBSX*crossTime; maxHeight = -0.5*vIntY*vIntY/g; maxTime = -2.0*vIntY/g; range = vIntX*maxTime; while (startFlag) { while (startFlag) { currentX = vIntX*dropTime; x[index] = x[0]+scale*currentX; currentY = dropTime*(vIntY+0.5*g*dropTime); y[index] = y[0]-scale*currentY; vY = vIntY+g*dropTime; xpos[index] = (int)(x[index]); ypos[index] = (int)(y[index]); repaint(); try { Thread.sleep(300); } catch (InterruptedException e) { } } } repaint(); try { Thread.sleep(1); } catch (InterruptedException e) { } } } public void update(Graphics g) { paint(g); } public void paint(Graphics g) { int i; // Draw background offscreenG.setColor(Color.lightGray); offscreenG.fillRect(0,0,500,200); offscreenG.setColor(Color.white); offscreenG.fillRect(0,200,500,430); // Draw mass offscreenG.setColor(Color.black); offscreenG.drawLine(10, 220, 290, 220); offscreenG.drawLine(10, 380, 290, 380); offscreenG.drawLine(150, 210, 150, 220); offscreenG.drawLine(150, 380, 150, 390); offscreenG.setColor(Color.blue); offscreenG.drawString("Velocity of the river relative to the shore", 300, 210); offscreenG.drawString("X component : Vrsx = " + vRSX + " m/s", 310, 228); offscreenG.drawString("Y component : Vrsy = " + vRSY + " m/s", 310, 246); offscreenG.setColor(Color.red); offscreenG.fillOval(xpos[index],ypos[index],ballDiameter,ballDiameter); offscreenG.drawString("Velocity of the boat relative to the river", 300, 266); offscreenG.drawString("X component : Vbrx = " + vBRX + " m/s", 310, 284); offscreenG.drawString("Y component : Vbry = " + vBRY + " m/s", 310, 302); offscreenG.setColor(Color.black); offscreenG.drawString("Velocity of the boat relative to the shore", 300, 322); offscreenG.drawString("X component : Vbsx = " + vBSX + " m/s", 310, 340); offscreenG.drawString("Y component : Vbsy = " + vBSY + " m/s", 310, 358); offscreenG.drawString("Time to cross river = " + crossTime + " s", 300, 378); offscreenG.drawString("Distance traveled in x direction = " + xDistance + " m", 300, 396); offscreenG.drawString("(when the boat reaches the far shore) ", 310, 414); g.drawImage(offscreenImg,0,0,this); } public void destroy() { offscreenG.dispose(); } public boolean action (Event evt, Object arg) { if (evt.target instanceof Button) { if ((Button)evt.target == Start) { if (Start.getLabel().equals("Start")) { startFlag = true; Start.setLabel("Reset"); } else { startFlag = false; Start.setLabel("Start"); } } } else return super.action(evt, arg); return true; } public boolean handleEvent(Event evt) { if (evt.target instanceof Scrollbar) { if ((Scrollbar)evt.target == riverSpeedscroll) { riverSpeed = ((Scrollbar)evt.target).getValue(); riverSpeedS.setText(String.valueOf(riverSpeed)); } else if ((Scrollbar)evt.target == boatSpeedscroll) { boatSpeed = ((Scrollbar)evt.target).getValue(); boatSpeedS.setText(String.valueOf(boatSpeed)); } else if ((Scrollbar)evt.target == boatAnglescroll) { boatAngle = ((Scrollbar)evt.target).getValue(); boatAngleS.setText(String.valueOf(boatAngle)); } repaint(); } else return super.handleEvent(evt); return true; } }