// 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);
}