示例#1
0
        /// <summary>
        /// The activeTrackLocation needs to be between two nodes on the track, if it is to be valid.
        /// Here we find whether indeed it is.
        /// </summary>
        /// <param name="drawnPathData">The data structure with the information on the drawn path</param>
        /// <param name="trackNodeIndex">The index of the track node</param>
        /// <returns>The node that will be before a possible new node on the track</returns>
        TrainpathNode FindPrevNodeOfActiveTrack(DrawnPathData drawnPathData, int trackNodeIndex)
        {
            Collection <TrainpathNode> nodesOnTrack = drawnPathData.NodesOnTrack(trackNodeIndex);

            // We are given a set of nodes. We know that a part of the path was drawn following those nodes
            // All of these parts are on the same track.
            // The nodes are ordered in pairs.
            for (int i = nodesOnTrack.Count - 1; i > 0; i -= 2)
            {
                if (activeTrackLocation.IsBetween(nodesOnTrack[i - 1], nodesOnTrack[i]))
                {
                    return(nodesOnTrack[i - 1]);
                }
            }
            return(null);
        }
示例#2
0
        /// <summary>
        /// Find the location on the track that can be used as a new end or wait node (or possibly start)
        /// </summary>
        /// <param name="drawnPathData">The data structure with the information on the drawn path</param>
        void FindActiveTrackLocation(DrawnPathData drawnPathData)
        {
            if (drawTrackDB.ClosestTrack == null ||
                drawTrackDB.ClosestTrack.TrackNode == null)
            {
                activeTrackLocation.Location = WorldLocation.None;
                return;
            }

            uint tni     = drawTrackDB.ClosestTrack.TrackNode.Index;
            int  tni_int = (int)tni;

            if (!drawnPathData.TrackHasBeenDrawn(tni_int) && CurrentTrainPath.FirstNode != null && activeMouseDragAction == null)
            {
                activeTrackLocation.Location = WorldLocation.None;
                return;
            }

            int   tvsi     = drawTrackDB.ClosestTrack.TrackVectorSectionIndex;
            float distance = drawTrackDB.ClosestTrack.DistanceAlongTrack;

            // find location
            WorldLocation location = drawTrackDB.FindLocation(tni, tvsi, distance, true);

            // fill the properties of the activeTrackLocation
            activeTrackLocation.TvnIndex = tni_int;
            activeTrackLocation.TrackVectorSectionIndex = tvsi;
            activeTrackLocation.TrackSectionOffset      = distance;
            activeTrackLocation.Location = location;

            if ((CurrentTrainPath.FirstNode != null) && (activeMouseDragAction == null))
            {   //Only in case this is not the first path.
                TrainpathNode prevNode = FindPrevNodeOfActiveTrack(drawnPathData, tni_int);
                if (prevNode == null || prevNode.HasSidingPath)
                {
                    activeTrackLocation.Location = WorldLocation.None;
                }
                else
                {
                    activeTrackLocation.PrevNode = prevNode;
                }
            }
        }
示例#3
0
        /// <summary>
        /// Find the node in the path that is closest to the mouse,
        /// </summary>
        /// <param name="drawArea">Area that is being drawn upon and where we have a mouse location</param>
        /// <param name="drawnPathData">The data structure with the information on the drawn path</param>
        void FindActiveNode(DrawArea drawArea, DrawnPathData drawnPathData)
        {
            // Initial simplest implementation: find simply the closest and first.
            float         closestMouseDistanceSquared = float.MaxValue;
            TrainpathNode closestNode = null;

            foreach (TrainpathNode node in drawnPathData.DrawnNodes)
            {
                float distanceSquared = CloseToMouse.GetGroundDistanceSquared(node.Location, drawArea.MouseLocation);
                // by using '<=' instead of '<' we should get the latest one, which overrides earlier ones
                if (distanceSquared <= closestMouseDistanceSquared)
                {
                    closestMouseDistanceSquared = distanceSquared;
                    closestNode = node;
                }
            }

            activeNode = closestNode;
        }
