public void TestSimulationCoordinateSpaceFromLatLon() { var space = new SimulationCoordinateSpace(50.083239, 14.435278); var vector = space.To(50.1, 14.5); Assert.Equal(4617.97265625, vector.X, 5); Assert.Equal(1863.73815918, vector.Y, 5); }
) LoadScenario(string filename) { var basePath = Path.GetDirectoryName(filename); using (StreamReader file = File.OpenText(filename)) { var desc = LoadScenarioDescriptor(file); var coordinateSpace = new SimulationCoordinateSpace(desc.CoordinateSystemOrigin[0], desc.CoordinateSystemOrigin[1]); var networkDatabase = new GeoJsonNetworkDatabase(coordinateSpace, Path.Join(basePath, desc.NetworkDatabaseFileName)); var unitClassDatabase = new JsonUnitClassDatabase(Path.Join(basePath, desc.UnitClassDatabaseFileName)); var units = new List <Unit>(); foreach (var unitDesc in desc.Units) { var class_ = unitClassDatabase.UnitClassByName(unitDesc.Class); var randomly = false; // Place units randomly if (randomly) { var rand = new Random(); // randomly pick a track segment int segId = rand.Next(1, 600); var seg = networkDatabase.GetSegmentById(segId); var(pos, dir) = seg.GetPointAndTangent(0.5f, SegmentEndpoint.Start); var orientation = Utility.DirectionVectorToQuaternion(dir); Console.Out.WriteLine( $"{{\"class\": \"generic\", \"pos\": [{pos.X,7:F1}, {pos.Y,7:F1}, {pos.Z,5:F1}], " + $"\"orientation\": [{orientation.X,6:F3}, {orientation.Y,6:F3}, {orientation.Z,6:F3}, {orientation.W,5:F3}], " + $"\"segId\": {segId}}},"); units.Add(new Unit(class_, pos, Vector3.Zero, orientation)); } else { var(x, y, z) = (unitDesc.Pos[0], unitDesc.Pos[1], unitDesc.Pos[2]); var pos = new Vector3(x, y, z); var(xx, yy, zz, ww) = (unitDesc.Orientation[0], unitDesc.Orientation[1], unitDesc.Orientation[2], unitDesc.Orientation[3]); var orientation = new Quaternion(xx, yy, zz, ww); units.Add(new Unit(class_, pos, Vector3.Zero, orientation)); } } return(coordinateSpace, networkDatabase, unitClassDatabase, units); } }
public GeoJsonNetworkDatabase(SimulationCoordinateSpace coordinateSpace, string path) { _coordinateSpace = coordinateSpace; JsonDocument document; // Collect all segments using (StreamReader file = File.OpenText(path)) { document = JsonDocument.Parse(file.BaseStream); } var maxCoordinate = ProcessTracks(document.RootElement, _segments); // Do you think I care?? int powerOf2 = 1024; while (powerOf2 < maxCoordinate) { powerOf2 *= 2; } // First-pass: remove duplicates var uniqueSegments = FindUniqueSegments(powerOf2); // Second-pass: create segment links _segments = uniqueSegments; var quadTree = new QuadTree(this, new Vector3(-powerOf2, -powerOf2, 0), new Vector3(powerOf2, powerOf2, 0)); int i = 1; foreach (var seg in _segments) { quadTree.InsertSegment(seg); i++; } var segmentLinks = new List <SegmentLink>(); NetworkImporterUtility.CreateSegmentLinks(_segments, segmentLinks, quadTree, 0.2f, (float)(45 / 180.0f * Math.PI), (float)(65 / 180.0f * Math.PI) ); // Only after we have the final set of segments is it possible to load stations var stations = new Dictionary <string, Station>(); ProcessStations(document.RootElement, quadTree, stations); _quadTree = quadTree; _segmentLinks = segmentLinks; _stations = stations; }
public static void RenderPng(SimulationCoordinateSpace coordinateSpace, INetworkDatabase ndb, IUnitDatabase units, IDictionary <int, TrainControlStateSummary>?controllerMap, string filename, int w, int h, double scale, int fontSize) { var center = new PointD(w / 2, h / 2); var surf = new ImageSurface(Format.Argb32, w, h); Context cr = new Context(surf); RenderToContext(coordinateSpace, ndb, units, controllerMap, cr, center, scale, fontSize); cr.Dispose(); surf.WriteToPng(filename); surf.Finish(); surf.Dispose(); }
public Simulation(SimulationCoordinateSpace coordSpace, INetworkDatabase network, IUnitDatabase units, LoggingManager log) { CoordSpace = coordSpace; Network = network; Units = units; _log = log; _currentSegmentByUnitId = new int?[units.GetNumUnits()]; _dirByUnitId = new SegmentEndpoint[units.GetNumUnits()]; _tByUnitId = new float[units.GetNumUnits()]; _unitProperties = new UnitProperties[units.GetNumUnits()]; for (var unitIndex = 0; unitIndex < Units.GetNumUnits(); unitIndex++) { var unit = Units.GetUnitByIndex(unitIndex); var result = Network.FindSegmentAt(unit.Pos, unit.Orientation, 0.2f, (float)(Math.PI * 0.25)); if (result == null) { Console.Error.WriteLine($"Simulation: could not snap unit {unitIndex} to railroad network!"); continue; } var(segmentId, dir, t) = result.Value; _currentSegmentByUnitId[unitIndex] = segmentId; _dirByUnitId[unitIndex] = dir; _tByUnitId[unitIndex] = t; var eh = _log.GetEntityHandle(_unitProperties[unitIndex].GetType(), unitIndex); _unitProperties[unitIndex] = new UnitProperties { Controller = new TrainControlStack(unitIndex, _log, Network), AccelerationPin = _log.GetSignalPin(eh, "acceleration"), VelocityPin = _log.GetSignalPin(eh, "velocity"), SegmentIdPin = _log.GetSignalPin(eh, "segmentId"), TPin = _log.GetSignalPin(eh, "t"), }; _unitProperties[unitIndex].Controller.GoAutoSchedule(); } }
public static void RenderSvg(SimulationCoordinateSpace coordinateSpace, INetworkDatabase ndb, IUnitDatabase units, string filename) { var w = 1000; var h = 600; var scale = 0.04; // meters/pixel var fontSize = 8; var center = new PointD(w / 2, h / 2); var surf = new SvgSurface(filename, w, h); Context cr = new Context(surf); RenderToContext(coordinateSpace, ndb, units, null, cr, center, scale, fontSize); cr.Dispose(); surf.Flush(); surf.Finish(); surf.Dispose(); }
private static void RenderToContext(SimulationCoordinateSpace coordinateSpace, INetworkDatabase ndb, IUnitDatabase units, IDictionary <int, TrainControlStateSummary>?controllerMap, Context cr, PointD center, double scale, int fontSize) { //Console.WriteLine("RenderFullView start"); cr.SetSourceColor(aluminium1); cr.Paint(); // cr.MoveTo(0, h); // cr.ShowText($"Scale: full width = {(w / scale)} meters"); // Draw quadtree var maybeQuadTree = ndb.GetQuadTreeIfYouHaveOne(); if (maybeQuadTree is {} quadTree) { DrawQuadTreeNode(quadTree.Root, cr, center, scale); } // Draw rail links DrawLinks(ndb, cr, center, scale); // Draw railway foreach (var seg in ndb.EnumerateSegments()) { Trace.Assert(seg.ControlPoints.Length == 2); var start = SimToCanvasSpace(seg.ControlPoints[0], center, scale); var end = SimToCanvasSpace(seg.ControlPoints[1], center, scale); cr.LineWidth = railLineWidth; cr.SetSourceColor(seg.Oneway == false ? aluminium6 : aluminium5); cr.MoveTo(start); cr.LineTo(end); cr.Stroke(); // DrawTextRegular(cr, $"{seg.Id}", new PointD((start.X + end.X) / 2, (start.Y + end.Y) / 2), 9); } // Draw stations foreach (var station in ndb.EnumerateStations()) { PointD pos0 = new PointD(); cr.SetSourceColor(skyBlue2); foreach (var stop in station.Stops) { var pos = ndb.GetSegmentById(stop.SegmentId).GetPoint(stop.T); var posCS = SimToCanvasSpace(pos, center, scale); pos0 = posCS; cr.LineWidth = 0.5; DrawCrosshair(cr, posCS, 5); } cr.SetSourceColor(aluminium2); DrawTextRegular(cr, station.Name, pos0, fontSize); } // Draw trains int unitIndex = 0; foreach (var unit in units.EnumerateUnits()) { var pos = unit.Pos; var head = unit.Pos + Vector3.Transform(new Vector3((float)(5 / scale), 0, 0), unit.Orientation); var posCS = SimToCanvasSpace(pos, center, scale); var headCS = SimToCanvasSpace(head, center, scale); var info = $"{unit.Class.Name}\n{unit.Velocity.Length() * 3.6:F1} km/h"; if (controllerMap != null && controllerMap.ContainsKey(unitIndex)) { info += "\n" + controllerMap[unitIndex].SchedulerState; var route = controllerMap[unitIndex].SegmentsToFollow; if (route != null) { foreach (var entry in route) { // try { // Console.WriteLine($"Segment => {entry.SegmentId}"); var seg = ndb.GetSegmentById(entry.SegmentId); Trace.Assert(seg.ControlPoints.Length == 2); var startXyz = seg.GetEndpoint(entry.EntryEp); var endXyz = entry.GoalT >= 0 ? seg.GetPoint(entry.GoalT) : seg.GetEndpoint(entry.EntryEp.Other()); var start = SimToCanvasSpace(startXyz, center, scale); var end = SimToCanvasSpace(endXyz, center, scale); cr.LineWidth = railLineWidth * 2; cr.SetSourceColor(plum1); cr.MoveTo(start); cr.LineTo(end); cr.Stroke(); // } // catch (System.InvalidOperationException ex) { // } } } } cr.LineWidth = railLineWidth * 2; cr.SetSourceColor(chameleon1); cr.MoveTo(posCS.X * 2 - headCS.X, posCS.Y * 2 - headCS.Y); cr.LineTo(headCS); cr.Stroke(); cr.SetSourceColor(chameleon3); DrawTextBold(cr, info, posCS, fontSize); unitIndex++; } // Draw info about agents // if (agents != null) // { // int i = 0; // foreach (var agent in agents) // { // DrawTextRegular(cr, agent.ToString(), new PointD(0, i * 10), 9); // i++; // } // } cr.LineWidth = 1; cr.SetSourceColor(scarledRed1); DrawCrosshair(cr, center, 10); //Console.WriteLine("RenderFullView done"); }