package org.opentrafficsim.demo.ntm;
import java.awt.geom.Point2D;
import java.rmi.RemoteException;
import java.util.ArrayList;
import javax.media.j3d.Bounds;
import org.djunits.unit.DurationUnit;
import org.djunits.unit.FrequencyUnit;
import org.djunits.unit.LengthUnit;
import org.djunits.unit.LinearDensityUnit;
import org.djunits.unit.SpeedUnit;
import org.djunits.value.vdouble.scalar.Duration;
import org.djunits.value.vdouble.scalar.Frequency;
import org.djunits.value.vdouble.scalar.Length;
import org.djunits.value.vdouble.scalar.LinearDensity;
import org.djunits.value.vdouble.scalar.Speed;
import org.opentrafficsim.demo.ntm.NTMNode.TrafficBehaviourType;
import org.opentrafficsim.demo.ntm.fundamentaldiagrams.FundamentalDiagram;
import nl.tudelft.simulation.dsol.animation.Locatable;
import nl.tudelft.simulation.language.d3.DirectedPoint;
/**
*
* Copyright (c) 2013-2017 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved.
* BSD-style license. See OpenTrafficSim License.
*
* $LastChangedDate$, @version $Revision$, by $Author$,
* initial version 14 Oct 2014
* @author Alexander Verbraeck
* @author Hans van Lint
* @author Peter Knoppers
* @author Guus Tamminga
* @author Yufei Yuan
*/
public class FlowCell implements Locatable
{
/** Link length in a length unit. */
private Length cellLength;
/** Link capacity in vehicles per hour. This is a mutable property (e.g., blockage). */
private Frequency maxCapacity;
/** Lanes in a link */
private int numberOfLanes;
/** SPEEDAB class java.lang.Double 120.0. */
private Speed currentSpeed;
/** SPEEDAB class java.lang.Double 120.0. */
private Duration currentTravelDuration;
/** */
private CellBehaviourFlow cellBehaviour;
/**
* @param cellLength Length;
* @param maxCapacity Frequency;
* @param speed Speed;
* @param numberOfLanes int;
* @param behaviourType TrafficBehaviourType;
*/
public FlowCell(final Length cellLength, final Frequency maxCapacity, Speed speed, final int numberOfLanes,
final TrafficBehaviourType behaviourType)
{
this.cellLength = cellLength;
this.maxCapacity = maxCapacity;
this.numberOfLanes = numberOfLanes;
ParametersFundamentalDiagram parametersFD = new ParametersFundamentalDiagram(speed, maxCapacity, numberOfLanes);
if (behaviourType == TrafficBehaviourType.FLOW)
{
this.cellBehaviour = new CellBehaviourFlow(null, parametersFD);
}
}
/**
* Retrieves car production from network fundamental diagram.
* @param accumulatedCarsPerLengthUnit double; number of cars in Cell
* @param maximumCapacity Frequency; based on area information
* @param param ParametersFundamentalDiagram; parameters FD
* @return carProduction
*/
public final Frequency retrieveCurrentInflowCapacity(final double accumulatedCarsPerLengthUnit,
final Frequency maximumCapacity, final ParametersFundamentalDiagram param)
{
Frequency currentInflowCapacity;
if (accumulatedCarsPerLengthUnit > param.getAccCritical().get(0))
{
ArrayList xyPairs = new ArrayList();
Point2D p = new Point2D.Double();
p.setLocation(0, 0);
xyPairs.add(p);
p = new Point2D.Double();
p.setLocation(param.getAccCritical().get(0), maximumCapacity.getInUnit());
xyPairs.add(p);
p = new Point2D.Double();
p.setLocation(param.getAccCritical().get(1), 0);
xyPairs.add(p);
currentInflowCapacity = FundamentalDiagram.PieceWiseLinear(xyPairs, accumulatedCarsPerLengthUnit);
}
else
{
currentInflowCapacity = maximumCapacity;
}
return currentInflowCapacity;
}
/**
* @param accumulatedCarsPerLengthUnit double;
* @return actualSpeed.
*/
public Speed retrieveCurrentSpeed(final double accumulatedCarsPerLengthUnit)
{
double speedDouble;
Frequency currentInflowCapacity = retrieveCurrentInflowCapacity(accumulatedCarsPerLengthUnit, this.maxCapacity,
this.cellBehaviour.getParametersFundamentalDiagram());
LinearDensity density = new LinearDensity(accumulatedCarsPerLengthUnit, LinearDensityUnit.PER_KILOMETER);
if (density.getInUnit(LinearDensityUnit.PER_KILOMETER) > this.cellBehaviour.getParametersFundamentalDiagram()
.getAccCritical().get(0))
{
speedDouble = currentInflowCapacity.getInUnit(FrequencyUnit.PER_HOUR)
/ density.getInUnit(LinearDensityUnit.PER_KILOMETER);
// speedDouble =
// Math.max(speedDouble, this.getCellBehaviourFlow().getParametersFundamentalDiagram().getFreeSpeed()
// .getInUnit(SpeedUnit.KM_PER_HOUR));
}
else
{
speedDouble = this.cellBehaviour.getParametersFundamentalDiagram().getCapacity().getInUnit(FrequencyUnit.PER_HOUR)
/ this.cellBehaviour.getParametersFundamentalDiagram().getAccCritical().get(0);
}
return this.setActualSpeed(new Speed(speedDouble, SpeedUnit.KM_PER_HOUR));
}
/**
* @param accumulatedCars
* @return actualSpeed.
*/
public Duration retrieveCurrentTravelDuration()
{
double densityPerLengthUnit =
this.getCellBehaviourFlow().getAccumulatedCars() / this.cellLength.getInUnit(LengthUnit.KILOMETER);
double timeDouble = this.cellLength.getInUnit(LengthUnit.KILOMETER)
/ retrieveCurrentSpeed(densityPerLengthUnit).getInUnit(SpeedUnit.KM_PER_HOUR);
double UPPERBOUND_TRAVELTIME_HOUR = 99;
timeDouble = Math.min(UPPERBOUND_TRAVELTIME_HOUR, timeDouble);
return this.setCurrentTravelDuration(new Duration(timeDouble, DurationUnit.HOUR));
}
/** {@inheritDoc} */
@Override
public DirectedPoint getLocation() throws RemoteException
{
return null;
}
/** {@inheritDoc} */
@Override
public Bounds getBounds() throws RemoteException
{
return null;
}
/**
* @return cellLength.
*/
public Length getCellLength()
{
return this.cellLength;
}
/**
* @param cellLength Length; set cellLength.
*/
public void setCellLength(Length cellLength)
{
this.cellLength = cellLength;
}
/**
* @return capacity.
*/
public Frequency getMaxCapacity()
{
return this.maxCapacity;
}
/**
* @param maxCapacity Frequency; set capacity.
*/
public void setMaxCapacity(Frequency maxCapacity)
{
this.maxCapacity = maxCapacity;
}
/**
* @return cellBehaviour.
*/
public CellBehaviourFlow getCellBehaviourFlow()
{
return this.cellBehaviour;
}
/**
* @param cellBehaviour CellBehaviourFlow; set cellBehaviour.
*/
public void setCellBehaviourFlow(CellBehaviourFlow cellBehaviour)
{
this.cellBehaviour = cellBehaviour;
}
/**
* @return numberOfLanes.
*/
public int getNumberOfLanes()
{
return this.numberOfLanes;
}
/**
* @param numberOfLanes int; set numberOfLanes.
*/
public void setNumberOfLanes(int numberOfLanes)
{
this.numberOfLanes = numberOfLanes;
}
/**
* @return actualSpeed.
*/
public Speed getCurrentSpeed()
{
return this.currentSpeed;
}
/**
* @param currentSpeed Speed; set actualSpeed.
*/
public Speed setActualSpeed(Speed currentSpeed)
{
this.currentSpeed = currentSpeed;
return currentSpeed;
}
/**
* @return currentTravelTime.
*/
public Duration getCurrentTravelDuration()
{
return this.currentTravelDuration;
}
/**
* @param currentTravelDuration Duration; set currentTravelTime.
*/
public Duration setCurrentTravelDuration(Duration currentTravelDuration)
{
this.currentTravelDuration = currentTravelDuration;
return currentTravelDuration;
}
}