/// <summary>
        /// Determine the trackItems and their location in the given tracknode.
        /// </summary>
        /// <param name="tn">The tracknode in which to search for track items</param>
        /// <returns>The list/set of track itemss together with their position information</returns>
        public IEnumerable <ChartableTrackItem> GetItemsInTracknode(TrackNode tn)
        {
            if (cachedItems.ContainsKey(tn))
            {
                return(cachedItems[tn]);
            }

            List <ChartableTrackItem> tracknodeItems = new List <ChartableTrackItem>();
            TrVectorNode vectorNode = tn.TrVectorNode;

            if (vectorNode.TrItemRefs == null)
            {
                return(tracknodeItems);
            }

            foreach (int trackItemIndex in vectorNode.TrItemRefs)
            {
                TrItem trItem = trackDB.TrItemTable[trackItemIndex];
                if (supportedTrackTypes.Contains(trItem.ItemType))
                {
                    var travellerAtItem = new Traveller(tsectionDat, trackDB.TrackNodes, tn,
                                                        trItem.TileX, trItem.TileZ, trItem.X, trItem.Z, Traveller.TravellerDirection.Forward);

                    if (travellerAtItem != null)
                    {
                        tracknodeItems.Add(new ChartableTrackItem(trItem, travellerAtItem));
                    }
                }
            }
            tracknodeItems.Sort(new AlongTrackComparer());
            cachedItems[tn] = tracknodeItems;
            return(tracknodeItems);
        }
        /// <summary>
        /// From section information create a point for charting the path, and add it to newPoints.
        /// In case there are track items in this particular section, add those also (starting with the last item as seen from the direction of the path)
        /// </summary>
        /// <param name="newPoints">The list to which to add the point</param>
        /// <param name="vectorNode">The vectorNode to use for curvature and grade</param>
        /// <param name="trackItems">A list of track items in this vector tracknode</param>
        /// <param name="isForward">Is the path in the same direction as the tracknode</param>
        /// <param name="height">Height to store in the point</param>
        /// <param name="tvsi">The section index in the track vector node</param>
        /// <param name="sectionOffsetStart">Offset of the start of this section (in forward direction of track, not of path)</param>
        /// <param name="sectionOffsetStart">Offset of the end of this section (in forward direction of track, not of path)</param>
        private void AddPointAndTrackItems(List <PathChartPoint> newPoints, TrVectorNode vectorNode, IEnumerable <ChartableTrackItem> trackItems,
                                           bool isForward, float height, int tvsi, float sectionOffsetStart, float sectionOffsetEnd)
        {
            //Note, we are adding points in in reverse direction

            var additionalPoints = new List <PathChartPoint>();

            // not a percentage. We can safely assume the pitch is small enough so we do not to take tan(pitch)
            float gradeFromPitch = -vectorNode.TrVectorSections[tvsi].AX * (isForward ? 1 : -1);
            float curvature      = GetCurvature(vectorNode, tvsi, isForward);

            List <ChartableTrackItem> items_local = trackItems.ToList();

            if (isForward)
            {
                items_local.Reverse();
            }

            PathChartPoint newPoint;

            foreach (ChartableTrackItem chartableItem in items_local)
            {
                if (chartableItem.TrackVectorSectionIndex == tvsi && sectionOffsetStart <= chartableItem.TrackVectorSectionOffset && chartableItem.TrackVectorSectionOffset < sectionOffsetEnd)
                {
                    if (isForward)
                    {
                        //For forward, we start at the last item in the track
                        newPoint         = new PathChartPoint(chartableItem.Height, curvature, gradeFromPitch, sectionOffsetEnd - chartableItem.TrackVectorSectionOffset, chartableItem.ItemText, chartableItem.ItemType);
                        sectionOffsetEnd = chartableItem.TrackVectorSectionOffset;
                    }
                    else
                    {
                        //For reverse, we have to swap forward and reverse speed limits
                        ChartableTrackItemType itemType =
                            chartableItem.ItemType == ChartableTrackItemType.SpeedLimitForward ? ChartableTrackItemType.SpeedLimitReverse :
                            chartableItem.ItemType == ChartableTrackItemType.SpeedLimitReverse ? ChartableTrackItemType.SpeedLimitForward :
                            chartableItem.ItemType;
                        //For reverse, we start at the first item in the track
                        newPoint           = new PathChartPoint(chartableItem.Height, curvature, gradeFromPitch, chartableItem.TrackVectorSectionOffset - sectionOffsetStart, chartableItem.ItemText, itemType);
                        sectionOffsetStart = chartableItem.TrackVectorSectionOffset;
                    }
                    additionalPoints.Add(newPoint);
                }
            }

            newPoint = new PathChartPoint(height, curvature, gradeFromPitch, sectionOffsetEnd - sectionOffsetStart);
            additionalPoints.Add(newPoint);

            newPoints.AddRange(additionalPoints);
        }
