📄 graphpanel.java
字号:
/* * "Copyright (c) 2001 and The Regents of the University * of California. All rights reserved. * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose, without fee, and without written agreement is * hereby granted, provided that the above copyright notice and the following * two paragraphs appear in all copies of this software. * * IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE UNIVERSITY OF * CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS * ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATION TO * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS." * * $\Id$ *//** * File: GraphPanel.java * * Description: * Communicates with SerialForward, receiving packets and displaying * the received data graphically. * * @author Jason Hill and Eric Heien */package net.tinyos.oscope;import net.tinyos.util.*;import net.tinyos.message.*;import java.io.*;import java.util.*;import java.awt.*;import java.applet.Applet;import java.awt.event.*;import javax.swing.*;import javax.swing.event.*;//import java.sql.Time;public class GraphPanel extends Panel implements MouseListener, MouseMotionListener, MessageListener { // If true, verbosely report received packet contents private static final boolean VERBOSE = false; // If true, log data to a file called LOG_FILENAME private static final boolean LOG = false; private static final String LOG_FILENAME = "log"; // Set the number of channels to display and the number of readings // per packet. 2 channels and 4 reading means 2 readings per packet // per channel. static final int NUM_CHANNELS = 10; static int NUM_READINGS = 10; private static final double DEFAULT_BOTTOM = 0; private static final double DEFAULT_TOP = 1024.0; private static final int DEFAULT_START = -100; private static final int DEFAULT_END = 1000; private static final double X_AXIS_POSITION = 0.1; private static final double Y_AXIS_POSITION = 0.1; boolean sliding = false; boolean legend = true; boolean connectPoints = true; boolean yaxishex = false; boolean valueTest = false; int testChannel = -1, valueX, valueY; oscilloscope graph; MoteIF mote; //output stream for logging the data to. PrintWriter log_os; double bottom, top; int start, end; int maximum_x = 0, minimum_x = Integer.MAX_VALUE; Vector cutoff; Vector2 data[]; String dataLegend[]; boolean legendActive[]; Color plotColors[]; int moteNum[]; // Maps channel # to mote # int streamNum[]; // Maps channel # to mote stream # int lastPacketNum[]; // Last packet # for channel Point highlight_start, highlight_end; GraphPanel(oscilloscope graph) { setBackground(Color.white); addMouseListener(this); addMouseMotionListener(this); cutoff = new Vector(); //create an array to hold the data sets. data = new Vector2[NUM_CHANNELS]; for(int i = 0; i < NUM_CHANNELS; i ++) data[i] = new Vector2(); dataLegend = new String[NUM_CHANNELS]; legendActive = new boolean[NUM_CHANNELS]; lastPacketNum = new int[NUM_CHANNELS]; streamNum = new int[NUM_CHANNELS]; moteNum = new int[NUM_CHANNELS]; plotColors = new Color[NUM_CHANNELS]; for(int i = 0; i < NUM_CHANNELS; i++) { lastPacketNum[i] = -1; streamNum[i] = -1; moteNum[i] = -1; dataLegend[i] = ""; legendActive[i] = false; } plotColors[0] = Color.green; plotColors[1] = Color.red; plotColors[2] = Color.blue; plotColors[3] = Color.magenta; plotColors[4] = Color.orange; plotColors[5] = Color.yellow; plotColors[6] = Color.cyan; plotColors[7] = Color.pink; plotColors[8] = Color.green; plotColors[9] = Color.white; try{ //create a file for logging data to. FileOutputStream f = new FileOutputStream(LOG_FILENAME); log_os = new PrintWriter(f); } catch (Exception e) { e.printStackTrace(); } this.graph = graph; bottom = DEFAULT_BOTTOM; top = DEFAULT_TOP; start = DEFAULT_START; end = DEFAULT_END; // OK, connect to the serial forwarder and start receiving data try { mote = new MoteIF("127.0.0.1", 9000, oscilloscope.group_id); mote.registerListener(new OscopeMsg(), this); mote.registerListener(new DiagRspMsg(), this); mote.start(); } catch(Exception e){ e.printStackTrace(); System.exit(-1); } } int big_filter; int sm_filter; int db_filter; /* Add a point to the graph. */ void add_point(Point2D val, int place){ if(place >= data.length) return; data[place].add(val); if (val != null) { if ((int)val.x < minimum_x) minimum_x = (int)val.x; if ((int)val.x > maximum_x) maximum_x = (int)val.x; } if(val != null && sliding && ((val.getX() > (end - 20)) || (val.getX() < start)) && place == 0) { int diff = end - start; end = (int)val.getX() + 20; start = end - diff; } int max_length = 0x3fff; for(int i = 0; i < NUM_CHANNELS; i ++){ if(data[i].size() > max_length) { synchronized(data[i]){data[i].chop(max_length/10); } } } if( LOG && val != null ) log_os.println(""+val.toString() + ", " + place); repaint(100); } /** * This is the handler invoked when a msg is received from * SerialForward. */ public void messageReceived(int dest_addr, Message msg) { if (msg instanceof OscopeMsg) { oscopeReceived( dest_addr, (OscopeMsg)msg); } else if (msg instanceof DiagRspMsg) { diagRspReceived(dest_addr, (DiagRspMsg)msg); } else { throw new RuntimeException("messageReceived: Got bad message type: "+msg); } } public void oscopeReceived(int dest_addr, OscopeMsg omsg) { boolean foundPlot = false; int moteID, packetNum, channelID, channel = -1, i; moteID = omsg.get_sourceMoteID(); channelID = omsg.get_channel(); packetNum = omsg.get_lastSampleNumber(); for(i = 0; i < NUM_CHANNELS; i++) { if(moteNum[i] == moteID && streamNum[i] == channelID) { foundPlot = true; legendActive[i] = true; channel = i; i = NUM_CHANNELS+1; } } if (!foundPlot) { for(i = 0; i < NUM_CHANNELS && moteNum[i] != -1; i++); if (i >= NUM_CHANNELS) { System.err.println("\nWARNING: Cannot find empty channel for packet from mote ID "+moteID+" channelID "+channelID+" - recompile GraphViz.java with a larger setting for NUM_CHANNELS (currently "+NUM_CHANNELS+")"); return; } channel = i; moteNum[i] = moteID; streamNum[i] = channelID; lastPacketNum[i] = packetNum; legendActive[i] = true; dataLegend[i] = "Mote "+moteID+" Chan "+channelID; } if(channel < 0) { System.err.println("All data streams full. Please clear data set."); return; } if(lastPacketNum[channel] == -1) lastPacketNum[channel] = packetNum; int packetLoss = packetNum - lastPacketNum[channel] - NUM_READINGS; for(int j = 0; j < packetLoss; j++) { // Add "NUM_READINGS" blank points for each lost packet for(i = 0; i < NUM_READINGS; i++) add_point(null, channel); } lastPacketNum[channel] = packetNum; int limit = omsg.numElements_data(); for (i = 0; i < limit; i++) { Point2D newPoint; int val = omsg.getElement_data(i); if (VERBOSE) System.err.println("val: "+val+" (0x"+Integer.toHexString(val)+")"); newPoint = new Point2D( ((double)(packetNum+i)), val ); add_point( newPoint, channel); } } public void diagRspReceived(int dest_addr, DiagRspMsg dmsg) { boolean foundPlot = false; int moteID, packetNum, channelID, channel = -1, i; moteID = dmsg.get_source_mote_id(); channelID = 1; packetNum = dmsg.get_sequence_num(); for(i = 0; i < NUM_CHANNELS; i++) { if(moteNum[i] == moteID && streamNum[i] == channelID) { foundPlot = true; legendActive[i] = true; channel = i; //i = NUM_CHANNELS+1; } } if (!foundPlot) { for(i=0; i<NUM_READINGS&&moteNum[i]!=-1; i++);System.err.print("!foundPlot, i = "+ i +"\n"); channel = i; moteNum[i] = moteID; streamNum[i] = channelID; lastPacketNum[i] = packetNum; legendActive[i] = true; dataLegend[i] = "Packet Loss for Mote "+moteID; } if(channel < 0) { System.err.println("All data streams full. Please clear data set."); return; } if(lastPacketNum[channel] == -1) lastPacketNum[channel] = packetNum; int packetLoss = packetNum - lastPacketNum[channel] - 1; for(int j = 0; j < packetLoss; j++) { // Add "NUM_READINGS" blank points for each lost packet for(i = 0; i < NUM_READINGS; i++) add_point(null, channel); } lastPacketNum[channel] = packetNum; for (i=0; i<NUM_READINGS; i++) { Point2D newPoint; int val = packetLoss; newPoint = new Point2D( ((double)(packetNum+i)), val ); add_point( newPoint, channel); } } // end of diagRspReceived() public void mouseEntered(MouseEvent e) { } public void mouseExited(MouseEvent e) { } /* Select a view rectangle. */ public void mouseDragged(MouseEvent e) { Dimension d = getSize(); if (valueTest) { Point2D virt_drag = screenToVirtual(new Point2D(e.getX(), e.getY())); Point2D dp = findNearestX(data[testChannel], virt_drag); if (dp != null) { valueX = (int)dp.x; valueY = (int)dp.y; } } else if (highlight_start != null) { highlight_end.x = e.getX(); highlight_end.y = e.getY(); } repaint(100); e.consume(); } public void mouseMoved(MouseEvent e) { } public void mouseClicked(MouseEvent e) { } /* Set zoom to selected rectangle. */ public void mouseReleased(MouseEvent e) { removeMouseMotionListener(this); if( highlight_start != null ) set_zoom(); valueTest = false; testChannel = -1; highlight_start = null; highlight_end = null; e.consume(); repaint(100); } public void mousePressed(MouseEvent e) { addMouseMotionListener(this); // Check to see if mouse clicked near plot Dimension d = getSize(); double xVal,yVal; Point2D virt_click = screenToVirtual(new Point2D(e.getX(), e.getY())); for(int i = 0; i < NUM_CHANNELS; i++) { Point2D dp = findNearestX(data[i], virt_click); if (dp != null) { if (Math.abs(dp.y - virt_click.y) <= (top-bottom)/10) { valueTest = true; testChannel = i; valueX = (int)dp.x; valueY = (int)dp.y; } } } if (!valueTest) { highlight_start = new Point(); highlight_end = new Point(); highlight_start.x = e.getX(); highlight_start.y = e.getY(); highlight_end.x = e.getX(); highlight_end.y = e.getY(); } repaint(100); e.consume(); } public void start() { } public void stop() { } //double buffer the graphics. Image offscreen; Dimension offscreensize; Graphics offgraphics; public synchronized void update(Graphics g) { //get the size of the window. Dimension d = getSize(); //get the end value of the window. int end = this.end; //graph.time_location.setValue((int)(end / ((maximum_x - minimum_x)*1.0))); //create the offscreen image if necessary (only done once) if ((offscreen == null) || (d.width != offscreensize.width) || (d.height != offscreensize.height)) { offscreen = createImage(d.width, d.height); offscreensize = d; if (offgraphics != null) { offgraphics.dispose(); } offgraphics = offscreen.getGraphics(); offgraphics.setFont(getFont()); } //blank the screen. offgraphics.setColor(Color.black); offgraphics.fillRect(0, 0, d.width, d.height); // Draw axes Point2D origin = new Point2D(0,0); double xTicSpacing = (end - start)/25.03; double yTicSpacing = (top - bottom)/13.7; origin.x = start + ((end - start) * X_AXIS_POSITION); origin.y = bottom + ((top - bottom) * Y_AXIS_POSITION); if (yaxishex) { // Round origin to integer if ((origin.x % 1.0) != 0) origin.x -= (origin.x % 1.0); if ((origin.y % 1.0) != 0) origin.y -= (origin.y % 1.0); } else { // Round origin to integer if ((origin.x % 1.0) != 0) origin.x -= (origin.x % 1.0); if ((origin.y % 1.0) != 0) origin.y -= (origin.y % 1.0); } // Prevent tics from being too small if (yTicSpacing < 1.0) yTicSpacing = 1.0; if ((yTicSpacing % 1.0) != 0) yTicSpacing += (1.0 - (yTicSpacing % 1.0)); if (xTicSpacing < 1.0) xTicSpacing = 1.0; if ((xTicSpacing % 1.0) != 0) xTicSpacing += (1.0 - (xTicSpacing % 1.0)); Color xColor,yColor; xColor = Color.white; yColor = Color.white; drawGridLines(offgraphics, origin, xTicSpacing, yTicSpacing); drawAxisAndTics(offgraphics, origin, start, end, top, bottom, xTicSpacing, yTicSpacing, xColor, yColor); //draw the highlight box if there is one. draw_highlight(offgraphics); //draw the input channels. for(int i = 0; i < NUM_CHANNELS; i ++) { offgraphics.setColor(plotColors[i]); if( legendActive[i] ) draw_data(offgraphics, data[i], start, end); } // Draw the value tester line if needed if (valueTest) { offgraphics.setFont(new Font("Default", Font.PLAIN, 12)); offgraphics.setColor(new Color((float)0.9, (float)0.9, (float)1.0)); Point2D vt = virtualToScreen(new Point2D(valueX, valueY)); offgraphics.drawLine((int)vt.x, 0, (int)vt.x, d.height); offgraphics.drawRect((int)vt.x - 3, (int)vt.y - 3, 6, 6); if (yaxishex) { offgraphics.drawString("["+valueX+",0x"+Integer.toHexString(valueY)+"]", (int)vt.x+15, (int)vt.y-15); } else { offgraphics.drawString("["+valueX+","+valueY+"]", (int)vt.x+15, (int)vt.y-15); } } drawLegend(offgraphics); //transfer the constructed image to the screen. g.drawImage(offscreen, 0, 0, null); } // Draw the grid lines void drawGridLines(Graphics offgraphics, Point2D origin, double xTicSpacing, double yTicSpacing ) { offgraphics.setColor(new Color((float)0.2, (float)0.6, (float)0.2)); int i = 0; Point2D virt, screen; virt = new Point2D(origin.x, origin.y); screen = virtualToScreen(virt); while (screen.x < getSize().width) { offgraphics.drawLine((int)screen.x, 0, (int)screen.x, getSize().height); virt.x += xTicSpacing; screen = virtualToScreen(virt); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -