Пример #1
0
        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);
        }
Пример #2
0
                       ) 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);
            }
        }
Пример #3
0
        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;
        }
Пример #4
0
        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();
        }
Пример #5
0
        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();
            }
        }
Пример #6
0
        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();
        }
Пример #7
0
        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");
        }