예제 #1
0
        //
        // CREATE ROUTE MAP
        //
        /// <summary>Creates and returns the route map as Bitmap.</summary>
        /// <returns>The route map.</returns>
        /// <param name="Width">The width of the bitmap to create.</param>
        /// <param name="Height">The height of the bitmap to create.</param>
        /// <param name="inGame"><c>true</c> = bitmap for in-game overlay | <c>false</c> = for standard window.</param>
        internal static Bitmap CreateRouteMap(int Width, int Height, bool inGame)
        {
            int n, n0, n1;

            RouteRange(out n, out n0, out n1);
            // find dimensions
            double x0 = double.PositiveInfinity, z0 = double.PositiveInfinity;
            double x1 = double.NegativeInfinity, z1 = double.NegativeInfinity;

            for (int i = n0; i <= n1; i++)
            {
                double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                double z = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                if (x < x0)
                {
                    x0 = x;
                }
                if (x > x1)
                {
                    x1 = x;
                }
                if (z < z0)
                {
                    z0 = z;
                }
                if (z > z1)
                {
                    z1 = z;
                }
            }
            // avoid 0 or negative height or width
            if (x0 >= x1 - 1.0)
            {
                x0 = x1 - 1.0;
            }
            if (z0 >= z1 - 1.0)
            {
                z0 = z1 - 1.0;
            }
            // remember area occupied so far
            double xMin, xMax, zMin, zMax;                              // used to track the bitmap area actually occupied by drawings

            xMin = x0;
            xMax = x1;
            zMin = z1;                                                                          // bitmap z goes down, while world z goes up
            zMax = z0;
            // fit route w/h ratio in image w/h ratio
            double wrh = (double)Width / (double)Height;

            if ((x1 - x0) / (z1 - z0) <= wrh)                           // if route ratio is taller than bitmap ratio
            {
                double dx = 0.5 * (z1 - z0) * wrh;                      //	scale (half of) x range as much as (half of) z range
                double px = 0.5 * (x0 + x1);                            //	x range mid point
                x0 = px - dx;                                           //	centre scaled x range around mid point
                x1 = px + dx;
            }
            else                                                                                // if route ratio is wider than bitmap ratio
            {                                                                                   //	do the opposite (scale z range on x)
                double dz = 0.5 * (x1 - x0) / wrh;
                double pz = 0.5 * (z0 + z1);
                z0 = pz - dz;
                z1 = pz + dz;
            }
            double ox = LeftPad, oy = TopPad;
            double w = (double)(Width - (LeftPad + RightPad));
            double h = (double)(Height - (TopPad + BottomPad));
            // horizontal and vertical scales
            double xd = w / (x1 - x0);
            double zd = h / (z1 - z0);

            // convert bitmap occupied area from world to bitmap coordinates
            xMin = ox + (xMin - x0) * xd;
            xMax = ox + (xMax - x0) * xd;
            zMin = oy + (z0 - zMin) * zd + h;
            zMax = oy + (z0 - zMax) * zd + h;
            // create bitmap
            int    mode = inGame ? 1 : 0;
            Bitmap b    = new Bitmap(Width, Height, inGame ? System.Drawing.Imaging.PixelFormat.Format32bppArgb
                                : System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);

            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.Clear(mapColors[mode].background);

            // ROUTE PATH
            {
                int  start = 0;
                bool atc   = false;
                n = n1 - n0 + 1;
                PointF[] p = new PointF[n];
                for (int i = 0; i < n; i++)
                {
                    double x = TrackManager.CurrentTrack.Elements[i + n0].WorldPosition.X;
                    double z = TrackManager.CurrentTrack.Elements[i + n0].WorldPosition.Z;
                    x    = ox + (x - x0) * xd;
                    z    = oy + (z0 - z) * zd + h;
                    p[i] = new PointF((float)x, (float)z);
                    // ATS / ATC
                    // for each track element, look for a StationStartEvent
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i + n0].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i + n0].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e =
                                (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i + n0].Events[j];
                            // if StationStartEvent found, look for a change in ATS/ATC control;
                            // if there is a change, draw all previous track elements
                            // with colour for the previous control state
                            if (Game.Stations[e.StationIndex].SafetySystem == Game.SafetySystem.Atc)
                            {
                                if (!atc)
                                {
                                    atc = true;
                                    if (i - start - 1 > 0)
                                    {
                                        g.DrawCurve(mapColors[mode].normalMap, p, start, i - start - 1);
                                    }
                                    start = i;
                                }
                            }
                            else
                            {
                                if (atc)
                                {
                                    atc = false;
                                    if (i - start - 1 > 0)
                                    {
                                        g.DrawCurve(mapColors[mode].atcMap, p, start, i - start - 1);
                                    }
                                    start = i;
                                }
                            }
                            break;
                        }
                    }
                }
                // draw all remaining track element not drawn yet
                DrawSegmentedCurve(g, atc ? mapColors[mode].atcMap : mapColors[mode].normalMap, p, start, n - start - 1);
            }

            // STATION ICONS
            for (int i = n0; i <= n1; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                    {
                        TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                        if (Game.Stations[e.StationIndex].Name != string.Empty)
                        {
                            double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                            double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                            x = ox + (x - x0) * xd;
                            y = oy + (z0 - y) * zd + h;
                            // station circle
                            RectangleF r = new RectangleF((float)x - StationRadius, (float)y - StationRadius,
                                                          StationDiameter, StationDiameter);
                            bool q = Game.PlayerStopsAtStation(e.StationIndex);
                            g.FillEllipse(q ? mapColors[mode].actStatnFill : mapColors[mode].inactStatnFill, r);
                            g.DrawEllipse(q ? mapColors[mode].actStatnBrdr : mapColors[mode].inactStatnBrdr, r);
                            // adjust bitmap occupied area
                            if (r.Left < xMin)
                            {
                                xMin = r.Left;
                            }
                            if (r.Top < zMin)
                            {
                                zMin = r.Top;
                            }
                            if (r.Right > xMax)
                            {
                                xMax = r.Right;
                            }
                            if (r.Bottom > zMax)
                            {
                                zMax = r.Bottom;
                            }
                        }
                    }
                }
            }

            // STATION NAMES
            {
                double wh = w * h;
                Font   f  = new Font(FontFamily.GenericSansSerif, wh < 65536.0 ? 9.0f : 10.0f, GraphicsUnit.Pixel);
                for (int i = n0; i <= n1; i++)
                {
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].Name != string.Empty)
                            {
                                double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                                double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                                x = ox + (x - x0) * xd;
                                y = oy + (z0 - y) * zd + h;
                                RectangleF r = new RectangleF((float)x - StationRadius, (float)y - StationRadius,
                                                              StationDiameter, StationDiameter);
                                bool   stop = Game.PlayerStopsAtStation(e.StationIndex);
                                string t = Game.Stations[e.StationIndex].Name;
                                SizeF  m = g.MeasureString(t, f, Width, StringFormat.GenericDefault);
                                double sx = TrackManager.CurrentTrack.Elements[i].WorldSide.X;
                                double sz = TrackManager.CurrentTrack.Elements[i].WorldSide.Z;
                                double xt, yt;
                                if (Math.Sign(sx) == Math.Sign(sz))
                                {
                                    // descending
                                    bool o = (x - ox) * (h - y) <= (w - x) * (y - oy);
                                    if (o)
                                    {
                                        // up-right
                                        xt = x + StationTextPad;
                                        yt = y - StationTextPad - m.Height;
                                    }
                                    else
                                    {
                                        // down-left
                                        xt = x - StationTextPad - m.Width;
                                        yt = y + StationTextPad;
                                    }
                                }
                                else
                                {
                                    // ascending
                                    bool o = (h - y) * (w - x) <= (x - ox) * (y - oy);
                                    if (o)
                                    {
                                        // up-left
                                        xt = x - StationTextPad - m.Width;
                                        yt = y - StationTextPad - m.Height;
                                    }
                                    else
                                    {
                                        // down-right
                                        xt = x + StationTextPad;
                                        yt = y + StationTextPad;
                                    }
                                }
                                // constrain text within bitmap edges (taking into account also paddings)
                                if (xt < ox)
                                {
                                    xt = ox;
                                }
                                else if (xt + m.Width > w)
                                {
                                    xt = w - m.Width;
                                }
                                if (yt < oy)
                                {
                                    yt = oy;
                                }
                                else if (yt + m.Height > h)
                                {
                                    yt = h - m.Height;
                                }
                                r = new RectangleF((float)xt - 1.0f, (float)yt - 1.0f, m.Width + 2.0f, m.Height + 2.0f);
                                g.FillRectangle(stop ? mapColors[mode].actNameFill : mapColors[mode].inactNameFill,
                                                r.Left, r.Top, r.Width, r.Height);
                                g.DrawRectangle(stop ? mapColors[mode].actNameBrdr : mapColors[mode].inactNameBrdr,
                                                r.Left, r.Top, r.Width, r.Height);
                                g.DrawString(t, f, stop ? mapColors[mode].actNameText : mapColors[mode].inactNameText,
                                             (float)xt, (float)yt);
                                // adjust bitmap occupied area
                                if (r.Left < xMin)
                                {
                                    xMin = r.Left;
                                }
                                if (r.Top < zMin)
                                {
                                    zMin = r.Top;
                                }
                                if (r.Right > xMax)
                                {
                                    xMax = r.Right;
                                }
                                if (r.Bottom > zMax)
                                {
                                    zMax = r.Bottom;
                                }
                            }
                        }
                    }
                }
            }
            // if in-game, trim unused parts of the bitmap
            if (inGame)
            {
                xMin -= LeftPad;
                xMax += RightPad;
                zMin -= TopPad;
                zMax += BottomPad;
                if (xMin < 0)
                {
                    xMin = 0;
                }
                if (xMax >= Width)
                {
                    xMax = Width - 1;
                }
                if (zMin < 0)
                {
                    zMin = 0;
                }
                if (zMax >= Height)
                {
                    zMax = Height - 1;
                }
                Bitmap nb = new Bitmap((int)(xMax - xMin + 1.0), (int)(zMax - zMin + 1.0));                     // round up
                g = Graphics.FromImage(nb);
                g.DrawImage(b, (int)-xMin, (int)-zMin);                                                         // round down
                // set total bitmap world X and Z ranges from bitmap ranges
                lastRouteMinX = (int)((xMin - ox) / xd + x0);
                lastRouteMaxX = (int)((xMax - ox) / xd + x0);
                lastRouteMinZ = (int)(z0 - (zMax - oy - h) / zd);
                lastRouteMaxZ = (int)(z0 - (zMin - oy - h) / zd);
                return(nb);
            }
            //set total bitmap X and Z ranges
            lastRouteMinX = (int)(x0 - ox * (x1 - x0) / w);
            lastRouteMaxX = (int)(x1 + (Width - w - ox) * (x1 - x0) / w);
            lastRouteMinZ = (int)(z0 - oy * (z1 - z0) / h);
            lastRouteMaxZ = (int)(z1 + (Height - h - oy) * (z1 - z0) / h);
            return(b);
        }