Exemple #3
0
        public static int searchIdx(this TrackNode node, TrVectorSection currentSection)
        {
            TrVectorNode nodes = node.TrVectorNode;

            if (nodes == null || nodes.TrVectorSections == null)
            {
                return(0);
            }
            for (int cnt = 0; cnt < nodes.TrVectorSections.Count(); cnt++)
            {
                if (nodes.TrVectorSections[cnt].SectionIndex == currentSection.SectionIndex &&
                    nodes.TrVectorSections[cnt].WorldFileUiD == currentSection.WorldFileUiD)
                {
                    return(cnt);
                }
            }
            return(0);
        }
        private List <string> StationNamesBetweenNodes(TrainpathNode firstNode, TrainpathNode secondNode)
        {
            var stationNames = new List <string>();
            int tvnIndex     = firstNode.NextMainTvnIndex;

            if (tvnIndex < 0)
            {
                return(stationNames);
            }

            TrackNode    tn  = trackDB.TrackNodes[tvnIndex];
            TrVectorNode tvn = tn.TrVectorNode;

            if (tvn == null)
            {
                return(stationNames);
            }
            if (tvn.TrItemRefs == null)
            {
                return(stationNames);
            }

            foreach (int trackItemIndex in tvn.TrItemRefs)
            {
                TrItem trItem = trackDB.TrItemTable[trackItemIndex];
                if (trItem.ItemType == TrItem.trItemType.trPLATFORM)
                {
                    var traveller = new Traveller(tsectionDat, trackDB.TrackNodes, tn,
                                                  trItem.TileX, trItem.TileZ, trItem.X, trItem.Z, Traveller.TravellerDirection.Forward);
                    if (traveller != null)
                    {
                        var platformNode = new TrainpathVectorNode(firstNode, traveller);
                        if (platformNode.IsBetween(firstNode, secondNode))
                        {
                            PlatformItem platform = trItem as PlatformItem;
                            stationNames.Add(platform.Station);
                        }
                    }
                }
            }

            return(stationNames);
        }
        /// <summary>
        /// Get the curvature for the current section index in a vector track node.
        /// </summary>
        /// <param name="vectorNode">The vector track node</param>
        /// <param name="tvsi">The tracknode vector section index in the given verctor track node</param>
        /// <param name="isForward">Is the path in the same direction as the vector track node?</param>
        private float GetCurvature(TrVectorNode vectorNode, int tvsi, bool isForward)
        {
            TrVectorSection tvs          = vectorNode.TrVectorSections[tvsi];
            TrackSection    trackSection = tsectionDat.TrackSections.Get(tvs.SectionIndex);

            float curvature = 0;

            if (trackSection != null) // if it is null, something is wrong but we do not want to crash
            {
                SectionCurve thisCurve = trackSection.SectionCurve;

                if (thisCurve != null)
                {
                    curvature = Math.Sign(thisCurve.Angle) / thisCurve.Radius;
                    if (!isForward)
                    {
                        curvature *= -1;
                    }
                }
            }

            return(curvature);
        }
        /// <summary>
        /// Determine the ChartPoints from the startNode (included) until but not including the endNode=startNode.NextMainNode
        /// Each tracksection-begin should be a new point
        /// </summary>
        /// <param name="thisNode">The node to start with</param>
        /// <remarks>The assumption is that the two trainpath nodes only have a single tracknode connecting them</remarks>
        /// <returns>At least one new chart point</returns>
        private IEnumerable <PathChartPoint> DetermineChartPoints(TrainpathNode thisNode)
        {
            // The track consists of a number of sections. These sections might be along the direction we are going in (isForward) or not
            // The first point (belonging to currentNode) is the first we return, and possibly the only one.
            // Any new  points we are going to add are all at the boundaries of sections
            // From the track database we get the (height) data only at start of a section.
            // If we are moving forward the height at the section boundary is coming from the section just after the boundary
            // If we are moving reverse the height at the section boundary is coming from the section just before the boundary;
            var           newPoints = new List <PathChartPoint>();
            TrainpathNode nextNode  = thisNode.NextMainNode;

            if (nextNode == null)
            {
                PathChartPoint singlePoint = new PathChartPoint(thisNode);
                newPoints.Add(singlePoint);
                return(newPoints);
            }

            if (thisNode.IsBroken || nextNode.IsBroken || thisNode.NextMainTvnIndex == -1)
            {
                PathChartPoint singlePoint = CreateBrokenChartPoint(thisNode, nextNode);
                newPoints.Add(singlePoint);
                return(newPoints);
            }

            TrackNode tn = trackDB.TrackNodes[thisNode.NextMainTvnIndex];

            TrVectorNode vectorNode            = tn.TrVectorNode;
            var          trackItemsInTracknode = trackItems.GetItemsInTracknode(tn);


            bool  isForward;
            bool  isReverse; // only dummy out argument
            int   tvsiStart;
            int   tvsiStop;
            float sectionOffsetStart;
            float sectionOffsetStop;

            DetermineSectionDetails(thisNode, nextNode, tn, out isForward, out tvsiStart, out sectionOffsetStart);
            DetermineSectionDetails(nextNode, thisNode, tn, out isReverse, out tvsiStop, out sectionOffsetStop);

            float height;

            if (isForward)
            {
                // We add points in reverse order, so starting at the last section and its index
                float sectionOffsetNext = sectionOffsetStop;
                for (int tvsi = tvsiStop; tvsi > tvsiStart; tvsi--)
                {
                    height = vectorNode.TrVectorSections[tvsi].Y;
                    AddPointAndTrackItems(newPoints, vectorNode, trackItemsInTracknode, isForward, height, tvsi, 0, sectionOffsetNext);

                    sectionOffsetNext = SectionLengthAlongTrack(tn, tvsi - 1);
                }

                //Also works in case this is the only point we are adding
                height = thisNode.Location.Location.Y;
                AddPointAndTrackItems(newPoints, vectorNode, trackItemsInTracknode, isForward, height, tvsiStart, sectionOffsetStart, sectionOffsetNext);
            }
            else
            {   //reverse
                // We add points in reverse order, so starting at the first section and its index
                float sectionOffsetNext = sectionOffsetStop;
                for (int tvsi = tvsiStop; tvsi < tvsiStart; tvsi++)
                {
                    // The height needs to come from the end of the section, so the where the next section starts. And we only know the height at the start.
                    height = vectorNode.TrVectorSections[tvsi + 1].Y;
                    AddPointAndTrackItems(newPoints, vectorNode, trackItemsInTracknode, isForward, height, tvsi, sectionOffsetNext, SectionLengthAlongTrack(tn, tvsi));

                    sectionOffsetNext = 0;
                }

                //Also works in case this is the only point we are adding
                height = thisNode.Location.Location.Y;
                AddPointAndTrackItems(newPoints, vectorNode, trackItemsInTracknode, isForward, height, tvsiStart, sectionOffsetNext, sectionOffsetStart);
            }
            newPoints.Reverse();
            return(newPoints);
        }