示例#4
0
        /// <summary>
        /// Find the active node and active node candidate and draw them
        /// </summary>
        /// <param name="drawArea">Area to draw upon</param>
        public void Draw(DrawArea drawArea)
        {
            DrawnPathData drawnPathData = new DrawnPathData();

            int numberDrawn = drawPath.Draw(drawArea, currentTrainPath.FirstNode, currentTrainPath.FirstNodeOfTail, numberToDraw,
                                            drawnPathData);

            if (numberDrawn < numberToDraw)
            {
                // Apparently we were not able to draw all nodes. Reset maximum number to draw, and possibly add a node
                numberToDraw = numberDrawn;
                if (EditingIsActive && allowAddingNodes &&
                    (CurrentNode != null) && (CurrentNode.NodeType != TrainpathNodeType.End))
                {
                    nonInteractiveAction.AddMainNode(CurrentNode, UpdateAfterEdits);
                }
            }

            if (!EditingIsActive)
            {
                return;
            }

            if (EnableMouseUpdate)
            {
                FindActiveNode(drawArea, drawnPathData);
                FindActiveTrackLocation(drawnPathData);
            }

            float textureSize  = 8f;
            int   minPixelSize = 7;
            int   maxPixelSize = 24;

            if (activeNode != null && activeNode.Location != null)
            {
                drawArea.DrawTexture(activeNode.Location, "ring", textureSize, minPixelSize, maxPixelSize, DrawColors.colorsNormal.ActiveNode);
            }
            if (activeTrackLocation != null && activeTrackLocation.Location != WorldLocation.None)
            {
                drawArea.DrawTexture(activeTrackLocation.Location, "ring", textureSize, minPixelSize, maxPixelSize, DrawColors.colorsNormal.CandidateNode);
            }
        }
示例#5
0
        /// <summary>
        /// Find the node in the path that is closest to the mouse,
        /// </summary>
        /// <param name="drawArea">Area that is being drawn upon and where we have a mouse location</param>
        /// <param name="drawnPathData">The data structure with the information on the drawn path</param>
        void FindActiveNode(DrawArea drawArea, DrawnPathData drawnPathData)
        {
            // Initial simplest implementation: find simply the closest and first.
            float         closestMouseDistanceSquared = float.MaxValue;
            TrainpathNode closestNode = null;

            foreach (TrainpathNode node in drawnPathData.DrawnNodes)
            {
                float distanceSquared = CloseToMouse.GetGroundDistanceSquared(node.Location, drawArea.MouseLocation);
                // by using '<=' instead of '<' we should get the latest one, which overrides earlier ones
                // To prevent numerical issues, we add a small number (smaller than two junctions would normally be together
                if (distanceSquared <= closestMouseDistanceSquared + 0.1f)
                {
                    closestMouseDistanceSquared = distanceSquared;
                    closestNode = node;
                }
            }

            activeNode = closestNode;
        }
