import java.awt.*; import java.awt.image.*; import java.*; import java.net.*; import java.applet.*; import java.awt.event.*; import java.util.Random; public class Hurr extends Applet implements MouseListener, MouseMotionListener, ActionListener, AdjustmentListener, KeyListener { Random rand; AnimIt animThread; Image bubbleImage; Image[] hurrback; int[][] hurrtemps; int season = 0; int showSeasonCount = 20; int hurrIndex; double xHurr, yHurr; int xHi, yHi; boolean isDraggingHi = false; boolean tempUnitC = true; int hurrWidth = 320; int hurrHeight = 240; int cat = 0; double category = 0.; double dcat = 0.; double sizeHurr; Image[][] hurricane; String[] catnames = {"-as.gif","-bs.gif","-cs.gif","-ds.gif"}; Font labelFont, hiFont, loFont, tFont; boolean debug = false; boolean isManual = true; boolean automove = false; boolean toggleManual = true; boolean showTemp = false; boolean toggleTemp = true; int temperature = 0; final double scale = 10.; /* double[] xloc = {160., 320., 480., 160., 320., 480., 160., 320., 480.}; double[] yloc = {120., 120., 120., 240., 240., 240., 360., 360., 360.}; double[] dx = {1., 1., 1., .3, .5, .6, -.8, -1., -1.}; double[] dy = {-.5, -.4, -.4, -.8, -1., -1., .3, .1, -.1}; */ double[] xloc = {-500.,-500.,-340.,-380.,-380.,-120.,-120.,-160., 0., 0., 160., 120., 120., 380., 380., 340., 500., 500.}; double[] yloc = {-300.,+300., 0., -200., +200., -200., +200., 0., -300., +300., 0., -200., +200., -200., +200., 0., -300., +300.}; double[] dx = { 1., -1., 0., .7, -.7, .7, -.7, 0., 1., -1., 0., .7, -.7, .7, -.7, 0., 1., -1.}; double[] dy = { 0., 0., 1., .7, .7, -.7, -.7, -1., 0., 0., 1., .7, .7, -.7, -.7, -1., 0., 0.}; String[] seaname = {"Winter","Spring","Summer","Fall"}; String[] hurrbase = {"hurrbase-dec.gif","hurrbase-mar.gif","hurrbase-june.gif","hurrbase-sept.gif"}; //Gray Shades 1-149 represent SST values 270-305K //Gray Shades 150-255 represent heights of 0-4000 meters. public void init() { rand = new Random(); reset(); labelFont = new Font("sans",Font.BOLD,22); hiFont = new Font("serif",Font.BOLD,50); loFont = new Font("serif",Font.BOLD,30); tFont = new Font("sansserif",Font.BOLD,16); hurrback = new Image[4]; hurrtemps = new int[4][]; try { GetImageFile gif = new GetImageFile(this); //URL eturl = new URL(getDocumentBase(),"HURRBASE.ET"); URL eturl = gif.getFile("HURRBASE.ET"); EnhancementTable et = new EnhancementTable(eturl); hurricane = new Image[6][4]; Image bb = gif.getImage("bubble.gif"); bubbleImage = new TransparentImage(this,bb,50,0).getImage(); for (int k=0; k<4; k++) { hurrback[k] = gif.getImage(hurrbase[k]); hurrtemps[k] = new int[640 * 480]; PixelGrabber pg = new PixelGrabber(hurrback[k],0,0,640,480,hurrtemps[k],0,640); pg.grabPixels(); int stat = pg.status(); for (int i=0; i<640*480; i++) { int v = et.getIndex(hurrtemps[k][i]); if (v < 1 || v > 149) v = 0; hurrtemps[k][i] = v; } } for (int k=0; k<6; k++) { for (int i=0; i<4; i++) { Image img = gif.getImage("cat"+(k)+catnames[i]); hurricane[k][i] = new TransparentImage(this,img,100,55).getImage(); } } } catch (Exception erx) { System.out.println("#### Cannot initialize: "+erx); return; } addMouseMotionListener(this); addMouseListener(this); addKeyListener(this); animThread = new AnimIt(this); animThread.start(); requestFocus(); } public void reset() { // reset initial size, location, etc. xHurr = 600; yHurr = 440; xHi = 25; yHi = 25; sizeHurr = .3; category = 0.; cat = 0; } public void actionPerformed(ActionEvent e) { repaint(); } public void adjustmentValueChanged(AdjustmentEvent e) { } public void itemStateChanged(ItemEvent e) { repaint(); } public void mouseClicked(MouseEvent e) {;} public void mouseEntered(MouseEvent e) {;} public void mouseExited(MouseEvent e) {;} public void mouseReleased(MouseEvent e) { isDraggingHi = false; } public void mousePressed(MouseEvent e) { if (Math.abs(xHi - e.getX()) < 120 && Math.abs(yHi - e.getY()) < 120) { isDraggingHi = true; } else { isDraggingHi = false; } } public void mouseMoved(MouseEvent e) {;} public void mouseDragged(MouseEvent e) { if (isDraggingHi) { xHi = e.getX(); yHi = e.getY(); } else { xHurr = e.getX(); yHurr = e.getY(); if (xHurr < 0.) xHurr = 0.; if (yHurr < 0.) yHurr = 0.; if (xHurr > 639.) xHurr = 639.; if (yHurr > 479.) yHurr = 479.; } repaint(); } public void getCategory() { final double changeRate = 20.; double avg = 0.; int size2 = 10; double cnt = 0; int pv, xx, yy, rgba; int v; temperature = -999; for (int x=-size2; x 639) xx = 639; for (int y=-size2; y 479) yy = 479; v = hurrtemps[season][640*yy+xx]; avg = avg + v; cnt = cnt + 1; if (x == 0 && y == 0 && v > 0 && v < 150) { temperature = 270 + (int)Math.round( (305 - 270)*(v - 1.)/(149. - 1.)) - 273; } } } //Gray Shades 1-149 represent SST values 270-305K // 126 is about 26.5 degrees C double targetCat = 6.4*((avg/cnt) - 126.)/(149. - 126.); if (debug) System.out.println("#### avg, cnt = "+(avg/cnt)+" "+cnt); if (targetCat < 0.) targetCat = 0.; dcat = (targetCat - category)/changeRate; category = category + dcat; sizeHurr = sizeHurr + dcat/6.; if (sizeHurr < .3) sizeHurr = .3; if (sizeHurr > 1.3) sizeHurr = 1.3; cat = (int)category; if (debug) System.out.println("#### cat = "+(float)category +" targ="+(float)targetCat+" size = "+(float)sizeHurr); } public void moveIt() { double sumdx = 0.; double sumdy = 0.; double sumw = 0; double w = 0; if (!isManual && automove) { for (int i=0; i 800 || yHurr < -100 || yHurr > 600 ) reset(); } //is it too close to H? double dh = (yHurr - yHi)*(yHurr - yHi) + (xHurr - xHi)*(xHurr - xHi); if (dh < 150.*150.) { double theta = Math.atan2(yHurr - yHi,xHurr - xHi); double newx = 150. * Math.cos(theta); double newy = 150. * Math.sin(theta); xHurr = xHi + newx; yHurr = yHi + newy; } automove = false; } public synchronized void paint(Graphics g) { moveIt(); if (!isDraggingHi) getCategory(); Image buff = createImage(640,480); Graphics bg = buff.getGraphics(); bg.drawImage(hurrback[season],0,0,null); int hw = (int)Math.round(hurrWidth * sizeHurr); int hh = (int)Math.round(hurrHeight * sizeHurr); bg.drawImage(hurricane[cat][hurrIndex], (int)Math.round(xHurr-hw/2), (int)Math.round(yHurr-hh/2) ,hw, hh,null); bg.setFont(labelFont); String c = cat+" "; if (cat == 0) { bg.setFont(loFont); c = "L"; } bg.drawString(c,(int)Math.round(xHurr)-15,(int)Math.round(yHurr)+10); if (showTemp) { bg.setFont(tFont); String ct = "SST="+temperature+"\u00b0C"; if (!tempUnitC) { ct = "SST="+((90*temperature+5)/50+32)+"\u00b0F"; } if (temperature == -999) ct = " "; bg.drawString(ct, (int)Math.round(xHurr)-30,(int)Math.round(yHurr)+30); } if (showSeasonCount > 0) { bg.setFont(labelFont); bg.drawString(seaname[season], 510, 30); showSeasonCount --; if (showSeasonCount < 0) showSeasonCount = 0; } bg.setFont(hiFont); bg.drawImage(bubbleImage,xHi-150,yHi-150,300,300,null); bg.drawString("H",xHi-20, yHi+20); if (debug) { // show vectors bg.setColor(Color.white); for (int i=0; i 3) season = 0; showSeasonCount = 10; } repaint(); } public void keyReleased(KeyEvent e) {} public void keyTyped(KeyEvent e) {} public void update(Graphics g) { paint(g); } public void nextStep(int hi) { automove = true; hurrIndex = hi; repaint(); } public void stop() { if (animThread != null) animThread.quitIt(); } } class AnimIt extends Thread { Hurr mom; boolean isRunning; int hurrIndex; public AnimIt (Hurr p) { mom = p; hurrIndex = 0; isRunning = true; } public void quitIt () { isRunning = false; } // this thread determines the state of each hydrometeor public void run () { while (isRunning) { try { Thread.sleep(300); } catch (InterruptedException e) {;} hurrIndex = hurrIndex + 1; if (hurrIndex > 3) { hurrIndex = 0; } mom.nextStep(hurrIndex); } } }