Files
LeafWeb/Web/Controllers/ChartController.cs
T

189 lines
5.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Net;
using System.Web.Mvc;
using System.Web.UI.DataVisualization.Charting;
using System.Web.UI.WebControls;
using LeafWeb.Core.Charter;
using LeafWeb.Core.Entities;
using LeafWeb.Core.Parsers;
using LeafWeb.Core.Utility;
using LeafWeb.Web.Services;
using LeafWeb.Web.ViewModels.Chart;
using NLog;
namespace LeafWeb.Web.Controllers
{
public class ChartController : ControllerBase
{
public ActionResult Index(int leafInputId)
{
var leafOutputFile = DataService.GetLeafOutput_ChartFile(leafInputId);
if (leafOutputFile == null)
throw new ArgumentOutOfRangeException(); // TODO: break
try
{
var curveIds = GetCurveIds(leafOutputFile.FileContents.Contents);
var viewModel = new ChartViewModel
{
AvailableCurveId = curveIds,
LeafInputId = leafInputId,
LeafInputIdentifier = leafOutputFile.LeafInput.Identifier
};
return View(viewModel);
}
catch (ParseException parseException)
{
var logger = LogManager.GetCurrentClassLogger();
logger.Warn(parseException);
return View("DataError", model: parseException.Message);
}
}
public ActionResult ChartCurve(int leafInputId, string curveId)
{
var leafOutputFile = DataService.GetLeafOutput_ChartFile(leafInputId);
if (leafOutputFile == null)
throw new ArgumentOutOfRangeException(); // TODO: break
var curveData = GetCurveData(leafOutputFile.FileContents.Contents, curveId);
if (curveData == null)
return new HttpStatusCodeResult(HttpStatusCode.NotFound);
var charts = GetChartBitmaps(curveData).ToList();
var combinedChart = CombineBitmaps(charts);
foreach (var chart in charts) chart.Dispose(); // cleanup
using (var ms = new MemoryStream())
{
combinedChart.Save(ms, ImageFormat.Png);
ms.Seek(0, SeekOrigin.Begin);
return File(ms.ToArray(), "image/png", curveId.FilterValidFilename() + ".png");
}
}
private CurveData GetCurveData(byte[] fileContents, string curveId)
{
try
{
LeafGasComparison[] leafGasComparisons;
using (var parser = new LeafGasComparisonParser(fileContents))
leafGasComparisons = parser.Parse(curveId);
return CurveDataConverter.Convert(leafGasComparisons).First();
}
catch (Exception e)
{
LogManager.GetCurrentClassLogger().Warn(e);
}
return null;
}
private string[] GetCurveIds(byte[] fileContents)
{
using (var parser = new LeafGasComparisonParser(fileContents))
return parser.ExtractCurveIds();
}
private IEnumerable<Bitmap> GetChartBitmaps(CurveData curveData)
{
var charts = LeafGasCharter.ProduceCharts(curveData);
foreach (var chart in charts)
{
// http://stackoverflow.com/a/336396/99492
var ms = new MemoryStream(); // this gets attached to the bmp, dispose of it later
chart.SaveImage(ms, ChartImageFormat.Bmp);
ms.Seek(0, SeekOrigin.Begin);
yield return new Bitmap(ms);
}
}
private Bitmap CombineBitmaps(IList<Bitmap> bitmaps, int columnCount = 2)
{
if (!bitmaps.Any())
return null;
// bitmaps assumed to have same dimensions, use the first one to define that
var cellWidth = bitmaps[0].Width;
var cellHeight = bitmaps[0].Height;
var width = cellWidth * columnCount;
var height = cellHeight * bitmaps.Count / columnCount;
var combinedBitmap = new Bitmap(width, height);
using (var g = Graphics.FromImage(combinedBitmap))
{
var currentCol = 0;
var currentRow = 0;
foreach (var image in bitmaps)
{
g.DrawImage(image, currentCol * cellWidth, currentRow * cellHeight);
currentCol = (currentCol + 1)%columnCount;
currentRow += currentCol == 0 ? 1 : 0;
}
}
return combinedBitmap;
}
public ActionResult ChartSample()
{
var chart = new Chart
{
BackColor = Color.FromArgb(255, 255, 255),
Width = Unit.Pixel(250),
Height = Unit.Pixel(2500)
};
var series = new Series
{
ChartArea = "ca1",
ChartType = SeriesChartType.Line
};
//series.Font = new Font("Verdana", 8.25f, FontStyle.Regular);
var myRandom = new Random();
for (int i = 0; i < 100; i++)
{
var dp = new DataPoint();
dp.AxisLabel = String.Format("{0}-{1}", i, Guid.NewGuid().ToString().Substring(0, 4));
dp.YValues = new double[] { myRandom.Next(5, 100) };
series.Points.Add(dp);
}
chart.Series.Add(series);
var area = new ChartArea("ca1");
area.Area3DStyle.Enable3D = false;
area.AxisX.Interval = 1;
//area.BackColor = Color.Transparent;
//var labelStyle = new LabelStyle();
//labelStyle.Enabled = true;
//labelStyle.Font = new Font("Arial", 3f);
area.AxisX.LabelStyle.Font = new Font("Verdana", 8.25f, FontStyle.Underline);//Why does it recognize the style but not the font!!!???
chart.ChartAreas.Add(area);
using (var ms = new MemoryStream())
{
chart.SaveImage(ms, ChartImageFormat.Png);
ms.Seek(0, SeekOrigin.Begin);
return File(ms.ToArray(), "image/png", "mychart.png");
}
}
}
}