/**
** SillyPedsWithUI.java
**
** Copyright 2011 by Sarah Wise, Mark Coletti, Andrew Crooks, and
** George Mason University.
**
** Licensed under the Academic Free License version 3.0
**
** See the file "LICENSE" for more information
**
** $Id$
**/
package sim.app.geo.sillypeds;
import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.geom.Rectangle2D;
import java.util.ArrayList;
import javax.swing.JFrame;
import org.jfree.data.xy.XYSeries;
import sim.display.Console;
import sim.display.Controller;
import sim.display.Display2D;
import sim.display.GUIState;
import sim.engine.SimState;
import sim.engine.Steppable;
import sim.portrayal.DrawInfo2D;
//import sim.portrayal.grid.ObjectGridPortrayal2D;
import sim.portrayal.grid.FastObjectGridPortrayal2D;
import sim.portrayal.simple.RectanglePortrayal2D;
import sim.util.gui.ColorMap;
import sim.util.media.chart.TimeSeriesChartGenerator;
/**
* the GUIState that visualizes the simulation defined in WaterWorld.java
*
*/
public class SillyPedsWithUI extends GUIState
{
SillyPeds pedworld;
public ArrayList<Display2D> displays = new ArrayList<Display2D>();
ArrayList<JFrame> displayFrames = new ArrayList<JFrame>();
int numFrames = 1; // set when SillyPeds instance is read in
// portrayal data
ArrayList<FastObjectGridPortrayal2D> traces = new ArrayList<FastObjectGridPortrayal2D>();
ArrayList<FastObjectGridPortrayal2D> floors = new ArrayList<FastObjectGridPortrayal2D>();
ArrayList<FastObjectGridPortrayal2D> people = new ArrayList<FastObjectGridPortrayal2D>();
// chart information
TimeSeriesChartGenerator pedestrianChart;
XYSeries numPedestrians;
/**
* Constructor
* @param state
*/
protected SillyPedsWithUI(SimState state)
{
super(state);
pedworld = (SillyPeds) state;
numFrames = 1;
}
/**
* Main function
* @param args
*/
public static void main(String[] args)
{
SillyPedsWithUI simple = new SillyPedsWithUI(new SillyPeds(System.currentTimeMillis()));
Console c = new Console(simple);
c.setVisible(true);
}
/**
* @return name of the simulation
*/
public static String getName()
{
return "SillyPedestrians";
}
/**
* Called when starting a new run of the simulation. Sets up the portrayals
* and chart data.
*/
public void start()
{
super.start();
// set up the chart info
numPedestrians = new XYSeries("Pedestrians");
pedestrianChart.removeAllSeries();
pedestrianChart.addSeries(numPedestrians, null);
// schedule the chart to take data
state.schedule.scheduleRepeating(new Steppable()
{
public void step(SimState state)
{
numPedestrians.add(state.schedule.getTime(),
((SillyPeds) state).peds.size(),
true);
}
});
// set up the portrayals
for (int i = 0; i < displayFrames.size(); i++)
{
FastObjectGridPortrayal2D floor = floors.get(i);
floor.setField(pedworld.landscape.get(i).field);
//floor.setPortrayalForAll(new FloorPortrayal());
FastObjectGridPortrayal2D trace = traces.get(i);
trace.setField(pedworld.landscape.get(i).field);
//trace.setPortrayalForAll(new TracePortrayal());
FastObjectGridPortrayal2D peeps = people.get(i);
peeps.setField(pedworld.landscape.get(i).field);
//peeps.setPortrayalForAll(new PedPortrayal());
}
// reschedule the displayers
for (Display2D d : displays)
{
d.reset();
d.setBackdrop(backdropColor);
d.repaint();
}
}
/**
* Called when first beginning a SillyPedsWithUI. Sets up the display windows,
* the JFrames, and the chart structure.
*/
public void init(Controller c)
{
super.init(c);
// dipslay windows and JFrames
for (int i = 0; i < numFrames; i++)
{
// make a displayer
Display2D display = new Display2D(600, 600, this);
// turn off clipping
display.setClipping(false);
displays.add(display);
JFrame frame = display.createFrame();
frame.setTitle("SillyPeds Display " + (i + 1));
c.registerFrame(frame);
frame.setVisible(true);
displayFrames.add(frame);
// do the attaching here
FastObjectGridPortrayal2D newfloor = new FastObjectGridPortrayal2D()
{
public double doubleValue(Object object)
{
return ((Tile)object).baseheight;
}
};
newfloor.setMap(gradientColor);
floors.add(i, newfloor);
display.attach(newfloor, "Floor " + (i + 1));
FastObjectGridPortrayal2D newtrace = new FastObjectGridPortrayal2D()
{
public double doubleValue(Object object)
{
// Seriously, who writes Math.pow(foo, 2.0) ? See TracePortrayal below, gagh...
//return Math.pow(((Tile)object).trace, 2.0);
double trace = ((Tile)object).trace;
if (trace < 0) return trace;
else return trace * trace;
}
};
newtrace.setMap(traceColor);
traces.add(i, newtrace);
display.attach(newtrace, "Trace " + (i + 1));
FastObjectGridPortrayal2D newpeople = new FastObjectGridPortrayal2D()
{
public double doubleValue(Object object)
{
return (((Tile)object).peds.size() > 0) ? 1.0 : 0.0;
}
};
newpeople.setMap(pedColor);
people.add(i, newpeople);
display.attach(newpeople, "People " + (i + 1));
}
// chart!
pedestrianChart = new TimeSeriesChartGenerator();
pedestrianChart.setTitle("Number of Pedestrians in Simulation");
pedestrianChart.setYAxisLabel("Number of Pedestrians");
pedestrianChart.setXAxisLabel("Time");
JFrame chartFrame = pedestrianChart.createFrame(this);
// chartFrame.setVisible(true);
chartFrame.pack();
c.registerFrame(chartFrame);
}
/**
* called when quitting a simulation. Does appropriate garbage collection.
*/
public void quit()
{
super.quit();
for (JFrame frame : displayFrames)
{
if (frame != null)
{
frame.dispose();
}
frame = null;
}
for (Display2D display : displays)
{
display = null; // let gc
}
}
/////////////////////
// PORTRAYALS
/////////////////////
// colormap for ground height, which is assumed to be between 0 and 300.
ColorMap gradientColor = new sim.util.gui.SimpleColorMap(0, 2000, new Color(237, 246, 250), new Color(36, 44, 53))
{
public Color getColor(double level)
{
if (level == Double.MAX_VALUE)
{
return offwhite;
}
else return super.getColor(level);
}
public int getRGB(double level)
{
if (level == Double.MAX_VALUE)
{
return offwhite.getRGB();
}
else return super.getRGB(level);
}
public int getAlpha(double level)
{
if (level == Double.MAX_VALUE)
{
return offwhite.getAlpha();
}
else return super.getAlpha(level);
}
};
static final Color EMPTY = new Color(0,0,0,0);
// ColorMap traceColor = new sim.util.gui.SimpleColorMap(0, 2000, new Color(250, 250, 0, 50), new Color(250, 250, 0, 255));
ColorMap traceColor = new sim.util.gui.SimpleColorMap(0, 2000, new Color(250, 250, 0, 50), new Color(250, 250, 0, 255))
{
public Color getColor(double level)
{
if (level >= 0)
return super.getColor(level);
else return EMPTY;
}
public int getRGB(double level)
{
if (level >= 0)
return super.getRGB(level);
else return EMPTY.getRGB();
}
public int getAlpha(double level)
{
if (level >= 0)
return super.getAlpha(level);
else return EMPTY.getAlpha();
}
};
ColorMap pedColor = new sim.util.gui.SimpleColorMap(new Color[]{EMPTY, Color.red});
Color offwhite = new Color(253, 253, 253);
Color backdropColor = new Color(237, 246, 250);
/*
// elevation-based portrayal
class FloorPortrayal extends RectanglePortrayal2D
{
public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
{
Rectangle2D.Double draw = info.draw;
final double width = draw.width * scale;
final double height = draw.height * scale;
final int x = (int) (draw.x - width / 2.0);
final int y = (int) (draw.y - height / 2.0);
final int w = (int) (width);
final int h = (int) (height);
Tile b = (Tile) object;
graphics.setColor(gradientColor.getColor(b.baseheight));
if (b.baseheight == Double.MAX_VALUE)
{
graphics.setColor(offwhite);
}
graphics.fillRect(x, y, w, h);
}
}
// water depth-based portrayal
class PedPortrayal extends RectanglePortrayal2D
{
public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
{
Rectangle2D.Double draw = info.draw;
final double width = draw.width * scale;
final double height = draw.height * scale;
final int x = (int) (draw.x - width / 2.0);
final int y = (int) (draw.y - height / 2.0);
final int w = (int) (width);
final int h = (int) (height);
Tile b = (Tile) object;
if (b.peds.size() > 0)
{
graphics.setColor(Color.red);
graphics.fillRect(x, y, w, h);
}
}
}
// portrayal of traffic over a given tile
class TracePortrayal extends RectanglePortrayal2D
{
public void draw(Object object, Graphics2D graphics, DrawInfo2D info)
{
Rectangle2D.Double draw = info.draw;
final double width = draw.width * scale;
final double height = draw.height * scale;
final int x = (int) (draw.x - width / 2.0);
final int y = (int) (draw.y - height / 2.0);
final int w = (int) (width);
final int h = (int) (height);
Tile b = (Tile) object;
if (b.trace >= 0)
{
graphics.setColor(traceColor.getColor(Math.pow(b.trace, 2)));
graphics.fillRect(x, y, w, h);
}
}
}
*/
}