public async Task <IActionResult> Post(SignalItem item)
        {
            _logger.LogInformation($"{nameof(Post)} {item.Message}");

            await _signalHub.Clients.All.SendCoreAsync("ReceiveMessage", new[] { item.Message });

            return(StatusCode(StatusCodes.Status200OK, true));
        }
Esempio n. 2
0
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="originalTrItem">The original track item that we are representing for drawing</param>
        public DrawableSignalItem(TrackItem originalTrItem)
            : base(originalTrItem)
        {
            this.Description = "signal";
            this.isNormal    = true; // default value
            SignalItem originalSignalItem = originalTrItem as SignalItem;

            this.direction  = originalSignalItem.Direction == 0 ? Traveller.TravellerDirection.Forward : Traveller.TravellerDirection.Backward;
            this.signalType = originalSignalItem.SignalType;
        }
Esempio n. 3
0
        /// <summary>
        /// Default constructor
        /// </summary>
        /// <param name="originalTrItem">The original track item that we are representing for drawing</param>
        public DrawableSignalItem(TrackItem originalTrItem)
            : base(originalTrItem)
        {
            this.Description = "signal";
            this.isNormal    = true; // default value
            SignalItem originalSignalItem = originalTrItem as SignalItem;

            this.direction  = originalSignalItem.Direction;
            this.signalType = originalSignalItem.SignalType;
        }
Esempio n. 4
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="item"></param>
 /// <param name="signal"></param>
 public AESignalItem(SignalItem item, SignalObject signal, TDBFile TDB)
 {
     typeWidget  = (int)TypeWidget.SIGNAL_WIDGET;
     Item        = item;
     Signal      = signal;
     sigFonction = new List <SignalHead.MstsSignalFunction>();
     foreach (var sig in Signal.SignalHeads)
     {
         sigFonction.Add(sig.sigFunction);
         if (sig.sigFunction == SignalHead.MstsSignalFunction.SPEED)
         {
             File.AppendAllText(@"C:\temp\AE.txt", "SPEED\n");
         }
     }
     foreach (var fn in sigFonction)
     {
         File.AppendAllText(@"C:\temp\AE.txt", "FN " + fn + "\n");
     }
     hasDir     = false;
     Location.X = item.TileX * 2048 + item.X;
     Location.Y = item.TileZ * 2048 + item.Z;
     try
     {
         var     node = TDB.TrackDB.TrackNodes[signal.trackNode];
         Vector2 v2;
         if (node.TrVectorNode != null)
         {
             var ts = node.TrVectorNode.TrVectorSections[0];
             v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z);
         }
         else if (node.TrJunctionNode != null)
         {
             var ts = node.UiD;
             v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z);
         }
         else
         {
             throw new Exception();
         }
         var v1 = new Vector2(Location.X, Location.Y);
         var v3 = v1 - v2;
         v3.Normalize();
         //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 12f : -12f);
         v2    = v1 - Vector2.Multiply(v3, 12f);
         Dir.X = (float)v2.X;
         Dir.Y = (float)v2.Y;
         //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 1.5f : -1.5f);//shift signal along the dir for 2m, so signals will not be overlapped
         v2         = v1 - Vector2.Multiply(v3, 1.5f);
         Location.X = (float)v2.X;
         Location.Y = (float)v2.Y;
         hasDir     = true;
     }
     catch { }
 }
