kopia lustrzana https://github.com/dl2alf/AirScout
813 wiersze
36 KiB
C#
813 wiersze
36 KiB
C#
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<int, Dictionary<Coordinate, float?>> NWP = new Dictionary<int, Dictionary<Coordinate, float?>>();
|
|
|
|
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<HTTPDirectoryItem> 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<KeyValuePair<int, int>> levels = new List<KeyValuePair<int, int>>();
|
|
levels.Add(new KeyValuePair<int, int>(51, 1000));
|
|
levels.Add(new KeyValuePair<int, int>(47, 2000));
|
|
levels.Add(new KeyValuePair<int, int>(43, 3000));
|
|
levels.Add(new KeyValuePair<int, int>(40, 4000));
|
|
levels.Add(new KeyValuePair<int, int>(37, 5000));
|
|
levels.Add(new KeyValuePair<int, int>(34, 6000));
|
|
levels.Add(new KeyValuePair<int, int>(32, 7000));
|
|
levels.Add(new KeyValuePair<int, int>(29, 8000));
|
|
levels.Add(new KeyValuePair<int, int>(27, 9000));
|
|
levels.Add(new KeyValuePair<int, int>(25, 10000));
|
|
levels.Add(new KeyValuePair<int, int>(22, 11000));
|
|
levels.Add(new KeyValuePair<int, int>(20, 12000));
|
|
levels.Add(new KeyValuePair<int, int>(17, 13000));
|
|
levels.Add(new KeyValuePair<int, int>(14, 14000));
|
|
levels.Add(new KeyValuePair<int, int>(12, 15000));
|
|
levels.Add(new KeyValuePair<int, int>(10, 16000));
|
|
levels.Add(new KeyValuePair<int, int>(8, 17000));
|
|
levels.Add(new KeyValuePair<int, int>(7, 18000));
|
|
levels.Add(new KeyValuePair<int, int>(5, 19000));
|
|
levels.Add(new KeyValuePair<int, int>(4, 20000));
|
|
foreach (KeyValuePair<int,int> level in levels)
|
|
{
|
|
NWP[level.Value] = new Dictionary<Coordinate, float?>();
|
|
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<NGrib.Grib2.Message> messages = gr.ReadMessages();
|
|
NGrib.Grib2.DataSet dataset = messages.ElementAt(0).DataSets.ElementAt(0);
|
|
IEnumerable<KeyValuePair<Coordinate, float?>> values = gr.ReadDataSetValues(dataset);
|
|
foreach (KeyValuePair<Coordinate, float?> 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();
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|