Interpolation.java

  1. package org.opentrafficsim.road.gtu.strategical.od;

  2. import org.djunits.unit.FrequencyUnit;
  3. import org.djunits.unit.TimeUnit;
  4. import org.djunits.value.ValueException;
  5. import org.djunits.value.vdouble.scalar.Frequency;
  6. import org.djunits.value.vdouble.scalar.Time;
  7. import org.djunits.value.vdouble.vector.FrequencyVector;
  8. import org.djunits.value.vdouble.vector.TimeVector;

  9. /**
  10.  * Interpolation of demand.
  11.  * <p>
  12.  * Copyright (c) 2013-2018 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  13.  * BSD-style license. See <a href="http://opentrafficsim.org/docs/current/license.html">OpenTrafficSim License</a>.
  14.  * <p>
  15.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version Sep 15, 2016 <br>
  16.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  17.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  18.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  19.  */
  20. public enum Interpolation
  21. {

  22.     /** Stepwise interpolation of demand. */
  23.     STEPWISE
  24.     {
  25.         /** {@inheritDoc} */
  26.         @Override
  27.         Frequency interpolate(final Frequency frequency0, final Time time0, final Frequency frequency1,
  28.                 final Time time1, final Time time)
  29.         {
  30.             return frequency0;
  31.         }

  32.         /** {@inheritDoc} */
  33.         @Override
  34.         int integrate(final Frequency frequency0, final Time time0, final Frequency frequency1, final Time time1)
  35.         {
  36.             return (int) (frequency0.getInUnit(FrequencyUnit.PER_HOUR)
  37.                     * (time1.getInUnit(TimeUnit.BASE_HOUR) - time0.getInUnit(TimeUnit.BASE_HOUR)));
  38.         }
  39.     },

  40.     /** Linear interpolation of demand. */
  41.     LINEAR
  42.     {
  43.         /** {@inheritDoc} */
  44.         @Override
  45.         Frequency interpolate(final Frequency frequency0, final Time time0, final Frequency frequency1,
  46.                 final Time time1, final Time time)
  47.         {
  48.             return Frequency.interpolate(frequency0, frequency1, (time.si - time0.si) / (time1.si - time0.si));
  49.         }

  50.         /** {@inheritDoc} */
  51.         @Override
  52.         int integrate(final Frequency frequency0, final Time time0, final Frequency frequency1, final Time time1)
  53.         {
  54.             return (int) (0.5 * (frequency0.getInUnit(FrequencyUnit.PER_HOUR) + frequency1.getInUnit(FrequencyUnit.PER_HOUR))
  55.                     * (time1.getInUnit(TimeUnit.BASE_HOUR) - time0.getInUnit(TimeUnit.BASE_HOUR)));
  56.         }
  57.     };

  58.     /**
  59.      * Interpolate between given frequencies.
  60.      * @param frequency0 frequency at {@code time0}
  61.      * @param time0 time of {@code frequency0} (&le; {@code time})
  62.      * @param frequency1 frequency at {@code time1}
  63.      * @param time1 time of {@code frequency1} (&gt; {@code time})
  64.      * @param time {@code time0} &le; {@code time} &lt; {@code time1}
  65.      * @return interpolated frequency
  66.      */
  67.     abstract Frequency interpolate(Frequency frequency0, Time time0, Frequency frequency1, Time time1, Time time);

  68.     /**
  69.      * Integrates to the number of trips in given period.
  70.      * @param frequency0 frequency at {@code time0}
  71.      * @param time0 time of {@code frequency0} (&le; {@code time})
  72.      * @param frequency1 frequency at {@code time1}
  73.      * @param time1 time of {@code frequency1} (&gt; {@code time})
  74.      * @return number of trips in given period
  75.      */
  76.     abstract int integrate(Frequency frequency0, Time time0, Frequency frequency1, Time time1);

  77.     /**
  78.      * @return whether this is step-wise interpolation
  79.      */
  80.     public boolean isStepWise()
  81.     {
  82.         return this.equals(STEPWISE);
  83.     }

  84.     /**
  85.      * @return whether this is linear interpolation
  86.      */
  87.     public boolean isLinear()
  88.     {
  89.         return this.equals(LINEAR);
  90.     }

  91.     /**
  92.      * Returns interpolated value from array at given time. If time is outside of the vector range, 0 is returned.
  93.      * @param time Time; time to determine the frequency at
  94.      * @param demandVector FrequencyVevtor; demand vector
  95.      * @param timeVector DurationVector; time vector
  96.      * @param sliceStart boolean; whether the time is at the start of an arbitrary time slice
  97.      * @return interpolated value from array at given time, or 0 when time is outside of range
  98.      */
  99.     public final Frequency interpolateVector(final Time time, final FrequencyVector demandVector,
  100.             final TimeVector timeVector, final boolean sliceStart)
  101.     {
  102.         try
  103.         {
  104.             // empty data or before start or after end, return 0
  105.             // case 1: t < t(0)
  106.             // case 2: sliceEnd & t == t(0), i.e. end of no-demand time before time array
  107.             // case 3: sliceStart & t == t(end), i.e. start of no-demand time after time array
  108.             // case 4: t > t(end)
  109.             if (timeVector.size() == 0 || (sliceStart ? time.lt(timeVector.get(0)) : time.le(timeVector.get(0))) || (sliceStart
  110.                     ? time.ge(timeVector.get(timeVector.size() - 1)) : time.gt(timeVector.get(timeVector.size() - 1))))
  111.             {
  112.                 return new Frequency(0.0, FrequencyUnit.PER_HOUR); // Frequency.ZERO give "Hz" which is not nice for flow
  113.             }
  114.             // interpolate
  115.             for (int i = 0; i < timeVector.size() - 1; i++)
  116.             {
  117.                 // cases where we can take the slice from i to i+1
  118.                 // case 1: sliceStart & t(i+1) > t [edge case: t(i) = t]
  119.                 // case 2: sliceEnd & t(i+1) >= t [edge case: t(i+1) = t]
  120.                 if (sliceStart ? timeVector.get(i + 1).gt(time) : timeVector.get(i + 1).ge(time))
  121.                 {
  122.                     return interpolate(demandVector.get(i), timeVector.get(i), demandVector.get(i + 1), timeVector.get(i + 1),
  123.                             time);
  124.                 }
  125.             }
  126.         }
  127.         catch (ValueException ve)
  128.         {
  129.             // should not happen, vector lengths are checked when given is input
  130.             throw new RuntimeException("Index out of bounds.", ve);
  131.         }
  132.         // should not happen
  133.         throw new RuntimeException("Demand interpolation failed.");
  134.     }

  135. }