Commit 1805e61f authored by David Johnson's avatar David Johnson

More changes to handle new wifi stuff, including support for zooming on

maps, changing building floors, etc.  Also revamped the applet to work
with all the new stuff.
parent ed47be9c
This diff is collapsed.
This diff is collapsed.
/*
* Dataset.java
*
* Created on July 7, 2006, 2:53 PM
*
* To change this template, choose Tools | Template Manager
* and open the template in the editor.
*/
import java.util.*;
/**
*
* @author david
*/
public class Dataset {
public String name;
public String building;
public int[] floor;
public int[] scale;
public float[] scaleFactor;
public String image_path;
public float[] ppm;
public String positionFile;
public String dataFile;
public MapDataModel model;
public Hashtable bgImages;
public GenericWirelessData data;
public NodePosition positions;
public Dataset(String name,String positionFile,String dataFile,
String building,int floor,String image_path,float ppm) {
this.name = name;
this.building = building;
this.floor = new int[1];
this.floor[0] = floor;
this.image_path = image_path;
this.ppm = new float[1];
this.ppm[0] = ppm;
this.scale = new int[1];
this.scale[0] = 1;
this.scaleFactor = new float[1];
this.scaleFactor[0] = 1;
this.positionFile = positionFile;
this.dataFile = dataFile;
this.bgImages = new Hashtable();
}
public Dataset() {
this.name = null;
this.building = null;
this.floor = null;
this.image_path = null;
this.scale = null;
this.scaleFactor = null;
this.ppm = null;
this.positionFile = null;
this.dataFile = null;
this.bgImages = new Hashtable();
}
// We only don't take the building argument because I postulate that
// it will never be the case that we have statistics from between
// buildings. For me, one building per dataset is good enough for our
// needs into the foreseeable future... just like 64k. :-)
public java.awt.Image getImage(int floor,int scale) {
System.err.println("getting image for building="+this.building+",floor="+floor+",scale="+scale);
String tag = "" + floor + "-" + scale;
return (java.awt.Image)this.bgImages.get(tag);
}
public void addImage(java.awt.Image img,int floor,int scale) {
System.err.println("adding image for building="+this.building+",floor="+floor+",scale="+scale);
String tag = "" + floor + "-" + scale;
this.bgImages.put(tag,img);
}
public float getScaleFactor(int scale) {
if (this.scale != null) {
int i;
for (i = 0; i < this.scale.length; ++i) {
if (this.scale[i] == scale) {
break;
}
}
if (i != this.scale.length) {
return this.scaleFactor[i];
}
}
return 1.0f;
}
public void addFloor(int f) {
int[] tmp;
if (this.floor == null) {
tmp = new int[1];
tmp[1] = f;
this.floor = tmp;
}
else {
// check and see if it's already in the array:
for (int i = 0; i < this.floor.length; ++i) {
if (this.floor[i] == f) {
return;
}
}
tmp = new int[this.floor.length+1];
System.arraycopy(this.floor,0,tmp,0,this.floor.length);
tmp[this.floor.length] = f;
this.floor = tmp;
}
}
public void addScale(int f) {
int[] tmp;
if (this.scale == null) {
tmp = new int[1];
tmp[1] = f;
this.scale = tmp;
}
else {
tmp = new int[this.scale.length+1];
System.arraycopy(this.scale,0,tmp,0,this.scale.length);
tmp[this.scale.length] = f;
this.scale = tmp;
}
}
}
......@@ -32,7 +32,7 @@ public class GenericLinkStats {
public void addStat(String statName,Object stat) {
stats.put(statName,stat);
System.out.println("GLS: added "+recvNode+" <- "+sendNode+", "+statName+"="+stat);
//System.out.println("GLS: added "+recvNode+" <- "+sendNode+", "+statName+"="+stat);
}
public void addMetaStat(String statName,String metaName,Object stat) {
......@@ -61,7 +61,7 @@ public class GenericLinkStats {
float myTicks = 100/(max-min);
float myPercent = (myValue - min)*myTicks;
System.out.println("GPOPR: statName="+statName+"min="+min+",max="+max+",myValue="+myValue+",myTicks="+myTicks+"myPercent="+myPercent);
//System.out.println("GPOPR: statName="+statName+"min="+min+",max="+max+",myValue="+myValue+",myTicks="+myTicks+"myPercent="+myPercent);
return new Float(myPercent);
}
......
......@@ -411,7 +411,10 @@ public class GenericStats implements GenericWirelessData {
// so at least grabbing it as a string will work.
obj = sdm.group(1);
// try to take as float if possible...
obj = new Float(Float.parseFloat(sdm.group(2)));
float tf = Float.parseFloat(sdm.group(2));
int bf = (int)(tf*100.0);
tf = ((float)bf)/100.0f;
obj = new Float(tf);
}
catch (Exception ex) {
;
......@@ -484,7 +487,10 @@ public class GenericStats implements GenericWirelessData {
// so at least grabbing it as a string will work.
obj = dm.group(1);
// try to take as float if possible...
obj = new Float(Float.parseFloat(dm.group(2)));
float tf = Float.parseFloat(dm.group(2));
int bf = (int)(tf*100.0);
tf = ((float)bf)/100.0f;
obj = new Float(tf);
}
catch (Exception ex) {
;
......@@ -539,7 +545,7 @@ public class GenericStats implements GenericWirelessData {
throw new IOException("file read failed");
}
System.out.println("GenericStats parsed "+linecount+" lines.");
System.err.println("GenericStats parsed "+linecount+" lines.");
GenericStats retval = new GenericStats(indices,indexValues,
nodes,properties,
......@@ -589,7 +595,7 @@ public class GenericStats implements GenericWirelessData {
allStats.add(gls);
//}
System.out.println("GS.addReceiverStats: added '"+gls.toString()+"'!");
//System.out.println("GS.addReceiverStats: added '"+gls.toString()+"'!");
}
public GenericLinkStats getStats(String recvNode,String sendNode) {
......
......@@ -49,14 +49,22 @@ public class MapDataModel {
private Hashtable options;
private int currentFloor;
private int currentScale;
private int minScale;
private int maxScale;
private Dataset dataset;
/** Creates a new instance of MapDataModel */
private MapDataModel() {
this(null,null);
this(new Dataset());
}
public MapDataModel(GenericWirelessData data,NodePosition positions) {
this.data = data;
this.positions = positions;
public MapDataModel(Dataset ds) {
this.dataset = ds;
this.data = ds.data;
this.positions = ds.positions;
selectionList = new Vector();
threshold = new Float(0);
neighborCount = 3;
......@@ -79,6 +87,32 @@ public class MapDataModel {
limit = LIMIT_NONE;
this.options = new Hashtable();
options.put(OPTION_NO_ZERO_LINKS,OPTION_SET);
// find min/max scale items:
int min = 65535;
this.minScale = -1;
for (int i = 0; i < ds.scale.length; ++i) {
if (ds.scale[i] < min) {
min = ds.scale[i];
this.minScale = min;
}
}
int max = -65535;
this.maxScale = -1;
for (int i = 0; i < ds.scale.length; ++i) {
if (ds.scale[i] > max) {
max = ds.scale[i];
this.maxScale = max;
}
}
this.currentScale = this.minScale;
System.err.println("model set minScale="+minScale+",maxScale"+maxScale+",currentScale="+currentScale);
System.err.println("model set min="+min+",max"+max);
// now set floor:
// just take the first one :-)
this.currentFloor = ds.floor[0];
System.err.println("model set currentFloor="+currentFloor);
}
public Float getCurrentPropertyDelta() {
......@@ -328,6 +362,10 @@ public class MapDataModel {
return positions.getPoint(node);
}
public Dataset getDataset() {
return this.dataset;
}
public void addChangeListener(ChangeListener listener) {
if (listener != null && !changeListeners.contains(listener)) {
changeListeners.add(listener);
......@@ -383,6 +421,36 @@ public class MapDataModel {
}
}
public void setFloor(int floor) {
this.currentFloor = floor;
notifyChangeListeners();
}
public void setScale(int scale) {
this.currentScale = scale;
notifyChangeListeners();
}
public int getFloor() {
return this.currentFloor;
}
public int getScale() {
return this.currentScale;
}
public int getMinScale() {
return this.minScale;
}
public int getMaxScale() {
return this.maxScale;
}
public float getScaleFactor() {
return this.dataset.getScaleFactor(this.currentScale);
}
private void notifyChangeListeners() {
for (Enumeration e1 = changeListeners.elements(); e1.hasMoreElements(); ) {
((ChangeListener)e1.nextElement()).stateChanged(new ChangeEvent(this));
......
......@@ -47,7 +47,7 @@
</Property>
</Properties>
<AuxValues>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ControlPanel(datasets,mapImages,nodeMapPanel);"/>
<AuxValue name="JavaCodeGenerator_CreateCodeCustom" type="java.lang.String" value="new ControlPanel(datasets,nodeMapPanel);"/>
</AuxValues>
<Constraints>
<Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout" value="org.netbeans.modules.form.compat2.layouts.DesignGridBagLayout$GridBagConstraintsDescription">
......
......@@ -12,61 +12,54 @@ import java.util.*;
public class MoteLinkViewer extends javax.swing.JFrame {
private Image bgImage;
private java.awt.image.ImageObserver io;
private Hashtable datasets;
private Hashtable mapImages;
public MoteLinkViewer() {
public MoteLinkViewer(Dataset[] sets) {
this.datasets = new Hashtable();
this.mapImages = new Hashtable();
io = new java.awt.Component() {
public boolean updateImage(Image img, int infoflags, int x, int y, int width, int height) {
System.out.println("w = "+width+",h = "+height);
return true;
for (int i = 0; i < sets.length; ++i) {
java.awt.image.ImageObserver io;
java.awt.Image bgImage;
io = new java.awt.Component() {
public boolean updateImage(Image img, int infoflags, int x, int y, int width, int height) {
System.out.println("w = "+width+",h = "+height);
return true;
}
};
sets[i].addFloor(0);
sets[i].addScale(1);
Image ti = Toolkit.getDefaultToolkit().getImage(sets[i].image_path);
sets[i].addImage(ti,0,1);
try {
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(ti, 0);
tracker.waitForID(0);
//System.out.println("width = "+bgImage.getWidth(io));
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
};
bgImage = Toolkit.getDefaultToolkit().getImage("/home/david/from_cvs/wireless-stats/floormap.jpg");
mapImages.put("Floor4/WSN",bgImage);
try {
MediaTracker tracker = new MediaTracker(this);
tracker.addImage(bgImage, 0);
tracker.waitForID(0);
//System.out.println("width = "+bgImage.getWidth(io));
}
catch (InterruptedException ex) {
ex.printStackTrace();
}
// in the applet, we'll read in the possible datasets and
GenericWirelessData defaultData = null;
NodePosition defaultPositions = null;
MapDataModel defaultModel = null;
String defaultDatasetName = "Floor4/WSN";
try {
defaultData = GenericStats.parseDumpFile("/home/david/from_cvs/wireless-stats/nn_client.log");
defaultPositions = NodePositions.parseFile("/home/david/from_cvs/wireless-stats/mote_positions");
defaultModel = new MapDataModel(defaultData,defaultPositions);
datasets.put(defaultDatasetName,defaultModel);
}
catch (Exception e) {
e.printStackTrace();
System.exit(-2);
// in the applet, we'll read in the possible datasets and
try {
sets[i].data = GenericStats.parseDumpFile(sets[i].dataFile);
sets[i].positions = NodePositions.parseFile(sets[i].positionFile);
sets[i].model = new MapDataModel(sets[i]);
datasets.put(sets[i].name,sets[i]);
}
catch (Exception e) {
e.printStackTrace();
System.exit(-2);
}
}
initComponents();
;
}
// <editor-fold defaultstate="collapsed" desc=" Generated Code ">//GEN-BEGIN:initComponents
......@@ -78,7 +71,7 @@ public class MoteLinkViewer extends javax.swing.JFrame {
//nodeMapPanel.setBackgroundImage(bgImage);
//nodeMapPanel.setPositions(positions);
//nodeMapPanel.setILEStats(model);
controlPanel = new ControlPanel(datasets,mapImages,nodeMapPanel);
controlPanel = new ControlPanel(datasets,nodeMapPanel);
getContentPane().setLayout(new java.awt.GridBagLayout());
......@@ -100,13 +93,39 @@ public class MoteLinkViewer extends javax.swing.JFrame {
getContentPane().add(controlPanel, gridBagConstraints);
pack();
}
// </editor-fold>//GEN-END:initComponents
}// </editor-fold>//GEN-END:initComponents
public static void main(final String args[]) {
int floor;
float ppm;
String name,positionFile,dataFile,image_path,building;
Vector dsaV = new Vector();
for (int i = 0; i < args.length; ++i) {
String[] aa = args[i].split(",");
if (aa.length == 7) {
name = aa[0];
positionFile = aa[1];
dataFile = aa[2];
building = aa[3];
floor = Integer.parseInt(aa[4]);
image_path = aa[5];
ppm = Float.parseFloat(aa[6]);
dsaV.add(new Dataset(name,positionFile,dataFile,building,floor,image_path,ppm));
}
}
final Dataset[] dsa = new Dataset[dsaV.size()];
int i = 0;
for (Enumeration e1 = dsaV.elements(); e1.hasMoreElements(); ) {
dsa[i++] = (Dataset)e1.nextElement();
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new MoteLinkViewer().setVisible(true);
new MoteLinkViewer(dsa).setVisible(true);
}
});
}
......
......@@ -17,6 +17,7 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
private Vector widgets;
private MapDataModel model;
private ControlPanel controlPanel;
private float scaleFactor;
/**
* Creates new form NodeMapPanel
......@@ -37,37 +38,6 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
initComponents();
//setOpaque(true);
// NodeWidget nw1,nw2;
// nw1 = new NodeWidget("mote101",50,50);
// nw2 = new NodeWidget("mote102",100,150);
// widgets.add(nw1);
// widgets.add(nw2);
// widgets.add(new LinkWidget(nw1,nw2,0.75f,0.25f));
//
// nw1 = new NodeWidget("mote103",400,250);
// nw2 = new NodeWidget("mote104",200,50);
// widgets.add(nw1);
// widgets.add(nw2);
// widgets.add(new LinkWidget(nw1,nw2,0.20f,0.60f));
//
// nw1 = new NodeWidget("mote110",100,300);
// nw2 = new NodeWidget("mote111", 300, 100);
// widgets.add(nw1);
// widgets.add(nw2);
// widgets.add(new LinkWidget(nw1,nw2,0.25f,0.75f));
//
// nw1 = new NodeWidget("mote105",300,350);
// nw2 = new NodeWidget("mote106",100,480);
// widgets.add(nw1);
// widgets.add(nw2);
// widgets.add(new LinkWidget(nw1,nw2,0.85f,0.10f));
//
// widgets.add(new NodeWidget("mote107",100,100));
// widgets.add(new NodeWidget("mote108",300,200));
// widgets.add(new LinkWidget(null,100,100,300,200,12));
}
public void setModel(MapDataModel model) {
......@@ -104,6 +74,8 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
// return;
// }
this.scaleFactor = this.model.getScaleFactor();
this.widgets.clear();
this.nodeWidgets.clear();
this.linkWidgets.clear();
......@@ -111,9 +83,11 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
String[] nodes = model.getNodes();
if (nodes != null) {
for (int i = 0; i < nodes.length; ++i) {
//System.out.println("nodes["+i+"] = '"+nodes[i]+"'");
System.out.println("nodes["+i+"] = '"+nodes[i]+"'");
Point posit = model.getPosition(nodes[i]);
NodeWidget nw = new NodeWidget(nodes[i],posit.x,posit.y);
NodeWidget nw = new NodeWidget(nodes[i],
(int)(posit.x*this.scaleFactor),
(int)(posit.y*this.scaleFactor));
this.widgets.add(nw);
this.nodeWidgets.put(nodes[i],nw);
}
......@@ -273,14 +247,14 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
// for the mote stuff, we could draw the obstacles and labels
// ourselves, but that wouldn't help for the wireless stuff...
// Composite old = g2.getComposite();
// AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f);
// g2.setComposite(ac);
//
// g2.setColor(java.awt.Color.WHITE);
// g2.fillRect(0,0,getWidth(),getHeight());
//
// g2.setComposite(old);
Composite old = g2.getComposite();
AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER,0.5f);
g2.setComposite(ac);
g2.setColor(java.awt.Color.WHITE);
g2.fillRect(0,0,getWidth(),getHeight());
g2.setComposite(old);
}
else {
......@@ -312,6 +286,10 @@ public class NodeMapPanel extends javax.swing.JPanel implements ChangeListener {
g2.dispose(); //clean up
}
public void setScaleFactor(float f) {
this.scaleFactor = f;
}
public void setBackgroundImage(final Image bgImage) {
this.bgImage = bgImage;
......
......@@ -13,7 +13,7 @@
* @author david
*/
public interface NodePosition {
public float[] getPosition(String nodeName);
public Position getPosition(String nodeName);
public java.util.Enumeration getNodeList();
public java.awt.Point getPoint(String nodeName);
}
......@@ -32,7 +32,7 @@ public class NodePositions implements NodePosition {
private static NodePositions parseReader(BufferedReader br)
throws IOException, java.text.ParseException {
Hashtable p = new Hashtable();
Hashtable pH = new Hashtable();
try {
//br = new BufferedReader(new FileReader(f));
......@@ -40,22 +40,41 @@ public class NodePositions implements NodePosition {
String line = null;
while ((line = br.readLine()) != null) {
// parse line: "mote101 350 708 0.2"
Pattern posit = Pattern.compile("([a-zA-Z0-9\\-_]+)\\s+(\\-*\\d+)\\s+(\\-*\\d+)\\s+(\\-*\\d+\\.\\d+E*\\-*\\d*)");
// parse line: "mote101 350 708 0.2 4"
// where line corresponds to "<nodename> <x> <y> <z> <floor>""
Pattern posit = Pattern.compile("([a-zA-Z0-9\\-_]+)\\s+(.+)\\s+(.+)\\s+(.+)\\s+(.+)");
Matcher positM = posit.matcher(line);
if (positM.matches()) {
float xyz[] = new float[3];
float p[] = new float[3];
int floor = -1;;
try {
p[0] = 0.0f;
p[0] = Float.parseFloat(positM.group(2));
}
catch (Exception ex) { }
try {
p[1] = 0.0f;
p[1] = Float.parseFloat(positM.group(3));
}
catch (Exception ex) { }
try {
p[2] = 0.0f;
p[2] = Float.parseFloat(positM.group(4));
}
catch (Exception ex) { }
try {
floor = Integer.parseInt(positM.group(5));
}
catch (Exception ex) { }
xyz[0] = Float.parseFloat(positM.group(2));
xyz[1] = Float.parseFloat(positM.group(3));
xyz[2] = Float.parseFloat(positM.group(4));
pH.put(positM.group(1),new Position(positM.group(1),p[0],p[1],p[2],floor));
p.put(positM.group(1),xyz);
//System.out.println(""+positM.group(1)+" ("+xyz[0]+","+xyz[1]+","+xyz[2]+")");
System.err.println(""+positM.group(1)+" ("+p[0]+","+p[1]+","+p[2]+"; "+floor+")");
}
else {
System.err.println("positline '"+line+"' did not match!");
}
}
}
......@@ -64,8 +83,11 @@ public class NodePositions implements NodePosition {
throw e;
}
return new NodePositions(p);
return new NodePositions(pH);
}
public java.util.Enumeration getNodeList() {
return this.positions.keys();
}
public static NodePositions parseInputStream(InputStream is)
......@@ -101,18 +123,15 @@ public class NodePositions implements NodePosition {
return parseReader(br);
}
public float[] getPosition(String nodeName) {
float retval[] = null;
retval = (float[])(positions.get(nodeName));
return retval;
public Position getPosition(String nodeName) {
return (Position)positions.get(nodeName);
}
public java.awt.Point getPoint(String nodeName) {