Exemple #1
0
        /// <summary>
        /// Creates a Person with a start and end PseudoNode and a name.
        /// </summary>
        /// <param name="name"></param>
        /// <param name="start_node"></param>
        /// <param name="end_node"></param>
        public Person(string name, PseudoNode start_node, PseudoNode end_node)
        {
            this.name = name;
            route     = new Route(start_node, end_node);
            List <Node> node_route = route.GetNodeRoute();

            position            = start_node;
            destination_reached = false;
        }
Exemple #2
0
 /// <summary>
 /// This method returns a double representing the length of time (in seconds) that it would
 /// take to get to from a PseudoNode to a Node along the same Path. If the given Node is
 /// not on the same Path, this returns Double.MAX_VALUE as this method contains no support
 /// for routing.
 /// </summary>
 /// <param name="node"></param>
 /// <param name="pseudoNode"></param>
 /// <returns></returns>
 public double GetTimeToNodeFrom(Node node, PseudoNode pseudoNode)
 {
     if (pseudoNode.GetPath() == this)
     {
         return(GetTimeToNodeFrom(node, pseudoNode.GetDistanceAlongPath()));
     }
     else
     {
         Debug.WriteLine("The PseudoNode does not lie on this Path.");
         return(Double.MaxValue);
     }
 }
Exemple #3
0
        /// <summary>
        /// This method returns a double that represents the length of time (in seconds) that it
        /// would take to get from one PseudoNode on the Path to another on the Path. If one of
        /// the nodes is not on this Path, this method will return Double.MaxValue.
        /// </summary>
        /// <param name="destination_node"></param>
        /// <param name="source_node"></param>
        /// <returns></returns>
        public double GetTimeToPseudoNodeFrom(PseudoNode destination_node, PseudoNode source_node)
        {
            // Check both PseudoNodes are on the Path
            if (destination_node.GetPath() != this || source_node.GetPath() != this)
            {
                return(Double.MaxValue);
            }

            // Calculate length of time
            double destination_distance = destination_node.GetDistanceAlongPath();
            double source_distance      = source_node.GetDistanceAlongPath();
            double time = (destination_distance - source_distance) / speed_limit;

            time = (time > 0) ? time : -time;
            return(time);
        }
