Class TrainsEnvironment


public class TrainsEnvironment extends LongAgentsEnvironment<RailNode,RailArc,LongAgentWeightKey>
Environment for trains (see Train class). Supports @TrainRoute calculation consider maneuvers, non-moving trains blocking traffic, as well as reserved tracks.. Trains can live only in this type of environments.
Author:
Andrey Korotin
  • Field Details

  • Constructor Details

    • TrainsEnvironment

      public TrainsEnvironment()
  • Method Details

    • pathsCacheEnabled

      public boolean pathsCacheEnabled()
      Description copied from class: GraphEnvironment
      Checks whether caching of the paths is enabled. Enabling paths cache increases the speed of modeling but must be used with caution when the weight of nodes or arcs change as the simulation time goes. In this case, it is still possible to use paths caching but GraphEnvironment.clearCache() method must be called when the weights of nodes or arcs change.

      Paths cache can be enabled or disabled in constructor of this class.

      Overrides:
      pathsCacheEnabled in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Returns:
      true if caching of the paths is enabled, false otherwise
    • createNewTrain

      public Train createNewTrain(List<? extends RailCar> cars)
      Creates a new Train composed of the specified list of rail cars.

      This method is intended to be overridden by subclasses to provide a proper implementation for creating trains. The default implementation throws a RuntimeException.

      Parameters:
      cars - the list of RailCars that make up the new train
      Returns:
      a new Train instance composed of the given cars
      Throws:
      RuntimeException - always, unless overridden in a subclass
    • createNewRailTrack

      public RailTrack createNewRailTrack(String name, Graph<RailNode,RailArc>.Arc forwardArc, Graph<RailNode,RailArc>.Arc backwardArc)
      Creates a new RailTrack with the specified name and connecting arcs.
      Parameters:
      name - the name of the new rail track
      forwardArc - the forward Graph.Arc
      backwardArc - the backward Graph.Arc
      Returns:
      a new RailTrack instance connecting the given arcs
    • createNewRailNode

      public RailNode createNewRailNode(String name, Point point)
      Creates a new RailNode at the specified point with the given name.
      Parameters:
      name - the name of the new rail node
      point - the Point representing the position of the node
      Returns:
      a new RailNode instance at the specified location
    • getArcWeight

      public double getArcWeight(RailArc arcValue, LongAgentWeightKey longAgentWeightKey)
      Description copied from class: GraphEnvironment
      Returns the weight of the specified arc used when calculating the shortest paths for agents' movements. Can be overridden in subclasses. The default implementation returns the length of the specified arc, i.e.:

      return arcValue.getLength();

      Overrides:
      getArcWeight in class LongAgentsEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Parameters:
      arcValue - specified arc
      longAgentWeightKey - an additional parameter used to parameterize the calculation if necessary. For example, can be agent if the paths should be calculated differently for each agent
      Returns:
      weight of this arc, must be non-negative
    • getPartialArcWeight

      public double getPartialArcWeight(RailArc arcValue, double startAbsOffset, double endAbsOffset, double startRelOffset, double endRelOffset, LongAgentWeightKey longAgentWeightKey)
      Description copied from class: GraphEnvironment
      Returns the weight of the fragment of the specified arc. The fragment of the arc is defined by absolute and relative offsets of its beginning and end.

      Overriding this method allows users, for example, to make certain fragments of arcs less preferable or forbidden for use in path finding.

      The default implementation is to return the weight of the fragment, i.e.:

      return getArcWeight(arcValue, weightKey) * Utils.zidz(endAbsOffset - startAbsOffset, arcValue.getLength());

      For more information about absolute and relative offsets, see documentation of Polyline class. See how the total weight of the arc is calculated:

      Overrides:
      getPartialArcWeight in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Parameters:
      arcValue - specified arc
      startAbsOffset - absolute offset of the fragment's beginning
      endAbsOffset - absolute offset of the fragment's end
      startRelOffset - relative offset of the fragment's beginning
      endRelOffset - relative offset of the fragment's end
      longAgentWeightKey - an additional parameter used to parameterize the calculation if necessary. For example, can be agent if the paths should be calculated differently for each agent
      Returns:
      weight of the fragment of the specified arc, must be non-negative
    • barrierArcsCacheEnabled

      public boolean barrierArcsCacheEnabled()
      Overrides:
      barrierArcsCacheEnabled in class LongAgentsEnvironment<RailNode,RailArc,LongAgentWeightKey>
    • isAngleSharp

      public boolean isAngleSharp(Graph<RailNode,RailArc>.Arc prevArc, Graph<RailNode,RailArc>.Arc nextArc)
      Determines whether the corner formed by two consecutive arcs is a sharp angle.

      The angle is considered sharp if it is greater than or equal to SHARP_CORNER_THRESHOLD.

      Parameters:
      prevArc - the previous Graph.Arc
      nextArc - the next Graph.Arc
      Returns:
      true if the angle between the arcs is sharp, false otherwise
    • getAngleBetweenArcs

      public static double getAngleBetweenArcs(Graph<RailNode,RailArc>.Arc prevArc, Graph<RailNode,RailArc>.Arc nextArc)
      Calculates the angle (in radians) between two consecutive arcs.

      The angle is computed using the last segment of the previous arc and the first segment of the next arc, based on their direction vectors.

      Parameters:
      prevArc - the previous Graph.Arc
      nextArc - the next Graph.Arc
      Returns:
      the angle between the two arcs in radians, normalized to [0, 2π)
    • getSharpTurnOffsets

      public static List<Pair<Double,Double>> getSharpTurnOffsets(Polyline polyline, double sharpTurnLength, double minHeadingDifferenceOfSharpTurn)
      Identifies sections of a polyline that contain sharp turns.

      A turn is considered sharp if the absolute heading difference between consecutive segments exceeds the specified minHeadingDifferenceOfSharpTurn. For each detected sharp turn, the method returns a pair of offsets defining a segment of the polyline that should be considered for special handling (e.g., slowing down a train).

      Parameters:
      polyline - the Polyline to analyze for sharp turns
      sharpTurnLength - the length before and after the turning point to include in the sharp turn segment
      minHeadingDifferenceOfSharpTurn - the minimum heading difference (in radians or degrees, consistent with GeometryUtil.getAbsHeadingDifference(double, double)) between consecutive segments to consider a turn sharp
      Returns:
      a list of Pairs, where each pair contains:
      • the beginning offset of the sharp turn segment along the polyline
      • the ending offset of the sharp turn segment along the polyline
    • addRailNode

      public RailNode addRailNode(String name, Point point)
      Creates a new RailNode with the given name and position, adds it to the graph, and returns the created node.
      Parameters:
      name - the name of the new rail node
      point - the Point representing the position of the rail node
      Returns:
      the newly created RailNode added to the graph
    • addRailTrack

      public RailTrack addRailTrack(RailNode sourceNode, RailNode destNode, String name, Polyline forwardPolyline)
      Adds a new RailTrack between the specified source and destination nodes, using the given forward Polyline. A backward polyline is automatically created as the reversed version of the forward polyline.

      This method validates that the nodes exist in the graph and that the polyline has at least two points and non-zero length. It creates forward and backward RailArcs, links them as reverse arcs, adds them to the graph, and returns a new RailTrack representing the connection.

      Parameters:
      sourceNode - the source RailNode for the track
      destNode - the destination RailNode for the track
      name - the name of the rail track
      forwardPolyline - the Polyline representing the forward direction of the track
      Returns:
      the newly created RailTrack connecting the source and destination nodes
      Throws:
      RuntimeException - if the polyline is null, has fewer than 2 points, or has zero length, or if either node is null or not present in the graph
    • addRailNode

      public RailNode addRailNode(RailNode railNode)
      Adds an existing RailNode to the rail graph.

      The method checks that the node is not null and has not already been added to the graph.

      Parameters:
      railNode - the RailNode to add
      Returns:
      the added RailNode
      Throws:
      NullPointerException - if railNode is null
      RuntimeException - if the node is already present in the graph
    • addNode

      public Graph<RailNode,RailArc>.Node addNode(RailNode railNode)
      Description copied from class: GraphEnvironment
      Creates a new graph node with the specified node value and adds it to the graph.
      Overrides:
      addNode in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Parameters:
      railNode - value of the node being added
      Returns:
      Graph.Node instance that was created and added to the graph
    • addArc

      public Graph<RailNode,RailArc>.Arc addArc(RailNode n1, RailNode n2, RailArc a)
      Description copied from class: GraphEnvironment
      Creates a new graph arc between the nodes with the specified values. Assigns the specified value to the created arc and adds it to the graph.
      Overrides:
      addArc in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Parameters:
      n1 - value of the source node
      n2 - value of the destination node
      a - value of the arc being added
      Returns:
      Graph.Arc instance that was created and added to the graph, or null if no source or destination node with the specified values were found
    • addArc

      Description copied from class: GraphEnvironment
      Creates two new graph arcs (one forward and one backward) between the nodes with the specified values. Assigns the specified values to the created arcs and adds them to the graph.
      Overrides:
      addArc in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
      Parameters:
      n1 - value of the source node of the forward arc
      n2 - value of the destination node of the forward arc
      a1 - value of the forward arc being added
      a2 - value of the reverse arc being added
      Returns:
      a Pair of Graph.Arc instances that were created and added to the graph, or null if no source or destination node with the specified values were found
    • calculatePartialArcWeight

      public double calculatePartialArcWeight(RailArc arcValue, double startAbsOffset, double endAbsOffset, Set<RailArc> prohibitedArcs, Predicate<Train> considerTrainsPredicate)
      Calculates the weight of a partial arc segment between the specified absolute offsets.

      The base weight equals the length of the segment (endAbsOffset - startAbsOffset), but it may be replaced by OCCUPIED_TRACK_WEIGHT if the arc is either explicitly prohibited or overlaps with other agents (e.g., trains) according to the specified predicate.

      When the arc is considered occupied, it is added to barrierArcs.

      Parameters:
      arcValue - the RailArc whose segment weight is being calculated
      startAbsOffset - the starting absolute offset along the arc
      endAbsOffset - the ending absolute offset along the arc
      prohibitedArcs - a set of arcs that are prohibited for traversal
      considerTrainsPredicate - a predicate determining which Trains should be considered when checking for overlapping non-moving agents
      Returns:
      the calculated segment weight — either the physical length of the segment or OCCUPIED_TRACK_WEIGHT if the arc is blocked
    • calculateArcWeight

      public double calculateArcWeight(RailArc arcValue, LongAgentWeightKey longAgentWeightKey)
      Calculates the weight of traversing the specified RailArc.

      The base weight is the physical length of the arc’s polyline. If the arc is in the set of prohibited arcs or if there are trains on the corresponding track that must be considered, the arc is marked as a barrier and the weight is replaced with OCCUPIED_TRACK_WEIGHT.

      Parameters:
      arcValue - the RailArc whose weight is being calculated
      longAgentWeightKey - a key representing the agent for which weight is considered; may be used in custom weighting logic
      Returns:
      the calculated arc weight — either the polyline length or OCCUPIED_TRACK_WEIGHT if the arc is blocked
    • getShortestPath

      Overrides:
      getShortestPath in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
    • getShortestPath

      public AgentGraphPath<RailNode,RailArc> getShortestPath(GeometricGraphPosition<RailNode,RailArc> sourcePosition, Predicate<Graph<RailNode,RailArc>.Node> destNodeIndicator)
      Overrides:
      getShortestPath in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
    • getShortestPath

      public AgentGraphPath<RailNode,RailArc> getShortestPath(Graph<RailNode,RailArc>.Node sourceNode, Graph<RailNode,RailArc>.Node destNode)
      Overrides:
      getShortestPath in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
    • getShortestPath

      public AgentGraphPath<RailNode,RailArc> getShortestPath(RailNode sourceNodeValue, RailNode destNodeValue)
      Overrides:
      getShortestPath in class GraphEnvironment<RailNode,RailArc,LongAgentWeightKey>
    • calculateRoute

      public TrainRoute calculateRoute(GeometricGraphPosition<RailNode,RailArc> sourcePosition, GeometricGraphPosition<RailNode,RailArc> destPosition, Train train, boolean considerBookedTracks, boolean considerTrainsPredicate, Set<RailArc> prohibitedArcs, double beginTime, double velocity)
      Calculates a route for the specified Train from a source position to a destination position.

      The route calculation considers booked tracks, prohibited arcs, and necessary nodes to visit. Arcs that are blocked or overlap with non-moving trains according to the provided predicates are marked as barriers and influence the route selection.

      Parameters:
      sourcePosition - the starting position in the geometric graph
      destPosition - the destination position in the geometric graph
      train - the Train for which the route is being calculated
      considerBookedTracks - whether booked tracks should be considered as obstacles
      considerTrainsPredicate - whether non-moving trains should be considered as obstacles
      prohibitedArcs - a set of RailArcs that are forbidden for the train
      beginTime - the starting time for the route calculation
      velocity - the velocity of the train, used for timing along the route
      Returns:
      a TrainRoute representing the calculated path from source to destination
    • calculateRouteOrBarrierArcs

      public Pair<TrainRoute,List<RailArc>> calculateRouteOrBarrierArcs(GeometricGraphPosition<RailNode,RailArc> sourcePosition, GeometricGraphPosition<RailNode,RailArc> destPosition, Train train, boolean considerBookedTracks, boolean considerTrainsPredicate, Set<RailArc> prohibitedArcs, List<RailNode> visitNodes, double beginTime, double velocity)
      Calculates a route and barriers arcs for the specified Train from a source position to a destination position.

      The route calculation considers booked tracks, prohibited arcs, and necessary nodes to visit. Arcs that are blocked or overlap with non-moving trains according to the provided predicates are marked as barriers and influence the route selection.

      Parameters:
      sourcePosition - the starting position in the geometric graph
      destPosition - the destination position in the geometric graph
      train - the Train for which the route is being calculated
      considerBookedTracks - whether booked tracks should be considered as obstacles
      considerTrainsPredicate - whether non-moving trains should be considered as obstacles
      prohibitedArcs - a set of RailArcs that are forbidden for the train
      visitNodes - a list of RailNodes that the route must visit in the specified order
      beginTime - the starting time for the route calculation
      velocity - the velocity of the train, used for timing along the route
      Returns:
      a Pair containing:
      • the calculated TrainRoute, or null if no route could be found
      • a list of RailArcs which prevent the route from being found
    • calculateRouteOrBarrierArcs

      public Pair<TrainRoute,List<RailArc>> calculateRouteOrBarrierArcs(GeometricGraphPosition<RailNode,RailArc> sourcePosition, GeometricGraphPosition<RailNode,RailArc> destPosition, Train train, boolean considerBookedTracks, boolean considerTrainsPredicate, Set<RailArc> prohibitedArcs, double beginTime, double velocity)
      Calculates a route and barriers arcs for the specified Train from a source position to a destination position.

      The route calculation considers booked tracks, prohibited arcs, and necessary nodes to visit. Arcs that are blocked or overlap with non-moving trains according to the provided predicates are marked as barriers and influence the route selection.

      Parameters:
      sourcePosition - the starting position in the geometric graph
      destPosition - the destination position in the geometric graph
      train - the Train for which the route is being calculated
      considerBookedTracks - whether booked tracks should be considered as obstacles
      considerTrainsPredicate - whether non-moving trains should be considered as obstacles
      prohibitedArcs - a set of RailArcs that are forbidden for the train
      beginTime - the starting time for the route calculation
      velocity - the velocity of the train, used for timing along the route
      Returns:
      a Pair containing:
      • the calculated TrainRoute, or null if no route could be found
      • a list of RailArcs which prevent the route from being found
    • calculateRoute

      public TrainRoute calculateRoute(GeometricGraphPosition<RailNode,RailArc> sourcePosition, GeometricGraphPosition<RailNode,RailArc> destPosition, Train train, boolean considerBookedTracks, boolean considerTrainsPredicate, Set<RailArc> prohibitedArcs, List<RailNode> visitNodes, double beginTime, double velocity)
      Calculates a route for the specified Train from a source position to a destination position.

      The route calculation considers booked tracks, prohibited arcs, and necessary nodes to visit. Arcs that are blocked or overlap with non-moving trains according to the provided predicates are marked as barriers and influence the route selection.

      Parameters:
      sourcePosition - the starting position in the geometric graph
      destPosition - the destination position in the geometric graph
      train - the Train for which the route is being calculated
      considerBookedTracks - whether booked tracks should be considered as obstacles
      considerTrainsPredicate - whether non-moving trains should be considered as obstacles
      prohibitedArcs - a set of RailArcs that are forbidden for the train
      visitNodes - a list of RailNodes that the route must visit in the specified order
      beginTime - the starting time for the route calculation
      velocity - the velocity of the train, used for timing along the route
      Returns:
      a TrainRoute representing the calculated path from source to destination
    • calculateRoute

      public TrainRoute calculateRoute(GeometricGraphPosition<RailNode,RailArc> sourcePosition, GeometricGraphPosition<RailNode,RailArc> destPosition, Train train, BiPredicate<RailTrack,Object> considerBookedTracks, Predicate<Train> considerTrainsPredicate, Set<RailArc> prohibitedArcs, List<RailNode> visitNodes, double beginTime, double velocity)
      Calculates a route for the specified Train from a source position to a destination position.

      The route calculation considers booked tracks, prohibited arcs, and necessary nodes to visit. Arcs that are blocked or overlap with non-moving trains according to the provided predicates are marked as barriers and influence the route selection.

      Parameters:
      sourcePosition - the starting position in the geometric graph
      destPosition - the destination position in the geometric graph
      train - the Train for which the route is being calculated
      considerBookedTracks - a BiPredicate to determine which booked tracks should be treated as occupied; the first argument is a RailTrack, the second is the booker object
      considerTrainsPredicate - a Predicate that determines which non-moving trains should be considered as obstacles; only trains for which this predicate returns true are considered
      prohibitedArcs - a set of RailArcs that are forbidden for the moving
      visitNodes - a list of RailNodes that the route must visit, in the specified order
      beginTime - the starting time for the route calculation
      velocity - the velocity of the train, used for timing along the route
      Returns:
      a TrainRoute representing the calculated path from source to destination
    • getStartMovementTime

      protected double getStartMovementTime(com.amalgamasimulation.trains.TrainsEnvironment.ContextRecord context, double agentLengthBeforeDestNode, double beginTime, double velocity, double agentLength, Graph<RailNode,RailArc>.Arc beforePathSourceArc, boolean isIncludeArcAfterNode, Graph<RailNode,RailArc>.Node destNode, LongAgentWeightKey weighterKey)
    • getContextLength

      protected double getContextLength(com.amalgamasimulation.trains.TrainsEnvironment.ContextRecord context, double agentLengthBeforeDestNode, double agentLength, boolean isIncludeArcAfterNode)
    • getEndMovementTime

      protected double getEndMovementTime(List<Graph<RailNode,RailArc>.Arc> arcs, double agentLengthBeforeDestNode, double beginTime, double velocity, double agentLength, Graph<RailNode,RailArc>.Arc beforePathSourceArc, boolean isIncludeArcAfterNode, Graph<RailNode,RailArc>.Node destNode, LongAgentWeightKey weighterKey)
    • shiftIntervalSet

      protected IntervalSet shiftIntervalSet(IntervalSet intervalSet, double shift)