Beispiel #1
0
        /// <summary>
        /// Determine where exactly the current trainpath node is on the track node
        /// </summary>
        /// <param name="startNode">The start node</param>
        /// <param name="nextNode">The next node (so also the direction can be understood)</param>
        /// <param name="tn">The tracknode connecting the startNode and nextNode</param>
        /// <param name="isForward">Output: whether going from startNode to nextNode is in the forward direction of the track</param>
        /// <param name="tvsiStart">Output: the track vector section index of where the startNode is</param>
        /// <param name="sectionOffsetStart">Output: the offset in the section (in the direction of the tracknode, not necessarily in the direction from startNode to nextNode)</param>
        private void DetermineSectionDetails(TrainpathNode startNode, TrainpathNode nextNode, TrackNode tn, out bool isForward, out int tvsiStart, out float sectionOffsetStart)
        {
            TrainpathVectorNode   currentNodeAsVector   = startNode as TrainpathVectorNode;
            TrainpathJunctionNode currentNodeAsJunction = startNode as TrainpathJunctionNode;

            if (currentNodeAsJunction != null)
            {   // we start at a junction node
                isForward = (currentNodeAsJunction.JunctionIndex == tn.JunctionIndexAtStart());
                if (isForward)
                {
                    tvsiStart          = 0;
                    sectionOffsetStart = 0;
                }
                else
                {
                    tvsiStart          = tn.TrVectorNode.TrVectorSections.Count() - 1;
                    sectionOffsetStart = SectionLengthAlongTrack(tn, tvsiStart);
                }
            }
            else
            {   // we start at a vector node
                isForward          = currentNodeAsVector.IsEarlierOnTrackThan(nextNode);
                tvsiStart          = currentNodeAsVector.TrackVectorSectionIndex;
                sectionOffsetStart = currentNodeAsVector.TrackSectionOffset;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Update (or fully recalculate) the data for charting the path
        /// </summary>
        /// <param name="trainpath">The train path for which to store chart data</param>
        public void Update(Trainpath trainpath)
        {
            this.PathName = trainpath.PathName;
            var localPathChartPoints = new List <PathChartPoint>();

            DistanceAlongPath = new Dictionary <TrainpathNode, double>();
            ResetAllMinMax();

            TrainpathNode node         = trainpath.FirstNode;
            float         lastDistance = 0;

            while (node != null)
            {
                DistanceAlongPath[node] = lastDistance;
                IEnumerable <PathChartPoint> additionalPoints = DetermineChartPoints(node);

                foreach (PathChartPoint relativePoint in additionalPoints)
                {
                    PathChartPoint absolutePoint = new PathChartPoint(relativePoint, lastDistance);
                    lastDistance += relativePoint.DistanceAlongNextSection;
                    AddPoint(localPathChartPoints, absolutePoint);
                }

                node = node.NextMainNode;
            }

            //todo possibly we need to change the information on the last node, and copy e.g. the grade from the last-but-one node

            PathChartPoints = localPathChartPoints;
            StoreAllMinMax();
        }
Beispiel #3
0
 /// <summary>
 /// Constructor for a first point
 /// </summary>
 /// <param name="node">The node describing where the location of the point is</param>
 public PathChartPoint(TrainpathNode node)
 {
     HeightM                  = node.Location.Location.Y;
     DistanceAlongPath        = 0;
     Curvature                = 0;
     GradePercent             = 0;
     DistanceAlongNextSection = 0;
     TrackItemText            = String.Empty;
     TrackItemType            = ChartableTrackItemType.None;
 }
Beispiel #4
0
        private PathChartPoint CreateBrokenChartPoint(TrainpathNode thisNode, TrainpathNode nextNode)
        {
            float          height      = thisNode.Location.Location.Y;
            float          distance    = (float)Math.Sqrt(WorldLocation.GetDistanceSquared(thisNode.Location, nextNode.Location));
            float          heightOther = nextNode.Location.Location.Y;
            float          grade       = (heightOther - height) / distance;
            float          curvature   = 0;
            PathChartPoint brokenPoint = new PathChartPoint(height, curvature, grade, distance);

            return(brokenPoint);
        }
Beispiel #5
0
        /// <summary>
        /// Determine if the path from currentNode to nextNode is in the forward direction of the track (along main path)
        /// </summary>
        private bool DetermineIfForward(TrainpathNode currentNode, TrainpathNode nextNode)
        {   // It would be nice if we could separate this into different classes for vector and junction, but this would mean creating three additional classes for only a few methods
            TrainpathVectorNode currentNodeAsVector = currentNode as TrainpathVectorNode;

            if (currentNodeAsVector != null)
            {
                return(currentNodeAsVector.IsEarlierOnTrackThan(nextNode));
            }
            else
            {
                TrainpathJunctionNode currentNodeAsJunction = currentNode as TrainpathJunctionNode;
                return(currentNodeAsJunction.JunctionIndex == trackDB.TrackNodes[currentNode.NextMainTvnIndex].JunctionIndexAtStart());
            }
        }
Beispiel #6
0
        /// <summary>
        /// Determine the index of the trackvectorsection of the node in the track defined by the track vector node
        /// </summary>
        /// <param name="node">The node for which to determine the track vector section index</param>
        /// <param name="tvn">Track vector index of which we want to find the section</param>
        /// <returns></returns>
        private int DetermineTrackVectorSection(TrainpathNode node, int tvn)
        { // It would be nice if we could separate this into different classes for vector and junction, but this would mean creating three additional classes for only a few methods
            TrainpathVectorNode nodeAsVector = node as TrainpathVectorNode;

            if (nodeAsVector != null)
            {
                return(nodeAsVector.TrackVectorSectionIndex);
            }
            else
            {
                TrainpathJunctionNode currentNodeAsJunction = node as TrainpathJunctionNode;
                if (currentNodeAsJunction.JunctionIndex == trackDB.TrackNodes[node.NextMainTvnIndex].JunctionIndexAtStart())
                {
                    return(0);
                }
                else
                {
                    return(trackDB.TrackNodes[node.NextMainTvnIndex].TrVectorNode.TrVectorSections.Count() - 1);
                }
            }
        }
Beispiel #7
0
        /// <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);
        }