Exemple #4
0
 /// <summary>
 /// Sets up a PseudoNode at the same point as the given PseudoNode.
 /// </summary>
 /// <param name="node"></param>
 public PseudoNode(PseudoNode node)
 {
     path = node.GetPath();
     distance_along_path = node.GetDistanceAlongPath();
 }
        /// <summary>
        /// Initialises a Route by giving a start and end PseudoNode, and calculates the quickest Route between them.
        /// </summary>
        /// <param name="_source_node"></param>
        /// <param name="_end_node"></param>
        public Route(PseudoNode _source_node, PseudoNode _end_node)
        {
            // Storing the source and destination nodes
            source_node = new PseudoNode(_source_node);
            end_node    = new PseudoNode(_end_node);

            Node [] source_nodes     = source_node.GetPath().GetNodes();
            Node [] end_nodes        = end_node.GetPath().GetNodes();
            bool [] end_nodes_mapped = { false, false };

            List <NodeAndTime> nodes_and_times = new List <NodeAndTime>();
            List <Node>        nodes           = Map.GetNodes();

            // Setting the initial times to get to each node from the source node
            foreach (Node node in nodes)
            {
                if (node == source_nodes[0] || node == source_nodes[1])
                {
                    nodes_and_times.Add(new NodeAndTime(node, source_node.GetPath().GetTimeToNodeFrom(node, source_node)));
                }
                else
                {
                    nodes_and_times.Add(new NodeAndTime(node, false));
                }
            }

            // Implementing Dijkstra's algorithm:

            bool complete = false;

            while (!complete)
            {
                // Sort to ensure that the nearest (by time) nodes to the source node are at the top of the List
                Sort(nodes_and_times);

                // Finding the next node that has not been mapped
                NodeAndTime analysis_node = null;
                foreach (NodeAndTime node_and_time in nodes_and_times)
                {
                    if (!node_and_time.AdjacentNodesMapped())
                    {
                        analysis_node = node_and_time;
                        break;
                    }
                }

                // If all nodes have been mapped, then the analysis_node was not set in the previous code snippet.
                // Hence we need not run the rest of the loop and we can finish the while loop. This is a fail safe
                // to ensure that the code does not crash. In ordinary circumstances, this scenario should be
                // handled below, at the bottom of the while loop.
                if (analysis_node == null)
                {
                    complete = true;
                    continue;
                }

                // Get adjacent nodes
                List <Node> adj_nodes_temp = Map.GetNodesAdjacentToNode(analysis_node.GetNode());

                foreach (Node node in adj_nodes_temp)
                {
                    // Calculate time coming from this node
                    double new_time = Map.GetPathWithNodes(analysis_node.GetNode(), node).GetTime() + analysis_node.GetTime();

                    // If the time lower than it would be taking the previous route here, change that NodeAndTime object to come through this way instead
                    NodeAndTime previous_node_and_time = GetNodeAndTime(node, nodes_and_times);
                    if (new_time < previous_node_and_time.GetTime())
                    {
                        List <NodeAndTime> new_shortest_route = new List <NodeAndTime>(analysis_node.GetShortestRouteToNodeForCalc());
                        new_shortest_route.Add(analysis_node);
                        previous_node_and_time.SetShortestRouteToNode(new_shortest_route);
                        previous_node_and_time.SetTime(new_time);
                    }
                }
                analysis_node.SetAdjacentNodesMapped(true);

                // Check if both Nodes either side of the PseudoNode have been analysed.
                if (analysis_node.GetNode() == end_nodes[0])
                {
                    end_nodes_mapped[0] = true;
                }
                else if (analysis_node.GetNode() == end_nodes[1])
                {
                    end_nodes_mapped[1] = true;
                }

                // Completing the loop if both of the end Nodes have been mapped
                if (end_nodes_mapped[0] && end_nodes_mapped[1])
                {
                    complete = true;
                }
            }

            // Getting the time that it will take to get to the PseudoNode via both Nodes either side of the containing Route
            NodeAndTime [] end_node_and_times   = { GetNodeAndTime(end_nodes[0], nodes_and_times), GetNodeAndTime(end_nodes[1], nodes_and_times) };
            double         time_from_end_node_1 = end_node_and_times[0].GetTime() + end_node.GetPath().GetTimeToNodeFrom(end_node_and_times[0].GetNode(), end_node);
            double         time_from_end_node_2 = end_node_and_times[1].GetTime() + end_node.GetPath().GetTimeToNodeFrom(end_node_and_times[1].GetNode(), end_node);

            // Selecting to go through the Node that will give the shortest time, and converting these to a list of Nodes.
            if (time_from_end_node_1 <= time_from_end_node_2)
            {
                node_route = end_node_and_times[0].ConvertToListOfNodes();
                path_route = end_node_and_times[0].ConvertToListOfPaths();
            }
            else
            {
                node_route = end_node_and_times[1].ConvertToListOfNodes();
                path_route = end_node_and_times[1].ConvertToListOfPaths();
            }

            // Adding start and end Paths on as they may not currently be there
            if (path_route.Count == 0)
            {
                path_route.Add(source_node.GetPath());
            }
            if (path_route[0] != source_node.GetPath())
            {
                path_route.Insert(0, source_node.GetPath());
            }
            if (path_route[path_route.Count - 1] != end_node.GetPath())
            {
                path_route.Add(end_node.GetPath());
            }

            // Determine which directions the Paths should be travelled in
            DetermineDirections();
        }
 /// <summary>
 /// Initialises a Route by giving a start PseudoNode and end Node, and calculates the quickest Route between
 /// them.
 /// </summary>
 /// <param name="source_node"></param>
 /// <param name="end_node"></param>
 public Route(PseudoNode source_node, Node end_node) : this(source_node, new PseudoNode(end_node))
 {
 }
 /// <summary>
 /// Initialises a Route by giving a start Node and end PseudoNode, and calculates the quickest Route between
 /// them.
 /// </summary>
 /// <param name="source_node"></param>
 /// <param name="end_node"></param>
 public Route(Node source_node, PseudoNode end_node) : this(new PseudoNode(source_node), end_node)
 {
 }
 /// <summary>
 /// This method returns a Direction that specifies whether the Path that the PseudoNode is on should be travelled
 /// forwards or backwards (i.e. from Path.GetNodes()[0] to Path.GetNodes()[1] or vice versa). If the PseudoNode
 /// does not sit on a Path in this Route, this method will return Direction.FORWARDS.
 /// </summary>
 /// <param name="pseudo_node"></param>
 /// <returns></returns>
 public Direction GetDirection(PseudoNode pseudo_node)
 {
     return(GetDirection(pseudo_node.GetPath()));
 }
 /// <summary>
 /// This method finds the next Path on the Route by the current position of the PseudoNode. If the PseudoNode is
 /// not on the Route, or if it lies on the last Path in the Route, this method will return null.
 /// </summary>
 /// <param name="current_position"></param>
 /// <returns></returns>
 public Path GetNextPath(PseudoNode current_position)
 {
     return(GetNextPath(current_position.GetPath()));
 }
