/// <summary>
        /// Is there a connection on the same track between two nodes?
        /// </summary>
        /// <param name="fromNode">The node to connect from</param>
        /// <param name="toNode">The node to connect to</param>
        /// <param name="tvnIndex">Possibly a requirement on the index of the trackvectornode</param>
        private bool ExistsConnectionSameTrack(ConnectableNode fromNode, ConnectableNode toNode, int?tvnIndex)
        {
            if (connectableNodeOptions.Count == 0)
            {
                return(false);
            }

            // we can only connect on the same track if the both start and reconnectnodes are on the same track
            // This means that both need to be vector nodes.
            // It also means, this is only possible for the first node
            TrainpathVectorNode fromAsVector = fromNode.OriginalNodeAsVector;
            TrainpathVectorNode toAsVector   = toNode.OriginalNodeAsVector;

            if (fromAsVector == null)
            {
                return(false);
            }
            if (toAsVector == null)
            {
                return(false);
            }
            if (fromAsVector.TvnIndex != toAsVector.TvnIndex)
            {
                return(false);
            }
            if (tvnIndex.HasValue && (tvnIndex.Value != fromAsVector.TvnIndex))
            {
                return(false);
            }

            //for a reverse point the orientation is defined as being after the reversal.
            bool reconnectIsForward = (toAsVector.NodeType == TrainpathNodeType.Reverse)
                ? !toAsVector.ForwardOriented
                : toAsVector.ForwardOriented;

            if (fromAsVector.ForwardOriented != reconnectIsForward)
            {
                return(false);
            }

            if (isForwardConnecting)
            {
                if (fromAsVector.ForwardOriented != fromAsVector.IsEarlierOnTrackThan(toAsVector))
                {
                    return(false);
                }
            }
            else
            {
                if (fromAsVector.ForwardOriented == fromAsVector.IsEarlierOnTrackThan(toAsVector))
                {
                    return(false);
                }
            }

            return(true);
        }
        /// <summary>
        /// Determine if a connection can be made (and store the found solution), from a 'dynamic node' meaning that
        /// it can change.
        /// </summary>
        /// <param name="fromNode">The node that is from which to connect</param>
        public bool CanConnect(TrainpathVectorNode fromNode)
        {
            autoConnectFromNode  = new ConnectableNode(fromNode, true, isForward);
            FromNodeNeedsReverse = false; // reset to correct value
            bool canIndeedConnect = FindConnectionFromTo(null, true);

            //debugWindows[isForward].DrawString = String.Format("{0}:{1} ({2}) {3}", canIndeedConnect,
            //    (autoConnectToNodeOptions.ActualReconnectNode == null ? "none" : autoConnectToNodeOptions.ActualReconnectNode.OriginalNode.ToStringShort()),
            //    LinkingTvnsAsString(), debugString);
            return(canIndeedConnect);
        }
        /// <summary>
        /// Try to find a connection between two given nodes. Depth-first search via main track at junctions.
        /// Also reversing the start or reconnectNode is tried, in case one of these nodes has a non-defined orientation
        /// because both before and after the node the path is broken.
        /// </summary>
        /// <param name="fromNode">Node at which the reconnection should start</param>
        /// <param name="toNode">Node at which the reconnection should end</param>
        /// <param name="firstTvnIndex">In case defined, the index of the first TVN the path has to follow</param>
        /// <returns>True if a connection has been found</returns>
        public bool FindConnection(TrainpathNode fromNode, TrainpathNode toNode, int?firstTvnIndex)

        {
            // We try to find a connection between two non-broken nodes.
            // We store the connection as a stack of linking tvns (track-node-vector-indexes)
            // The connection will only contain junctions (apart from maybe start and end=reconnect nodes)

            autoConnectFromNode      = new ConnectableNode(fromNode, true, true);
            autoConnectToNodeOptions = new ReconnectNodeOptions(true);
            autoConnectToNodeOptions.AddNode(toNode, false); // only one option here

            return(FindConnectionFromTo(firstTvnIndex, false));
        }
        /// <summary>
        /// Find whether it is possible to connect directly two points on the same track.
        /// Store the reconnectpoint for later use during actual reconnecting
        /// </summary>
        /// <param name="fromNode">The point to connect from</param>
        /// <param name="firstTvnIndex">In case defined, the index of the first TVN the path has to follow</param>
        /// <returns>true if such a direct path has been found</returns>
        public bool FoundConnectionSameTrack(ConnectableNode fromNode, int?firstTvnIndex)
        {
            if (connectableNodeOptions.Count == 0)
            {
                return(false);
            }

            ConnectableNode candidate = connectableNodeOptions[0];

            if (ExistsConnectionSameTrack(fromNode, candidate, firstTvnIndex))
            {
                ActualReconnectNode = candidate;
                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Actually create the path by linking nodes following the stored linking tvns.
        /// </summary>
        /// <param name="modificationTools">The tool set that is used to actually modify the path</param>
        /// <param name="isMainPath">Do we add the node to the main path or not</param>
        /// <param name="isFromNodeDirectionOK">Set this to true when the FromNode has already been set to correct orientation elsewhere</param>
        public void CreateFoundConnection(ModificationTools modificationTools, bool isMainPath, bool isFromNodeDirectionOK)
        {
            ConnectableNode autoConnectToNode = autoConnectToNodeOptions.ActualReconnectNode;


            if (FromNodeNeedsReverse && !isFromNodeDirectionOK)
            {
                autoConnectFromNode.ReverseOrientation();
            }
            if (ToNodeNeedsReverse)
            {
                autoConnectToNode.ReverseOrientation();
            }

            if (!autoConnectToNode.IsConnectingForward)
            {
                linkingTvns.Reverse();
                ConnectableNode swap = autoConnectToNode;
                autoConnectToNode   = autoConnectFromNode;
                autoConnectFromNode = swap;
            }


            TrainpathNode currentNode = autoConnectFromNode.OriginalNode;

            if ((currentNode is TrainpathVectorNode) && !sameTrackConnect)
            {   // in case the first node is a vector node (and not a direct connect), go to its junction first
                currentNode = modificationTools.AddAdditionalNode(currentNode, isMainPath);
            }

            //create the new path using the stored Tvns
            foreach (int tvn in linkingTvns)
            {
                currentNode = modificationTools.AddAdditionalNode(currentNode, tvn, isMainPath);
                while (currentNode is TrainpathVectorNode)
                {   // apparently a disambiguity node has been added.
                    currentNode = modificationTools.AddAdditionalNode(currentNode, tvn, isMainPath);
                }
            }

            //make the final connections
            TrainpathNode toNode = autoConnectToNode.OriginalNode;

            modificationTools.StitchTwoPaths(currentNode, toNode, isMainPath);
        }
        /// <summary>
        /// Try to find a connection between a previously defined startNode and previously defined possible endNodes.
        /// Depth-first search via main track at junctions.
        /// Also reversing the start or single endNode is tried, in case one of these nodes has a non-defined orientation
        /// because both before and after the node the path is broken.
        /// </summary>
        /// <param name="firstTvnIndex">If non-null define the first TVN index that needs to be followed</param>
        /// <param name="allowOnlyStartReverse">If true, only start node is allowed to be reversed</param>
        /// <returns>Whether a path has been found</returns>
        protected bool FindConnectionFromTo(int?firstTvnIndex, bool allowOnlyStartReverse)
        {
            if (FindConnectionSameTrack(firstTvnIndex))
            {
                return(true);
            }

            //first try to see if we succeed without re-orienting the startNode or reconnectNode
            if (FindConnectionThisOrientation(firstTvnIndex))
            {
                return(true);
            }

            //perhaps there is a path with a reversed start node.
            if (allowOnlyStartReverse || CanReverse(autoConnectFromNode.OriginalNode))
            {
                autoConnectFromNode.ReverseOrientation();
                FromNodeNeedsReverse = FindConnectionThisOrientation(firstTvnIndex);
                autoConnectFromNode.ReverseOrientation(); // we only do the actual reverse in CreateFoundConnection
                if (FromNodeNeedsReverse)
                {
                    return(true);
                }
            }

            //perhaps there is a path with a reversed reconnect node.
            ConnectableNode reconnectNode = autoConnectToNodeOptions.SingleNode();

            if ((reconnectNode != null) && !allowOnlyStartReverse && CanReverse(reconnectNode.OriginalNode))
            {
                reconnectNode.ReverseOrientation();
                ToNodeNeedsReverse = FindConnectionThisOrientation(firstTvnIndex);
                reconnectNode.ReverseOrientation(); // we only do the actual reverse in CreateFoundConnection
                if (ToNodeNeedsReverse)
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Does the junction with given index correspond to the connecting junction of any of the options.
        /// If so, determine whether the connection is good (based on the direction of the junctions).
        /// If the connection is good, store the actual Connectable node for later use.
        /// </summary>
        /// <param name="junctionIndex">The index of the junction that we want to check for a connection</param>
        /// <param name="isFacing">Whether the junction is a facing junction</param>
        /// <returns>true if a connection can be made, even if it is not a good connection</returns>
        public bool FoundConnection(int junctionIndex, bool isFacing)
        {
            ActualReconnectNode = null; // give a good default
            if (connectableNodeOptions.Count == 0)
            {
                return(false);
            }

            foreach (ConnectableNode candidate in connectableNodeOptions)
            {
                if (candidate.ConnectingJunctionIndex == junctionIndex)
                {   // we found a connection. We will not search for other connections.
                    // Now we just need to check if it is in the right direction
                    // If it is not in the right direction, we did not succeed.
                    bool goodConnection = (candidate.IsConnectingJunctionFacing == isFacing);
                    if (goodConnection)
                    {
                        ActualReconnectNode = candidate;
                    }
                    return(true);
                }
            }
            return(false);
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 /// <param name="isConnectingForward">Are the options needed for connecting forwards (along the path) or not</param>
 public ReconnectNodeOptions(bool isConnectingForward)
 {
     connectableNodeOptions   = new List <ConnectableNode>();
     ActualReconnectNode      = null;
     this.isForwardConnecting = isConnectingForward;
 }