import java.awt.*; import java.awt.event.*; import java.lang.*; import java.lang.Math; import java.text.*; public class RelV2 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, boatAngle, ballDiameter, index; int[] xpos = new int[11]; double[] x = new double[11]; int[] ypos = new int[11]; double[] y = new double[11]; double[] vectorX = new double[7]; int[] vectorXpos = new int[7]; double[] vectorY = new double[7]; int[] vectorYpos = new int[7]; int[] floaterX = new int[5]; int[] floaterY = new int[5]; 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, 2, 1, 0, 5); 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, 1, 1, 1, 20, 0); constraints.fill = GridBagConstraints.HORIZONTAL; constraints.anchor = GridBagConstraints.WEST; boatSpeedscroll = new Scrollbar(Scrollbar.HORIZONTAL, 5, 1, 1, 12); 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, 2, -30, 30); 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() { int i, temp; double xOrigin, yOrigin, kAngle, scale, tempA, arrowScale, riverScale; ballDiameter = 16; kAngle = pi/180.0; yOrigin = 380.0; xOrigin = 150.0; scale = 10.0; arrowScale = 1.2*scale; startFlag = false; for (i=0; i<=4; i++) { floaterX[i] = (int)(10+250*Math.random()); floaterY[i] = (int)(yOrigin - 10 - 140*Math.random()); } while (true) { index = 0; riverV = riverSpeed; boatV = boatSpeed; boatA = kAngle*boatAngle; vRSX = riverV; vRSY = 0.0; vBRX = boatV*Math.sin(boatA); vBRY = boatV*Math.cos(boatA); vBSX = vBRX + vRSX; vBSY = vBRY + vRSY; if (Math.abs(vBSX) < 0.000001) vBSX = 0.0; x[0] = xOrigin-(ballDiameter/2); xpos[0] = (int)(x[0]); vectorX[0] = xOrigin; vectorX[1] = vectorX[0]+scale*vBRX; temp=270-boatAngle-30; tempA = kAngle*temp; vectorX[2] = vectorX[1]+arrowScale*Math.cos(tempA); temp=270-boatAngle+30; tempA = kAngle*temp; vectorX[3] = vectorX[1]+arrowScale*Math.cos(tempA); vectorX[4] = vectorX[1]+scale*vRSX; temp=180-30; tempA = kAngle*temp; vectorX[5] = vectorX[4]+arrowScale*Math.cos(tempA); temp=180+30; tempA = kAngle*temp; vectorX[6] = vectorX[4]+arrowScale*Math.cos(tempA); y[0] = yOrigin-ballDiameter; ypos[0] = (int)(y[0]); vectorY[0] = yOrigin-(ballDiameter/2); vectorY[1] = vectorY[0]-scale*vBRY; temp=270-boatAngle-30; tempA = kAngle*temp; vectorY[2] = vectorY[1]-arrowScale*Math.sin(tempA); temp=270-boatAngle+30; tempA = kAngle*temp; vectorY[3] = vectorY[1]-arrowScale*Math.sin(tempA); vectorY[4] = vectorY[1]-scale*vRSY; temp=180-30; tempA = kAngle*temp; vectorY[5] = vectorY[4]+arrowScale*Math.sin(tempA); temp=180+30; tempA = kAngle*temp; vectorY[6] = vectorY[4]+arrowScale*Math.sin(tempA); for (i=0; i <=6; i++) { vectorXpos[i] = (int)(vectorX[i]); vectorYpos[i] = (int)(vectorY[i]); } for (i=0; i<=4; i++) { floaterX[i] = floaterX[i]+riverSpeed; if (floaterX[i] > 290) { floaterX[i] = 10; floaterY[i] = (int)(yOrigin - 10 - 140*Math.random()); } } crossTime = 50.0/vBSY; xDistance = vBSX*crossTime; riverScale = (160 - ballDiameter)/10.0; while (startFlag) { while (startFlag) { index = index +1; if (index > 10 ) { index = 10; } x[index] = x[0]+riverScale*index*vBSX/vBSY; y[index] = y[0]-riverScale*index; xpos[index] = (int)(x[index]); ypos[index] = (int)(y[index]); for (i=0; i<=4; i++) { floaterX[i] = floaterX[i]+riverSpeed; if (floaterX[i] > 290) { floaterX[i] = 10; floaterY[i] = (int)(yOrigin - 10 - 140*Math.random()); } } repaint(); try { Thread.sleep(150); } catch (InterruptedException e) { } } } repaint(); try { Thread.sleep(150); } 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,560,200); offscreenG.setColor(Color.white); offscreenG.fillRect(0,200,560,430); // Draw mass NumberFormat nf = NumberFormat.getInstance(); nf.setMaximumFractionDigits(4); 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); for (i=0; i<=4; i++) { offscreenG.drawOval(floaterX[i],floaterY[i],2,2); } offscreenG.drawLine(vectorXpos[1],vectorYpos[1],vectorXpos[4],vectorYpos[4]); if (riverSpeed > 0) { offscreenG.drawLine(vectorXpos[4],vectorYpos[4],vectorXpos[5],vectorYpos[5]); offscreenG.drawLine(vectorXpos[4],vectorYpos[4],vectorXpos[6],vectorYpos[6]); } offscreenG.drawString("Velocity of the river relative to the shore", 300, 210); offscreenG.drawString("X component : Vrsx = " + nf.format(vRSX) + " m/s", 310, 228); offscreenG.drawString("Y component : Vrsy = " + nf.format(vRSY) + " m/s", 310, 246); offscreenG.setColor(Color.red); if (xpos[index]< 285) offscreenG.drawOval(xpos[index],ypos[index],ballDiameter,ballDiameter); offscreenG.drawLine(vectorXpos[0],vectorYpos[0],vectorXpos[1],vectorYpos[1]); offscreenG.drawLine(vectorXpos[1],vectorYpos[1],vectorXpos[2],vectorYpos[2]); offscreenG.drawLine(vectorXpos[1],vectorYpos[1],vectorXpos[3],vectorYpos[3]); offscreenG.drawString("Velocity of the boat relative to the river", 300, 266); offscreenG.drawString("X component : Vbrx = " + nf.format(vBRX) + " m/s", 310, 284); offscreenG.drawString("Y component : Vbry = " + nf.format(vBRY) + " m/s", 310, 302); offscreenG.setColor(Color.black); offscreenG.drawLine(vectorXpos[0],vectorYpos[0],vectorXpos[4],vectorYpos[4]); offscreenG.drawString("Velocity of the boat relative to the shore", 300, 322); offscreenG.drawString("X component : Vbsx = " + nf.format(vBSX) + " m/s", 310, 340); offscreenG.drawString("Y component : Vbsy = " + nf.format(vBSY) + " m/s", 310, 358); offscreenG.drawString("Time to cross river = " + nf.format(crossTime) + " s", 300, 378); offscreenG.drawString("Distance traveled in x direction = " + nf.format(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; } }