city-generation/Tools/MapViewer/MapViewer/Business/MapRenderer.cs

126 lines
3.7 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using TransportGame.Model;
namespace TransportGame.MapViewer
{
public class MapRenderer
{
[Flags]
public enum Layers
{
None = 0,
Elevation = 1,
All = Elevation
};
/// <summary>
/// Gets or sets the scale
/// </summary>
private int _scale;
public int 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.White;
public MapRenderer()
{
Scale = 4;
}
///<summary>
///Renders a map to a file
///</summary>
///<param name="file"></param>
///<param name="map"></param>
///<param name="layers"></param>
public Color[,] Render(Map map, Layers layers = Layers.All)
{
lock (this)
{
// Create texture on which to draw
Color[,] pixels = new Color[map.Width * Scale, map.Height * Scale];
// First layer - cells
DrawCells(pixels, map, (layers & Layers.Elevation) > 0);
// Done
return pixels;
}
}
private void DrawCells(Color[,] pixels, Map map, bool elevation)
{
for (int x = 0; x < pixels.GetLength(0); x++)
for (int y = 0; y < pixels.GetLength(1); y++)
{
int mapX = x / Scale;
int mapY = y / Scale;
// Draw water
if (map.IsWater(mapX, mapY))
pixels[x, y] = WaterColor;
// Draw elevation
else if (elevation)
{
float alpha = (map[mapX, mapY] - map.Biome.HeightRange.Minimum) / (map.Biome.HeightRange.Maximum - map.Biome.HeightRange.Minimum);
pixels[x, y] = Color.Multiply(ElevationTerrainColor, alpha);
}
// Draw terrain
else
{
pixels[x, y] = TerrainColor;
}
}
}
public async Task<BitmapSource> RenderToImageSource(Map map, Layers layers = Layers.All)
{
var colors = await Task.Run(() => Render(map, layers));
colors[0, 0] = Colors.Red;
colors[colors.GetLength(0) - 1, 0] = Colors.Red;
// Convert to raw pixels
byte[] raw = new byte[colors.GetLength(0) * colors.GetLength(1) * 3];
for (int x = 0; x < colors.GetLength(0); x++)
for (int y = 0; y < colors.GetLength(1); y++)
{
int pixelIndex = x + y * colors.GetLength(0);
raw[3 * pixelIndex] = colors[x, y].R;
raw[3 * pixelIndex + 1] = colors[x, y].G;
raw[3 * pixelIndex + 2] = colors[x, y].B;
}
// Create bitmap source
BitmapSource bmp = BitmapSource.Create(colors.GetLength(0), colors.GetLength(1),
96, 96, PixelFormats.Rgb24, null, raw, colors.GetLength(0) * 3);
return bmp;
}
}
}