using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Drawing2D; using System.Net; using RainScout.Core; using System.Security.Cryptography.X509Certificates; using System.ComponentModel; using System.Net.Cache; using System.IO; using System.IO.IsolatedStorage; using GMap.NET; using GMap.NET.Projections; using Newtonsoft.Json; using NGrib; using NGrib.Grib2; using System.Threading; using System.Runtime.CompilerServices; using System.Windows.Forms; namespace RainScout.Radars { [Serializable] public class RadarHD_EU : RainScout.Radars.GenericRadar { string BaseURL = "https://www.rainviewer.com/weather-radar-map-live.html"; // Radar images private Bitmap IntensityImage = null; private Bitmap CloudTopsImage = null; private Bitmap LightningImage = null; // values private int[,] LightningValues = null; // Radar legend private ValueColorTable CloudTopsLegend = new ValueColorTable(); private ValueColorTable IntensityLegend = new ValueColorTable(); private ValueColorTable LightningLegend = new ValueColorTable(); // update cylce in seconds private int UpdateCycle = 5 * 60; // map zoom level private readonly int MapZoom = 20; // Numeric weather prediction private Dictionary> NWP = new Dictionary>(); public RadarHD_EU() { Name = "RadarHD EU"; Source = "https://www.rainviewer.com/"; Left = -14.5; Right = 45.25; Top = 72.5; Bottom = 31.0; RadarLayers.Add(RADARLAYER.INTENSITY); RadarLayers.Add(RADARLAYER.CLOUDTOPS); RadarLayers.Add(RADARLAYER.LIGHTNING); // initialize intensity dictionary IntensityLegend.Add(-1,Color.FromArgb(0, 0, 0, 0)); IntensityLegend.Add(0, Color.Transparent); IntensityLegend.Add(1, ColorTranslator.FromHtml("#626262")); IntensityLegend.Add(5, ColorTranslator.FromHtml("#28EDEB")); IntensityLegend.Add(10, ColorTranslator.FromHtml("#19A1F0")); IntensityLegend.Add(15, ColorTranslator.FromHtml("#0412EF")); IntensityLegend.Add(20, ColorTranslator.FromHtml("#2BFE2D")); IntensityLegend.Add(25, ColorTranslator.FromHtml("#1FC721")); IntensityLegend.Add(30, ColorTranslator.FromHtml("#149015")); IntensityLegend.Add(35, ColorTranslator.FromHtml("#FDFD35")); IntensityLegend.Add(40, ColorTranslator.FromHtml("#E3BF27")); IntensityLegend.Add(45, ColorTranslator.FromHtml("#FC8E22")); IntensityLegend.Add(50, ColorTranslator.FromHtml("#F90017")); IntensityLegend.Add(55, ColorTranslator.FromHtml("#D10011")); IntensityLegend.Add(60, ColorTranslator.FromHtml("#BE000F")); IntensityLegend.Add(65, ColorTranslator.FromHtml("#FA00F9")); IntensityLegend.Add(70, ColorTranslator.FromHtml("#9856C6")); IntensityLegend.Add(75, ColorTranslator.FromHtml("#EBEBEB")); // initialize cloud tops dictionary CloudTopsLegend.Add(-1, Color.FromArgb(0, 0, 0, 0)); CloudTopsLegend.Add(0, Color.Transparent); CloudTopsLegend.Add(-92, ColorTranslator.FromHtml("#000000")); CloudTopsLegend.Add(-90, ColorTranslator.FromHtml("#181818")); CloudTopsLegend.Add(-88, ColorTranslator.FromHtml("#2C1C1C")); CloudTopsLegend.Add(-86, ColorTranslator.FromHtml("#411416")); CloudTopsLegend.Add(-84, ColorTranslator.FromHtml("#550C10")); CloudTopsLegend.Add(-82 , ColorTranslator.FromHtml("#67040C")); CloudTopsLegend.Add(-80, ColorTranslator.FromHtml("#7D0007")); CloudTopsLegend.Add(-78, ColorTranslator.FromHtml("#900008")); CloudTopsLegend.Add(-76, ColorTranslator.FromHtml("#A6000B")); CloudTopsLegend.Add(-74, ColorTranslator.FromHtml("#B8000E")); CloudTopsLegend.Add(-72, ColorTranslator.FromHtml("#C60010")); CloudTopsLegend.Add(-70, ColorTranslator.FromHtml("#DD0013")); CloudTopsLegend.Add(-69, ColorTranslator.FromHtml("#F10016")); CloudTopsLegend.Add(-68, ColorTranslator.FromHtml("#FC0018")); CloudTopsLegend.Add(-67, ColorTranslator.FromHtml("#FC2518")); CloudTopsLegend.Add(-66, ColorTranslator.FromHtml("#FC3E1A")); CloudTopsLegend.Add(-65, ColorTranslator.FromHtml("#FC5C1C")); CloudTopsLegend.Add(-64, ColorTranslator.FromHtml("#FD7B20")); CloudTopsLegend.Add(-63, ColorTranslator.FromHtml("#FD9924")); CloudTopsLegend.Add(-62, ColorTranslator.FromHtml("#FDB628")); CloudTopsLegend.Add(-61, ColorTranslator.FromHtml("#FEC82B")); CloudTopsLegend.Add(-60, ColorTranslator.FromHtml("#FEE430")); CloudTopsLegend.Add(-59, ColorTranslator.FromHtml("#FDFE35")); CloudTopsLegend.Add(-58, ColorTranslator.FromHtml("#DFFF3D")); CloudTopsLegend.Add(-57, ColorTranslator.FromHtml("#C2FF4F")); CloudTopsLegend.Add(-56, ColorTranslator.FromHtml("#AEFF5F")); CloudTopsLegend.Add(-55, ColorTranslator.FromHtml("#97FF74")); CloudTopsLegend.Add(-54, ColorTranslator.FromHtml("#80FF8A")); CloudTopsLegend.Add(-53, ColorTranslator.FromHtml("#68FFA2")); CloudTopsLegend.Add(-52, ColorTranslator.FromHtml("#53FFBA")); CloudTopsLegend.Add(-51, ColorTranslator.FromHtml("#53FFBA")); CloudTopsLegend.Add(-50, ColorTranslator.FromHtml("#32FFEB")); CloudTopsLegend.Add(-49, ColorTranslator.FromHtml("#2BFAFE")); CloudTopsLegend.Add(-48, ColorTranslator.FromHtml("#26E2FD")); CloudTopsLegend.Add(-47, ColorTranslator.FromHtml("#21C8FD")); CloudTopsLegend.Add(-46, ColorTranslator.FromHtml("#1CB2FC")); CloudTopsLegend.Add(-45, ColorTranslator.FromHtml("#1799FC")); CloudTopsLegend.Add(-44, ColorTranslator.FromHtml("#1385FC")); CloudTopsLegend.Add(-43, ColorTranslator.FromHtml("#0D64FB")); CloudTopsLegend.Add(-42, ColorTranslator.FromHtml("#0A52FB")); CloudTopsLegend.Add(-41, ColorTranslator.FromHtml("#0740FB")); CloudTopsLegend.Add(-40, ColorTranslator.FromHtml("#0520FB")); CloudTopsLegend.Add(-38, ColorTranslator.FromHtml("#0311E6")); CloudTopsLegend.Add(-36, ColorTranslator.FromHtml("#00035E")); CloudTopsLegend.Add(-34, ColorTranslator.FromHtml("#010794")); CloudTopsLegend.Add(-32, ColorTranslator.FromHtml("#EFEFEF")); CloudTopsLegend.Add(-30, ColorTranslator.FromHtml("#E1E1E1")); CloudTopsLegend.Add(-26, ColorTranslator.FromHtml("#D5D5D5")); CloudTopsLegend.Add(-22, ColorTranslator.FromHtml("#C9C9C9")); CloudTopsLegend.Add(-18, ColorTranslator.FromHtml("#BDBDBD")); CloudTopsLegend.Add(-14, ColorTranslator.FromHtml("#B3B3B3")); CloudTopsLegend.Add(-10, ColorTranslator.FromHtml("#ADADAD")); CloudTopsLegend.Add(-8, ColorTranslator.FromHtml("#A7A7A7")); CloudTopsLegend.Add(-6, ColorTranslator.FromHtml("#A1A1A1")); CloudTopsLegend.Add(-4, ColorTranslator.FromHtml("#9B9B9B")); CloudTopsLegend.Add(-2, ColorTranslator.FromHtml("#8F8F8F")); } private Bitmap GetIntensityTile(DateTime utc, int x, int y, int z, int colorscheme) { // gets tile from url Bitmap image1 = null; // 1622129403 Bitmap image2 = null; // 1622128200 utc = utc.AddMinutes(-1); DateTime imagetime = new DateTime(utc.Year, utc.Month, utc.Day, utc.Hour, (int)(utc.Minute / 10) * 10, 0, DateTimeKind.Utc); int time = (int)(imagetime - new DateTime(1970, 1, 1)).TotalSeconds; string url = "https://tilecache.rainviewer.com/v2/radar/" + time.ToString() + "/256/" + z.ToString() + "/" + x.ToString() + "/" + y.ToString() + "/" + colorscheme.ToString() + "/1_1.png"; try { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { using (var stream = response.GetResponseStream()) { image1 = new Bitmap(stream); } } this.Timestamp = utc; } catch (Exception ex) { // do nothing return null; } return image1; } private Bitmap GetCoverageTile(int x, int y, int z) { // gets tile from url Bitmap image1 = null; // 1622129403 Bitmap image2 = null; // 1622128200 // https://tilecache.rainviewer.com/v2/coverage/0/256/5/17/7.png string url = "https://tilecache.rainviewer.com/v2/coverage/0/256/" + z.ToString() + "/" + "/" + x.ToString() + "/" + y.ToString() + ".png"; try { var request = WebRequest.Create(url); using (var response = request.GetResponse()) { using (var stream = response.GetResponseStream()) { image1 = new Bitmap(stream); } } } catch (Exception ex) { // do nothing return null; } return image1; } public Bitmap GetIntensityImage(string saveraw) { // get current date and time string DateTime utc = DateTime.UtcNow; int left = 14; int top = 6; int right = 20; int bottom = 13; Bitmap radar; Bitmap coverage; Bitmap image1 = new Bitmap((right - left) * 256, (bottom - top) * 256); Bitmap image2 = null; for (int x = left; x <= right; x++) { for (int y = top; y <= bottom; y++) { radar = GetIntensityTile(utc, x, y, 5, 6); coverage = GetCoverageTile(x, y, 5); using (Graphics g = Graphics.FromImage(image1)) { try { if (radar != null) { Rectangle rect = new Rectangle((x - left) * 256, (y - top) * 256, 256, 256); g.DrawImage(radar, rect); g.DrawImage(coverage, rect); } } catch (Exception ex) { } } } } if (image1 == null) return null; int shrinkleft = 250; int shrinktop = 170; int shrinkright = 115; int shrinkbottom = 30; Color outofrange = Color.Transparent; Color inrange = Color.Transparent; // crop image Rectangle crop = new Rectangle(); crop.X = shrinkleft; crop.Y = shrinktop; crop.Width = image1.Width - shrinkleft - shrinkright; crop.Height = image1.Height - shrinktop - shrinkbottom; image2 = new Bitmap(crop.Width, crop.Height); using (Graphics g = Graphics.FromImage(image2)) { g.DrawImage(image1, -crop.X, -crop.Y); } // save raw image if filename is not empty if (!String.IsNullOrEmpty(saveraw)) { try { image1.Save(saveraw, ImageFormat.Png); } catch (Exception ex) { // do nothing } } image1.Save("RadarHD_EU.png", ImageFormat.Png); return image2; } private Bitmap GetCloudTopsImage(string saveraw) { Bitmap image1 = null; Bitmap image2 = null; Bitmap image3 = null; int start = 0; int stop = 0; string search = "weather.us/images/data/cache/sat/sat_"; try { string url = "https://weather.us/satellite/europe/top-alert-5min.html"; RequestCachePolicy policy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); request.CachePolicy = policy; request.CookieContainer = new CookieContainer(); string imageurl = ""; // get html page using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (var stream = response.GetResponseStream()) { StreamReader reader = new StreamReader(stream, Encoding.UTF8); string content = reader.ReadToEnd(); // grab out the url of the latest image start = content.IndexOf(search, start) - 13; // return on no image found if (start <= 0) return null; stop = content.IndexOf(".jpg", start) + 4; if (stop < start) return null; // get the picture try { imageurl = content.Substring(start, stop - start); Console.WriteLine("Getting picture from web resource: " + imageurl); HttpWebRequest picrequest = (HttpWebRequest)HttpWebRequest.Create(imageurl); picrequest.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36"; picrequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"; picrequest.CookieContainer = new CookieContainer(); foreach (Cookie cookie in response.Cookies) { picrequest.CookieContainer.Add(cookie); } using (var picresponse = picrequest.GetResponse()) { using (var picstream = picresponse.GetResponseStream()) { image1 = new Bitmap(picstream); } } } catch (Exception ex) { Console.WriteLine("Error while getting picture: " + ex.Message); } // no picture loaded if (image1 == null) return null; // save raw image if filename is not empty if (!String.IsNullOrEmpty(saveraw)) { try { image1.Save(saveraw, ImageFormat.Png); } catch (Exception ex) { // do nothing } } // process image try { // save raw image if filename is not empty if (!String.IsNullOrEmpty(saveraw)) { try { image1.Save(saveraw, ImageFormat.Png); } catch (Exception ex) { // do nothing } } int zoom = 3; GPoint srctl = PlateCarreeProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Top, this.Left), zoom); GPoint srcbr = PlateCarreeProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Bottom, this.Right), zoom); int srcwidth = (int)srcbr.X - (int)srctl.X; int srcheight = (int)srcbr.Y - (int)srctl.Y; GPoint dsttl = MercatorProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Top, this.Left), zoom + 2); GPoint dstbr = MercatorProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Bottom, this.Right), zoom + 2); int dstwidth = (int)dstbr.X - (int)dsttl.X; int dstheight = (int)dstbr.Y - (int)dsttl.Y; image2 = new Bitmap(dstwidth, dstheight); for (int x = 0; x < dstwidth; x++) { for (int y = 0; y < dstheight; y++) { PointLatLng p = MercatorProjection.Instance.FromPixelToLatLng(dsttl.X + x, dsttl.Y + y, zoom + 2); GPoint g = PlateCarreeProjection.Instance.FromLatLngToPixel(p, zoom); int srcx = (int)((g.X - srctl.X) * (double)image1.Width / (double)srcwidth); int srcy = (int)((g.Y - srctl.Y) * (double)image1.Height / (double)srcheight); Color c = Color.Green; if ((srcx >= 0) && (srcx < image1.Width) && (srcy >= 0) && (srcy < image1.Height)) { c = image1.GetPixel(srcx, srcy); } image2.SetPixel(x, y, c); } } // save raw image if filename is not empty if (!String.IsNullOrEmpty(saveraw)) { try { image2.Save(saveraw, ImageFormat.Png); } catch (Exception ex) { // do nothing } } int shrinkleft = 280; int shrinktop = 0; int shrinkright = 0; int shrinkbottom = 0; Color outofrange = Color.Transparent; Color inrange = Color.Transparent; // crop image Rectangle crop = new Rectangle(); crop.X = shrinkleft; crop.Y = shrinktop; crop.Width = image2.Width - shrinkleft - shrinkright; crop.Height = image2.Height - shrinktop - shrinkbottom; image3 = new Bitmap(crop.Width, crop.Height); using (Graphics g = Graphics.FromImage(image3)) { g.DrawImage(image2, -crop.X, -crop.Y); } // be aware that there are two representations of transparent background: // image.MakeTransparent uses ARGB(0,0,0,0) // Color.Transparent uses ARGB(0,255,255,255) // make out of range background transparent image3.MakeTransparent(outofrange); // convert out of range color into semi-transparent grey ColorMap[] colormap = new ColorMap[1]; colormap[0] = new ColorMap(); colormap[0].OldColor = Color.FromArgb(0, 0, 0, 0); colormap[0].NewColor = Color.FromArgb(112, 0, 0, 0); ImageAttributes attr = new ImageAttributes(); attr.SetRemapTable(colormap); // Draw using the color map using (Graphics g = Graphics.FromImage(image3)) { Rectangle rect = new Rectangle(0, 0, image3.Width, image3.Height); g.DrawImage(image3, rect, 0, 0, rect.Width, rect.Height, GraphicsUnit.Pixel, attr); } // make in range background transparent image3.MakeTransparent(inrange); // convert in range color into Color.Transparent colormap = new ColorMap[1]; colormap[0] = new ColorMap(); colormap[0].OldColor = Color.FromArgb(0, 0, 0, 0); colormap[0].NewColor = Color.Transparent; attr = new ImageAttributes(); attr.SetRemapTable(colormap); // Draw using the color map & stretch using (Graphics g = Graphics.FromImage(image3)) { Rectangle rect = new Rectangle(0, 0, image3.Width, image3.Height); g.DrawImage(image3, rect, 0, 0, rect.Width, rect.Height, GraphicsUnit.Pixel, attr); } } catch (Exception ex) { Console.WriteLine("Error while processing picture: " + ex.Message); } } } // return if processing fails if (image3 == null) return null; // extract timestamp from url DateTime utc = DateTime.UtcNow; try { start = imageurl.IndexOf(search) + search.Length; utc = new DateTime( System.Convert.ToInt32(imageurl.Substring(start, 4)), System.Convert.ToInt32(imageurl.Substring(start + 5, 2)), System.Convert.ToInt32(imageurl.Substring(start + 8, 2)), System.Convert.ToInt32(imageurl.Substring(start + 11, 2)), System.Convert.ToInt32(imageurl.Substring(start + 14, 2)), 0, DateTimeKind.Utc); } catch (Exception ex) { Console.WriteLine(ex.Message); } this.Timestamp = utc; return image3; } catch (Exception ex) { // do nothing } return null; } private void GetLightningFromJSON() { if (IntensityImage == null) return; int zoom = 5; GPoint dsttl = MercatorProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Top, this.Left), zoom); GPoint dstbr = MercatorProjection.Instance.FromLatLngToPixel(new PointLatLng(this.Bottom, this.Right), zoom); int dstwidth = (int)dstbr.X - (int)dsttl.X; int dstheight = (int)dstbr.Y - (int)dsttl.Y; LightningValues = new int[dstwidth, dstheight]; string baseurl = "https://map.blitzortung.org/GEOjson/getjson.php?f=s&n="; for (int i = 0; i <=23; i++) { try { HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(baseurl + i.ToString("00")); RequestCachePolicy policy = new RequestCachePolicy(RequestCacheLevel.NoCacheNoStore); request.CachePolicy = policy; request.CookieContainer = new CookieContainer(); request.Referer = "https://map.blitzortung.org/"; // get html page using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (var stream = response.GetResponseStream()) { StreamReader reader = new StreamReader(stream, Encoding.UTF8); string json = reader.ReadToEnd(); dynamic root = JsonConvert.DeserializeObject(json); foreach (dynamic entry in root) { double lon = entry[0]; double lat = entry[1]; DateTime time = entry[2]; int age = (int)(DateTime.UtcNow - time).TotalMinutes; GPoint p = MercatorProjection.Instance.FromLatLngToPixel(new PointLatLng(lat,lon), zoom); int x = (int)p.X - (int)dsttl.X; int y = (int)p.Y - (int)dsttl.Y; if ((x > 1) && (x < dstwidth - 1) && (y >= 1) && (y < dstheight - 1)) { LightningValues[x, y] = age; LightningValues[x, y + 1] = age; LightningValues[x + 1, y] = age; LightningValues[x + 1, y + 1] = age; } } } } } catch (Exception ex) { } } } private void GetTemperaturesFromGRIB(DateTime utc) { try { string baseurl = "https://opendata.dwd.de/weather/nwp/icon-eu/grib/12/t/"; // calculate filename for download HTTPDirectorySearcher dir = new HTTPDirectorySearcher(); List files = dir.GetDirectoryInformation(baseurl); // get time of latest forecast run HTTPDirectoryItem item = files.Last(file => file.Name.Contains("icon-eu_europe_regular-lat-lon_model-level_")); if (item == null) return; string fct = item.Name.Substring(item.Name.IndexOf("icon-eu_europe_regular-lat-lon_model-level_") + 43, 10); DateTime fctime = DateTime.MinValue; if (!DateTime.TryParse(fct.Substring(0, 4) + "-" + fct.Substring(4, 2) + "-" + fct.Substring(6, 2) + "T" + fct.Substring(8, 2) + ":00:00.000Z", System.Globalization.DateTimeFormatInfo.InvariantInfo, System.Globalization.DateTimeStyles.AssumeUniversal, out fctime)) return; fctime = fctime.ToUniversalTime(); // calculate forecast offset int fchour = (int)(utc - fctime).TotalHours; string basefilename = "icon-eu_europe_regular-lat-lon_model-level_" + fct + "_" + fchour.ToString("000"); // find files in directory item = files.First(file => file.Name.Contains(basefilename)); // return on no files found if (item == null) return; List> levels = new List>(); levels.Add(new KeyValuePair(51, 1000)); levels.Add(new KeyValuePair(47, 2000)); levels.Add(new KeyValuePair(43, 3000)); levels.Add(new KeyValuePair(40, 4000)); levels.Add(new KeyValuePair(37, 5000)); levels.Add(new KeyValuePair(34, 6000)); levels.Add(new KeyValuePair(32, 7000)); levels.Add(new KeyValuePair(29, 8000)); levels.Add(new KeyValuePair(27, 9000)); levels.Add(new KeyValuePair(25, 10000)); levels.Add(new KeyValuePair(22, 11000)); levels.Add(new KeyValuePair(20, 12000)); levels.Add(new KeyValuePair(17, 13000)); levels.Add(new KeyValuePair(14, 14000)); levels.Add(new KeyValuePair(12, 15000)); levels.Add(new KeyValuePair(10, 16000)); levels.Add(new KeyValuePair(8, 17000)); levels.Add(new KeyValuePair(7, 18000)); levels.Add(new KeyValuePair(5, 19000)); levels.Add(new KeyValuePair(4, 20000)); foreach (KeyValuePair level in levels) { NWP[level.Value] = new Dictionary(); string filename = basefilename + "_" + level.Key.ToString() + "_T.grib2.bz2"; string url = baseurl + filename; AutoDecompressionWebClient client = new AutoDecompressionWebClient(); DOWNLOADFILESTATUS status = client.DownloadFileIfNewer(url, filename, true, true); if ((status == DOWNLOADFILESTATUS.NEWER) || (status == DOWNLOADFILESTATUS.NOTNEWER)) { Grib2Reader gr = new Grib2Reader("Z:\\Downloads\\DWD\\icon-eu_europe_regular-lat-lon_model-level_2021052812_000_10_T.grib2"); IEnumerable messages = gr.ReadMessages(); NGrib.Grib2.DataSet dataset = messages.ElementAt(0).DataSets.ElementAt(0); IEnumerable> values = gr.ReadDataSetValues(dataset); foreach (KeyValuePair value in values) { if ((value.Key.Longitude >= this.Left) && (value.Key.Longitude <= this.Right) && (value.Key.Latitude >= this.Bottom) && (value.Key.Latitude <= this.Top)) { NWP[level.Value][value.Key] = value.Value; } } int i = values.Count(); } } } catch (Exception ex) { } } public override Bitmap GetRadarImage() { // check for last update and get new images if necessary // if (Timestamp.AddSeconds(UpdateCycle) < DateTime.UtcNow) { /* Left = -11; Right = 45; Top = 74; Bottom = 32; */ Left = -11; Right = 40; Top = 71.5; Bottom = 33; IntensityImage = GetIntensityImage("Intensity_EU.png"); // GetTemperaturesFromGRIB(utc); CloudTopsImage = GetCloudTopsImage("CloudTops_EU.png"); GetLightningFromJSON(); } return IntensityImage; } public override int[,] GetRadarLayer(RADARLAYER layer) { // check for last update and get new images if necessary // if (Timestamp.AddSeconds(UpdateCycle) < DateTime.UtcNow) { GetRadarImage(); } switch (layer) { case RADARLAYER.INTENSITY: return GetValuesFromImage(IntensityImage, IntensityLegend, NEARESTCOLORSTRATEGY.RGB); case RADARLAYER.CLOUDTOPS: return GetCloudTopValuesFromImage(CloudTopsImage, CloudTopsLegend, NEARESTCOLORSTRATEGY.RGB); case RADARLAYER.LIGHTNING: return LightningValues; } return null; } private int[,] GetValuesFromImage(Bitmap image, ValueColorTable legend, NEARESTCOLORSTRATEGY strategy) { if (image == null) return null; int[,] values = new int[image.Width, image.Height]; for (int x = 0; x < image.Width; x++) { for (int y = 0; y < image.Height; y++) { Color c = image.GetPixel(x, y); try { if (c.A == 0) values[x, y] = 0; else if ((c.A > 0) && (c.A < 255)) values[x, y] = -1; else { int v = legend.GetValueFromColor(c, strategy); values[x, y] = v; } } catch (Exception ex) { Console.WriteLine("Error getting color at (" + x.ToString() + "," + y.ToString() + ") - " + c.ToString() + ": " + ex.Message); } } } return values; } private int[,] GetCloudTopValuesFromImage(Bitmap image, ValueColorTable legend, NEARESTCOLORSTRATEGY strategy) { if (image == null) return null; int[,] values = new int[image.Width, image.Height]; for (int x = 0; x < image.Width; x++) { for (int y = 0; y < image.Height; y++) { Color c = image.GetPixel(x, y); try { if (c.A == 0) values[x, y] = 0; else if ((c.A > 0) && (c.A < 255)) values[x, y] = -1; else { int v = legend.GetValueFromColor(c, strategy); // convert °F into K // v = (int)((v + 459.67) * 5.0 / 9.0); v = (int)(((v - 32) * 5.0 / 9.0 - 15.0) / -56.5 * 11000 - 10000); values[x, y] = v; } } catch (Exception ex) { Console.WriteLine("Error getting color at (" + x.ToString() + "," + y.ToString() + ") - " + c.ToString() + ": " + ex.Message); } } } return values; } private void SaveLightningValuesAsCSV() { if (LightningImage == null) return; using (StreamWriter sw = new StreamWriter(File.OpenWrite("LightningValues.csv"))) { for (int x = 0; x < LightningImage.Width; x++) { sw.Write(x.ToString() + ";"); } sw.WriteLine(); for (int x = 0; x < LightningImage.Height; x++) { for (int y = 0; y < LightningImage.Width; y++) { Color c = LightningImage.GetPixel(y, x); sw.Write(LightningLegend.GetValueFromColor(c, NEARESTCOLORSTRATEGY.RGB).ToString() + ";"); } sw.WriteLine(); } } } } }