137 lines
4.3 KiB
C#
137 lines
4.3 KiB
C#
using System;
|
|
using System.Windows.Media;
|
|
using TransportGame.MapViewer.Model;
|
|
using TransportGame.Model;
|
|
|
|
namespace TransportGame.MapViewer
|
|
{
|
|
public class MapRenderer
|
|
{
|
|
[Flags]
|
|
public enum Layers
|
|
{
|
|
None = 0,
|
|
Elevation = 1,
|
|
Population = 2,
|
|
RoadArticulations = 4,
|
|
All = Elevation | Population | RoadArticulations
|
|
};
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scale
|
|
/// </summary>
|
|
private float _scale;
|
|
public float Scale
|
|
{
|
|
get
|
|
{
|
|
return _scale;
|
|
}
|
|
set
|
|
{
|
|
lock (this)
|
|
{
|
|
_scale = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private readonly Color WaterColor = Colors.Navy;
|
|
private readonly Color ElevationTerrainColor = Colors.White;
|
|
private readonly Color TerrainColor = Colors.Silver;
|
|
|
|
public MapRenderer()
|
|
{
|
|
Scale = 1;
|
|
}
|
|
|
|
///<summary>
|
|
///Renders a map to a file
|
|
///</summary>
|
|
///<param name="file"></param>
|
|
///<param name="map"></param>
|
|
///<param name="layers"></param>
|
|
public Bitmap24 Render(CityMap map, Layers layers = Layers.All)
|
|
{
|
|
lock (this)
|
|
{
|
|
// Create texture on which to draw
|
|
Bitmap24 bitmap = new Bitmap24(Convert.ToInt32(map.Width * Scale), Convert.ToInt32(map.Height * Scale));
|
|
|
|
// Elevation, population
|
|
DrawPixels(bitmap, map, (layers & Layers.Elevation) > 0, (layers & Layers.Population) > 0);
|
|
|
|
// Roads
|
|
if ((layers & Layers.RoadArticulations) > 0)
|
|
DrawRoads(bitmap, map);
|
|
|
|
// Done
|
|
return bitmap;
|
|
}
|
|
}
|
|
|
|
private Color AlphaBlend(Color top, Color dst)
|
|
{
|
|
float A = top.ScA + dst.ScA * (1 - top.ScA);
|
|
float R = (top.ScR * top.ScA + dst.ScR * (1 - top.ScA)) / A;
|
|
float G = (top.ScG * top.ScA + dst.ScG * (1 - top.ScA)) / A;
|
|
float B = (top.ScB * top.ScA + dst.ScB * (1 - top.ScA)) / A;
|
|
|
|
return Color.FromScRgb(A, R, G, B);
|
|
}
|
|
|
|
private void DrawPixels(Bitmap24 bitmap, CityMap map, bool elevation, bool population)
|
|
{
|
|
for (int x = 0; x < bitmap.Width; x++)
|
|
for (int y = 0; y < bitmap.Height; y++)
|
|
{
|
|
int mapX = Convert.ToInt32(x / Scale);
|
|
int mapY = Convert.ToInt32(y / Scale);
|
|
|
|
if (mapX >= map.Width)
|
|
mapX = map.Width - 1;
|
|
|
|
if (mapY >= map.Height)
|
|
mapY = map.Height - 1;
|
|
|
|
// Draw water
|
|
if (map.IsWater(mapX, mapY))
|
|
bitmap[x, y] = WaterColor;
|
|
|
|
else
|
|
{
|
|
// Draw elevation
|
|
if (elevation)
|
|
{
|
|
float alpha = map.Heightmap[mapX, mapY]; // map.Heights range is [0,1]
|
|
bitmap[x, y] = Color.Multiply(ElevationTerrainColor, alpha);
|
|
}
|
|
|
|
// No elevation, just put a terrain color
|
|
else bitmap[x, y] = TerrainColor;
|
|
|
|
// Population
|
|
if (population)
|
|
{
|
|
Color popColor = Color.FromScRgb(map.GetPopulation(mapX, mapY) * 0.7f, 1, 0, 1);
|
|
bitmap[x, y] = AlphaBlend(popColor, bitmap[x, y]);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void DrawRoads(Bitmap24 bitmap, CityMap map)
|
|
{
|
|
// Draw road segments
|
|
foreach (var pair in map.RoadNetwork.ArticulationSegments)
|
|
{
|
|
bitmap.DrawLine(Convert.ToInt32(pair.Value.Terminal1.X * Scale),
|
|
Convert.ToInt32(pair.Value.Terminal1.Y * Scale),
|
|
Convert.ToInt32(pair.Value.Terminal2.X * Scale),
|
|
Convert.ToInt32(pair.Value.Terminal2.Y * Scale),
|
|
Colors.Black);
|
|
}
|
|
}
|
|
}
|
|
}
|