/// <summary> /// Constructor that immediately sets the closest item (and distance) /// </summary> /// <param name="tn">Tracknode that will be stored as closest item</param> /// <param name="tsectionDat">The track section Dat file that we can use to calculate the distance to the track</param> public CloseToMouseTrack(TrackSectionsFile tsectionDat, TrackNode tn) { this.tsectionDat = tsectionDat; sortedTrackCandidates = new SortedList<double, TrackCandidate>(new ReverseDoubleComparer()); sortedTrackCandidates.Add(0, new TrackCandidate(tn, null, 0, 0)); realDistancesAreCalculated = true; // we do not want to calculate distance if we override the highlight }
/// <summary> /// Creates an trainpath from PAT file information. /// First creates all the nodes and then links them together into a main list /// with optional parallel siding list. /// </summary> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> /// <param name="filePath">file name including path of the .pat file</param> public Trainpath(TrackDB trackDB, TrackSectionsFile tsectionDat, string filePath) : this(trackDB, tsectionDat) { this.FilePath = filePath; PathFile patFile = new PathFile(filePath); if (PatFileIsIncomplete(patFile)) { MessageBox.Show("The .pat file is somehow incomplete. Cannot load the path.", "Trackviewer Path Editor", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } PathId = patFile.PathID; PathName = patFile.Name; PathStart = patFile.Start; PathEnd = patFile.End; PathFlags = patFile.Flags; List <TrainpathNode> Nodes = new List <TrainpathNode>(); CreateNodes(patFile, Nodes); LinkNodes(patFile, Nodes); SetFacingPoints(Nodes); FindSidingEnds(); FindNodeOrientations(); FindWronglyOrientedLinks(); DetermineIfBroken(); }
/// <summary> /// Constructor /// </summary> public DrawPath (TrackDB trackDB, TrackSectionsFile tsectionDat) { this.trackDB = trackDB; this.tsectionDat = tsectionDat; this.colorSchemeMain = DrawColors.colorsPathMain; this.colorSchemeSiding = DrawColors.colorsPathSiding; }
public MSTSData(string mstsPath, string Route) { MstsPath = mstsPath; RoutePath = Route; TRK = new RouteFile(MSTS.MSTSPath.GetTRKFileName(RoutePath)); string routePath = Path.Combine(Route, TRK.Tr_RouteFile.FileName); TDB = new TrackDatabaseFile(RoutePath + @"\" + TRK.Tr_RouteFile.FileName + ".tdb"); string ORfilepath = System.IO.Path.Combine(RoutePath, "OpenRails"); if (File.Exists(ORfilepath + @"\sigcfg.dat")) { SIGCFG = new SignalConfigurationFile(ORfilepath + @"\sigcfg.dat", true); } else { SIGCFG = new SignalConfigurationFile(RoutePath + @"\sigcfg.dat", false); } if (Directory.Exists(MstsPath + @"\GLOBAL") && File.Exists(MstsPath + @"\GLOBAL\TSECTION.DAT")) { TSectionDat = new TrackSectionsFile(MstsPath + @"\GLOBAL\TSECTION.DAT"); } else { TSectionDat = new TrackSectionsFile(RoutePath + @"\GLOBAL\TSECTION.DAT"); } if (File.Exists(RoutePath + @"\TSECTION.DAT")) { TSectionDat.AddRouteTSectionDatFile(RoutePath + @"\TSECTION.DAT"); } Signals = new AESignals(this, SIGCFG); }
int currentIndexUnmodified; // The index of the last saved path. #endregion /// <summary> /// Basic constructor creating an empty path, but storing track database and track section data /// </summary> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public Trainpath(TrackDB trackDB, TrackSectionsFile tsectionDat) { this.trackDB = trackDB; this.tsectionDat = tsectionDat; trainPaths = new List <TrainPathData>(); trainPaths.Add(new TrainPathData()); }
/// <summary> /// Constructor /// </summary> /// <param name="routeData">The data needed for the route</param> public TrackItemManager(ORTS.TrackViewer.Drawing.RouteData routeData) { this.trackDB = routeData.TrackDB; this.tsectionDat = routeData.TsectionDat; cachedItems = new Dictionary <TrackNode, IEnumerable <ChartableTrackItem> >(); }
/// <summary> /// Constructor /// </summary> public DrawPath(TrackDB trackDB, TrackSectionsFile tsectionDat) { this.trackDB = trackDB; this.tsectionDat = tsectionDat; this.ColorSchemeMain = DrawColors.colorsPathMain; this.ColorSchemeSiding = DrawColors.colorsPathSiding; this.ColorSchemeLast = DrawColors.ShadeColor(DrawColors.otherPathsReferenceColor, 0, 1); }
public TrackContent(TrackDB trackDB, RoadTrackDB roadTrackDB, TrackSectionsFile trackSections, SignalConfigurationFile signalConfig, bool metricUnits) { this.trackDB = trackDB; this.roadTrackDB = roadTrackDB; trackSectionsFile = trackSections; UseMetricUnits = metricUnits; SignalConfigFile = signalConfig; }
/// <summary> /// Creates a single trainpathNode and initializes everything that do not depend on other nodes. /// The trainpath constructor will initialize the rest. /// </summary> protected TrainpathNode(TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : this(trackDB, tsectionDat) { Location = new WorldLocation(pdp.TileX, pdp.TileZ, pdp.X, pdp.Y, pdp.Z); if (pdp.IsInvalid) // not a valid point { this.SetBroken(NodeStatus.SetAsInvalid); } }
/// <summary> /// basic constructor, in case node is not created from PAT file, and only some parts are needed /// </summary> protected TrainpathNode(TrackDB trackDB, TrackSectionsFile tsectionDat) { this.TrackDB = trackDB; this.TsectionDat = tsectionDat; HasSidingPath = false; NextMainTvnIndex = 0; NextSidingTvnIndex = 0; NodeType = TrainpathNodeType.Other; }
/// <summary> /// Creates a single trainpathNode and initializes everything that do not depend on other nodes. /// The trainpath constructor will initialize the rest. /// </summary> protected TrainpathNode(PathDataPoint pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : this(trackDB, tsectionDat) { Location = pdp.Location; if (pdp.IsInvalid) // not a valid point { this.SetBroken(NodeStatus.SetAsInvalid); } }
/// <summary> /// Constructor /// </summary> /// <param name="routeData">The data needed for the route</param> public TrackItemManager(ORTS.TrackViewer.Drawing.RouteData routeData) { this.trackDB = routeData.TrackDB; this.tsectionDat = routeData.TsectionDat; cachedItems = new Dictionary <TrackNode, IEnumerable <ChartableTrackItem> >(); supportedTrackTypes = new HashSet <TrItem.trItemType> { TrItem.trItemType.trPLATFORM, TrItem.trItemType.trSPEEDPOST, }; }
public void SetTraveller(TrackSectionsFile TSectionDat, TrackDatabaseFile TDB) { TrackNode[] TrackNodes = TDB.TrackDB.TrackNodes; traveller = new AETraveller(TSectionDat, TDB); foreach (var item in routeItems) { if (item.GetType() == typeof(StationItem)) { ((StationItem)item).setTraveller(traveller); } } }
public async Task Initialize() { List <Task> initializer = new List <Task> { Task.Run(async() => await InitializeTrackSegments().ConfigureAwait(false)) }; await Task.WhenAll(initializer).ConfigureAwait(false); trackDB = null; roadTrackDB = null; trackSectionsFile = null; }
/// <summary> /// Find the angle that the signal needs to be drawn at /// </summary> /// <param name="tsectionDat">Database with track sections</param> /// <param name="trackDB">Database with tracks</param> /// <param name="tn">TrackNode on which the signal actually is</param> public void FindAngle(TrackSectionsFile tsectionDat, TrackDB trackDB, TrackNode tn) { this.angle = 0; try { Traveller signalTraveller = new Traveller(tsectionDat, trackDB.TrackNodes, tn, this.WorldLocation.TileX, this.WorldLocation.TileZ, this.WorldLocation.Location.X, this.WorldLocation.Location.Z, this.direction); this.angle = signalTraveller.RotY; } catch { } }
/// <summary> /// Returns the index of the vector node connection this path node to the (given) nextNode. /// </summary> public int FindTVNIndex(AIPathNode nextNode, TrackDatabaseFile TDB, TrackSectionsFile tsectiondat) { int junctionIndexThis = JunctionIndex; int junctionIndexNext = nextNode.JunctionIndex; // if this is no junction, try to find the TVN index if (junctionIndexThis < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, this)); } catch { junctionIndexThis = FindJunctionOrEndIndex(this.Location, TDB.TrackDB, false); } } // this is a junction; if the next node is no junction, try that one. if (junctionIndexNext < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, nextNode)); } catch { junctionIndexNext = FindJunctionOrEndIndex(nextNode.Location, TDB.TrackDB, false); } } //both this node and the next node are junctions: find the vector node connecting them. for (int i = 0; i < TDB.TrackDB.TrackNodes.Count(); i++) { TrackNode tn = TDB.TrackDB.TrackNodes[i]; if (tn == null || tn.TrVectorNode == null) { continue; } if (tn.TrPins[0].Link == junctionIndexThis && tn.TrPins[1].Link == junctionIndexNext) { return(i); } if (tn.TrPins[1].Link == junctionIndexThis && tn.TrPins[0].Link == junctionIndexNext) { return(i); } } return(-1); }
/// <summary> /// Find the angle that the signal needs to be drawn at /// </summary> /// <param name="tsectionDat">Database with track sections</param> /// <param name="trackDB">Database with tracks</param> /// <param name="tn">TrackNode on which the signal actually is</param> public void FindAngle(TrackSectionsFile tsectionDat, TrackDB trackDB, TrackVectorNode tn) { this.angle = 0; try { Traveller signalTraveller = new Traveller(tsectionDat, trackDB.TrackNodes, tn, WorldLocation, this.direction); this.angle = signalTraveller.RotY; // Shift signal a little bit to be able to distinguish backfacing from normal facing Microsoft.Xna.Framework.Vector3 shiftedLocation = this.WorldLocation.Location + 0.0001f * new Microsoft.Xna.Framework.Vector3((float)Math.Cos(this.angle), 0f, -(float)Math.Sin(this.angle)); this.WorldLocation = new WorldLocation(this.WorldLocation.TileX, this.WorldLocation.TileZ, shiftedLocation); } catch { } }
/// <summary> /// Try to load the file. /// Possibly this might raise an exception. That exception is not caught here /// </summary> /// <param name="file">The file that needs to be loaded</param> public override void TryLoading(string file) { string subdirname = Path.GetFileName(Path.GetDirectoryName(file)); if (subdirname.Equals("openrails", System.StringComparison.OrdinalIgnoreCase)) { //todo Need good examples for this. Might not actually be found via SIMIS header //Also not clear if this needs a global tracksection or not _ = new TrackSectionsFile(file); } else { globalTsection.AddRouteTSectionDatFile(file); } }
/// <summary> /// Try to load the file. /// Possibly this might raise an exception. That exception is not caught here /// </summary> /// <param name="file">The file that needs to be loaded</param> public override void TryLoading(string file) { var subdirname = Path.GetFileName(Path.GetDirectoryName(file)).ToLowerInvariant(); if (subdirname == "openrails") { //todo Need good examples for this. Might not actually be found via SIMIS header //Also not clear if this needs a global tracksection or not var TSectionDat = new TrackSectionsFile(file); } else { _globalTsection.AddRouteTSectionDatFile(file); } }
/// <summary> /// Constructor /// </summary> public DrawMultiplePaths(RouteData routeData, Collection <Path> paths) { this.trackDB = routeData.TrackDB; this.tsectionDat = routeData.TsectionDat; fullPathNames = new Dictionary <string, string>(); loadedPaths = new Dictionary <string, Trainpath>(); selectedTrainpaths = new List <Trainpath>(); drawPaths = new Dictionary <Trainpath, DrawPath>(); foreach (Path path in paths) { string pathName = ORTS.TrackViewer.UserInterface.MenuControl.MakePathMenyEntryName(path); fullPathNames[pathName] = path.FilePath; } }
/// <summary> /// Constructor based on PAT file information. /// </summary> /// <param name="tpn">TrPathNode from .pat file</param> /// <param name="pdp">TrackPDP from .pat file</param> /// <param name="trackDB"></param> /// <param name="tsectionDat"></param> public TrainpathVectorNode(TrPathNode tpn, TrackPDP pdp, TrackDB trackDB, TrackSectionsFile tsectionDat) : base(pdp, trackDB, tsectionDat) { try { Traveller traveller = new Traveller(tsectionDat, trackDB.TrackNodes, this.Location); CopyDataFromTraveller(traveller); } catch { SetBroken(NodeStatus.NotOnTrack); } ForwardOriented = true; // only initial setting InterpretPathNodeFlags(tpn); }
/// <summary> /// base constructor that only stores the information of the tracks. /// </summary> /// <param name="routeData">The route information that contains track data base and track section data</param> /// <param name="drawTrackDB">The drawn tracks to know about where the mouse is</param> private PathEditor(RouteData routeData, DrawTrackDB drawTrackDB) { this.drawTrackDB = drawTrackDB; this.trackDB = routeData.TrackDB; this.tsectionDat = routeData.TsectionDat; TrackExtensions.Initialize(trackDB.TrackNodes, tsectionDat); // we might be calling this more than once, but so be it. enableMouseUpdate = true; drawPath = new DrawPath(trackDB, tsectionDat); CreateNonMenuActions(); CreateDirectActions(); CreateContextMenuEntries(); CreateContextMenu(); }
internal async Task LoadTrackData(bool?useMetricUnits, CancellationToken cancellationToken) { List <Task> loadTasks = new List <Task>(); FolderStructure.ContentFolder.RouteFolder routeFolder = FolderStructure.Route(routePath); RouteFile routeFile = new RouteFile(routeFolder.TrackFileName); RouteName = routeFile.Route.Name; UseMetricUnits = useMetricUnits.GetValueOrDefault(routeFile.Route.MilepostUnitsMetric); loadTasks.Add(Task.Run(() => { string tdbFile = routeFolder.TrackDatabaseFile(routeFile); if (!File.Exists(tdbFile)) { Trace.TraceError($"Track Database File not found in {tdbFile}"); return; } TrackDB = new TrackDatabaseFile(tdbFile).TrackDB; }, cancellationToken)); loadTasks.Add(Task.Run(() => { TrackSections = new TrackSectionsFile(routeFolder.TrackSectionFile); if (File.Exists(routeFolder.RouteTrackSectionFile)) { TrackSections.AddRouteTSectionDatFile(routeFolder.RouteTrackSectionFile); } }, cancellationToken)); loadTasks.Add(Task.Run(() => { string rdbFile = routeFolder.RoadTrackDatabaseFile(routeFile); if (!File.Exists(rdbFile)) { Trace.TraceError($"Road Database File not found in {rdbFile}"); return; } RoadTrackDB = new RoadDatabaseFile(rdbFile).RoadTrackDB; }, cancellationToken)); loadTasks.Add(Task.Run(() => SignalConfig = new SignalConfigurationFile(routeFolder.SignalConfigurationFile, routeFolder.ORSignalConfigFile), cancellationToken)); await Task.WhenAll(loadTasks).ConfigureAwait(false); }
/// <summary> /// Find the indices we need to use for TrPins in the various junction nodes in case we want to use either main /// or siding path. That information is available in the trackshapes in the tsectionDat. /// </summary> /// <param name="trackNodesIn">The tracknodes</param> /// <param name="tsectionDatIn">Track section Data</param> public static void Initialize(TrackNode[] trackNodesIn, TrackSectionsFile tsectionDatIn) { trackNodes = trackNodesIn; tsectionDat = tsectionDatIn; mainRouteIndex = new uint[trackNodes.Length]; sidingRouteIndex = new uint[trackNodes.Length]; for (int tni = 0; tni < trackNodes.Length; tni++) { TrackNode tn = trackNodes[tni]; if (tn == null) { continue; } if (tn.TrJunctionNode == null) { continue; } uint mainRoute = 0; uint trackShapeIndex = tn.TrJunctionNode.ShapeIndex; try { TrackShape trackShape = tsectionDat.TrackShapes.Get(trackShapeIndex); mainRoute = trackShape.MainRoute; } catch (System.IO.InvalidDataException exception) { exception.ToString(); } mainRouteIndex[tni] = tn.Inpins + mainRoute; if (mainRoute == 0) { // sidingRouteIndex is simply the next sidingRouteIndex[tni] = tn.Inpins + 1; } else { // sidingRouteIndex is the first sidingRouteIndex[tni] = tn.Inpins; } } }
// restore game state public AIPath(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, BinaryReader inf) { pathName = inf.ReadString(); TrackDB = TDB.TrackDB; TSectionDat = tsectiondat; int n = inf.ReadInt32(); for (int i = 0; i < n; i++) { Nodes.Add(new AIPathNode(inf)); } for (int i = 0; i < n; i++) { Nodes[i].NextMainNode = ReadNode(inf); Nodes[i].NextSidingNode = ReadNode(inf); } FirstNode = Nodes[0]; //LastVisitedNode = ReadNode(inf); }
/// <summary> /// constructor out of other path /// </summary> /// <param name="otherPath"></param> public AIPath(AIPath otherPath) { TrackDB = otherPath.TrackDB;; TSectionDat = otherPath.TSectionDat; FirstNode = new AIPathNode(otherPath.FirstNode); foreach (AIPathNode otherNode in otherPath.Nodes) { Nodes.Add(new AIPathNode(otherNode)); } // set correct node references for (int iNode = 0; iNode <= otherPath.Nodes.Count - 1; iNode++) { AIPathNode otherNode = otherPath.Nodes[iNode]; if (otherNode.NextMainNode != null) { Nodes[iNode].NextMainNode = Nodes[otherNode.NextMainNode.Index]; } if (otherNode.NextSidingNode != null) { Nodes[iNode].NextSidingNode = Nodes[otherNode.NextSidingNode.Index]; } } if (otherPath.FirstNode.NextMainNode != null) { FirstNode.NextMainNode = Nodes[otherPath.FirstNode.NextMainNode.Index]; } if (otherPath.FirstNode.NextSidingNode != null) { FirstNode.NextSidingNode = Nodes[otherPath.FirstNode.NextSidingNode.Index]; } pathName = otherPath.pathName; }
/// <summary> /// Constructor giving the information this loaded depends on /// </summary> /// <param name="globalTsection">The global Tsection that is used as a base</param> public TSectionLoader(TrackSectionsFile globalTsection) : this() { this.globalTsection = globalTsection; }
/// <summary> /// Try to find the tracknode corresponding to the given node's location. /// This will raise an exception if it cannot be found /// </summary> /// <param name="TDB"></param> /// <param name="tsectiondat"></param> /// <param name="node"></param> /// <returns>The track node index that has been found (or an exception)</returns> private static int findTrackNodeIndex(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, AIPathNode node) { Traveller traveller = new Traveller(tsectiondat, TDB.TrackDB.TrackNodes, node.Location); return(traveller.TrackNodeIndex); }
public string pathName; //name of the path to be able to print it. /// <summary> /// Creates an AIPath from PAT file information. /// First creates all the nodes and then links them together into a main list /// with optional parallel siding list. /// </summary> public AIPath(TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, string filePath, bool isTimetableMode) { PathFile patFile = new PathFile(filePath); pathName = patFile.Name; TrackDB = TDB.TrackDB; TSectionDat = tsectiondat; bool fatalerror = false; if (patFile.PathNodes.Count <= 0) { fatalerror = true; Nodes = null; return; } foreach (PathNode tpn in patFile.PathNodes) { Nodes.Add(new AIPathNode(tpn, patFile.DataPoints[(int)tpn.PathDataPoint], TrackDB, isTimetableMode)); } FirstNode = Nodes[0]; //LastVisitedNode = FirstNode; // Connect the various nodes to each other for (int i = 0; i < Nodes.Count; i++) { AIPathNode node = Nodes[i]; node.Index = i; PathNode tpn = patFile.PathNodes[i]; // find TVNindex to next main node. if (tpn.HasNextMainNode) { node.NextMainNode = Nodes[(int)tpn.NextMainNode]; node.NextMainTVNIndex = node.FindTVNIndex(node.NextMainNode, TDB, tsectiondat, i == 0 ? -1 : Nodes[i - 1].NextMainTVNIndex); if (node.JunctionIndex >= 0) { node.IsFacingPoint = TestFacingPoint(node.JunctionIndex, node.NextMainTVNIndex); } if (node.NextMainTVNIndex < 0) { node.NextMainNode = null; Trace.TraceWarning("Cannot find main track for node {1} in path {0}", filePath, i); fatalerror = true; } } // find TVNindex to next siding node if (tpn.HasNextSidingNode) { node.NextSidingNode = Nodes[(int)tpn.NextSidingNode]; node.NextSidingTVNIndex = node.FindTVNIndex(node.NextSidingNode, TDB, tsectiondat, i == 0 ? -1 : Nodes[i - 1].NextMainTVNIndex); if (node.JunctionIndex >= 0) { node.IsFacingPoint = TestFacingPoint(node.JunctionIndex, node.NextSidingTVNIndex); } if (node.NextSidingTVNIndex < 0) { node.NextSidingNode = null; Trace.TraceWarning("Cannot find siding track for node {1} in path {0}", filePath, i); fatalerror = true; } } if (node.NextMainNode != null && node.NextSidingNode != null) { node.Type = AIPathNodeType.SidingStart; } } FindSidingEnds(); if (fatalerror) { Nodes = null; // invalid path - do not return any nodes } }
/// <summary> /// Returns the index of the vector node connection this path node to the (given) nextNode. /// </summary> public int FindTVNIndex(AIPathNode nextNode, TrackDatabaseFile TDB, TrackSectionsFile tsectiondat, int previousNextMainTVNIndex) { int junctionIndexThis = JunctionIndex; int junctionIndexNext = nextNode.JunctionIndex; // if this is no junction, try to find the TVN index if (junctionIndexThis < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, this)); } catch { junctionIndexThis = FindJunctionOrEndIndex(this.Location, TDB.TrackDB, false); } } // this is a junction; if the next node is no junction, try that one. if (junctionIndexNext < 0) { try { return(findTrackNodeIndex(TDB, tsectiondat, nextNode)); } catch { junctionIndexNext = FindJunctionOrEndIndex(nextNode.Location, TDB.TrackDB, false); } } //both this node and the next node are junctions: find the vector node connecting them. var iCand = -1; for (int i = 0; i < TDB.TrackDB.TrackNodes.Count(); i++) { if (!(TDB.TrackDB.TrackNodes[i] is TrackVectorNode tn)) { continue; } if (tn.TrackPins[0].Link == junctionIndexThis && tn.TrackPins[1].Link == junctionIndexNext) { iCand = i; if (i != previousNextMainTVNIndex) { break; } Trace.TraceInformation("Managing rocket loop at trackNode {0}", iCand); } else if (tn.TrackPins[1].Link == junctionIndexThis && tn.TrackPins[0].Link == junctionIndexNext) { iCand = i; if (i != previousNextMainTVNIndex) { break; } Trace.TraceInformation("Managing rocket loop at trackNode {0}", iCand); } } return(iCand); }