예제 #2
0
        //
        // CREATE GRADIENT PROFILE
        //
        /// <summary>Creates the route gradient profile.</summary>
        /// <returns>The route gradient profile as Bitmap.</returns>
        /// <param name="Width">The width of the bitmap to create.</param>
        /// <param name="Height">The height of the bitmap to create.</param>
        /// <param name="inGame"><c>true</c> = bitmap for in-game overlay | <c>false</c> = for standard window.</param>
        internal static Bitmap CreateRouteGradientProfile(int Width, int Height, bool inGame)
        {
            if (TrackManager.CurrentTrack.Elements.Length > 36 && Game.Stations.Length == 0)
            {
                // If we have track elements, but no stations, show a specific error message, rather
                // than the more generic one thrown later
                // NOTE: Will throw the generic error message on routes shorter than 900m with no stations
                throw new Exception(Interface.GetInterfaceString("errors_route_corrupt_nostations"));
            }
            // Track elements are assumed to be all of the same length, and this length
            // is used as measure unit, rather than computing the incremental track length
            // in any 'real world' unit (like m).

            // HORIZONTAL RANGE: find first and last used element based on stations
            int n, n0, n1;

            RouteRange(out n, out n0, out n1);
            // VERTICAL RANGE
            double y0 = double.PositiveInfinity, y1 = double.NegativeInfinity;

            for (int i = n0; i <= n1; i++)
            {
                double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Y;
                if (y < y0)
                {
                    y0 = y;
                }
                if (y > y1)
                {
                    y1 = y;
                }
            }
            if (y0 >= y1 - 1.0)
            {
                y0 = y1 - 1.0;
            }

            // allow for some padding around actual data
            double ox = LeftPad, oy = TopPad;
            double w = (double)(Width - (LeftPad + RightPad));
            double h = (double)(Height - (TopPad + BottomPad + TrackOffsPad));
            // horizontal and vertical scale
            double nd = w / (double)(n1 - n0);
            double yd = h / (double)(y1 - y0);
            // set total bitmap track position range; used by in-game profile to place
            // the current position of the trains; as the train positions are known as track positions,
            // actual track positions are needed here, rather than indices into the track element array.
            double minX = TrackManager.CurrentTrack.Elements[n0].StartingTrackPosition;
            double maxX = TrackManager.CurrentTrack.Elements[n1].StartingTrackPosition;
            double offX = ox * (maxX - minX) / w;

            lastGradientMinTrack = (int)(minX - offX);
            lastGradientMaxTrack = (int)(maxX + offX);

            // BITMAP (in-game display needs transparency)
            Bitmap b = new Bitmap(Width, Height,
                                  inGame ? System.Drawing.Imaging.PixelFormat.Format32bppArgb
                                        : System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);

            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            int mode = inGame ? 1 : 0;

            g.Clear(mapColors[mode].background);

            // BELOW SEA LEVEL
            {
                double y  = oy + (h - 0.5 * (double)(-Game.RouteInitialElevation - y0) * yd);
                double x0 = ox - (double)(0) * nd;
                double x1 = ox + (double)(n1 - n0) * nd;
                g.FillRectangle(mapColors[mode].belowSeaFill, (float)x0, (float)y, (float)x1, (float)(oy + h) - (float)y);
                g.DrawLine(mapColors[mode].belowSeaBrdr, (float)x0, (float)y, (float)x1, (float)y);
            }
            // GRADIENT PROFILE
            {
                n = n1 - n0 + 1;
                PointF[] p = new PointF[n + 2];
                p[0] = new PointF((float)ox, (float)(oy + h));
                for (int i = n0; i <= n1; i++)
                {
                    double x = ox + (double)(i - n0) * nd;
                    double y = oy + (h - 0.5 *
                                     (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                    p[i - n0 + 1] = new PointF((float)x, (float)y);
                }
                p[n + 1] = new PointF((float)(ox + (double)(n - 1) * nd), (float)(oy + h));
                g.FillPolygon(mapColors[mode].elevFill, p);
                for (int i = 1; i < n; i++)
                {
                    g.DrawLine(mapColors[mode].elevBrdr, p[i], p[i + 1]);
                }
                g.DrawLine(mapColors[mode].elevBrdr, 0.0f, (float)(oy + h), (float)Width, (float)(oy + h));
            }
            // STATION NAMES
            {
                Font         f = new Font(FontFamily.GenericSansSerif, 12.0f, GraphicsUnit.Pixel);
                StringFormat m = new StringFormat();
                for (int i = n0; i <= n1; i++)
                {
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].Name != string.Empty)
                            {
                                bool stop = Game.PlayerStopsAtStation(e.StationIndex);
                                if (Interface.IsJapanese(Game.Stations[e.StationIndex].Name))
                                {
                                    m.Alignment     = StringAlignment.Near;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + (double)(i - n0) * nd;
                                    double y = oy + (h - 0.5 *
                                                     (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    string t = Game.Stations[e.StationIndex].Name;
                                    float  tx = 0.0f, ty = (float)oy;
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        if (s.Width > tx)
                                        {
                                            tx = s.Width;
                                        }
                                    }
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        g.DrawString(t.Substring(k, 1), f,
                                                     stop ? mapColors[mode].actNameText : mapColors[mode].inactNameText,
                                                     (float)x - 0.5f * tx, ty);
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        ty += s.Height;
                                    }
                                    g.DrawLine(stop ? mapColors[mode].actNameBrdr : mapColors[mode].inactNameBrdr,
                                               new PointF((float)x, ty + 4.0f), new PointF((float)x, (float)y));
                                }
                                else
                                {
                                    m.Alignment     = StringAlignment.Far;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + (double)(i - n0) * nd;
                                    double y = oy + (h - 0.5 *
                                                     (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    g.RotateTransform(-90.0f);
                                    g.TranslateTransform((float)x, (float)oy, System.Drawing.Drawing2D.MatrixOrder.Append);
                                    g.DrawString(Game.Stations[e.StationIndex].Name, f,
                                                 stop ? mapColors[mode].actNameText : mapColors[mode].inactNameText,
                                                 new PointF(0.0f, -5.0f), m);
                                    g.ResetTransform();
                                    SizeF s = g.MeasureString(Game.Stations[e.StationIndex].Name, f);
                                    g.DrawLine(stop ? mapColors[mode].actNameBrdr : mapColors[mode].inactNameBrdr,
                                               new PointF((float)x, (float)(oy + s.Width + 4)), new PointF((float)x, (float)y));
                                }
                            }
                        }
                    }
                }
            }
            // ROUTE MARKERS
            {
                Font         f  = new Font(FontFamily.GenericSansSerif, 10.0f, GraphicsUnit.Pixel);
                Font         fs = new Font(FontFamily.GenericSansSerif, 9.0f, GraphicsUnit.Pixel);
                StringFormat m  = new StringFormat
                {
                    Alignment     = StringAlignment.Far,
                    LineAlignment = StringAlignment.Center
                };
                System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                int k = TrackOffDist * n / Width;
                if (k == 0)
                {
                    //If k is equal to zero, this generally means that the WithTrack section is missing from our routefile
                    //Adding zero to the loop control variable will also produce an infinite loop, so that's a bad idea too
                    throw new Exception(Interface.GetInterfaceString("errors_route_corrupt_withtrack"));
                }
                for (int i = n0; i <= n1; i += k)
                {
                    double x = ox + (double)(i - n0) * nd;
                    double y = (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd;
                    // track offset label
                    if (x < w)
                    {
                        string t = ((int)Math.Round(TrackManager.CurrentTrack.Elements[i].StartingTrackPosition)).ToString(Culture);
                        g.DrawString(t + "m", f, mapColors[mode].actNameText, (float)x, (float)(oy + h + TrackOffY));
                    }
                    // route height at track offset (with measure and vertical line)
                    {
                        y = oy + (h - 0.5 * y) + 2.0f;
                        string t = ((int)Math.Round(Game.RouteInitialElevation + TrackManager.CurrentTrack.Elements[i].WorldPosition.Y)).ToString(Culture);
                        SizeF  s = g.MeasureString(t, fs);
                        if (y < oy + h - (double)s.Width - 10.0)
                        {
                            g.RotateTransform(-90.0f);
                            g.TranslateTransform((float)x, (float)y + 4.0f, System.Drawing.Drawing2D.MatrixOrder.Append);
                            g.DrawString(t + "m", fs, mapColors[mode].actNameText, 0.0f, 0.0f, m);
                            g.ResetTransform();
                            g.DrawLine(mapColors[mode].inactNameBrdr,
                                       (float)x, (float)(y + s.Width + 12.0), (float)x, (float)(oy + h));
                        }
                    }
                }
            }
            // finalize
            return(b);
        }
예제 #3
0
파일: Timetable.cs 프로젝트: hyusan/OpenBVE
        // collect data
        internal static void CollectData(out Table Table)
        {
            System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
            Table.Stations = new Station[16];
            Table.Tracks   = new Track[16];
            int    n = 0;
            double Limit = -1.0, LastLimit = 6.94444444444444;
            int    LastArrivalHours = -1, LastDepartureHours = -1;
            double LastTime = -1.0;

            for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    TrackManager.StationStartEvent sse = TrackManager.CurrentTrack.Elements[i].Events[j] as TrackManager.StationStartEvent;
                    if (sse != null && Game.Stations[sse.StationIndex].Name != string.Empty)
                    {
                        if (Limit == -1.0)
                        {
                            Limit = LastLimit;
                        }
                        // update station
                        if (n == Table.Stations.Length)
                        {
                            Array.Resize <Station>(ref Table.Stations, Table.Stations.Length << 1);
                        }
                        Table.Stations[n].Name         = Game.Stations[sse.StationIndex].Name;
                        Table.Stations[n].NameJapanese = Game.Stations[sse.StationIndex].Name.IsJapanese();
                        Table.Stations[n].Pass         = !Game.PlayerStopsAtStation(sse.StationIndex);
                        Table.Stations[n].Terminal     = Game.Stations[sse.StationIndex].Type != StationType.Normal;
                        double x;
                        if (Game.Stations[sse.StationIndex].ArrivalTime >= 0.0)
                        {
                            x  = Game.Stations[sse.StationIndex].ArrivalTime;
                            x -= 86400.0 * Math.Floor(x / 86400.0);
                            int hours = (int)Math.Floor(x / 3600.0);
                            x -= 3600.0 * (double)hours;
                            int minutes = (int)Math.Floor(x / 60.0);
                            x -= 60.0 * (double)minutes;
                            int seconds = (int)Math.Floor(x);
                            Table.Stations[n].Arrival.Hour = hours != LastArrivalHours?hours.ToString("00", Culture) : "";

                            Table.Stations[n].Arrival.Minute = minutes.ToString("00", Culture);
                            Table.Stations[n].Arrival.Second = seconds.ToString("00", Culture);
                            LastArrivalHours = hours;
                        }
                        else
                        {
                            Table.Stations[n].Arrival.Hour   = "";
                            Table.Stations[n].Arrival.Minute = "";
                            Table.Stations[n].Arrival.Second = "";
                        }
                        if (Game.Stations[sse.StationIndex].DepartureTime >= 0.0)
                        {
                            x  = Game.Stations[sse.StationIndex].DepartureTime;
                            x -= 86400.0 * Math.Floor(x / 86400.0);
                            int hours = (int)Math.Floor(x / 3600.0);
                            x -= 3600.0 * (double)hours;
                            int minutes = (int)Math.Floor(x / 60.0);
                            x -= 60.0 * (double)minutes;
                            int seconds = (int)Math.Floor(x);
                            Table.Stations[n].Departure.Hour = hours != LastDepartureHours?hours.ToString("00", Culture) : "";

                            Table.Stations[n].Departure.Minute = minutes.ToString("00", Culture);
                            Table.Stations[n].Departure.Second = seconds.ToString("00", Culture);
                            LastDepartureHours = hours;
                        }
                        else
                        {
                            Table.Stations[n].Departure.Hour   = "";
                            Table.Stations[n].Departure.Minute = "";
                            Table.Stations[n].Departure.Second = "";
                        }
                        // update track
                        if (n >= 1)
                        {
                            int m = n - 1;
                            if (m == Table.Tracks.Length)
                            {
                                Array.Resize <Track>(ref Table.Tracks, Table.Tracks.Length << 1);
                            }
                            // speed
                            x = Math.Round(3.6 * Limit);
                            Table.Tracks[m].Speed = x.ToString(Culture);
                            // time
                            if (LastTime >= 0.0)
                            {
                                if (Game.Stations[sse.StationIndex].ArrivalTime >= 0.0)
                                {
                                    x = Game.Stations[sse.StationIndex].ArrivalTime;
                                }
                                else if (Game.Stations[sse.StationIndex].DepartureTime >= 0.0)
                                {
                                    x = Game.Stations[sse.StationIndex].DepartureTime;
                                }
                                else
                                {
                                    x = -1.0;
                                }
                                if (x >= 0.0)
                                {
                                    x -= LastTime;
                                    int hours = (int)Math.Floor(x / 3600.0);
                                    x -= 3600.0 * (double)hours;
                                    int minutes = (int)Math.Floor(x / 60.0);
                                    x -= 60.0 * (double)minutes;
                                    int seconds = (int)Math.Floor(x);
                                    Table.Tracks[m].Time.Hour   = hours != 0 ? hours.ToString("0", Culture) : "";
                                    Table.Tracks[m].Time.Minute = minutes != 0 ? minutes.ToString("00", Culture) : "";
                                    Table.Tracks[m].Time.Second = seconds != 0 ? seconds.ToString("00", Culture) : "";
                                }
                                else
                                {
                                    Table.Tracks[m].Time.Hour   = "";
                                    Table.Tracks[m].Time.Minute = "";
                                    Table.Tracks[m].Time.Second = "";
                                }
                            }
                            else
                            {
                                Table.Tracks[m].Time.Hour   = "";
                                Table.Tracks[m].Time.Minute = "";
                                Table.Tracks[m].Time.Second = "";
                            }
                        }
                        // update last data
                        if (Game.Stations[sse.StationIndex].DepartureTime >= 0.0)
                        {
                            LastTime = Game.Stations[sse.StationIndex].DepartureTime;
                        }
                        else if (Game.Stations[sse.StationIndex].ArrivalTime >= 0.0)
                        {
                            LastTime = Game.Stations[sse.StationIndex].ArrivalTime;
                        }
                        else
                        {
                            LastTime = -1.0;
                        }
                        LastLimit = Limit;
                        Limit     = -1.0;
                        n++;
                    }
                    if (n >= 1)
                    {
                        TrackManager.LimitChangeEvent lce = TrackManager.CurrentTrack.Elements[i].Events[j] as TrackManager.LimitChangeEvent;
                        if (lce != null)
                        {
                            if (lce.NextSpeedLimit != double.PositiveInfinity & lce.NextSpeedLimit > Limit)
                            {
                                Limit = lce.NextSpeedLimit;
                            }
                        }
                    }
                }
            }
            Array.Resize <Station>(ref Table.Stations, n);
            if (n >= 2)
            {
                Array.Resize <Track>(ref Table.Tracks, n - 1);
            }
            else
            {
                Table.Tracks = new Track[] { };
            }
        }
