RiverRat  - An MIT iCampus project http://web.mit.edu/riverrat/

Main Page | Software Documentation | Hardware Documentation | People | Contact | Wiki

Main Page | Class Hierarchy | Class List | File List | Class Members

RiverRatDemo.java

00001 
00062 package riverrat;
00063 
00064 import java.awt.Font;
00065 import java.awt.Frame;
00066 import java.awt.Color;
00067 import java.awt.Graphics;
00068 import java.awt.Graphics2D;
00069 import java.awt.RenderingHints;
00070 import java.awt.Menu;
00071 import java.awt.MenuBar;
00072 import java.awt.MenuItem;
00073 import java.awt.event.WindowAdapter;
00074 import java.awt.event.WindowEvent;
00075 import java.awt.event.MouseListener;
00076 import java.awt.event.MouseMotionListener;
00077 import java.awt.event.MouseEvent;
00078 import java.awt.event.KeyListener;
00079 import java.awt.event.KeyEvent;
00080 import java.awt.event.ActionListener;
00081 import java.awt.event.ActionEvent;
00082 import java.util.Vector;
00083 
00087 public class RiverRatDemo extends Frame implements RiverRatClient, MouseListener, MouseMotionListener, KeyListener, ActionListener {
00088         static final int TRACK_DOT_RADIUS = 10; //dot size for track history dot
00089         static final int DOT_RADIUS = 10;                               //dot size for boat dot
00090         static final int MARK_RADIUS = 15;                      //dot size for mark dot
00091         
00092         static final int MAX_DIMENSION = 500;           //window max dimension size--should adjust aspect to Map getAspect()
00093         
00094         static final float NW_LAT = 42.3645f;
00095         static final float SE_LAT = 42.3505f;
00096         static final float NW_LON = -71.095f;
00097         static final float SE_LON = -71.075f;
00098         static final int GRID_DIVISIONS = 10;
00099 
00100         static final boolean DEBUG = false;
00101         static final boolean ENABLE_TRACKS = true;
00102         static final boolean DRAW_BOAT_ICON = true;
00103 
00104         static final Color BG_COLOR = Color.white;
00105         static final Color GRID_COLOR = Color.gray;
00106         
00107         static String host = "localhost";
00108         static int port = 8080;
00109         
00110         Map themap;
00111         Race therace;
00112         Color dotcolor;
00113         int boatid;
00114         int markid;
00115         int width = 1000;
00116         int height = 375;
00117         
00118         int mouse_x, mouse_y;
00119         boolean isButtonPressed = false;
00120         boolean drawPointerLocation = false;
00121         boolean drawRaceStatus = true;
00122         boolean drawBoatStatus = true;
00123         boolean drawGrid = false;
00124         boolean drawHelp = false;
00125         
00131         public RiverRatDemo() {
00132                 super("River Rat: The coolest sailing you've ever seen.");
00133                 this.addWindowListener(new WindowAdapter() {
00134                         public void windowClosing(WindowEvent e) {
00135                                 System.exit(0);
00136                         }
00137                 });
00138 
00139                 ViewMenu viewMenu = new ViewMenu((ActionListener) this);        //set up new top-level menu named "View"
00140                 MenuBar mb = new MenuBar(); //setup new menu bar
00141                 mb.add(viewMenu); //add "View" menu to menu bar
00142                 setMenuBar(mb);
00143                 
00144                 therace = new LiveRace(host, port); //tell Race to open connection localhost:8080
00145                 themap = new Map(new Fix(NW_LAT, NW_LON), new Fix(SE_LAT, SE_LON));
00146                 setSize(width, height);
00147                 setBackground(BG_COLOR);
00148                 setVisible(true);
00149 
00150                 addKeyListener(this);
00151                 addMouseListener(this);
00152                 addMouseMotionListener(this);
00153         }
00154         
00159         public void actionPerformed(ActionEvent e) {
00160                 String item = e.getActionCommand();
00161                 if(item.equals("Hide Race Status")) drawRaceStatus = !drawRaceStatus;
00162                 else if(item.equals("Hide Boat Status")) drawBoatStatus = !drawBoatStatus;
00163                 else if(item.equals("Draw Pointer Location")) drawPointerLocation = !drawPointerLocation;
00164                 else if(item.equals("Draw Lat/Lon Grid")) drawGrid = !drawGrid;
00165         }
00166         
00172         class ViewMenu extends Menu {
00179                 public ViewMenu(ActionListener al) {
00180                         super("View");
00181                         MenuItem mi;
00182                         add(mi = new MenuItem("Hide Race Status"));
00183                         mi.addActionListener(al);
00184                         add(mi = new MenuItem("Hide Boat Status"));
00185                         mi.addActionListener(al);
00186                         add(mi = new MenuItem("Draw Pointer Location"));
00187                         mi.addActionListener(al);
00188                         add(mi = new MenuItem("Draw Lat/Lon Grid"));
00189                         mi.addActionListener(al);
00190                 }
00191         }
00192         
00196         public void mouseEntered(MouseEvent e) {}
00197         public void mouseExited(MouseEvent e) {}
00198         public void mouseClicked(MouseEvent e) {}
00199         
00204         public void mousePressed(MouseEvent e)  {
00205                 isButtonPressed = true;
00206                 repaint();
00207                 e.consume(); //"Consume" the event so it won't be processed in the default manner
00208         }
00209         
00214         public void mouseReleased(MouseEvent e) {
00215                 isButtonPressed = false;
00216                 repaint();
00217                 e.consume();
00218         }
00219         
00226         public void mouseMoved(MouseEvent e) {
00227                 mouse_x = e.getX();
00228                 mouse_y = e.getY();
00229                 repaint();
00230                 e.consume();
00231         }
00232         
00239         public void mouseDragged(MouseEvent e) {
00240                 mouse_x = e.getX();
00241                 mouse_y = e.getY();
00242                 repaint();
00243                 e.consume();
00244         }
00245         
00253         public void drawArrows(Graphics g) {
00254                 drawTriangle(g, 50, 450, (float) 0.0f);
00255                 drawTriangle(g, 100, 450, (float) (Math.PI)/4.0f);
00256                 drawTriangle(g, 150, 450, (float) (Math.PI)/2.0f);
00257                 drawTriangle(g, 200, 450, (float) (3.0f*Math.PI)/4.0f);
00258                 drawTriangle(g, 250, 450, (float) (1.0f*Math.PI));
00259                 drawTriangle(g, 300, 450, (float) (5.0f*Math.PI)/4.0f);
00260                 drawTriangle(g, 350, 450, (float) (3.0f*Math.PI)/2.0f);
00261                 drawTriangle(g, 400, 450, (float) (7.0f*Math.PI)/4.0f);
00262                 drawTriangle(g, 450, 450, (float) (2.0f*Math.PI));              
00263         }
00264 
00277         public void drawTriangle(Graphics g, int x, int y, float radians) {
00278                 int[] xPoints = new int[3];
00279                 int[] yPoints = new int[3];
00280                 yPoints[0] = - (int) ((float) 2.0f*DOT_RADIUS*Math.cos(radians));
00281                 yPoints[1] = - (int) ((float) DOT_RADIUS*Math.cos((radians)+(float) ((2.0f*Math.PI)/3.0f)));
00282                 yPoints[2] = - (int) ((float) DOT_RADIUS*Math.cos((radians)+(float) ((4.0f*Math.PI)/3.0f)));
00283                 xPoints[0] = (int) ((float) 2.0f*DOT_RADIUS*Math.sin(radians));
00284                 xPoints[1] = (int) ((float) DOT_RADIUS*Math.sin((radians)+(float) ((2.0f*Math.PI)/3.0f)));
00285                 xPoints[2] = (int) ((float) DOT_RADIUS*Math.sin((radians)+(float) ((4.0f*Math.PI)/3.0f)));
00286                 for(int i = 0; i < 3; i++) {
00287                         xPoints[i] += x;
00288                         yPoints[i] += y;
00289                 }
00290                 g.fillPolygon(xPoints, yPoints, 3);
00291         }
00292         
00306         public void drawBoatIcon(Graphics g, int x, int y, float radians) {
00307                 int[] xPoints = new int[7];
00308                 int[] yPoints = new int[7];
00309                 yPoints[0] = - (int) ((float) 2.0f*DOT_RADIUS*Math.cos(radians));                                                                                                                                               //0 degrees
00310                 yPoints[1] = - (int) ((float) 1.2f*DOT_RADIUS*Math.cos((radians)+(float) (Math.PI)/3.0f));                                      //60 degrees
00311                 yPoints[2] = - (int) ((float) 1.2f*DOT_RADIUS*Math.cos((radians)+(float) (Math.PI)/2.0f));                                      //90 degrees
00312                 yPoints[3] = - (int) ((float) DOT_RADIUS*Math.cos((radians)+(float) ((2.0f*Math.PI)/3.0f)));                            //120 degrees
00313                 yPoints[4] = - (int) ((float) DOT_RADIUS*Math.cos((radians)+(float) ((4.0f*Math.PI)/3.0f)));                            //240 degrees
00314                 yPoints[5] = - (int) ((float) 1.2f*DOT_RADIUS*Math.cos((radians)+(float) ((3.0f*Math.PI)/2.0f)));               //270 degrees
00315                 yPoints[6] = - (int) ((float) 1.2f*DOT_RADIUS*Math.cos((radians)+(float) ((5.0f*Math.PI)/3.0f)));               //300 degrees
00316                 
00317                 xPoints[0] = (int) ((float) 2.0f*DOT_RADIUS*Math.sin(radians));                                                                                                                                                 //0 degrees
00318                 xPoints[1] = (int) ((float) 1.2f*DOT_RADIUS*Math.sin((radians)+(float) (Math.PI)/3.0f));                                                //60 degrees
00319                 xPoints[2] = (int) ((float) 1.2f*DOT_RADIUS*Math.sin((radians)+(float) (Math.PI)/8.0f));                                                //90 degrees
00320                 xPoints[3] = (int) ((float) DOT_RADIUS*Math.sin((radians)+(float) ((2.0f*Math.PI)/3.0f)));                                      //120 degrees
00321                 xPoints[4] = (int) ((float) DOT_RADIUS*Math.sin((radians)+(float) ((4.0f*Math.PI)/3.0f)));                                      //240 degrees
00322                 xPoints[5] = (int) ((float) 1.2f*DOT_RADIUS*Math.sin((radians)+(float) ((11.0f*Math.PI)/8.0f)));                //270 degrees
00323                 xPoints[6] = (int) ((float) 1.2f*DOT_RADIUS*Math.sin((radians)+(float) ((3.0f*Math.PI)/2.0f)));                 //300 degrees
00324                 
00325                 for(int i = 0; i < 7; i++) {
00326                         xPoints[i] += x;
00327                         yPoints[i] += y;
00328                 }
00329                 g.fillPolygon(xPoints, yPoints, 7);
00330         }
00331         
00337         public void drawHelpMessage(Graphics g) {
00338                 if(drawHelp) {
00339                         g.setColor(Color.white);
00340                         g.fill3DRect((width/2)-70,(height/2)-45,180,80,true);
00341                         g.setColor(Color.red);
00342                         g.drawString("P to toggle pointer location",(width/2)-60,(height/2)-30);
00343                         g.drawString("G to toggle grid",(width/2)-60,(height/2)-15);
00344                         g.drawString("B to toggle boat status",(width/2)-60,(height/2));
00345                         g.drawString("R to toggle race status",(width/2)-60,(height/2)+15);
00346                         g.drawString("H to toggle this message",(width/2)-60,(height/2)+30);
00347                 }
00348         }
00349         
00356         public void drawCursorLatLon(Graphics g) {
00357                 g.drawString("Pointer at ("+themap.getLatFromY((float) mouse_y/(float) height)+", "+themap.getLonFromX((float) mouse_x/(float) width)+")",250,60);
00358         }
00359         
00365         public void drawLatLonGrid(Graphics g) {
00366                 g.setColor(GRID_COLOR);
00367                 //System.out.println("Map aspect ratio is "+themap.getAspect());
00368                 int inc = 0;
00369                 try {
00370                         inc = width/(GRID_DIVISIONS*(int)themap.getAspect());
00371                 } catch(ArithmeticException ae) {
00372                 }
00373                 for(int x = 1; x < width; x += inc) {
00374                         g.drawLine(x,0,x,height);
00375                 }
00376                 for(int y = 1; y < height; y += inc) {
00377                         g.drawLine(0,y,width,y);
00378                 }
00379         }
00380         
00387         public void drawMark(Graphics g, int markid) {
00388                 try {
00389                         if(DEBUG) System.out.println("drawMark(): "+therace.getMark(markid).markToString());
00390                         switch(markid % 3) {
00391                                 case 0: dotcolor = Color.yellow; break;
00392                                 case 1: dotcolor = Color.orange; break;
00393                         }
00394                         g.setColor(dotcolor);
00395                         g.fillOval( (int) (width*themap.getXFromLon(therace.getMark(markid).getLon()))-(DOT_RADIUS/2),
00396                                                                         (int) (height*themap.getYFromLat(therace.getMark(markid).getLat()))-(DOT_RADIUS/2),
00397                                                                         MARK_RADIUS,MARK_RADIUS);
00398                         g.setColor(Color.black);
00399                         g.drawOval( (int) (width*themap.getXFromLon(therace.getMark(markid).getLon()))-(DOT_RADIUS/2),
00400                                                                         (int) (height*themap.getYFromLat(therace.getMark(markid).getLat()))-(DOT_RADIUS/2),
00401                                                                         MARK_RADIUS,MARK_RADIUS);
00402                         g.drawString(""+(markid+1),
00403                                                                 (int) (width*themap.getXFromLon(therace.getMark(markid).getLon())),
00404                                                                 (int) (height*themap.getYFromLat(therace.getMark(markid).getLat()))+(int) ((7.0f/10.f)*DOT_RADIUS));
00405                 } catch(NoSuchObjectException ex) {
00406                         System.err.println("NoSuchObjectException caught.");
00407                         return;
00408                 }
00409         }
00410         
00417         public void drawBoat(Graphics g, int boatid) {
00418                 try {
00419                         Vector boattrack;
00420                         float colorvals[];
00421                         float alpha;
00422                         Fix tempfix;    
00423                         if(DEBUG) System.out.println("drawBoat(): "+therace.getBoat(boatid).boatToString());
00424                         switch(boatid % 5) {
00425                                 case 0: dotcolor = Color.green; break;
00426                                 case 1: dotcolor = Color.blue; break;
00427                                 case 2: dotcolor = Color.red; break;
00428                                 case 3: dotcolor = Color.pink; break;
00429                                 case 4: dotcolor = Color.green; break;
00430                         }
00431                         g.setColor(dotcolor);
00432                         if(drawBoatStatus) g.drawString(therace.getBoat(boatid).boatToString(),20,60+(20*boatid));
00433                         boattrack = therace.getBoat(boatid).getTrack();
00434                         colorvals = dotcolor.getColorComponents(null);
00435                         if((boattrack.size() > 1) && (ENABLE_TRACKS)) {
00436                                 if(DEBUG){
00437                                         System.out.println("paint(): painting track: ");
00438                                 }
00439                                 for(int i = 0; i < boattrack.size(); i++) {
00440                                         alpha = (float) (1.0-((1.0/boattrack.size())*(boattrack.size()-i)));
00441                                         tempfix = (Fix)boattrack.elementAt(i);
00442                                         if(DEBUG) {
00443                                                 System.out.println("paint(): alpha is "+alpha+", painting track dot at");
00444                                                 System.out.println("paint():  +"+tempfix.fixToString());
00445                                         }
00446                                         if(alpha > 255) alpha = 255;
00447                                         if(alpha < 0) alpha = 0;
00448                                         dotcolor = new Color(colorvals[0],colorvals[1],colorvals[2],alpha);
00449                                         g.setColor(dotcolor);
00450                                         g.fillOval( (int) (width*themap.getXFromLon(tempfix.getLon()))-(DOT_RADIUS/2),
00451                                                                                         (int) (height*themap.getYFromLat(tempfix.getLat()))-(DOT_RADIUS/2),
00452                                                                                         TRACK_DOT_RADIUS,TRACK_DOT_RADIUS);
00453                                 } //for
00454                         } //if(boattrack.size() > 1)
00455                         if(DRAW_BOAT_ICON) {
00456                                 drawTriangle( g, 
00457                                                                                         (int) (width*themap.getXFromLon(therace.getBoat(boatid).getLon())),
00458                                                                                         (int) (height*themap.getYFromLat(therace.getBoat(boatid).getLat())),
00459                                                                                         therace.getBoat(boatid).getHeading());
00460                         } else {
00461                                 g.fillOval( (int) (width*themap.getXFromLon(therace.getBoat(boatid).getLon()))-(DOT_RADIUS/2),
00462                                                                                 (int) (height*themap.getYFromLat(therace.getBoat(boatid).getLat()))-(DOT_RADIUS/2),
00463                                                                                 DOT_RADIUS,DOT_RADIUS);
00464                         }
00465                 } catch(NoSuchObjectException ex) {
00466                         System.err.println("NoSuchObjectException caught.");
00467                         return;
00468                 }
00469         }
00470 
00478         public void paint(Graphics g) {
00479                 if(DEBUG) System.out.println("paint(): called");
00480                 height = getHeight();
00481                 width = getWidth();
00482                 themap.setAspect((float)width/(float)height);
00483                 ((Graphics2D)g).setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
00484                 g.setFont(new Font("Helvetica",Font.PLAIN,12));
00485                 if(therace == null) {
00486                         g.setColor(Color.red);
00487                         g.drawString("Race has not begun",250,40);
00488                         return;
00489                 } else { //e.g. therace != null
00490                         g.setColor(Color.blue);
00491                         if(drawRaceStatus) g.drawString("Race has "+therace.numBoats()+" boats",250,40);
00492                 } //if
00493                 if(drawGrid) drawLatLonGrid(g);
00494                 if(drawPointerLocation) drawCursorLatLon(g);
00495                 for(markid = 0; markid < therace.numMarks(); markid++) {
00496                         drawMark(g, markid);
00497                 } //for
00498                 for(boatid = 0; boatid < therace.numBoats(); boatid++) {
00499                         drawBoat(g, boatid);
00500                 } //for
00501                 drawHelpMessage(g);
00502         } //paint()
00503         
00513         public void keyTyped(KeyEvent e) {
00514                 if(((String)"p").equals(""+e.getKeyChar())) {
00515                         drawPointerLocation = !drawPointerLocation;
00516                         System.out.println("Toggling pointer location.");
00517                 }
00518                 if(((String)"b").equals(""+e.getKeyChar())) {
00519                         drawBoatStatus = !drawBoatStatus;
00520                         System.out.println("Toggling boat status.");
00521                 }
00522                 if(((String)"r").equals(""+e.getKeyChar())) {
00523                         drawRaceStatus = !drawRaceStatus;
00524                         System.out.println("Toggling race status.");
00525                 }
00526                 if(((String)"g").equals(""+e.getKeyChar())) {
00527                         drawGrid = !drawGrid;
00528                         System.out.println("Toggling lat/lon grid.");
00529                 }
00530                 if(((String)"h").equals(""+e.getKeyChar())) {
00531                         drawHelp = !drawHelp;
00532                         System.out.println("Toggling help.");
00533                 }
00534         }
00535         
00536         public void keyReleased(KeyEvent e) {}
00537         
00538         public void keyPressed(KeyEvent e) {}
00539         
00545         public static void main(String args[]) {
00546                 System.out.println("Starting RiverRatDemo...");
00547                 RiverRatDemo rr = new RiverRatDemo();
00548 
00549                 while(true) {
00550                         rr.repaint();
00551                         try {
00552                                 Thread.sleep(500); //call repaint() every half-second, Thread.sleep() takes units of milliseconds
00553                         } catch(InterruptedException ie) {
00554                         } //try
00555                 } //while(true)
00556         } //main()
00557 } //class RiverRatDemo
 

Brought to you by the RiverRat team.