Esempio n. 5
0
        //================================================================================================//
        /// <summary>
        /// Set the signal type object from the SIGCFG file
        /// </summary>
        internal void SetSignalType(TrackItem[] trackItems, SignalConfigurationFile signalConfig)
        {
            SignalItem signalItem = (SignalItem)trackItems[TDBIndex];

            // set signal type
            if (signalConfig.SignalTypes.ContainsKey(signalItem.SignalType))
            {
                // set signal type
                SignalType = signalConfig.SignalTypes[signalItem.SignalType];

                // get related signalscript
                SignalScriptProcessing.SignalScripts.Scripts.TryGetValue(SignalType, out signalScript);

                // set signal speeds
                foreach (SignalAspect aspect in SignalType.Aspects)
                {
                    SpeedInfoSet[aspect.Aspect] = new SpeedInfo(aspect.SpeedLimit, aspect.SpeedLimit, aspect.Asap, aspect.Reset, aspect.NoSpeedReduction ? 1 : 0);
                }

                // set normal subtype
                OrtsNormalSubtypeIndex = SignalType.OrtsNormalSubTypeIndex;

                // update overall SignalNumClearAhead

                if (SignalFunction == SignalFunction.Normal)
                {
                    MainSignal.SignalNumClearAheadMsts   = Math.Max(MainSignal.SignalNumClearAheadMsts, SignalType.NumClearAhead_MSTS);
                    MainSignal.SignalNumClearAheadOrts   = Math.Max(MainSignal.SignalNumClearAheadOrts, SignalType.NumClearAhead_ORTS);
                    MainSignal.SignalNumClearAheadActive = MainSignal.SignalNumClearAheadOrts;
                }

                // set approach control limits
                if (SignalType.ApproachControlDetails != null)
                {
                    ApproachControlLimitPositionM = SignalType.ApproachControlDetails.ApproachControlPositionM;
                    ApproachControlLimitSpeedMpS  = SignalType.ApproachControlDetails.ApproachControlSpeedMpS;
                }
                else
                {
                    ApproachControlLimitPositionM = null;
                    ApproachControlLimitSpeedMpS  = null;
                }

                if (SignalFunction == SignalFunction.Speed)
                {
                    MainSignal.IsSignal      = false;
                    MainSignal.IsSpeedSignal = true;
                }
            }
            else
            {
                Trace.TraceWarning($"SignalObject trItem={MainSignal.TrackItemIndex}, trackNode={MainSignal.TrackNode} has SignalHead with undefined SignalType {signalItem.SignalType}.");
            }
        }
Esempio n. 6
0
        //================================================================================================//
        /// <summary>
        /// Constructor for signals
        /// </summary>

        public SignalHead(Signal signal, int trackItem, int tbdRef, SignalItem signalItem)
        {
            MainSignal     = signal ?? throw new ArgumentNullException(nameof(signal));
            TrackItemIndex = trackItem;
            TDBIndex       = tbdRef;

            if (signalItem?.SignalDirections?.Count > 0)
            {
                TrackJunctionNode = signalItem.SignalDirections[0].TrackNode;
                JunctionPath      = signalItem.SignalDirections[0].LinkLRPath;
            }
        }
Esempio n. 7
0
 /// <summary>
 ///
 /// </summary>
 /// <param name="sideItem"></param>
 /// <param name="signal"></param>
 public AESignalItem(SignalItem item, AESignalObject signal, TrackDatabaseFile TDB)
 {
     typeItem    = (int)TypeItem.SIGNAL_ITEM;
     Item        = item;
     Signal      = signal;
     sigFonction = new List <MstsSignalFunction>();
     foreach (var sig in Signal.SignalHeads)
     {
         sigFonction.Add(sig.sigFunction);
     }
     hasDir     = false;
     Location.X = item.TileX * 2048 + item.X;
     Location.Y = item.TileZ * 2048 + item.Z;
     try
     {
         associateNode = TDB.TrackDB.TrackNodes[signal.trackNode];
         Vector2 v2;
         if (associateNode.TrVectorNode != null)
         {
             associateNodeIdx = (int)associateNode.Index;
             var ts = associateNode.TrVectorNode.TrVectorSections[0];
             v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z);
         }
         else if (associateNode.TrJunctionNode != null)
         {
             associateNodeIdx = associateNode.TrJunctionNode.Idx;
             var ts = associateNode.UiD;
             v2 = new Vector2(ts.TileX * 2048 + ts.X, ts.TileZ * 2048 + ts.Z);
         }
         else
         {
             throw new Exception();
         }
         var v1 = new Vector2(Location.X, Location.Y);
         var v3 = v1 - v2;
         v3.Normalize();
         v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 12f : -12f);
         //v2 = v1 - Vector2.Multiply(v3, 12f);
         Dir.X = (float)v2.X;
         Dir.Y = (float)v2.Y;
         //v2 = v1 - Vector2.Multiply(v3, signal.direction == 0 ? 1.5f : -1.5f);//shift signal along the dir for 2m, so signals will not be overlapped
         v2         = v1 - Vector2.Multiply(v3, 1.5f);
         Location.X = (float)v2.X;
         Location.Y = (float)v2.Y;
         hasDir     = true;
     }
     catch { }
 }
        public void ParserSignalLineTextTest1()
        {
            //Given
            string signalLine = " SG_ Pt_tiEdrvShOff : 50|12@1+ (1,0) [0|4095] \"min\"  ED";

            //When
            SignalItem item = DBCFileParser.ParserSignalLineText(signalLine);

            //Then
            Assert.Equal("Pt_tiEdrvShOff", item.SignalName);
            Assert.Equal(50u, item.StartBit);
            Assert.Equal(12u, item.SignalSize);
            Assert.Equal(SignalItem.ByteOrderEnum.Intel, item.ByteOrder);
            Assert.Equal(SignalItem.ValueTypeEnum.Unsigned, item.ValueType);
            Assert.Equal(1f, item.Factor);
            Assert.Equal(0f, item.Offset);
            Assert.Equal(0u, item.Min);
            Assert.Equal(4095u, item.Max);
            Assert.Equal("min", item.Unit);
            Assert.Contains("ED", item.Receiver);
        }