예제 #4
0
            private void PerformDefault()
            {
                if (Train.Derailed)
                {
                    if (Train.Handles.EmergencyBrake.Driver != true)
                    {
                        Train.ApplyEmergencyBrake();
                    }
                    return;
                }
                // personality
                double spd = Train.CurrentSpeed;

                if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Boarding)
                {
                    if (Train.Station != this.LastStation)
                    {
                        this.LastStation = Train.Station;
                        double time;
                        if (Stations[Train.Station].ArrivalTime >= 0.0)
                        {
                            time = Stations[Train.Station].ArrivalTime - Train.TimetableDelta;
                        }
                        else if (Stations[Train.Station].DepartureTime >= 0.0)
                        {
                            time = Stations[Train.Station].DepartureTime - Train.TimetableDelta;
                            if (time > SecondsSinceMidnight)
                            {
                                time -= Stations[Train.Station].StopTime;
                                if (time > SecondsSinceMidnight)
                                {
                                    time = double.MinValue;
                                }
                            }
                        }
                        else
                        {
                            time = double.MinValue;
                        }
                        if (time != double.MinValue)
                        {
                            const double largeThreshold    = 30.0;
                            const double largeChangeFactor = 0.0025;
                            const double smallThreshold    = 15.0;
                            const double smallChange       = 0.05;
                            double       diff = SecondsSinceMidnight - time;
                            if (diff < -largeThreshold)
                            {
                                /* The AI is too fast. Decrease the preferred speed. */
                                this.CurrentSpeedFactor -= largeChangeFactor * (-diff - largeThreshold);
                                if (this.CurrentSpeedFactor < 0.7)
                                {
                                    this.CurrentSpeedFactor = 0.7;
                                }
                            }
                            else if (diff > largeThreshold)
                            {
                                /* The AI is too slow. Increase the preferred speed. */
                                this.CurrentSpeedFactor += largeChangeFactor * (diff - largeThreshold);
                                if (this.CurrentSpeedFactor > 1.1)
                                {
                                    this.CurrentSpeedFactor = 1.1;
                                }
                            }
                            else if (Math.Abs(diff) < smallThreshold)
                            {
                                /* The AI is at about the right speed. Change the preferred speed toward the personality default. */
                                if (this.CurrentSpeedFactor < this.PersonalitySpeedFactor)
                                {
                                    this.CurrentSpeedFactor += smallChange;
                                    if (this.CurrentSpeedFactor > this.PersonalitySpeedFactor)
                                    {
                                        this.CurrentSpeedFactor = this.PersonalitySpeedFactor;
                                    }
                                }
                                else if (this.CurrentSpeedFactor > this.PersonalitySpeedFactor)
                                {
                                    this.CurrentSpeedFactor -= smallChange;
                                    if (this.CurrentSpeedFactor < this.PersonalitySpeedFactor)
                                    {
                                        this.CurrentSpeedFactor = this.PersonalitySpeedFactor;
                                    }
                                }
                            }
                        }
                    }
                }
                // door states
                bool doorsopen = false;

                for (int i = 0; i < Train.Cars.Length; i++)
                {
                    for (int j = 0; j < Train.Cars[i].Doors.Length; j++)
                    {
                        if (Train.Cars[i].Doors[j].State != 0.0)
                        {
                            doorsopen = true;
                            break;
                        }
                        if (doorsopen)
                        {
                            break;
                        }
                    }
                }
                // do the ai
                Train.Specs.CurrentConstSpeed = false;
                Train.ApplyHoldBrake(false);
                int stopIndex = Train.Station >= 0 ? Game.Stations[Train.Station].GetStopIndex(Train.Cars.Length) : -1;

                if (Train.CurrentSectionLimit == 0.0)
                {
                    // passing red signal
                    Train.ApplyEmergencyBrake();
                    Train.ApplyNotch(-1, true, 1, true);
                    CurrentInterval = 0.5;
                }
                else if (doorsopen | Train.StationState == TrainManager.TrainStopState.Boarding)
                {
                    // door opened or boarding at station
                    this.PowerNotchAtWhichWheelSlipIsObserved = Train.Handles.Power.MaximumNotch + 1;
                    if (Train.Station >= 0 && Stations[Train.Station].Type != StationType.Normal && Stations[Train.Station].Type != StationType.RequestStop && Train == TrainManager.PlayerTrain)
                    {
                        // player's terminal station
                        if (Train.Plugin == null || Train.Plugin.LastReverser == -2)
                        {
                            Train.ApplyReverser(0, false);
                        }
                        Train.ApplyNotch(-1, true, 1, true);
                        Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                        Train.ApplyEmergencyBrake();
                        CurrentInterval = 1.0;
                    }
                    else
                    {
                        CurrentInterval = 1.0;
                        Train.ApplyNotch(-1, true, 0, true);
                        if (Train.Handles.Brake is TrainManager.AirBrakeHandle)
                        {
                            if (Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure < 0.3 * Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.ServiceMaximumPressure)
                            {
                                Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                            }
                            else if (Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.CurrentPressure > 0.9 * Train.Cars[Train.DriverCar].CarBrake.brakeCylinder.EmergencyMaximumPressure)
                            {
                                Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            }
                            else
                            {
                                Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Lap);
                            }
                        }
                        else
                        {
                            int b;
                            if (Math.Abs(spd) < 0.02)
                            {
                                b = (int)Math.Ceiling(0.5 * (double)Train.Handles.Brake.MaximumNotch);
                                CurrentInterval = 0.3;
                            }
                            else
                            {
                                b = Train.Handles.Brake.MaximumNotch;
                            }
                            if (Train.Handles.Brake.Driver < b)
                            {
                                Train.ApplyNotch(0, true, 1, true);
                            }
                            else if (Train.Handles.Brake.Driver > b)
                            {
                                Train.ApplyNotch(0, true, -1, true);
                            }
                        }
                        Train.UnapplyEmergencyBrake();
                        if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Completed)
                        {
                            // ready for departure - close doors
                            if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked)
                            {
                                TrainManager.CloseTrainDoors(Train, true, true);
                            }
                        }
                        else if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Boarding)
                        {
                        }
                        else
                        {
                            // not at station - close doors
                            if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked)
                            {
                                TrainManager.CloseTrainDoors(Train, true, true);
                            }
                        }
                    }
                }
                else if (Train.Station >= 0 && stopIndex >= 0 && Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].BackwardTolerance && (StopsAtStation(Train.Station, Train) & (Stations[Train.Station].OpenLeftDoors | Stations[Train.Station].OpenRightDoors) & Math.Abs(Train.CurrentSpeed) < 0.25 & Train.StationState == TrainManager.TrainStopState.Pending))
                {
                    // arrived at station - open doors
                    if (Train.Specs.DoorOpenMode != TrainManager.DoorMode.Automatic && Train.Specs.DoorInterlockState == DoorInterlockStates.Unlocked)
                    {
                        TrainManager.OpenTrainDoors(Train, Stations[Train.Station].OpenLeftDoors, Stations[Train.Station].OpenRightDoors);
                    }
                    CurrentInterval = 1.0;
                }
                else if (Train.Station >= 0 && stopIndex >= 0 && Stations[Train.Station].Type != StationType.Normal && Stations[Train.Station].Type != StationType.RequestStop && Train == TrainManager.PlayerTrain && Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].BackwardTolerance && -Train.StationDistanceToStopPoint < Stations[Train.Station].Stops[stopIndex].ForwardTolerance && Math.Abs(Train.CurrentSpeed) < 0.25)
                {
                    // player's terminal station (not boarding any longer)
                    if (Train.Plugin != null || Train.Plugin.LastReverser == -2)
                    {
                        Train.ApplyReverser(0, false);
                    }
                    Train.ApplyNotch(-1, true, 1, true);
                    Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                    Train.ApplyEmergencyBrake();
                    CurrentInterval = 10.0;
                }
                else
                {
                    // drive
                    Train.ApplyReverser(1, false);
                    if (Train.Cars[Train.DriverCar].FrontAxle.CurrentWheelSlip | Train.Cars[Train.DriverCar].RearAxle.CurrentWheelSlip)
                    {
                        // react to wheel slip
                        if (Train.Handles.Power.Driver > 1)
                        {
                            this.PowerNotchAtWhichWheelSlipIsObserved = Train.Handles.Power.Driver;
                            Train.ApplyNotch(-1, true, -1, true);
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            this.CurrentInterval = 2.5;
                            return;
                        }
                    }
                    // initialize
                    double acc = Train.Specs.CurrentAverageAcceleration;
                    double lim = PrecedingTrainSpeedLimit * 1.2;
                    if (Train.CurrentRouteLimit < lim)
                    {
                        lim = Train.CurrentRouteLimit;
                    }
                    if (Train.CurrentSectionLimit < lim)
                    {
                        lim = Train.CurrentSectionLimit;
                    }
                    double powerstart, powerend, brakestart;
                    if (double.IsPositiveInfinity(lim))
                    {
                        powerstart = lim;
                        powerend   = lim;
                        brakestart = lim;
                    }
                    else
                    {
                        lim *= this.CurrentSpeedFactor;
                        if (spd < 8.0)
                        {
                            powerstart = 0.75 * lim;
                            powerend   = 0.95 * lim;
                        }
                        else
                        {
                            powerstart = lim - 2.5;
                            powerend   = lim - 1.5;
                        }
                        if (this.BrakeMode)
                        {
                            brakestart = powerend;
                        }
                        else
                        {
                            brakestart = lim + 0.5;
                        }
                    }
                    double dec = 0.0;
                    double decelerationCruise;                       /* power below this deceleration, cruise above */
                    double decelerationStart;                        /* brake above this deceleration, cruise below */
                    double decelerationStep;                         /* the deceleration step per brake notch */
                    double BrakeDeceleration = Train.Cars[Train.DriverCar].CarBrake.DecelerationAtServiceMaximumPressure(Train.Handles.Brake.Actual, Train.Cars[Train.DriverCar].Specs.CurrentSpeed);
                    for (int i = 0; i < Train.Cars.Length; i++)
                    {
                        if (Train.Cars[i].Specs.IsMotorCar)
                        {
                            if (Train.Cars[Train.DriverCar].Specs.MotorDeceleration != 0 && Train.Cars[Train.DriverCar].Specs.MotorDeceleration < BrakeDeceleration)
                            {
                                BrakeDeceleration = Train.Cars[Train.DriverCar].Specs.MotorDeceleration;
                            }
                            break;
                        }
                    }
                    if (Train.Handles.Brake is TrainManager.AirBrakeHandle | Train.Handles.Brake.MaximumNotch <= 0)
                    {
                        decelerationCruise = 0.3 * BrakeDeceleration;
                        decelerationStart  = 0.5 * BrakeDeceleration;
                        decelerationStep   = 0.1 * BrakeDeceleration;
                    }
                    else if (Train.Handles.Brake.MaximumNotch <= 2)
                    {
                        decelerationCruise = 0.2 * BrakeDeceleration;
                        decelerationStart  = 0.4 * BrakeDeceleration;
                        decelerationStep   = 0.5 * BrakeDeceleration;
                    }
                    else
                    {
                        decelerationCruise = 0.2 * BrakeDeceleration;
                        decelerationStart  = 0.5 * BrakeDeceleration;
                        decelerationStep   = BrakeDeceleration / (double)Train.Handles.Brake.MaximumNotch;
                    }
                    if (this.CurrentSpeedFactor >= 1.0)
                    {
                        decelerationCruise *= 1.25;
                        decelerationStart  *= 1.25;
                        decelerationStep   *= 1.25;
                    }

                    if (spd > 0.0 & spd > brakestart)
                    {
                        dec = decelerationStep + 0.1 * (spd - brakestart);
                    }
                    bool reduceDecelerationCruiseAndStart = false;
                    // look ahead
                    double lookahead    = (Train.Station >= 0 ? 150.0 : 50.0) + (spd * spd) / (2.0 * decelerationCruise);
                    double tp           = Train.FrontCarTrackPosition();
                    double stopDistance = double.MaxValue;
                    {
                        // next station stop
                        int te = Train.Cars[0].FrontAxle.Follower.LastTrackElement;
                        for (int i = te; i < TrackManager.Tracks[0].Elements.Length; i++)
                        {
                            double stp = TrackManager.Tracks[0].Elements[i].StartingTrackPosition;
                            if (tp + lookahead <= stp)
                            {
                                break;
                            }
                            for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++)
                            {
                                if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None)
                                {
                                    TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                    if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex)
                                    {
                                        int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length);
                                        if (s >= 0)
                                        {
                                            double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp;
                                            if (dist > 0.0 & dist < stopDistance)
                                            {
                                                stopDistance = dist;
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                    {
                        // events
                        int te = Train.Cars[0].FrontAxle.Follower.LastTrackElement;
                        for (int i = te; i < TrackManager.Tracks[0].Elements.Length; i++)
                        {
                            double stp = TrackManager.Tracks[0].Elements[i].StartingTrackPosition;
                            if (tp + lookahead <= stp)
                            {
                                break;
                            }
                            for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++)
                            {
                                if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.LimitChangeEvent)
                                {
                                    // speed limit
                                    TrackManager.LimitChangeEvent e = (TrackManager.LimitChangeEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                    if (e.NextSpeedLimit < spd)
                                    {
                                        double dist = stp + e.TrackPositionDelta - tp;
                                        double edec = (spd * spd - e.NextSpeedLimit * e.NextSpeedLimit * this.CurrentSpeedFactor) / (2.0 * dist);
                                        if (edec > dec)
                                        {
                                            dec = edec;
                                        }
                                    }
                                }
                                else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.SectionChangeEvent)
                                {
                                    // section
                                    TrackManager.SectionChangeEvent e = (TrackManager.SectionChangeEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                    if (stp + e.TrackPositionDelta > tp)
                                    {
                                        if (!CurrentRoute.Sections[e.NextSectionIndex].Invisible & CurrentRoute.Sections[e.NextSectionIndex].CurrentAspect >= 0)
                                        {
                                            double elim = CurrentRoute.Sections[e.NextSectionIndex].Aspects[CurrentRoute.Sections[e.NextSectionIndex].CurrentAspect].Speed * this.CurrentSpeedFactor;
                                            if (elim < spd | spd <= 0.0)
                                            {
                                                double dist = stp + e.TrackPositionDelta - tp;
                                                double edec;
                                                if (elim == 0.0)
                                                {
                                                    double redstopdist;
                                                    if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Completed & dist < 120.0)
                                                    {
                                                        dist        = 1.0;
                                                        redstopdist = 25.0;
                                                    }
                                                    else if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Pending | stopDistance < dist)
                                                    {
                                                        redstopdist = 1.0;
                                                    }
                                                    else if (spd > 9.72222222222222)
                                                    {
                                                        redstopdist = 55.0;
                                                    }
                                                    else
                                                    {
                                                        redstopdist = 35.0;
                                                    }
                                                    if (dist > redstopdist)
                                                    {
                                                        edec = (spd * spd) / (2.0 * (dist - redstopdist));
                                                    }
                                                    else
                                                    {
                                                        edec = BrakeDeceleration;
                                                    }
                                                    if (dist < 100.0)
                                                    {
                                                        reduceDecelerationCruiseAndStart = true;
                                                    }
                                                }
                                                else
                                                {
                                                    if (dist >= 1.0)
                                                    {
                                                        edec = (spd * spd - elim * elim) / (2.0 * dist);
                                                    }
                                                    else
                                                    {
                                                        edec = 0.0;
                                                    }
                                                }
                                                if (edec > dec)
                                                {
                                                    dec = edec;
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None)
                                {
                                    // station start
                                    if (Train.Station == -1)
                                    {
                                        TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                        if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex)
                                        {
                                            int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length);
                                            if (s >= 0)
                                            {
                                                double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp;
                                                if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance)
                                                {
                                                    if (dist < 25.0)
                                                    {
                                                        reduceDecelerationCruiseAndStart = true;
                                                    }
                                                    else if (this.CurrentSpeedFactor < 1.0)
                                                    {
                                                        dist -= 5.0;
                                                    }
                                                    var edec = spd * spd / (2.0 * dist);
                                                    if (edec > dec)
                                                    {
                                                        dec = edec;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationStartEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.Decelerate)
                                {
                                    // Brakes the train when passing through a request stop, which is not to be passed at linespeed
                                    if (Train.Station == -1)
                                    {
                                        TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                        if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex)
                                        {
                                            int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length);
                                            if (s >= 0)
                                            {
                                                double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp;
                                                if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance)
                                                {
                                                    if (dist < 25.0)
                                                    {
                                                        reduceDecelerationCruiseAndStart = true;
                                                    }
                                                    else if (this.CurrentSpeedFactor < 1.0)
                                                    {
                                                        dist -= 5.0;
                                                    }
                                                    if (dist > 25)
                                                    {
                                                        var edec = spd * spd / (2.0 * dist);
                                                        if (edec > dec)
                                                        {
                                                            dec = edec;
                                                        }
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.StationEndEvent && Train.NextStopSkipped == TrainManager.StopSkipMode.None)
                                {
                                    // station end
                                    if (Train.Station == -1)
                                    {
                                        TrackManager.StationEndEvent e = (TrackManager.StationEndEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                        if (StopsAtStation(e.StationIndex, Train) & Train.LastStation != e.StationIndex)
                                        {
                                            int s = Game.Stations[e.StationIndex].GetStopIndex(Train.Cars.Length);
                                            if (s >= 0)
                                            {
                                                double dist = Stations[e.StationIndex].Stops[s].TrackPosition - tp;
                                                if (dist > -Stations[e.StationIndex].Stops[s].ForwardTolerance)
                                                {
                                                    if (dist < 25.0)
                                                    {
                                                        reduceDecelerationCruiseAndStart = true;
                                                    }
                                                    else if (this.CurrentSpeedFactor < 1.0)
                                                    {
                                                        dist -= 5.0;
                                                    }
                                                    var edec = spd * spd / (2.0 * dist);
                                                    if (edec > dec)
                                                    {
                                                        dec = edec;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                else if (TrackManager.Tracks[0].Elements[i].Events[j] is TrackManager.TrackEndEvent)
                                {
                                    // track end
                                    if (Train == TrainManager.PlayerTrain)
                                    {
                                        TrackManager.TrackEndEvent e = (TrackManager.TrackEndEvent)TrackManager.Tracks[0].Elements[i].Events[j];
                                        double dist = stp + e.TrackPositionDelta - tp;
                                        double edec;
                                        if (dist >= 15.0)
                                        {
                                            edec = spd * spd / (2.0 * dist);
                                        }
                                        else
                                        {
                                            edec = BrakeDeceleration;
                                        }
                                        if (edec > dec)
                                        {
                                            dec = edec;
                                        }
                                    }
                                }
                            }
                        }
                    }
                    // buffers ahead
                    if (Train == TrainManager.PlayerTrain)
                    {
                        for (int i = 0; i < BufferTrackPositions.Length; i++)
                        {
                            double dist = BufferTrackPositions[i] - tp;
                            if (dist > 0.0)
                            {
                                double edec;
                                if (dist >= 10.0)
                                {
                                    edec = spd * spd / (2.0 * dist);
                                }
                                else if (dist >= 5.0)
                                {
                                    Train.ApplyNotch(-1, true, 1, true);
                                    Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                                    this.CurrentInterval = 0.1;
                                    return;
                                }
                                else
                                {
                                    Train.ApplyNotch(-1, true, 1, true);
                                    Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                                    Train.ApplyEmergencyBrake();
                                    this.CurrentInterval = 10.0;
                                    return;
                                }
                                if (edec > dec)
                                {
                                    dec = edec;
                                }
                            }
                        }
                    }
                    // trains ahead
                    for (int i = 0; i < TrainManager.Trains.Length; i++)
                    {
                        if (TrainManager.Trains[i] != Train && TrainManager.Trains[i].State == TrainState.Available)
                        {
                            double pos =
                                TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].RearAxle.Follower.TrackPosition -
                                TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].RearAxle.Position -
                                0.5 * TrainManager.Trains[i].Cars[TrainManager.Trains[i].Cars.Length - 1].Length;
                            double dist = pos - tp;
                            if (dist > -10.0 & dist < lookahead)
                            {
                                const double minDistance = 10.0;
                                const double maxDistance = 100.0;
                                double       edec;
                                if (dist > minDistance)
                                {
                                    double shift = 0.75 * minDistance + 1.0 * spd;
                                    edec = spd * spd / (2.0 * (dist - shift));
                                }
                                else if (dist > 0.5 * minDistance)
                                {
                                    Train.ApplyNotch(-1, true, 1, true);
                                    Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                                    this.CurrentInterval = 0.1;
                                    return;
                                }
                                else
                                {
                                    Train.ApplyNotch(-1, true, 1, true);
                                    Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                                    Train.ApplyEmergencyBrake();
                                    this.CurrentInterval = 1.0;
                                    return;
                                }
                                if (dist < maxDistance)
                                {
                                    reduceDecelerationCruiseAndStart = true;
                                }
                                if (edec > dec)
                                {
                                    dec = edec;
                                }
                            }
                        }
                    }
                    Train.UnapplyEmergencyBrake();
                    // current station
                    if (Train.Station >= 0 & Train.StationState == TrainManager.TrainStopState.Pending)
                    {
                        if (StopsAtStation(Train.Station, Train))
                        {
                            int s = Game.Stations[Train.Station].GetStopIndex(Train.Cars.Length);
                            if (s >= 0)
                            {
                                double dist = Stations[Train.Station].Stops[s].TrackPosition - tp;
                                if (dist > 0.0)
                                {
                                    if (dist < 25.0)
                                    {
                                        reduceDecelerationCruiseAndStart = true;
                                    }
                                    else if (this.CurrentSpeedFactor < 1.0)
                                    {
                                        dist -= 5.0;
                                    }
                                    var edec = spd * spd / (2.0 * dist);
                                    if (edec > dec)
                                    {
                                        dec = edec;
                                    }
                                }
                                else
                                {
                                    dec = BrakeDeceleration;
                                }
                            }
                        }
                    }
                    // power / brake
                    if (reduceDecelerationCruiseAndStart)
                    {
                        decelerationCruise *= 0.3;
                        decelerationStart  *= 0.3;
                    }
                    double brakeModeBrakeThreshold = 0.75 * decelerationStart + 0.25 * decelerationCruise;
                    if (!BrakeMode & dec > decelerationStart | BrakeMode & dec > brakeModeBrakeThreshold | false)
                    {
                        // brake
                        BrakeMode = true;
                        double decdiff = -acc - dec;
                        if (decdiff < -decelerationStep)
                        {
                            // brake start
                            if (Train.Handles.Power.Driver == 0)
                            {
                                Train.ApplyNotch(0, true, 1, true);
                                Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Service);
                            }
                            else
                            {
                                Train.ApplyNotch(-1, true, 0, true);
                            }
                            CurrentInterval *= 0.4;
                            if (CurrentInterval < 0.3)
                            {
                                CurrentInterval = 0.3;
                            }
                        }
                        else if (decdiff > decelerationStep)
                        {
                            // brake stop
                            Train.ApplyNotch(-1, true, -1, true);
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            CurrentInterval *= 0.4;
                            if (CurrentInterval < 0.3)
                            {
                                CurrentInterval = 0.3;
                            }
                        }
                        else
                        {
                            // keep brake
                            Train.ApplyNotch(-1, true, 0, true);
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Lap);
                            CurrentInterval *= 1.2;
                            if (CurrentInterval > 1.0)
                            {
                                CurrentInterval = 1.0;
                            }
                        }
                        if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0)
                        {
                            Train.ApplyHoldBrake(Train.Handles.HasHoldBrake);
                        }
                        if (Train.Handles.Brake is TrainManager.AirBrakeHandle)
                        {
                            CurrentInterval = 0.1;
                        }
                    }
                    else if (dec > decelerationCruise)
                    {
                        // cut power/brake
                        BrakeMode = false;
                        Train.ApplyNotch(-1, true, -1, true);
                        Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                        if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0)
                        {
                            Train.ApplyHoldBrake(Train.Handles.HasHoldBrake);
                        }
                        CurrentInterval *= 0.4;
                        if (CurrentInterval < 0.3)
                        {
                            CurrentInterval = 0.3;
                        }
                    }
                    else
                    {
                        // power
                        BrakeMode = false;
                        double acclim;
                        if (!double.IsInfinity(lim))
                        {
                            double d = lim - spd;
                            if (d > 0.0)
                            {
                                acclim = 0.1 / (0.1 * d + 1.0) - 0.12;
                            }
                            else
                            {
                                acclim = -1.0;
                            }
                        }
                        else
                        {
                            acclim = -1.0;
                        }
                        if (spd < powerstart)
                        {
                            // power start (under-speed)
                            if (Train.Handles.Brake.Driver == 0)
                            {
                                if (Train.Handles.Power.Driver < this.PowerNotchAtWhichWheelSlipIsObserved - 1)
                                {
                                    Train.ApplyNotch(1, true, 0, true);
                                }
                            }
                            else
                            {
                                Train.ApplyNotch(0, true, -1, true);
                            }
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            if (double.IsPositiveInfinity(powerstart))
                            {
                                CurrentInterval = 0.3 + 0.1 * Train.Handles.Power.Driver;
                            }
                            else
                            {
                                double p = (double)Train.Handles.Power.Driver / (double)Train.Handles.Power.MaximumNotch;
                                CurrentInterval = 0.3 + 15.0 * p / (powerstart - spd + 1.0);
                            }
                            if (CurrentInterval > 1.3)
                            {
                                CurrentInterval = 1.3;
                            }
                        }
                        else if (spd > powerend)
                        {
                            // power end (over-speed)
                            Train.ApplyNotch(-1, true, -1, true);
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            CurrentInterval *= 0.3;
                            if (CurrentInterval < 0.2)
                            {
                                CurrentInterval = 0.2;
                            }
                        }
                        else if (acc < acclim)
                        {
                            // power start (under-acceleration)
                            if (Train.Handles.Brake.Driver == 0)
                            {
                                if (Train.Handles.Power.Driver < this.PowerNotchAtWhichWheelSlipIsObserved - 1)
                                {
                                    if (Train.Handles.Power.Driver == Train.Handles.Power.Actual)
                                    {
                                        Train.ApplyNotch(1, true, 0, true);
                                    }
                                }
                            }
                            else
                            {
                                Train.ApplyNotch(0, true, -1, true);
                            }
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            CurrentInterval = 1.3;
                        }
                        else
                        {
                            // keep power
                            Train.ApplyNotch(0, true, -1, true);
                            Train.ApplyAirBrakeHandle(TrainManager.AirBrakeHandleState.Release);
                            if (Train.Handles.Power.Driver != 0)
                            {
                                Train.Specs.CurrentConstSpeed = Train.Specs.HasConstSpeed;
                            }
                            if (Train.Handles.Power.Driver == 0 & Train.Handles.Brake.Driver == 0)
                            {
                                Train.ApplyHoldBrake(Train.Handles.HasHoldBrake);
                            }
                            CurrentInterval *= 1.1;
                            if (CurrentInterval > 1.5)
                            {
                                CurrentInterval = 1.5;
                            }
                        }
                    }
                }
            }
예제 #5
0
        // create route map
        internal static Bitmap CreateRouteMap(int Width, int Height)
        {
            // find first and last used element based on stations
            int n  = TrackManager.CurrentTrack.Elements.Length;
            int n0 = n - 1;
            int n1 = 0;

            for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                    {
                        if (i < n0)
                        {
                            n0 = i;
                        }
                        if (i > n1)
                        {
                            n1 = i;
                        }
                    }
                }
            }
            n0 -= 4;
            n1 += 8;
            if (n0 < 0)
            {
                n0 = 0;
            }
            if (n1 >= TrackManager.CurrentTrack.Elements.Length)
            {
                n1 = TrackManager.CurrentTrack.Elements.Length - 1;
            }
            if (n1 <= n0)
            {
                n1 = n0 + 1;
            }
            // find dimensions
            double x0 = double.PositiveInfinity, z0 = double.PositiveInfinity;
            double x1 = double.NegativeInfinity, z1 = double.NegativeInfinity;

            for (int i = n0; i <= n1; i++)
            {
                double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                double z = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                if (x < x0)
                {
                    x0 = x;
                }
                if (x > x1)
                {
                    x1 = x;
                }
                if (z < z0)
                {
                    z0 = z;
                }
                if (z > z1)
                {
                    z1 = z;
                }
            }
            if (x0 >= x1 - 1.0)
            {
                x0 = x1 - 1.0;
            }
            if (z0 >= z1 - 1.0)
            {
                z0 = z1 - 1.0;
            }
            double wrh = (double)Width / (double)Height;

            if ((x1 - x0) / (z1 - z0) <= wrh)
            {
                double dx = 0.5 * (z1 - z0) * wrh;
                double px = 0.5 * (x0 + x1);
                x0 = px - dx;
                x1 = px + dx;
            }
            else
            {
                double dz = 0.5 * (x1 - x0) / wrh;
                double pz = 0.5 * (z0 + z1);
                z0 = pz - dz;
                z1 = pz + dz;
            }
            double xd = 1.0 / (x1 - x0);
            double zd = 1.0 / (z1 - z0);
            double ox = 8.0, oy = 8.0;
            double w = (double)(Width - 16);
            double h = (double)(Height - 16);
            // create bitmap
            Bitmap   b = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);

            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.Clear(Color.White);
            // draw route path
            {
                int      start = 0;
                bool     atc   = false;
                PointF[] p     = new PointF[n];
                for (int i = 0; i < n; i++)
                {
                    double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                    double z = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                    x    = ox + w * (x - x0) * xd;
                    z    = oy + h + h * zd * (z0 - z);
                    p[i] = new PointF((float)x, (float)z);
                    // ats/atc
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].SafetySystem == Game.SafetySystem.Atc)
                            {
                                if (!atc)
                                {
                                    atc = true;
                                    if (i - start - 1 > 0)
                                    {
                                        g.DrawCurve(Pens.Black, p, start, i - start - 1);
                                    }
                                    start = i;
                                }
                            }
                            else
                            {
                                if (atc)
                                {
                                    atc = false;
                                    if (i - start - 1 > 0)
                                    {
                                        g.DrawCurve(Pens.DarkRed, p, start, i - start - 1);
                                    }
                                    start = i;
                                }
                            }
                        }
                    }
                }
                DrawSegmentedCurve(g, atc ? Pens.DarkRed : Pens.Black, p, start, n - start - 1);
            }
            // draw station circles
            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                    {
                        TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                        if (Game.Stations[e.StationIndex].Name != string.Empty)
                        {
                            double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                            double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                            x = ox + w * (x - x0) * xd;
                            y = oy + h + h * zd * (z0 - y);
                            // station circle
                            RectangleF r = new RectangleF((float)x - 4.0f, (float)y - 4.0f, 8.0f, 8.0f);
                            bool       q = Game.PlayerStopsAtStation(e.StationIndex);
                            g.FillEllipse(q ? Brushes.SkyBlue : Brushes.LightGray, r);
                            g.DrawEllipse(q ? Pens.Black : Pens.Gray, r);
                        }
                    }
                }
            }
            // draw station names
            {
                double wh = w * h;
                Font   f  = new Font(FontFamily.GenericSansSerif, wh < 65536.0 ? 9.0f : 10.0f, GraphicsUnit.Pixel);
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].Name != string.Empty)
                            {
                                double x = TrackManager.CurrentTrack.Elements[i].WorldPosition.X;
                                double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Z;
                                x = ox + w * (x - x0) * xd;
                                y = oy + h + h * zd * (z0 - y);
                                RectangleF r = new RectangleF((float)x - 4.0f, (float)y - 4.0f, 8.0f, 8.0f);
                                bool       stop = Game.PlayerStopsAtStation(e.StationIndex);
                                string     t = Game.Stations[e.StationIndex].Name;
                                SizeF      m = g.MeasureString(t, f, Width, StringFormat.GenericDefault);
                                double     sx = TrackManager.CurrentTrack.Elements[i].WorldSide.X;
                                double     sz = TrackManager.CurrentTrack.Elements[i].WorldSide.Z;
                                double     xt, yt;
                                if (Math.Sign(sx) == Math.Sign(sz))
                                {
                                    // descending
                                    bool o = (x - ox) * (h - y) <= (w - x) * (y - oy);
                                    if (o)
                                    {
                                        // up-right
                                        xt = x + 6.0;
                                        yt = y - 6.0 - m.Height;
                                    }
                                    else
                                    {
                                        // down-left
                                        xt = x - 6.0 - m.Width;
                                        yt = y + 6.0;
                                    }
                                }
                                else
                                {
                                    // ascending
                                    bool o = (h - y) * (w - x) <= (x - ox) * (y - oy);
                                    if (o)
                                    {
                                        // up-left
                                        xt = x - 6.0 - m.Width;
                                        yt = y - 6.0 - m.Height;
                                    }
                                    else
                                    {
                                        // down-right
                                        xt = x + 6.0;
                                        yt = y + 6.0;
                                    }
                                }
                                if (xt < ox)
                                {
                                    xt = ox;
                                }
                                else if (xt + m.Width > w)
                                {
                                    xt = w - m.Width;
                                }
                                if (yt < oy)
                                {
                                    yt = oy;
                                }
                                else if (yt + m.Height > h)
                                {
                                    yt = h - m.Height;
                                }
                                r = new RectangleF((float)xt, (float)yt, m.Width, m.Height);
                                g.FillRectangle(stop ? Brushes.White : Brushes.LightGray, r.Left - 1.0f, r.Top - 1.0f, r.Width + 2.0f, r.Height + 2.0f);
                                g.DrawRectangle(stop ? Pens.Black : Pens.Gray, r.Left - 1.0f, r.Top - 1.0f, r.Width + 2.0f, r.Height + 2.0f);
                                g.DrawString(t, f, stop ? Brushes.Black : Brushes.Gray, (float)xt, (float)yt);
                            }
                        }
                    }
                }
            }
            // finalize
            return(b);
        }
