//================================================================================================//
        //
        // Constructor from other route element
        //
        public TrackCircuitRouteElement(TrackCircuitRouteElement source)
        {
            if (null == source)
            {
                throw new ArgumentNullException(nameof(source));
            }

            TrackCircuitSection = source.TrackCircuitSection;
            Direction           = source.Direction;

            OutPin = new EnumArray <TrackDirection, Location>(source.OutPin);

            if (source.StartAlternativePath != null)
            {
                StartAlternativePath = new AlternativePath()
                {
                    PathIndex           = source.StartAlternativePath.PathIndex,
                    TrackCircuitSection = source.StartAlternativePath.TrackCircuitSection,
                };
            }

            if (source.EndAlternativePath != null)
            {
                EndAlternativePath = new AlternativePath()
                {
                    PathIndex           = source.EndAlternativePath.PathIndex,
                    TrackCircuitSection = source.EndAlternativePath.TrackCircuitSection,
                };
            }

            FacingPoint             = source.FacingPoint;
            UsedAlternativePath     = source.UsedAlternativePath;
            MovingTableApproachPath = source.MovingTableApproachPath;
        }
        /// Constructor (from route path details)
        public TrackCircuitReversalInfo(TrackCircuitPartialPathRoute lastRoute, int prevReversalIndex, TrackCircuitPartialPathRoute firstRoute, float reverseReversalOffset, int reversalIndex, int reversalSectionIndex)
        {
            // preset values
            Valid                  = false;
            LastDivergeIndex       = -1;
            FirstDivergeIndex      = -1;
            LastSignalIndex        = -1;
            FirstSignalIndex       = -1;
            SignalAvailable        = false;
            SignalUsed             = false;
            ReverseReversalOffset  = reverseReversalOffset;
            ReversalIndex          = reversalIndex;
            ReversalSectionIndex   = reversalSectionIndex;
            ReversalActionInserted = false;

            // search for first common section in last and first

            int lastIndex  = lastRoute.Count - 1;
            int firstIndex = 0;

            int lastCommonSection  = -1;
            int firstCommonSection = -1;

            bool commonFound   = false;
            bool validDivPoint = false;

            while (!commonFound && lastIndex >= 0)
            {
                TrackCircuitRouteElement lastElement = lastRoute[lastIndex];

                while (!commonFound && firstIndex <= firstRoute.Count - 1)
                {
                    TrackCircuitRouteElement firstElement = firstRoute[firstIndex];
                    if (lastElement.TrackCircuitSection.Index == firstElement.TrackCircuitSection.Index)
                    {
                        commonFound        = true;
                        lastCommonSection  = lastIndex;
                        firstCommonSection = firstIndex;

                        Valid = (lastElement.Direction != firstElement.Direction);
                    }
                    else
                    {
                        firstIndex++;
                    }
                }
                lastIndex--;
                firstIndex = 0;
            }

            // search for last common section going backward along route
            // do not go back on last route beyond previous reversal point to prevent fall through of reversals
            if (Valid)
            {
                Valid = false;

                lastIndex  = lastCommonSection;
                firstIndex = firstCommonSection;

                int endLastIndex = (prevReversalIndex > 0 && prevReversalIndex < lastCommonSection &&
                                    Simulator.Instance.TimetableMode) ? prevReversalIndex : 0;

                while (lastIndex >= endLastIndex && firstIndex <= (firstRoute.Count - 1) && lastRoute[lastIndex].TrackCircuitSection.Index == firstRoute[firstIndex].TrackCircuitSection.Index)
                {
                    LastDivergeIndex   = lastIndex;
                    FirstDivergeIndex  = firstIndex;
                    DivergeSectorIndex = lastRoute[lastIndex].TrackCircuitSection.Index;

                    lastIndex--;
                    firstIndex++;
                }

                // if next route ends within last one, last diverge index can be set to endLastIndex
                if (firstIndex > firstRoute.Count - 1)
                {
                    LastDivergeIndex   = endLastIndex;
                    DivergeSectorIndex = lastRoute[endLastIndex].TrackCircuitSection.Index;
                }

                Valid         = LastDivergeIndex >= 0; // it is a reversal
                validDivPoint = true;
                if (Simulator.Instance.TimetableMode)
                {
                    validDivPoint = LastDivergeIndex > 0 && FirstDivergeIndex < (firstRoute.Count - 1); // valid reversal point
                }
                if (lastRoute.Count == 1 && FirstDivergeIndex < (firstRoute.Count - 1))
                {
                    validDivPoint = true;                                                                     // valid reversal point in first and only section
                }
            }

            // determine offset

            if (validDivPoint)
            {
                DivergeOffset = 0.0f;
                for (int iSection = LastDivergeIndex; iSection < lastRoute.Count; iSection++)
                {
                    TrackCircuitSection thisSection = lastRoute[iSection].TrackCircuitSection;
                    DivergeOffset += thisSection.Length;
                }

                // find last signal furthest away from diverging point

                bool signalFound  = false;
                int  startSection = 0;

                if (!Simulator.Instance.TimetableMode)
                // In activity mode test starts only after reverse point.
                {
                    for (int iSection = 0; iSection < firstRoute.Count; iSection++)
                    {
                        if (firstRoute[iSection].TrackCircuitSection.Index == ReversalSectionIndex)
                        {
                            startSection = iSection;
                            break;
                        }
                    }
                    for (int iSection = startSection; iSection <= FirstDivergeIndex && !signalFound; iSection++)
                    {
                        TrackCircuitSection thisSection = firstRoute[iSection].TrackCircuitSection;
                        if (thisSection.EndSignals[firstRoute[iSection].Direction] != null)   // signal in required direction
                        {
                            signalFound       = true;
                            FirstSignalIndex  = iSection;
                            SignalSectorIndex = thisSection.Index;
                        }
                    }
                }
                // in timetable mode, search for first signal beyond diverging point
                else
                {
                    for (int iSection = FirstDivergeIndex; iSection >= startSection && !signalFound; iSection--)
                    {
                        TrackCircuitSection thisSection = firstRoute[iSection].TrackCircuitSection;
                        if (thisSection.EndSignals[firstRoute[iSection].Direction] != null)   // signal in required direction
                        {
                            signalFound       = true;
                            FirstSignalIndex  = iSection;
                            SignalSectorIndex = thisSection.Index;
                        }
                    }
                }

                // signal found
                if (signalFound)
                {
                    LastSignalIndex = lastRoute.GetRouteIndex(SignalSectorIndex, LastDivergeIndex);
                    if (LastSignalIndex > 0)
                    {
                        SignalAvailable = true;

                        SignalOffset = 0.0f;
                        for (int iSection = LastSignalIndex; iSection < lastRoute.Count; iSection++)
                        {
                            TrackCircuitSection thisSection = lastRoute[iSection].TrackCircuitSection;
                            SignalOffset += thisSection.Length;
                        }
                    }
                }
            }
            else
            {
                FirstDivergeIndex = -1;
                LastDivergeIndex  = -1;
            }
        }//constructor