Esempio n. 9
0
        public void PopulateItemLists()
        {
            foreach (var item in F.simulator.TDB.TrackDB.TrItemTable)
            {
                switch (item.ItemType)
                {
                case TrItem.trItemType.trSIGNAL:
                    if (item is SignalItem)
                    {
                        SignalItem si = item as SignalItem;

                        if (si.SigObj >= 0 && si.SigObj < F.simulator.Signals.SignalObjects.Length)
                        {
                            var s = F.simulator.Signals.SignalObjects[si.SigObj];
                            if (s != null && s.isSignal && s.isSignalNormal())
                            {
                                F.signals.Add(new SignalWidget(si, s));
                            }
                        }
                    }
                    break;

                case TrItem.trItemType.trSIDING:
                    // Sidings have 2 ends but are not always listed in pairs in the *.tdb file
                    // Neither are their names unique (e.g. Bernina Bahn).
                    // Find whether this siding is a new one or the other end of an old one.
                    // If other end, then find the right-hand one as the location for a single label.
                    // Note: Find() within a foreach() loop is O(n^2) but is only done at start.
                    var oldSidingIndex = F.sidings.FindIndex(r => r.LinkId == item.TrItemId && r.Name == item.ItemName);
                    if (oldSidingIndex < 0)
                    {
                        var newSiding = new SidingWidget(item as SidingItem);
                        F.sidings.Add(newSiding);
                    }
                    else
                    {
                        var oldSiding   = F.sidings[oldSidingIndex];
                        var oldLocation = oldSiding.Location;
                        var newLocation = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z);

                        // Because these are structs, not classes, compiler won't let you overwrite them.
                        // Instead create a single item which replaces the 2 platform items.
                        var replacement = new SidingWidget(item as SidingItem)
                        {
                            Location = GetMidPoint(oldLocation, newLocation)
                        };

                        // Replace the old siding item with the replacement
                        F.sidings.RemoveAt(oldSidingIndex);
                        F.sidings.Add(replacement);
                    }
                    break;

                case TrItem.trItemType.trPLATFORM:
                    // Platforms have 2 ends but are not always listed in pairs in the *.tdb file
                    // Neither are their names unique (e.g. Bernina Bahn).
                    // Find whether this platform is a new one or the other end of an old one.
                    // If other end, then find the right-hand one as the location for a single label.
                    var oldPlatformIndex = F.platforms.FindIndex(r => r.LinkId == item.TrItemId && r.Name == item.ItemName);
                    if (oldPlatformIndex < 0)
                    {
                        var newPlatform = new PlatformWidget(item as PlatformItem)
                        {
                            Extent1 = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z)
                        };
                        F.platforms.Add(newPlatform);
                    }
                    else
                    {
                        var oldPlatform = F.platforms[oldPlatformIndex];
                        var oldLocation = oldPlatform.Location;
                        var newLocation = new PointF(item.TileX * 2048 + item.X, item.TileZ * 2048 + item.Z);

                        // Because these are structs, not classes, compiler won't let you overwrite them.
                        // Instead create a single item which replaces the 2 platform items.
                        var replacement = new PlatformWidget(item as PlatformItem)
                        {
                            Extent1 = oldLocation
                            ,
                            Extent2 = newLocation
                                      // Give it the right-hand location
                            ,
                            Location = GetRightHandPoint(oldLocation, newLocation)
                        };

                        // Replace the old platform item with the replacement
                        F.platforms.RemoveAt(oldPlatformIndex);
                        F.platforms.Add(replacement);
                    }
                    break;

                default:
                    break;
                }
            }

            foreach (var p in F.platforms)
            {
                if (p.Extent1.IsEmpty || p.Extent2.IsEmpty)
                {
                    Trace.TraceWarning("Platform '{0}' is incomplete as the two ends do not match. It will not show in full in the Timetable Tab of the Map Window", p.Name);
                }
            }
        }
