/* * Bee foraging simulation. Copyright by Joerg Hoehne. * For suggestions or questions email me at hoehne@thinktel.de */ package de.thinktel.foragingBee.masonGlue; import java.util.ListIterator; import javax.swing.JFrame; import org.jfree.data.xy.XYSeries; import sim.display.Controller; import sim.display.GUIState; import sim.engine.Schedule; import sim.engine.SimState; import sim.engine.Steppable; import sim.util.media.chart.TimeSeriesAttributes; import sim.util.media.chart.TimeSeriesChartGenerator; import de.thinktel.foragingBee.simulation.FoodSource; import de.thinktel.foragingBee.simulation.Hive; import de.thinktel.utils.TimeSeriesChartInformation; /** * This class provides an interface for a 2D display of the simulation results. * This is a glue class that is gluing MASON with the basic simulation. An * instance of class {@link SimState} holds the simulation with all simulation * parameters. This class usually takes an instance of * {@link ForagingHoneyBeeSimulation} or more likely one of the subclasses as an * argument. * <p> * Changes: * <ul> * <li>20090827: Added the windows for displaying the amount of foraging bees * and the amount of honey in the hives (one hive at the moment).</li> * <li>20090828: Changed this class to a abstract to allow 2D and 3D subclass * visualization.</li> * </ul> * <p> * Copyright 2009 Joerg Hoehne * * @author hoehne (<a href="mailto:hoehne@thinktel.de">Jörg Höhne</a>) * */ public abstract class ForagingBeeGUI extends GUIState { /** * The time series diagram for the foraging bees locked on the sources. */ TimeSeriesChartInformation tsForagingBees; /** * The time series diagram for the honey amount of the hives. */ TimeSeriesChartInformation tsHives; /** * The time series diagram for the nectar concentration of the food sources. */ TimeSeriesChartInformation tsFoodSources; /** * The food sources in the simulation, used for plotting concentrations of * nectar and the number of bees locked on this source. */ FoodSource foodSources[]; /** * The hives in the simulation used for plotting the amount of nectar in * each hive. */ Hive hives[]; /** * The Java frame (window) where the simulation is displayed in. */ public JFrame displayFrame; /** * A constructor that creates a instance with the current system time as an * argument. The holds information about the simulation but does not * visualize. Visualization is implemented by the subclasses. * <p> * This class creates the visuals so it calls * {@link ForagingHoneyBeeSimulation#prepareSimulation()} to create all * objects that will be displayed in the model inspector user interface. */ public ForagingBeeGUI(ForagingHoneyBeeSimulation sim) { super(sim); sim.prepareSimulation(); } /** * A constructor that takes a {@link SimState} instance as an argument to * create the visuals. * * @param state */ public ForagingBeeGUI(SimState state) { super(state); } /** * Return the {@link GUIState#state} object so the inspector can inspect * this object. * * @return Return the {@link GUIState#state} object. */ public Object getSimulationInspectedObject() { return state; } /** * The name of the simulation. * * @return The string containing the name of the simulation. */ public static String getName() { return "Foraging Bee Simulation in 2D"; } /** * Set up the displays. */ public abstract void setupPortrayals(); /** * Initializing structures. */ public void start() { super.start(); setupPortrayals(); int i; ForagingHoneyBeeSimulation bs = (ForagingHoneyBeeSimulation) state; foodSources = new FoodSource[bs.foodSources.size()]; hives = new Hive[bs.hives.size()]; { TimeSeriesChartGenerator chart = tsForagingBees.getChart(); chart.removeAllSeries(); XYSeries series[] = new XYSeries[foodSources.length]; tsForagingBees.setSeries(series); ListIterator<FoodSource> li = bs.foodSources.listIterator(); for (i = 0; i < series.length; i++) { foodSources[i] = li.next(); series[i] = new XYSeries("Food source" + (i + 1), false); chart.addSeries(series[i], null); // get the series for the current index TimeSeriesAttributes tsa = (TimeSeriesAttributes) chart .getSeriesAttributes(i); tsa.setStrokeColor(foodSources[i].getVisualizationObject() .getColor()); } } { TimeSeriesChartGenerator chart = tsFoodSources.getChart(); chart.removeAllSeries(); XYSeries series[] = new XYSeries[foodSources.length]; tsFoodSources.setSeries(series); // ListIterator<FoodSource> li = bs.foodSources.listIterator(); for (i = 0; i < series.length; i++) { // foodSources[i] = li.next(); series[i] = new XYSeries("Concentration food source" + (i + 1), false); chart.addSeries(series[i], null); // get the series for the current index TimeSeriesAttributes tsa = (TimeSeriesAttributes) chart .getSeriesAttributes(i); tsa.setStrokeColor(foodSources[i].getVisualizationObject() .getColor()); } } { TimeSeriesChartGenerator chart = tsHives.getChart(); chart.removeAllSeries(); XYSeries series[] = new XYSeries[hives.length]; tsHives.setSeries(series); ListIterator<Hive> li = bs.hives.listIterator(); for (i = 0; i < series.length; i++) { hives[i] = li.next(); series[i] = new XYSeries("Hive" + (i + 1), false); chart.addSeries(series[i], null); // get the series for the current index TimeSeriesAttributes tsa = (TimeSeriesAttributes) chart .getSeriesAttributes(i); tsa.setStrokeColor(foodSources[i].getVisualizationObject() .getColor()); } } scheduleImmediateRepeat(true, new Steppable() { public void step(SimState state) { // at this stage we're adding data to our chart. We // need an X value and a Y value. Typically the X // value is the schedule's timestamp. The Y value // is whatever data you're extracting from your // simulation. For purposes of illustration, let's // extract the number of steps from the schedule and // run it through a sin wave. double t = state.schedule.time(); // now add the data if (t >= Schedule.EPOCH && t < Schedule.AFTER_SIMULATION) { int i; { XYSeries series[] = tsForagingBees.getSeries(); for (i = 0; i < series.length; i++) { series[i].add(t, foodSources[i].getBeeCount(), false); } tsForagingBees.startTimer(1000); } { XYSeries series[] = tsFoodSources.getSeries(); for (i = 0; i < series.length; i++) { series[i].add(t, foodSources[i].getConcentration(), false); } tsFoodSources.startTimer(1000); } { XYSeries series[] = tsHives.getSeries(); for (i = 0; i < series.length; i++) { series[i].add(t, hives[i].getHoneyAmount(), false); } tsHives.startTimer(1000); } } } }); } /** * Called by the Console when the user is loading in a new state from a * checkpoint. * * @param state * The current simulation. */ public void load(SimState state) { super.load(state); setupPortrayals(); } /** * Initialize the graphical displays. * * @param c */ public void initGraphDisplays(Controller c) { { tsForagingBees = new TimeSeriesChartInformation(this); JFrame frame = tsForagingBees.create("Number of foraging bees", "Bees", "Time"); // perhaps you might move the chart to where you like. frame.setVisible(true); frame.pack(); c.registerFrame(frame); } { tsFoodSources = new TimeSeriesChartInformation(this); JFrame frame = tsFoodSources.create( "Concentration nectar food sources", "Concentration", "Time"); // perhaps you might move the chart to where you like. frame.setVisible(true); frame.pack(); c.registerFrame(frame); } { tsHives = new TimeSeriesChartInformation(this); JFrame frame = tsHives.create("Amount of honey in the hives", "Hives", "Time"); // perhaps you might move the chart to where you like. frame.setVisible(true); frame.pack(); c.registerFrame(frame); } // the console automatically moves itself to the right of all // of its registered frames -- you might wish to rearrange the // location of all the windows, including the console, at this // point in time.... } /** * Tidying up when simulation is to be quit. */ public void quit() { super.quit(); if (displayFrame != null) displayFrame.dispose(); displayFrame = null; } }