示例#6
0
        /// <summary>
        /// Draw the actual path coded in the PATfile (for a number of nodes that can be extended or reduced)
        /// </summary>
        /// <param name="drawArea">Area to draw upon</param>
        /// <param name="firstNode">The first node of the path to draw</param>
        /// <param name="firstNodeOfTail">The node that is the start of the tail (if available)</param>
        /// <param name="numberToDraw">The requested number of nodes to draw</param>
        /// <param name="drawnPathData">Data structure that we will fill with information about the path we have drawn</param>
        /// <returns>the number of nodes actually drawn (not taking into account nodes on a siding)</returns>
        public int Draw(DrawArea drawArea, 
                         TrainpathNode firstNode,
                         TrainpathNode firstNodeOfTail,
                         int numberToDraw, 
                         DrawnPathData drawnPathData)
        {
            //List of all nodes that need to be drawn.
            List<TrainpathNode> drawnNodes = new List<TrainpathNode>();
 
            // start of path
            TrainpathNode currentSidingNode = null; // we start without siding path
            CurrentMainNode = firstNode;
            if (CurrentMainNode == null)
            {
                // no path, but there might still be a tail
                DrawTail(drawArea, colorSchemeMain, null, firstNodeOfTail);
                return 0;
            }
         
            drawnNodes.Add(CurrentMainNode);
            drawnPathData.AddNode(CurrentMainNode); 
            
            // We want to draw only a certain number of nodes. And if there is a siding, for the siding
            // we also want to draw the same number of nodes from where it splits from the main track
            int numberDrawn = 1;
            while (numberDrawn < numberToDraw)
            {
                
                // If we have a current siding track, we draw it 
                if (currentSidingNode != null)
                {
                    //finish the complete siding path if the main path is at end of siding already
                    int sidingNodesToDraw = (CurrentMainNode.NodeType == TrainpathNodeType.SidingEnd) ? Int32.MaxValue : 1;
                    while (sidingNodesToDraw >= 1)
                    {
                        //while tracking a siding, it has its own next node
                        TrainpathNode nextNodeOnSiding = currentSidingNode.NextSidingNode;
                        if (nextNodeOnSiding != null) // because also this path can run off at the end
                        {
                            DrawPathOnVectorNode(drawArea, colorSchemeSiding, currentSidingNode, nextNodeOnSiding, currentSidingNode.NextSidingTvnIndex);
                            drawnNodes.Add(nextNodeOnSiding);
                            drawnPathData.AddNode(nextNodeOnSiding);
                            //siding nodes will not be added to drawnPathData
                            sidingNodesToDraw--;
                        }
                        else
                        {
                            sidingNodesToDraw = 0;
                        }
                        currentSidingNode = nextNodeOnSiding;
                        
                    }
                }
 
                // Draw the start of a siding path, so from this main line point to the next siding node.
                // If there is a next siding node, we also reset the currentSidingNode
                // but probably it is not allowed to have siding on a siding
                TrainpathNode nextSidingNode = CurrentMainNode.NextSidingNode;             
                if (nextSidingNode != null)
                {
                    DrawPathOnVectorNode(drawArea, colorSchemeSiding, CurrentMainNode, nextSidingNode, CurrentMainNode.NextSidingTvnIndex);
                    drawnNodes.Add(nextSidingNode);
                    drawnPathData.AddNode(nextSidingNode);
                    currentSidingNode = nextSidingNode;
                }

                // From this mainline point to the next
                TrainpathNode nextMainNode = CurrentMainNode.NextMainNode;
                if (nextMainNode != null)
                {
                    DrawPathOnVectorNode(drawArea, colorSchemeMain, CurrentMainNode, nextMainNode, CurrentMainNode.NextMainTvnIndex);
                    drawnNodes.Add(nextMainNode);
                    drawnPathData.AddNode(nextMainNode);
                    drawnPathData.NoteAsDrawn(CurrentMainNode, nextMainNode);

                    CurrentMainNode = nextMainNode;
                    numberDrawn++;
                }
                else
                {
                    // no more nodes, so leave the loop even if we did not draw the amount of points requested
                    break;
                }
            }

            //Draw all the nodes themselves
            foreach (TrainpathNode node in drawnNodes) {
                DrawNodeItself(drawArea, node);
            }

            DrawTail(drawArea, colorSchemeMain, drawnNodes.Last(), firstNodeOfTail);

            return numberDrawn;
        }
示例#7
0
 /// <summary>
 /// Draw the actual path coded in the PATfile, completely.
 /// </summary>
 /// <param name="drawArea">Area to draw upon</param>
 /// <param name="firstNode">The first node of the path to draw</param>
 public void Draw(DrawArea drawArea, TrainpathNode firstNode)
 {
     DrawnPathData dummyData = new DrawnPathData();
     Draw(drawArea, firstNode, null, int.MaxValue, dummyData);
 }