Esempio n. 10
0
            public SignalShapeHead(Viewer viewer, SignalShape signalShape, int index, SignalHead signalHead,
                                   SignalItem mstsSignalItem, Formats.Msts.SignalShape.SignalSubObj mstsSignalSubObj)
            {
                Viewer      = viewer;
                SignalShape = signalShape;
#if DEBUG_SIGNAL_SHAPES
                Index = index;
#endif
                SignalHead = signalHead;
                for (int mindex = 0; mindex <= signalShape.SharedShape.MatrixNames.Count - 1; mindex++)
                {
                    string MatrixName = signalShape.SharedShape.MatrixNames[mindex];
                    if (String.Equals(MatrixName, mstsSignalSubObj.MatrixName))
                    {
                        MatrixIndices.Add(mindex);
                    }
                }


                if (!viewer.SIGCFG.SignalTypes.ContainsKey(mstsSignalSubObj.SignalSubSignalType))
                {
                    return;
                }

                var mstsSignalType = viewer.SIGCFG.SignalTypes[mstsSignalSubObj.SignalSubSignalType];

                SignalTypeData = viewer.SignalTypeDataManager.Get(mstsSignalType);

                if (SignalTypeData.Semaphore)
                {
                    // Check whether we have to correct the Semaphore position indexes following the strange rule of MSTS
                    // Such strange rule is that, if there are only two animation steps in the related .s file, MSTS behaves as follows:
                    // a SemaphorePos (2) in sigcfg.dat is executed as SemaphorePos (1)
                    // a SemaphorePos (1) in sigcfg.dat is executed as SemaphorePos (0)
                    // a SemaphorePos (0) in sigcfg.dat is executed as SemaphorePos (0)
                    // First we check if there are only two animation steps
                    if (signalShape.SharedShape.Animations != null && signalShape.SharedShape.Animations.Count != 0 && MatrixIndices.Count > 0 &&
                        signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers.Count != 0 &&
                        signalShape.SharedShape.Animations[0].anim_nodes[MatrixIndices[0]].controllers[0].Count == 2)
                    {
                        // OK, now we check if maximum SemaphorePos is 2 (we won't correct if there are only SemaphorePos 1 and 0,
                        // because they would both be executed as SemaphorePos (0) accordingly to above law, therefore leading to a static semaphore)
                        float maxIndex = float.MinValue;
                        foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values)
                        {
                            if (drAsp.SemaphorePos > maxIndex)
                            {
                                maxIndex = drAsp.SemaphorePos;
                            }
                        }
                        if (maxIndex == 2)
                        {
                            // in this case we modify the SemaphorePositions for compatibility with MSTS.
                            foreach (SignalAspectData drAsp in SignalTypeData.DrawAspects.Values)
                            {
                                switch ((int)drAsp.SemaphorePos)
                                {
                                case 2:
                                    drAsp.SemaphorePos = 1;
                                    break;

                                case 1:
                                    drAsp.SemaphorePos = 0;
                                    break;

                                default:
                                    break;
                                }
                            }
                            if (!SignalTypeData.AreSemaphoresReindexed)
                            {
                                Trace.TraceInformation("Reindexing semaphore entries of signal type {0} for compatibility with MSTS", mstsSignalType.Name);
                                SignalTypeData.AreSemaphoresReindexed = true;
                            }
                        }
                    }

                    foreach (int mindex in MatrixIndices)
                    {
                        if (mindex == 0 && (signalShape.SharedShape.Animations == null || signalShape.SharedShape.Animations.Count == 0 ||
                                            signalShape.SharedShape.Animations[0].anim_nodes[mindex].controllers.Count == 0))
                        {
                            continue;
                        }
                        AnimatedPart SemaphorePart = new AnimatedPart(signalShape);
                        SemaphorePart.AddMatrix(mindex);
                        SemaphoreParts.Add(SemaphorePart);
                    }

                    if (Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS != null)
                    {
                        var soundPath = Viewer.Simulator.RoutePath + @"\\sound\\" + Viewer.Simulator.TRK.Tr_RouteFile.DefaultSignalSMS;
                        try
                        {
                            Sound = new SoundSource(Viewer, SignalShape.Location.WorldLocation, Events.Source.MSTSSignal, soundPath);
                            Viewer.SoundProcess.AddSoundSources(this, new List <SoundSourceBase>()
                            {
                                Sound
                            });
                        }
                        catch (Exception error)
                        {
                            Trace.WriteLine(new FileLoadException(soundPath, error));
                        }
                    }
                }

                lightStates = new SignalLightState[SignalTypeData.Lights.Count];
                for (var i = 0; i < SignalTypeData.Lights.Count; i++)
                {
                    lightStates[i] = new SignalLightState(SignalTypeData.OnOffTimeS);
                }

