AbstractSpaceTimePlot.java

  1. package org.opentrafficsim.draw.graphs;

  2. import org.djunits.value.vdouble.scalar.Duration;
  3. import org.djunits.value.vdouble.scalar.Length;
  4. import org.djunits.value.vdouble.scalar.Time;
  5. import org.jfree.chart.JFreeChart;
  6. import org.jfree.chart.event.AxisChangeEvent;
  7. import org.jfree.chart.event.AxisChangeListener;
  8. import org.jfree.chart.plot.XYPlot;
  9. import org.opentrafficsim.core.dsol.OTSSimulatorInterface;

  10. /**
  11.  * Plots with space-time. This class adds some zoom control, where a user can manually select a zoom range, or the plot
  12.  * automatically zooms over the entire space range, and either the entire or some most recent fixed period in time.
  13.  * <p>
  14.  * Copyright (c) 2013-2020 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  15.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  16.  * <p>
  17.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 14 okt. 2018 <br>
  18.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  19.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  20.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  21.  */
  22. public abstract class AbstractSpaceTimePlot extends AbstractBoundedPlot
  23. {

  24.     /** Initial end time of plot. */
  25.     private final Time initialEnd;

  26.     /** Whether to update the axes. */
  27.     private boolean autoBoundAxes = true;

  28.     /** Whether to disable auto bounds on the axes on any change on the axes. */
  29.     private boolean virtualAutoBounds = false;

  30.     /** Fixed domain range. */
  31.     private Double fixedDomainRange = null;

  32.     /**
  33.      * Constructor.
  34.      * @param caption String; caption
  35.      * @param updateInterval Duration; regular update interval (simulation time)
  36.      * @param simulator OTSSimulatorInterface; simulator
  37.      * @param delay Duration; amount of time that chart runs behind simulation to prevent gaps in the charted data
  38.      * @param initialEnd Time; initial end time of plots, will be expanded if simulation time exceeds it
  39.      */
  40.     public AbstractSpaceTimePlot(final String caption, final Duration updateInterval, final OTSSimulatorInterface simulator,
  41.             final Duration delay, final Time initialEnd)
  42.     {
  43.         super(simulator, caption, updateInterval, delay);
  44.         this.initialEnd = initialEnd;
  45.     }

  46.     /** {@inheritDoc} */
  47.     @Override
  48.     protected void setChart(final JFreeChart chart)
  49.     {
  50.         super.setChart(chart);
  51.         XYPlot xyPlot = chart.getXYPlot();
  52.         setLowerRangeBound(0.0);
  53.         setUpperRangeBound(getEndLocation().si);
  54.         setLowerDomainBound(0.0);
  55.         setUpperDomainBound(this.initialEnd.si);
  56.         setAutoBounds(xyPlot);
  57.         // axis listeners to enable/disable auto zoom
  58.         xyPlot.getDomainAxis().addChangeListener(new AxisChangeListener()
  59.         {
  60.             /** {@inheritDoc} */
  61.             @SuppressWarnings("synthetic-access")
  62.             @Override
  63.             public void axisChanged(final AxisChangeEvent event)
  64.             {
  65.                 if (!AbstractSpaceTimePlot.this.virtualAutoBounds)
  66.                 {
  67.                     // the axis was changed, but not by a command from this class, auto bounds should be disabled
  68.                     AbstractSpaceTimePlot.this.autoBoundAxes = false;
  69.                 }
  70.             }
  71.         });
  72.     }

  73.     /** {@inheritDoc} */
  74.     @Override
  75.     protected void update()
  76.     {
  77.         if (getUpdateTime() != null && this.initialEnd != null)
  78.         {
  79.             setUpperDomainBound(Math.max(getUpdateTime().si, this.initialEnd.si));
  80.         }
  81.         if (this.autoBoundAxes && getChart() != null) // null during construction
  82.         {
  83.             setAutoBounds(getChart().getXYPlot());
  84.         }
  85.         super.update();
  86.     }

  87.     /**
  88.      * Update the fixed-ness of the domain range.
  89.      * @param fixed boolean; if true; the domain range will not update when new data becomes available; if false; the domain
  90.      *            range will update to show newly available data
  91.      */
  92.     public void updateFixedDomainRange(final boolean fixed)
  93.     {
  94.         this.fixedDomainRange = fixed ? getChart().getXYPlot().getDomainAxis().getRange().getLength() : null;
  95.         notifyPlotChange();
  96.     }

  97.     /**
  98.      * Sets the auto bounds without deactivating auto bounds through the axis change listener. This is used to initialize the
  99.      * plot, and to update the plot when time is increased.
  100.      * @param plot XYPlot; plot with default zoom-all bounds set
  101.      */
  102.     private void setAutoBounds(final XYPlot plot)
  103.     {
  104.         // disables the axis change listener from registering a user input that is actually an update of bounds as the time
  105.         // increases
  106.         this.virtualAutoBounds = true;
  107.         if (this.fixedDomainRange != null && getUpdateTime().si > 0.0)
  108.         {
  109.             plot.getDomainAxis().setRange(Math.max(getUpdateTime().si - this.fixedDomainRange, 0.0), getUpdateTime().si);
  110.         }
  111.         else
  112.         {
  113.             super.setAutoBoundDomain(plot); // super to skip setting autoBoundAxes = true
  114.         }
  115.         super.setAutoBoundRange(plot); // super to skip setting autoBoundAxes = true
  116.         this.virtualAutoBounds = false;
  117.     }

  118.     /** {@inheritDoc} This implementation overrides to enable it's own form of auto bounds. */
  119.     @Override
  120.     public final void setAutoBoundDomain(final XYPlot plot)
  121.     {
  122.         super.setAutoBoundDomain(plot);
  123.         this.autoBoundAxes = true;
  124.     }

  125.     /** {@inheritDoc} This implementation overrides to enable it's own form of auto bounds. */
  126.     @Override
  127.     public final void setAutoBoundRange(final XYPlot plot)
  128.     {
  129.         super.setAutoBoundRange(plot);
  130.         this.autoBoundAxes = true;
  131.     }

  132.     /**
  133.      * Returns the total path length.
  134.      * @return Length; total path length
  135.      */
  136.     protected abstract Length getEndLocation();

  137. }