Exemple #10
0
        /// <summary>
        /// This method will update the position of the Person. The number of seconds since the
        /// last update is required in order to calculate the Person's new position. If the
        /// Person reaches the next part of their Path, their current_path and last_node_passed
        /// values will be updated. If the Person reaches the end of their route, the Person will
        /// be deleted from the List in Persons.
        /// </summary>
        /// <param name="seconds_since_last_update"></param>
        public void update(double seconds_since_last_update)
        {
            // If the Pwerson is at the destination already, there's no need to change position
            if (destination_reached)
            {
                return;
            }

            double time_to_destination = Double.MaxValue;

            // Check if we're on the final path of the route

            if (route.GetNextPath(position.GetPath()) == null)
            {
                time_to_destination = position.GetPath().GetTimeToPseudoNodeFrom(route.GetDestinationNode(), position);
            }
            // If the Person is nearly at the destination, set the Person at the destination node

            if (time_to_destination <= seconds_since_last_update)
            {
                position            = new PseudoNode(route.GetDestinationNode());
                destination_reached = true;
                return;                 // Stop processing
            }

            // ------------------------------------------------
            // Otherwise, the Person is not at the destination:

            Direction current_direction = route.GetDirection(position);
            double    time_to_next_path = 0;

            // Work out the time it will take to reach the next Path
            if (current_direction == Direction.FORWARDS)
            {
                time_to_next_path = position.GetPath().GetTimeToNodeFrom(position.GetPath().GetNodes()[1], position);
            }
            else
            {
                time_to_next_path = position.GetPath().GetTimeToNodeFrom(position.GetPath().GetNodes()[0], position);
            }

            // If this loop is entered, the Person will switch paths. Update the position and the
            // path.
            while (time_to_next_path <= seconds_since_last_update)
            {
                // If this loop is entered, the Person will switch paths. Update the position
                // and the path.

                // Take off the amount of time that it would take to get to the next Path
                seconds_since_last_update -= time_to_next_path;

                // Update the position PseudoNode
                Path next_path = route.GetNextPath(position.GetPath());
                current_direction = route.GetDirection(next_path);
                if (current_direction == Direction.FORWARDS)
                {
                    position.SetPath(next_path, 0);
                    time_to_next_path = position.GetPath().GetTimeToNodeFrom(position.GetPath().GetNodes()[1], position);
                }
                else
                {
                    position.SetPath(next_path, next_path.GetDistance());
                    time_to_next_path = position.GetPath().GetTimeToNodeFrom(position.GetPath().GetNodes()[0], position);
                }
            }

            // Do the final updates on the current path only
            double new_distance = 0;

            if (current_direction == Direction.FORWARDS)
            {
                new_distance = position.GetDistanceAlongPath() + GetCurrentPath().GetSpeedLimit() * seconds_since_last_update;
            }
            else
            {
                new_distance = position.GetDistanceAlongPath() - GetCurrentPath().GetSpeedLimit() * seconds_since_last_update;
            }

            position.SetDistanceAlongPath(new_distance);
        }