#if DEBUG_SIGNAL_SHAPES
                Console.Write("  HEAD type={0,-8} lights={1,-2} sem={2}", SignalTypeData.Type, SignalTypeData.Lights.Count, SignalTypeData.Semaphore);
#endif
            }
Esempio n. 11
0
        public void LoadItemsFromMSTS()
        {
#if SHOW_STOPWATCH
            Stopwatch stopWatch = new Stopwatch();
            TimeSpan  ts;
            string    elapsedTime;
            if (File.Exists(@"C:\temp\stopwatch.txt"))
            {
                File.Delete(@"C:\temp\stopwatch.txt");
            }
#endif


            if (TDB == null ||
                TDB.TrackDB == null ||
                TDB.TrackDB.TrItemTable == null)
            {
                return;
            }
            foreach (GlobalItem item in orRouteConfig.AllItems)
            {
                if (item.GetType() == typeof(AEBufferItem))
                {
                    mstsItems.buffers.Add((AEBufferItem)item);
                }
            }
            Program.actEditor.DisplayStatusMessage("Start loading Track Nodes ...");
#if SHOW_STOPWATCH
            stopWatch.Start();
#endif
            nodes = TDB.TrackDB.TrackNodes;
            for (int nodeIdx = 0; nodeIdx < nodes.Length; nodeIdx++)
            {
                if (nodes[nodeIdx] != null)
                {
                    TrackNode currNode = nodes[nodeIdx];

                    AEBufferItem foundBuffer;
                    if (currNode.TrEndNode)
                    {
                        //Program.actEditor.DisplayStatusMessage("Init data for display...  Load End Nodes: " + currNode.Index);
                        try
                        {
                            foundBuffer = (AEBufferItem)orRouteConfig.AllItems.First(x => x.associateNodeIdx == currNode.Index);
                            foundBuffer.updateNode(currNode);
                        }
                        catch (InvalidOperationException)
                        {
                            foundBuffer = new AEBufferItem((TrackNode)currNode);
                            mstsItems.buffers.Add(foundBuffer);
                        }
#if SHOW_STOPWATCH
                        ts = stopWatch.Elapsed;
                        stopWatch.Reset();

                        // Format and display the TimeSpan value.
                        elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                                                    ts.Hours, ts.Minutes, ts.Seconds,
                                                    ts.Milliseconds);
                        File.AppendAllText(@"C:\temp\stopwatch.txt", "One END node: " + elapsedTime + "\n");
                        stopWatch.Start();
#endif
                    }
                    else if (currNode.TrVectorNode != null && currNode.TrVectorNode.TrVectorSections != null)
                    {
                        //Program.actEditor.DisplayStatusMessage("Init data for display...  Load Vector Nodes: " + currNode.Index);
                        if (currNode.TrVectorNode.TrVectorSections.Length > 1)
                        {
                            AddSegments(currNode);
                            TrVectorSection section = currNode.TrVectorNode.TrVectorSections[currNode.TrVectorNode.TrVectorSections.Length - 1];
                            MSTSCoord       A       = new MSTSCoord(section);

                            TrPin pin = currNode.TrPins[1];
                            {
                                TrackNode connectedNode = nodes[pin.Link];
                                int       direction     = DrawUtility.getDirection(currNode, connectedNode);
                                if (A == connectedNode.getMSTSCoord(direction))
                                {
                                    continue;
                                }
                                AESegment    aeSegment = new AESegment(A, connectedNode.getMSTSCoord(direction));
                                TrackSegment lineSeg   = new TrackSegment(aeSegment, currNode, currNode.TrVectorNode.TrVectorSections.Length - 1, direction, TSectionDat);
                                addTrItems(lineSeg, currNode);
                                mstsItems.AddSegment(lineSeg);
                            }
#if SHOW_STOPWATCH
                            ts = stopWatch.Elapsed;
                            stopWatch.Reset();

                            // Format and display the TimeSpan value.
                            elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                                                        ts.Hours, ts.Minutes, ts.Seconds,
                                                        ts.Milliseconds);
                            File.AppendAllText(@"C:\temp\stopwatch.txt", "One mult TRACK node: " + elapsedTime + "\n");
                            stopWatch.Start();
#endif
                        }
                        else
                        {
                            TrVectorSection s;
                            s = currNode.TrVectorNode.TrVectorSections[0];
                            areaRoute.manageTiles(s.TileX, s.TileZ);
                            foreach (TrPin pin in currNode.TrPins)
                            {
                                TrackNode connectedNode = nodes[pin.Link];
                                int       direction     = DrawUtility.getDirection(currNode, connectedNode);
                                if (MSTSCoord.near(currNode.getMSTSCoord(direction), connectedNode.getMSTSCoord(direction)))
                                {
                                    continue;
                                }
                                AESegment    aeSegment = new AESegment(currNode.getMSTSCoord(direction), connectedNode.getMSTSCoord(direction));
                                TrackSegment lineSeg   = new TrackSegment(aeSegment, currNode, 0, direction, TSectionDat);
                                addTrItems(lineSeg, currNode);
                                mstsItems.AddSegment(lineSeg);
                            }
#if SHOW_STOPWATCH
                            ts = stopWatch.Elapsed;
                            stopWatch.Reset();

                            // Format and display the TimeSpan value.
                            elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                                                        ts.Hours, ts.Minutes, ts.Seconds,
                                                        ts.Milliseconds);
                            File.AppendAllText(@"C:\temp\stopwatch.txt", "One simple TRACK node: " + elapsedTime + "\n");
                            stopWatch.Start();
#endif
                        }
                    }

                    else if (currNode.TrJunctionNode != null)
                    {
                        //Program.actEditor.DisplayStatusMessage("Init data for display...  Load Junction Nodes: " + currNode.Index);
                        mstsItems.switches.Add(new AEJunctionItem(currNode));
                        areaRoute.manageTiles(currNode.UiD.TileX, currNode.UiD.TileZ);
#if SHOW_STOPWATCH
                        ts = stopWatch.Elapsed;
                        stopWatch.Reset();

                        // Format and display the TimeSpan value.
                        elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                                                    ts.Hours, ts.Minutes, ts.Seconds,
                                                    ts.Milliseconds);
                        File.AppendAllText(@"C:\temp\stopwatch.txt", "One JN node: " + elapsedTime + "\n");
                        stopWatch.Start();
