/// <summary> /// Check wether this vector node is closest to the mouse location /// </summary> /// <param name="location">Location to check</param> /// <param name="mouseLocation">Current mouse location</param> /// <param name="trackNode">The trackNode that will be stored when indeed it is the closest to the mouse location</param> /// <param name="vectorSection">the vectorSection that will be stored when indeed it is closest to the mouse location</param> /// <param name="tvsi">Current index of the trackvectorsection</param> /// <param name="pixelsPerMeter"></param> public void CheckMouseDistance(WorldLocation location, WorldLocation mouseLocation, TrackNode trackNode, TrVectorSection vectorSection, int tvsi, double pixelsPerMeter) { storedMouseLocation = mouseLocation; float distanceSquared = WorldLocation.GetDistanceSquared2D(location, mouseLocation); // to make unique distances becasue they also act as Key double distanceSquaredIndexed = ((double)distanceSquared) * (1 + 1e-16 * trackNode.Index); if (distanceSquaredIndexed < sortedTrackCandidates.First().Key) { if (!sortedTrackCandidates.ContainsKey(distanceSquaredIndexed)) { sortedTrackCandidates.Add(distanceSquaredIndexed, new TrackCandidate(trackNode, vectorSection, tvsi, 0)); // The next one is a bit tricky. The problem is that the first culling is done based on the trackvector section location // Which is only at one side of the section. So the other end might be quiet far away. // Unfortunately, this means that we need to keep track of many candidates to make sure we can calculate the closest one // Which is costing performance. // The biggest issue is for a long track close to a region with lots junctions and hence small track segments // By making this number zoom dependent, we get good results for big zooms, and not a large // performance penalty for wide views int maxNumberOfCandidates = 50 + (int)(100 * pixelsPerMeter); while (sortedTrackCandidates.Count > maxNumberOfCandidates) { sortedTrackCandidates.RemoveAt(0); // First one has largest distance } } } }
public TrackCandidate(TrackNode node, TrVectorSection section, int tvsi, float lon) { trackNode = node; vectorSection = section; trackVectorSectionIndex = tvsi; distanceAlongSection = lon; }
public static uint getShapeIdx(this TrackNode node, int direction) { uint shapeIdx = 0; if (node.TrEndNode || node.TrJunctionNode != null) { shapeIdx = 0; } else if (node.TrVectorNode.TrVectorSections.Length > 1) { if (direction == 0) { TrVectorSection section = node.TrVectorNode.TrVectorSections.Last(); shapeIdx = section.ShapeIndex; } else { TrVectorSection section = node.TrVectorNode.TrVectorSections.First(); shapeIdx = section.ShapeIndex; } } else { shapeIdx = 0; } return(shapeIdx); }
public static uint getSectionIndex(this TrackNode node, int direction) { uint index = 0; if (node.TrEndNode) { index = (uint)node.UiD.WorldId; } else if (node.TrJunctionNode != null) { index = (uint)node.TrJunctionNode.Idx; } else if (node.TrVectorNode.TrVectorSections != null && node.TrVectorNode.TrVectorSections.Length > 1) { if (direction == 0) { TrVectorSection section = node.TrVectorNode.TrVectorSections.Last(); index = section.SectionIndex; } else { TrVectorSection section = node.TrVectorNode.TrVectorSections.First(); index = section.SectionIndex; } } else if (node.TrVectorNode.TrVectorSections != null) { index = node.TrVectorNode.TrVectorSections[0].SectionIndex; } else { index = (uint)node.UiD.WorldId; } return(index); }
public MSTSCoord(TrVectorSection section) { TileX = section.TileX; TileY = section.TileZ; X = section.X; Y = section.Z; Reduced = section.Reduced; }
public AESegment(TrVectorSection item1, TrVectorSection item2) { MSTSCoord A = new MSTSCoord(item1); MSTSCoord B = new MSTSCoord(item2); startPoint = A.ConvertToPointF(); endPoint = B.ConvertToPointF(); }
//remove a section from the tile-section map public static void RemoveSectionsFromMap(Simulator simulator, TrVectorSection section) { var key = (int)(Math.Abs(section.WFNameX) + Math.Abs(section.WFNameZ)); if (simulator.SuperElevation.Sections.ContainsKey(key)) { simulator.SuperElevation.Sections[key].Remove(section); } }
/// <summary> /// Calculate the closest distance to a track, as well as the 'longitude' along it. /// </summary> /// <param name="trackVectorSection">The vectorsection for which we want to know the distance</param> /// <param name="trackSection">The corresponding tracksection</param> /// <returns>Distance Squared to the track as well as length along track.</returns> /// <remarks>Partly the same code as in Traveller.cs, but here no culling, and we just want the distance. /// The math here is not perfect (it is quite difficult to calculate the distances to a curved line /// for all possibilities) but good enough. The math was designed (in Traveller.cs) to work well for close distances. /// Math is modified to prevent NaN and to combine straight and curved tracks.</remarks> DistanceLon CalcRealDistanceSquared(TrVectorSection trackVectorSection, TrackSection trackSection) { //Calculate the vector from start of track to the mouse Vector3 vectorToMouse = new Vector3 { X = storedMouseLocation.Location.X - trackVectorSection.X, Z = storedMouseLocation.Location.Z - trackVectorSection.Z }; vectorToMouse.X += (storedMouseLocation.TileX - trackVectorSection.TileX) * 2048; vectorToMouse.Z += (storedMouseLocation.TileZ - trackVectorSection.TileZ) * 2048; //Now rotate the vector such that a direction along the track is in a direction (x=0, z=1) vectorToMouse = Vector3.Transform(vectorToMouse, Matrix.CreateRotationY(-trackVectorSection.AY)); float lon, lat; if (trackSection.SectionCurve == null) { //Track is straight. In this coordinate system, the distance along track (lon) and orthogonal to track (lat) are easy. lon = vectorToMouse.Z; lat = vectorToMouse.X; } else { // make sure the vector is as if the vector section turns to the left. // The center of the curved track is now a (x=-radius, z=0), track starting at (0,0), pointing in positive Z if (trackSection.SectionCurve.Angle > 0) { vectorToMouse.X *= -1; } //make vector relative to center of curve. Track now starts at (radius,0) vectorToMouse.X += trackSection.SectionCurve.Radius; float radiansAlongCurve = (float)Math.Atan2(vectorToMouse.Z, vectorToMouse.X); //The following calculations make sense when close to the track. Otherwise they are not necessarily sensible, but at least well-defined. // Distance from mouse to circle through track section. lat = (float)Math.Sqrt(vectorToMouse.X * vectorToMouse.X + vectorToMouse.Z * vectorToMouse.Z) - trackSection.SectionCurve.Radius; lon = radiansAlongCurve * trackSection.SectionCurve.Radius; } float trackSectionLength = DrawTrackDB.GetLength(trackSection); if (lon < 0) { // distance from start of track return(new DistanceLon(lat * lat + lon * lon, 0)); } if (lon > trackSectionLength) { // distance from end of track return(new DistanceLon(lat * lat + (lon - trackSectionLength) * (lon - trackSectionLength), trackSectionLength)); //idem } // somewhere along track. Distance is only in lateral direction return(new DistanceLon(lat * lat, lon)); }
bool InitTrackSectionCurved(int tileX, int tileZ, float x, float z, TrVectorSection trackVectorSection, float treeWidth) { // We're working relative to the track section, so offset as needed. x += (tileX - trackVectorSection.TileX) * 2048; z += (tileZ - trackVectorSection.TileZ) * 2048; var sx = trackVectorSection.X; var sz = trackVectorSection.Z; // Do a preliminary cull based on a bounding square around the track section. // Bounding distance is (radius * angle + error) by (radius * angle + error) around starting coordinates but no more than 2 for angle. var boundingDistance = trackSection.SectionCurve.Radius * Math.Min(Math.Abs(MathHelper.ToRadians(trackSection.SectionCurve.Angle)), 2) + MaximumCenterlineOffset + treeWidth; var dx = Math.Abs(x - sx); var dz = Math.Abs(z - sz); if (dx > boundingDistance || dz > boundingDistance) { return(false); } // To simplify the math, center around the start of the track section, rotate such that the track section starts out pointing north (+z) and flip so the track curves to the right. x -= sx; z -= sz; MstsUtility.Rotate2D(trackVectorSection.AY, ref x, ref z); if (trackSection.SectionCurve.Angle < 0) { x *= -1; } // Compute distance to curve's center at (radius,0) then adjust to get distance from centerline. dx = x - trackSection.SectionCurve.Radius; var lat = Math.Sqrt(dx * dx + z * z) - trackSection.SectionCurve.Radius; if (Math.Abs(lat) > MaximumCenterlineOffset + treeWidth) { return(false); } // Compute distance along curve (ensure we are in the top right quadrant, otherwise our math goes wrong). if (z < -InitErrorMargin || x > trackSection.SectionCurve.Radius + InitErrorMargin || z > trackSection.SectionCurve.Radius + InitErrorMargin) { return(false); } var radiansAlongCurve = (float)Math.Asin(z / trackSection.SectionCurve.Radius); var lon = radiansAlongCurve * trackSection.SectionCurve.Radius; var trackSectionLength = GetLength(trackSection); if (lon < -InitErrorMargin || lon > trackSectionLength + InitErrorMargin) { return(false); } return(true); }
bool InitTrackSection(TrVectorSection section, Vector3 xnaTreePosition, int tileX, int tileZ, float treeWidth) { trackSection = Viewer.Simulator.TSectionDat.TrackSections.Get(section.SectionIndex); if (trackSection == null) { return(false); } if (trackSection.SectionCurve != null) { return(InitTrackSectionCurved(tileX, tileZ, xnaTreePosition.X, -xnaTreePosition.Z, section, treeWidth)); } return(InitTrackSectionStraight(tileX, tileZ, xnaTreePosition.X, -xnaTreePosition.Z, section, treeWidth)); }
/// <summary> /// Find the exact distance of the start of the current tracksection (from the beginning of the vector node) /// </summary> /// <returns></returns> private float GetSectionStartDistance() { float distanceFromStart = 0; TrackNode tn = TrackDB.TrackNodes[TvnIndex]; for (int tvsi = 0; tvsi < TrackVectorSectionIndex; tvsi++) { TrVectorSection tvs = tn.TrVectorNode.TrVectorSections[tvsi]; TrackSection trackSection = TsectionDat.TrackSections.Get(tvs.SectionIndex); if (trackSection != null) // if trackSection is missing somehow, well, do without. { distanceFromStart += ORTS.TrackViewer.Drawing.DrawTrackDB.GetLength(trackSection); } } return(distanceFromStart); }
/// <summary> /// Add information about the closest vector section /// </summary> /// <param name="trackViewer"></param> private void AddVectorSectionStatus(TrackViewer trackViewer) { if (Properties.Settings.Default.statusShowVectorSections) { TrVectorSection tvs = trackViewer.DrawTrackDB.ClosestTrack.VectorSection; if (tvs == null) { return; } uint shapeIndex = tvs.ShapeIndex; string shapeName = "Unknown:" + shapeIndex.ToString(System.Globalization.CultureInfo.CurrentCulture); try { // Try to find a fixed track TrackShape shape = trackViewer.RouteData.TsectionDat.TrackShapes.Get(shapeIndex); shapeName = shape.FileName; } catch { // try to find a dynamic track try { TrackPath trackPath = trackViewer.RouteData.TsectionDat.TSectionIdx.TrackPaths[tvs.ShapeIndex]; shapeName = "<dynamic ?>"; foreach (uint trackSection in trackPath.TrackSections) { if (trackSection == tvs.SectionIndex) { shapeName = "<dynamic>"; } // For some reason I do not undestand the (route) section.tdb. trackpaths are not consistent tracksections // so this foreach loop will not always find a combination } } catch { } } statusAdditional.Text += string.Format(System.Globalization.CultureInfo.CurrentCulture, " VectorSection ({3}/{4}) filename={2} Index={0} shapeIndex={1}", tvs.SectionIndex, shapeIndex, shapeName, trackViewer.DrawTrackDB.ClosestTrack.TrackVectorSectionIndex + 1, trackViewer.DrawTrackDB.ClosestTrack.TrackNode.TrVectorNode.TrVectorSections.Count()); } }
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); }
/// <summary> /// Determine the length of the section along the track. /// </summary> /// <param name="tn">The current tracknode, which needs to be a vector node</param> /// <param name="tvsi">The track vector section index</param> private float SectionLengthAlongTrack(TrackNode tn, int tvsi) { float fullSectionLength; TrVectorSection tvs = tn.TrVectorNode.TrVectorSections[tvsi]; TrackSection trackSection = tsectionDat.TrackSections.Get(tvs.SectionIndex); if (trackSection == null) { return(100); // need to return something. Not easy to recover } if (trackSection.SectionCurve != null) { fullSectionLength = trackSection.SectionCurve.Radius * Math.Abs(Microsoft.Xna.Framework.MathHelper.ToRadians(trackSection.SectionCurve.Angle)); } else { fullSectionLength = trackSection.SectionSize.Length; } return(fullSectionLength); }
/// <summary> /// Permet de récupérer les coordonnées du node au format MSTSCoord propre à l'éditeur d'activité /// Return the MSTSCoord for the current node as needed by Activity Editor /// For vectorNode with multiple section, the direction is used to give the first encountered section /// </summary> public static MSTSCoord getMSTSCoord(this TrackNode node, int direction) { MSTSCoord coord = new MSTSCoord(); if (node.TrEndNode || node.TrJunctionNode != null || node.TrVectorNode.TrVectorSections == null) { coord.TileX = node.UiD.TileX; coord.TileY = node.UiD.TileZ; coord.X = node.UiD.X; coord.Y = node.UiD.Z; } else if (node.TrVectorNode != null && node.TrVectorNode.TrVectorSections.Length > 1) { if (direction == 0) { TrVectorSection section = node.TrVectorNode.TrVectorSections.Last(); coord.TileX = section.TileX; coord.TileY = section.TileZ; coord.X = section.X; coord.Y = section.Z; } else { TrVectorSection section = node.TrVectorNode.TrVectorSections.First(); coord.TileX = section.TileX; coord.TileY = section.TileZ; coord.X = section.X; coord.Y = section.Z; } } else if (node.TrVectorNode != null) { coord.TileX = node.TrVectorNode.TrVectorSections[0].TileX; coord.TileY = node.TrVectorNode.TrVectorSections[0].TileZ; coord.X = node.TrVectorNode.TrVectorSections[0].X; coord.Y = node.TrVectorNode.TrVectorSections[0].Z; } return(coord); }
/// <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); }
public static TrVectorSection getVectorSection(this TrackNode node) { TrVectorSection section = null; if (node.TrEndNode) { //section = TrVectorNode.TrVectorSections[0]; } else if (node.TrJunctionNode != null) { } else if (node.TrVectorNode.TrVectorSections == null) { } else if (node.TrVectorNode.TrVectorSections.Length > 1) { } else { section = node.TrVectorNode.TrVectorSections[0]; } return(section); }
bool InitTrackSectionStraight(int tileX, int tileZ, float x, float z, TrVectorSection trackVectorSection, float treeWidth) { // We're working relative to the track section, so offset as needed. x += (tileX - trackVectorSection.TileX) * 2048; z += (tileZ - trackVectorSection.TileZ) * 2048; var sx = trackVectorSection.X; var sz = trackVectorSection.Z; // Do a preliminary cull based on a bounding square around the track section. // Bounding distance is (length + error) by (length + error) around starting coordinates. var boundingDistance = trackSection.SectionSize.Length + MaximumCenterlineOffset + treeWidth; var dx = Math.Abs(x - sx); var dz = Math.Abs(z - sz); if (dx > boundingDistance || dz > boundingDistance) { return(false); } // Calculate distance along and away from the track centerline. float lat, lon; MstsUtility.Survey(sx, sz, trackVectorSection.AY, x, z, out lon, out lat); var trackSectionLength = GetLength(trackSection); if (Math.Abs(lat) > MaximumCenterlineOffset + treeWidth) { return(false); } if (lon < -InitErrorMargin || lon > trackSectionLength + InitErrorMargin) { return(false); } return(true); }
public List <StationPath> explore(AETraveller myTravel, List <TrackSegment> listConnector, MSTSItems aeItems, StationItem parent) { List <AEJunctionItem> insideJunction = new List <AEJunctionItem>(); Stopwatch stopWatch = new Stopwatch(); TimeSpan ts; string elapsedTime; stopWatch.Start(); TrackNode currentNode = myTravel.GetCurrentNode(); int pathChecked = 0; int trackNodeIndex = myTravel.TrackNodeIndex; int lastCommonTrack = trackNodeIndex; int trackVectorSectionIndex = myTravel.TrackVectorSectionIndex; TrVectorSection currentSection = myTravel.GetCurrentSection(); GlobalItem startNode = aeItems.GetTrackSegment(currentNode, trackVectorSectionIndex); //paths.Add(new StationPath(startNode, myTravel)); paths.Add(new StationPath(myTravel)); paths[0].LastCommonTrack = trackNodeIndex; while ((pathChecked < paths.Count && !paths[pathChecked].complete) && paths.Count < 100) { TrackNode node2 = paths[pathChecked].explore(aeItems, listConnector, trackNodeIndex, parent); ts = stopWatch.Elapsed; // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("RunTime " + elapsedTime); if (node2.TrJunctionNode != null) { AEJunctionItem junction = (AEJunctionItem)paths[pathChecked].ComponentItem[paths[pathChecked].ComponentItem.Count - 1]; if (!insideJunction.Contains(junction)) { insideJunction.Add(junction); } if (node2.TrPins[0].Link == lastCommonTrack) { paths[pathChecked].jctnIdx = paths[pathChecked].ComponentItem.Count - 1; paths[pathChecked].LastCommonTrack = lastCommonTrack; paths.Add(new StationPath(paths[pathChecked])); paths[pathChecked].directionJunction = 0; paths[pathChecked].switchJnct(0); } else { paths[pathChecked].NextNode(); } } else if (node2.TrEndNode) { AEBufferItem buffer = (AEBufferItem)paths[pathChecked].ComponentItem[paths[pathChecked].ComponentItem.Count - 1]; if (!buffer.Configured || buffer.DirBuffer == AllowedDir.OUT) { //AEJunctionItem junction = (AEJunctionItem)paths[pathChecked].ComponentItem[paths[pathChecked].jctnIdx]; paths.RemoveAt(pathChecked); } else { paths[pathChecked].setComplete(buffer); pathChecked++; } if (pathChecked < paths.Count) { paths[pathChecked].switchJnct(paths[pathChecked].directionJunction); if (paths[pathChecked].ComponentItem.Count > 1) { lastCommonTrack = (int)paths[pathChecked].LastCommonTrack; } else { lastCommonTrack = trackNodeIndex; } } } else { int lastIndex = (int)node2.Index; //lastCommonTrack = (int)node2.Index; if (paths[pathChecked].complete) { TrackSegment segment = (TrackSegment)paths[pathChecked].ComponentItem[paths[pathChecked].ComponentItem.Count - 1]; if (segment.HasConnector == null || (segment.HasConnector != null && (segment.HasConnector.dirConnector == AllowedDir.IN || !segment.HasConnector.isConfigured()))) { paths.RemoveAt(pathChecked); } else { pathChecked++; } //pathChecked++; if (pathChecked < paths.Count) { lastIndex = (int)paths[pathChecked].ComponentItem[paths[pathChecked].ComponentItem.Count - 2].associateNode.Index; paths[pathChecked].switchJnct(paths[pathChecked].directionJunction); } } if (pathChecked < paths.Count) { if (paths[pathChecked].ComponentItem.Count > 1) { lastCommonTrack = lastIndex; //lastCommonTrack = (int)paths[pathChecked].ComponentItem[paths[pathChecked].ComponentItem.Count - 2].associateNode.Index; } else { lastCommonTrack = trackNodeIndex; } } } } stopWatch.Stop(); ts = stopWatch.Elapsed; // Format and display the TimeSpan value. elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}", ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10); Console.WriteLine("RunTime " + elapsedTime); pathChecked = 1; foreach (StationPath path in paths) { if (path.PassingYard > MaxPassingYard) { MaxPassingYard = path.PassingYard; } if (path.PassingYard < ShortPassingYard) { ShortPassingYard = path.PassingYard; } } return(paths); }
/// <summary> /// Decompose and add a SuperElevation on top of MSTS track section /// </summary> /// <param name="viewer">Viewer reference.</param> /// <param name="trackList">DynamicTrackViewer list.</param> /// <param name="trackObj">Dynamic track section to decompose.</param> /// <param name="worldMatrixInput">Position matrix.</param> /// <param name="TileX">TileX coordinates.</param> /// <param name="TileZ">TileZ coordinates.</param> /// <param name="shapeFilePath">Path to the shape file.</param> public static bool DecomposeStaticSuperElevation(Viewer viewer, List <DynamicTrackViewer> trackList, TrackObj trackObj, WorldPosition worldMatrixInput, int TileX, int TileZ, string shapeFilePath) { TrackShape shape = null; try { shape = viewer.Simulator.TSectionDat.TrackShapes.Get(trackObj.SectionIdx); if (shape.RoadShape == true) { return(false); } } catch (Exception) { return(false); } SectionIdx[] SectionIdxs = shape.SectionIdxs; int count = -1; int drawn = 0; bool isTunnel = shape.TunnelShape; List <TrVectorSection> sectionsinShape = new List <TrVectorSection>(); //List<DynamicTrackViewer> tmpTrackList = new List<DynamicTrackViewer>(); foreach (SectionIdx id in SectionIdxs) { uint[] sections = id.TrackSections; for (int i = 0; i < sections.Length; i++) { count++; uint sid = id.TrackSections[i]; TrackSection section = viewer.Simulator.TSectionDat.TrackSections.Get(sid); if (Math.Abs(section.SectionSize.Width - viewer.Simulator.SuperElevationGauge) > 0.2) { continue; //the main route has a gauge different than mine } if (section.SectionCurve == null) { continue; //with strait track, will remove all related sections later } TrVectorSection tmp = null; if (section.SectionCurve != null) { tmp = FindSectionValue(shape, viewer.Simulator, section, TileX, TileZ, trackObj.UID); } if (tmp == null) //cannot find the track for super elevation, will return 0; { continue; } sectionsinShape.Add(tmp); drawn++; } } if (drawn <= count || isTunnel)//tunnel or not every section is in SE, will remove all sections in the shape out { if (sectionsinShape.Count > 0) { RemoveTracks(viewer.Simulator, sectionsinShape); } return(false); } return(true); }
//no use anymore public static int DecomposeStaticSuperElevationOneSection(Viewer viewer, List <DynamicTrackViewer> dTrackList, int TileX, int TileZ, TrVectorSection ts) { if (ts == null) { return(0); } WorldLocation location = new WorldLocation(); Vector3 directionVector = new Vector3(); var tss = viewer.Simulator.TSectionDat.TrackSections.Get(ts.SectionIndex); if (tss == null || tss.SectionCurve == null) { return(0); } location.TileX = ts.TileX; location.TileZ = ts.TileZ; location.Location.X = ts.X; location.Location.Y = ts.Y; location.Location.Z = ts.Z; directionVector.X = ts.AX; directionVector.Y = ts.AY; directionVector.Z = ts.AZ; Vector3 trackLoc = new Vector3(ts.X, ts.Y, -ts.Z); WorldPosition root = new WorldPosition(); root.TileX = ts.TileX; root.TileZ = ts.TileZ; root.XNAMatrix = Matrix.CreateFromYawPitchRoll(-ts.AY, -ts.AX, ts.AZ);// CreateRotationX(-ts.AY) * Matrix.CreateRotationY(-ts.AX) * Matrix.CreateRotationZ(ts.AZ); root.XNAMatrix.Translation = Vector3.Zero; root.XNAMatrix.Translation += Vector3.Transform(trackLoc, Matrix.Identity); var sign = -Math.Sign(tss.SectionCurve.Angle); var to = Math.Abs(tss.SectionCurve.Angle * 0.0174f); var vectorCurveStartToCenter = Vector3.Left * tss.SectionCurve.Radius * sign; var curveRotation = Matrix.CreateRotationY(to * sign); Vector3 dummy; var displacement = Traveller.MSTSInterpolateAlongCurve(Vector3.Zero, vectorCurveStartToCenter, curveRotation, root.XNAMatrix, out dummy); WorldPosition nextRoot = new WorldPosition(root); nextRoot.XNAMatrix.Translation = displacement; sv = ev = mv = 0f; dir = 1f; sv = ts.StartElev; ev = ts.EndElev; mv = ts.MaxElev; //nextRoot.XNAMatrix.Translation += Vector3.Transform(trackLoc, worldMatrix.XNAMatrix); dTrackList.Add(new SuperElevationViewer(viewer, root, nextRoot, tss.SectionCurve.Radius, tss.SectionCurve.Angle * 3.14f / 180, sv, ev, mv, dir)); return(1); }
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 }