예제 #6
0
        // create route gradient profile
        internal static Bitmap CreateRouteGradientProfile(int Width, int Height)
        {
            // find first and last used element based on stations
            int n  = TrackManager.CurrentTrack.Elements.Length;
            int n0 = n - 1;
            int n1 = 0;

            for (int i = 0; i < TrackManager.CurrentTrack.Elements.Length; i++)
            {
                for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                {
                    if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                    {
                        if (i < n0)
                        {
                            n0 = i;
                        }
                        if (i > n1)
                        {
                            n1 = i;
                        }
                    }
                }
            }
            n0 -= 4;
            n1 += 8;
            if (n0 < 0)
            {
                n0 = 0;
            }
            if (n1 >= TrackManager.CurrentTrack.Elements.Length)
            {
                n1 = TrackManager.CurrentTrack.Elements.Length - 1;
            }
            if (n1 <= n0)
            {
                n1 = n0 + 1;
            }
            // find dimensions
            double y0 = double.PositiveInfinity, y1 = double.NegativeInfinity;

            for (int i = n0; i <= n1; i++)
            {
                double y = TrackManager.CurrentTrack.Elements[i].WorldPosition.Y;
                if (y < y0)
                {
                    y0 = y;
                }
                if (y > y1)
                {
                    y1 = y;
                }
            }
            if (y0 >= y1 - 1.0)
            {
                y0 = y1 - 1.0;
            }
            double nd = 1.0 / (double)(n1 - n0);
            double yd = 1.0 / (double)(y1 - y0);
            double ox = 8.0, oy = 8.0;
            double w = (double)(Width - 16);
            double h = (double)(Height - 32);
            // create bitmap
            Bitmap   b = new Bitmap(Width, Height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
            Graphics g = Graphics.FromImage(b);

            g.SmoothingMode     = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
            g.Clear(Color.White);
            // draw below sea level
            {
                double y  = oy + h * (1.0 - 0.5 * (double)(-Game.RouteInitialElevation - y0) * yd);
                double x0 = ox - w * (double)(n0) * nd;
                double x1 = ox + w * (double)(n - n0) * nd;
                g.FillRectangle(Brushes.PaleGoldenrod, (float)x0, (float)y, (float)x1, (float)(oy + h) - (float)y);
                g.DrawLine(Pens.Gray, (float)x0, (float)y, (float)x1, (float)y);
            }
            // draw route path
            {
                PointF[] p = new PointF[n + 2];
                p[0] = new PointF((float)(ox - w * (double)n0 * nd), (float)(oy + h));
                for (int i = 0; i < n; i++)
                {
                    double x = ox + w * (double)(i - n0) * nd;
                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                    p[i + 1] = new PointF((float)x, (float)y);
                }
                p[n + 1] = new PointF((float)(ox + w * (double)(n - n0 - 1) * nd), (float)(oy + h));
                g.FillPolygon(Brushes.Tan, p);
                for (int i = 1; i < n; i++)
                {
                    g.DrawLine(Pens.Black, p[i], p[i + 1]);
                }
                g.DrawLine(Pens.Black, 0.0f, (float)(oy + h), (float)Width, (float)(oy + h));
            }
            // draw station names
            {
                Font         f = new Font(FontFamily.GenericSansSerif, 12.0f, GraphicsUnit.Pixel);
                StringFormat m = new StringFormat();
                for (int i = 0; i < n; i++)
                {
                    for (int j = 0; j < TrackManager.CurrentTrack.Elements[i].Events.Length; j++)
                    {
                        if (TrackManager.CurrentTrack.Elements[i].Events[j] is TrackManager.StationStartEvent)
                        {
                            TrackManager.StationStartEvent e = (TrackManager.StationStartEvent)TrackManager.CurrentTrack.Elements[i].Events[j];
                            if (Game.Stations[e.StationIndex].Name != string.Empty)
                            {
                                bool stop = Game.PlayerStopsAtStation(e.StationIndex);
                                if (Interface.IsJapanese(Game.Stations[e.StationIndex].Name))
                                {
                                    m.Alignment     = StringAlignment.Near;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + w * (double)(i - n0) * nd;
                                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    string t = Game.Stations[e.StationIndex].Name;
                                    float  tx = 0.0f, ty = (float)oy;
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        if (s.Width > tx)
                                        {
                                            tx = s.Width;
                                        }
                                    }
                                    for (int k = 0; k < t.Length; k++)
                                    {
                                        g.DrawString(t.Substring(k, 1), f, stop ? Brushes.Black : Brushes.LightGray, (float)x - 0.5f * tx, ty);
                                        SizeF s = g.MeasureString(t.Substring(k, 1), f, 65536, StringFormat.GenericTypographic);
                                        ty += s.Height;
                                    }
                                    g.DrawLine(stop ? Pens.Gray : Pens.LightGray, new PointF((float)x, ty + 4.0f), new PointF((float)x, (float)y));
                                }
                                else
                                {
                                    m.Alignment     = StringAlignment.Far;
                                    m.LineAlignment = StringAlignment.Near;
                                    double x = ox + w * (double)(i - n0) * nd;
                                    double y = oy + h * (1.0 - 0.5 * (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd);
                                    g.RotateTransform(-90.0f);
                                    g.TranslateTransform((float)x, (float)oy, System.Drawing.Drawing2D.MatrixOrder.Append);
                                    g.DrawString(Game.Stations[e.StationIndex].Name, f, stop ? Brushes.Black : Brushes.LightGray, new PointF(0.0f, -5.0f), m);
                                    g.ResetTransform();
                                    SizeF s = g.MeasureString(Game.Stations[e.StationIndex].Name, f);
                                    g.DrawLine(stop ? Pens.Gray : Pens.LightGray, new PointF((float)x, (float)(oy + s.Width + 4)), new PointF((float)x, (float)y));
                                }
                            }
                        }
                    }
                }
            }
            // draw route markers
            {
                Font         f  = new Font(FontFamily.GenericSansSerif, 10.0f, GraphicsUnit.Pixel);
                Font         fs = new Font(FontFamily.GenericSansSerif, 9.0f, GraphicsUnit.Pixel);
                StringFormat m  = new StringFormat();
                m.Alignment     = StringAlignment.Far;
                m.LineAlignment = StringAlignment.Center;
                System.Globalization.CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
                int k = 48 * n / Width;
                for (int i = 0; i < n; i += k)
                {
                    double x = ox + w * (double)(i - n0) * nd;
                    double y = (double)(TrackManager.CurrentTrack.Elements[i].WorldPosition.Y - y0) * yd;
                    if (x < w)
                    {
                        string t = ((int)Math.Round(TrackManager.CurrentTrack.Elements[i].StartingTrackPosition)).ToString(Culture);
                        g.DrawString(t + "m", f, Brushes.Black, (float)x, (float)(oy + h + 6.0));
                    }
                    {
                        y = oy + h * (1.0 - 0.5 * y) + 2.0f;
                        string t = ((int)Math.Round(Game.RouteInitialElevation + TrackManager.CurrentTrack.Elements[i].WorldPosition.Y)).ToString(Culture);
                        SizeF  s = g.MeasureString(t, fs);
                        if (y < oy + h - (double)s.Width - 10.0)
                        {
                            g.RotateTransform(-90.0f);
                            g.TranslateTransform((float)x, (float)y + 4.0f, System.Drawing.Drawing2D.MatrixOrder.Append);
                            g.DrawString(t + "m", fs, Brushes.Black, 0.0f, 0.0f, m);
                            g.ResetTransform();
                            g.DrawLine(Pens.Gray, (float)x, (float)(y + s.Width + 12.0), (float)x, (float)(oy + h));
                        }
                    }
                }
            }
            // finalize
            return(b);
        }
예제 #7
0
        /// <summary>Renders a graphical visualisation of any events within camera range</summary>
        /// <param name="Camera">The absolute camera position</param>
        private static void RenderEvents(Vector3 Camera)
        {
            if (Interface.CurrentOptions.ShowEvents == false || TrackManager.Tracks[0].Elements == null)
            {
                return;
            }

            if (!Initialized)
            {
                Init();
                Initialized = true;
            }
            GL.Enable(EnableCap.CullFace); LibRender.Renderer.CullEnabled = true;
            GL.Enable(EnableCap.DepthTest);
            GL.DepthMask(true);
            if (LibRender.Renderer.LightingEnabled)
            {
                GL.Disable(EnableCap.Lighting);
                LibRender.Renderer.LightingEnabled = false;
            }
            if (LibRender.Renderer.AlphaTestEnabled)
            {
                GL.Disable(EnableCap.AlphaTest);
                LibRender.Renderer.AlphaTestEnabled = false;
            }
            double da = -World.BackwardViewingDistance - World.ExtraViewingDistance;
            double db = World.ForwardViewingDistance + World.ExtraViewingDistance;

            bool[] sta = new bool[CurrentRoute.Stations.Length];
            // events
            for (int i = 0; i < TrackManager.Tracks[0].Elements.Length; i++)
            {
                double p = TrackManager.Tracks[0].Elements[i].StartingTrackPosition;
                double d = p - World.CameraTrackFollower.TrackPosition;
                if (d >= da & d <= db)
                {
                    for (int j = 0; j < TrackManager.Tracks[0].Elements[i].Events.Length; j++)
                    {
                        dynamic e = TrackManager.Tracks[0].Elements[i].Events[j];
                        double  dy, dx = 0.0, dz = 0.0;
                        double  s; Texture t;
                        if (e is TrackManager.BrightnessChangeEvent)
                        {
                            s  = 0.15;
                            dy = 4.0;
                            t  = BrightnessChangeTexture;
                        }
                        else if (e is BackgroundChangeEvent)
                        {
                            s  = 0.25;
                            dy = 3.5;
                            t  = BackgroundChangeTexture;
                        }
                        else if (e is TrackManager.StationStartEvent)
                        {
                            s  = 0.25;
                            dy = 1.6;
                            t  = StationStartTexture;
                            TrackManager.StationStartEvent f = (TrackManager.StationStartEvent)e;
                            sta[f.StationIndex] = true;
                        }
                        else if (e is TrackManager.StationEndEvent)
                        {
                            s  = 0.25;
                            dy = 1.6;
                            t  = StationEndTexture;
                            TrackManager.StationEndEvent f = (TrackManager.StationEndEvent)e;
                            sta[f.StationIndex] = true;
                        }
                        else if (e is TrackManager.LimitChangeEvent)
                        {
                            s  = 0.2;
                            dy = 1.1;
                            t  = LimitTexture;
                        }
                        else if (e is TrackManager.SectionChangeEvent)
                        {
                            s  = 0.2;
                            dy = 0.8;
                            t  = SectionTexture;
                        }
                        else if (e is TrackManager.TransponderEvent)
                        {
                            s  = 0.15;
                            dy = 0.4;
                            t  = TransponderTexture;
                        }
                        else if (e is TrackManager.SoundEvent)
                        {
                            TrackManager.SoundEvent f = (TrackManager.SoundEvent)e;
                            s  = 0.2;
                            dx = f.Position.X;
                            dy = f.Position.Y < 0.1 ? 0.1 : f.Position.Y;
                            dz = f.Position.Z;
                            t  = SoundTexture;
                        }
                        else if (e is TrackManager.PointSoundEvent)
                        {
                            s  = 0.2;
                            dx = 0;
                            dy = 0.2;
                            dz = 0;
                            t  = PointSoundTexture;
                        }
                        else
                        {
                            s  = 0.2;
                            dy = 1.0;
                            t  = null;
                        }
                        if (t != null)
                        {
                            TrackManager.TrackFollower f = new TrackManager.TrackFollower();
                            f.TriggerType   = EventTriggerType.None;
                            f.TrackPosition = p;
                            f.Update(p + e.TrackPositionDelta, true, false);
                            f.WorldPosition.X += dx * f.WorldSide.X + dy * f.WorldUp.X + dz * f.WorldDirection.X;
                            f.WorldPosition.Y += dx * f.WorldSide.Y + dy * f.WorldUp.Y + dz * f.WorldDirection.Y;
                            f.WorldPosition.Z += dx * f.WorldSide.Z + dy * f.WorldUp.Z + dz * f.WorldDirection.Z;
                            LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, t);
                        }
                    }
                }
            }
            // stops
            for (int i = 0; i < sta.Length; i++)
            {
                if (sta[i])
                {
                    for (int j = 0; j < CurrentRoute.Stations[i].Stops.Length; j++)
                    {
                        const double dy = 1.4;
                        const double s  = 0.2;
                        double       p  = CurrentRoute.Stations[i].Stops[j].TrackPosition;
                        TrackManager.TrackFollower f = new TrackManager.TrackFollower();
                        f.TriggerType   = EventTriggerType.None;
                        f.TrackPosition = p;
                        f.Update(p, true, false);
                        f.WorldPosition.X += dy * f.WorldUp.X;
                        f.WorldPosition.Y += dy * f.WorldUp.Y;
                        f.WorldPosition.Z += dy * f.WorldUp.Z;
                        LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, StopTexture);
                    }
                }
            }
            // buffers
            for (int i = 0; i < Game.BufferTrackPositions.Length; i++)
            {
                double p = Game.BufferTrackPositions[i];
                double d = p - World.CameraTrackFollower.TrackPosition;
                if (d >= da & d <= db)
                {
                    const double dy = 2.5;
                    const double s  = 0.25;
                    TrackManager.TrackFollower f = new TrackManager.TrackFollower();
                    f.TriggerType   = EventTriggerType.None;
                    f.TrackPosition = p;
                    f.Update(p, true, false);
                    f.WorldPosition.X += dy * f.WorldUp.X;
                    f.WorldPosition.Y += dy * f.WorldUp.Y;
                    f.WorldPosition.Z += dy * f.WorldUp.Z;
                    LibRender.Renderer.DrawCube(f.WorldPosition, f.WorldDirection, f.WorldUp, f.WorldSide, s, Camera, BufferTexture);
                }
            }
        }