#endif
                    }
                }
            }
#if SPA_ADD
            var maxsize = maxX - minX > maxX - minX ? maxX - minX : maxX - minX;
            maxsize = (int)maxsize / 100 * 100;
            if (maxsize < 2000)
            {
                maxsize = 2000;
            }
            ZoomFactor = (decimal)maxsize;
#endif
            #region AddItem


            Program.actEditor.DisplayStatusMessage("Init data for display...  Load MSTS Items...");
            foreach (var item in TDB.TrackDB.TrItemTable)
            {
                if (item.ItemType == TrItem.trItemType.trSIGNAL && Signals != null)
                {
                    if (item is SignalItem)
                    {
#if SHOW_STOPWATCH
                        Program.actEditor.DisplayStatusMessage("Init data for display...  Load Items... Signal");
#endif
                        SignalItem si = item as SignalItem;

                        if (si.SigObj >= 0 && si.SigObj < Signals.SignalObjects.Length)
                        {
                            AESignalObject s = Signals.SignalObjects[si.SigObj];
                            if (s.isSignal) // && s.isSignalNormal())
                            {
                                mstsItems.AddSignal(new AESignalItem(si, s, TDB));
                            }
                        }
                    }
                }
            }

#if SHOW_STOPWATCH
            ts = stopWatch.Elapsed;

            // Format and display the TimeSpan value.
            elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:000}",
                                        ts.Hours, ts.Minutes, ts.Seconds,
                                        ts.Milliseconds);
            File.AppendAllText(@"C:\temp\stopwatch.txt", "Signals: " + elapsedTime + "\n");
            stopWatch.Stop();
#endif
            #endregion
        }