AirScout/RainScout.Radars/Radar3D_DE.cs

540 wiersze
25 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 System.IO;
using System.Net.Cache;
using System.Threading;
using System.Windows.Forms;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using RainScout.Core;
using GMap.NET;
using Newtonsoft.Json;
using GMap.NET.Projections;
namespace RainScout.Radars
{
[Serializable]
public class Radar3D_DE : RainScout.Radars.GenericRadar
{
// 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;
public Radar3D_DE()
{
Name = "Radar3D DE";
Source = "https://kachelmannwetter.com/";
// set bounds
Left = 1;
Right = 17;
Top = 55.9;
Bottom = 47;
RadarLayers.Add(RADARLAYER.INTENSITY);
RadarLayers.Add(RADARLAYER.CLOUDTOPS);
RadarLayers.Add(RADARLAYER.LIGHTNING);
// intialize intensity dictionary
IntensityLegend.Add(-1, Color.FromArgb(112, 0, 0, 0));
IntensityLegend.Add(0, Color.FromArgb(0,0,0,0));
IntensityLegend.Add(0, Color.Transparent);
IntensityLegend.Add(1, ColorTranslator.FromHtml("#828282"));
IntensityLegend.Add(2, ColorTranslator.FromHtml("#8C8C8C"));
IntensityLegend.Add(3, ColorTranslator.FromHtml("#A0A0A0"));
IntensityLegend.Add(4, ColorTranslator.FromHtml("#AFAFAF"));
IntensityLegend.Add(5, ColorTranslator.FromHtml("#BEBEBE"));
IntensityLegend.Add(6, ColorTranslator.FromHtml("#CDCDCD"));
IntensityLegend.Add(7, ColorTranslator.FromHtml("#DCDCDC"));
IntensityLegend.Add(8, ColorTranslator.FromHtml("#8FE7E1"));
IntensityLegend.Add(9, ColorTranslator.FromHtml("#51EFE5"));
IntensityLegend.Add(10, ColorTranslator.FromHtml("#22CFEE"));
IntensityLegend.Add(11, ColorTranslator.FromHtml("#1FBFF0"));
IntensityLegend.Add(12, ColorTranslator.FromHtml("#1CB0F2"));
IntensityLegend.Add(13, ColorTranslator.FromHtml("#19A1F3"));
IntensityLegend.Add(14, ColorTranslator.FromHtml("#127AF2"));
IntensityLegend.Add(15, ColorTranslator.FromHtml("#127AF2"));
IntensityLegend.Add(16, ColorTranslator.FromHtml("#0B53F2"));
IntensityLegend.Add(17, ColorTranslator.FromHtml("#052EF2"));
IntensityLegend.Add(18, ColorTranslator.FromHtml("#052EF1"));
IntensityLegend.Add(19, ColorTranslator.FromHtml("#2BFF2D"));
IntensityLegend.Add(20, ColorTranslator.FromHtml("#29F62B"));
IntensityLegend.Add(21, ColorTranslator.FromHtml("#27ED29"));
IntensityLegend.Add(22, ColorTranslator.FromHtml("#25E427"));
IntensityLegend.Add(23, ColorTranslator.FromHtml("#23DA25"));
IntensityLegend.Add(24, ColorTranslator.FromHtml("#21D123"));
IntensityLegend.Add(25, ColorTranslator.FromHtml("#1FC821"));
IntensityLegend.Add(26, ColorTranslator.FromHtml("#1FC821"));
IntensityLegend.Add(27, ColorTranslator.FromHtml("#1EC01F"));
IntensityLegend.Add(28, ColorTranslator.FromHtml("#1EC01F"));
IntensityLegend.Add(29, ColorTranslator.FromHtml("#1CB81D"));
IntensityLegend.Add(30, ColorTranslator.FromHtml("#1AB01C"));
IntensityLegend.Add(31, ColorTranslator.FromHtml("#19A81A"));
IntensityLegend.Add(32, ColorTranslator.FromHtml("#17A018"));
IntensityLegend.Add(33, ColorTranslator.FromHtml("#159816"));
IntensityLegend.Add(34, ColorTranslator.FromHtml("#139015"));
IntensityLegend.Add(35, ColorTranslator.FromHtml("#FEFD34"));
IntensityLegend.Add(36, ColorTranslator.FromHtml("#F9EE31"));
IntensityLegend.Add(37, ColorTranslator.FromHtml("#F2DF2E"));
IntensityLegend.Add(38, ColorTranslator.FromHtml("#ECCF2B"));
IntensityLegend.Add(39, ColorTranslator.FromHtml("#E6BF28"));
IntensityLegend.Add(40, ColorTranslator.FromHtml("#E6BF28"));
IntensityLegend.Add(41, ColorTranslator.FromHtml("#ECB326"));
IntensityLegend.Add(42, ColorTranslator.FromHtml("#F1A724"));
IntensityLegend.Add(43, ColorTranslator.FromHtml("#F79A23"));
IntensityLegend.Add(44, ColorTranslator.FromHtml("#FD8E22"));
IntensityLegend.Add(45, ColorTranslator.FromHtml("#FD8E22"));
IntensityLegend.Add(46, ColorTranslator.FromHtml("#FD691E"));
IntensityLegend.Add(47, ColorTranslator.FromHtml("#FC431A"));
IntensityLegend.Add(48, ColorTranslator.FromHtml("#FC1918"));
IntensityLegend.Add(49, ColorTranslator.FromHtml("#FC0017"));
IntensityLegend.Add(50, ColorTranslator.FromHtml("#FC0017"));
IntensityLegend.Add(51, ColorTranslator.FromHtml("#F20016"));
IntensityLegend.Add(52, ColorTranslator.FromHtml("#E80015"));
IntensityLegend.Add(53, ColorTranslator.FromHtml("#DD0013"));
IntensityLegend.Add(54, ColorTranslator.FromHtml("#D40012"));
IntensityLegend.Add(55, ColorTranslator.FromHtml("#D40012"));
IntensityLegend.Add(56, ColorTranslator.FromHtml("#C70010"));
IntensityLegend.Add(57, ColorTranslator.FromHtml("#B9000E"));
IntensityLegend.Add(58, ColorTranslator.FromHtml("#AC000C"));
IntensityLegend.Add(59, ColorTranslator.FromHtml("#9E000A"));
IntensityLegend.Add(60, ColorTranslator.FromHtml("#FEC8FE"));
IntensityLegend.Add(61, ColorTranslator.FromHtml("#F3B4F3"));
IntensityLegend.Add(62, ColorTranslator.FromHtml("#E7A0E7"));
IntensityLegend.Add(63, ColorTranslator.FromHtml("#DB8CDB"));
IntensityLegend.Add(64, ColorTranslator.FromHtml("#CF78CF"));
IntensityLegend.Add(65, ColorTranslator.FromHtml("#C464C4"));
IntensityLegend.Add(66, ColorTranslator.FromHtml("#B850B8"));
IntensityLegend.Add(67, ColorTranslator.FromHtml("#AD3CAD"));
IntensityLegend.Add(68, ColorTranslator.FromHtml("#A128A1"));
IntensityLegend.Add(69, ColorTranslator.FromHtml("#961396"));
IntensityLegend.Add(70, ColorTranslator.FromHtml("#8A008A"));
IntensityLegend.Add(100, ColorTranslator.FromHtml("#FFFFFF"));
// initialize cloud tops dictionary
CloudTopsLegend.Add(-1, Color.FromArgb(112, 0, 0, 0));
CloudTopsLegend.Add(0, Color.FromArgb(0, 0, 0, 0));
CloudTopsLegend.Add(0, Color.Transparent);
CloudTopsLegend.Add(1, Color.FromArgb(255, 170, 170, 170));
CloudTopsLegend.Add(500, Color.FromArgb(255, 226, 255, 255));
CloudTopsLegend.Add(1000, Color.FromArgb(255, 180, 240, 250));
CloudTopsLegend.Add(1500, Color.FromArgb(255, 150, 210, 250));
CloudTopsLegend.Add(2000, Color.FromArgb(255, 120, 185, 250));
CloudTopsLegend.Add(2500, Color.FromArgb(255, 80, 165, 245));
CloudTopsLegend.Add(3000, Color.FromArgb(255, 60, 150, 245));
CloudTopsLegend.Add(3500, Color.FromArgb(255, 45, 155, 150));
CloudTopsLegend.Add(4000, Color.FromArgb(255, 30, 180, 30));
CloudTopsLegend.Add(4500, Color.FromArgb(255, 55, 210, 60));
CloudTopsLegend.Add(5000, Color.FromArgb(255, 80, 240, 80));
CloudTopsLegend.Add(5500, Color.FromArgb(255, 150, 245, 140));
CloudTopsLegend.Add(6000, Color.FromArgb(255, 200, 255, 190));
CloudTopsLegend.Add(6500, Color.FromArgb(255, 255, 250, 170));
CloudTopsLegend.Add(7000, Color.FromArgb(255, 255, 232, 120));
CloudTopsLegend.Add(7500, Color.FromArgb(255, 255, 192, 60));
CloudTopsLegend.Add(8000, Color.FromArgb(255, 255, 160, 0));
CloudTopsLegend.Add(8500, Color.FromArgb(255, 255, 96, 0));
CloudTopsLegend.Add(9000, Color.FromArgb(255, 245, 50, 0));
CloudTopsLegend.Add(9500, Color.FromArgb(255, 225, 20, 0));
CloudTopsLegend.Add(10000, Color.FromArgb(255, 192, 0, 0));
CloudTopsLegend.Add(10500, Color.FromArgb(255, 165, 0, 0));
CloudTopsLegend.Add(11000, Color.FromArgb(255, 169, 0, 186));
CloudTopsLegend.Add(11500, Color.FromArgb(255, 236, 59, 255));
CloudTopsLegend.Add(20000, Color.FromArgb(255, 255, 0, 255));
}
private Bitmap GetRawImage(string url, string search, Color inrange, Color outofrange, int shrinkleft, int shrinktop, int shrinkright, int shrinkbottom, string saveraw)
{
Bitmap image1 = null;
Bitmap image2 = null;
Bitmap image3 = null;
try
{
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
int start = 0;
start = content.IndexOf(search, start) - 12;
// return on no image found
if (start <= 0)
return null;
int stop = content.IndexOf(".png", 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
{
// 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);
}
// Test
Color c;
c = image2.GetPixel(10, 10);
c = image2.GetPixel(600, 350);
// 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
image2.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(image2))
{
Rectangle rect = new Rectangle(0, 0, image2.Width, image2.Height);
g.DrawImage(image2, rect, 0, 0, rect.Width, rect.Height, GraphicsUnit.Pixel, attr);
}
// make in range background transparent
image2.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(image2))
{
Rectangle rect = new Rectangle(0, 0, image2.Width, image2.Height);
g.DrawImage(image2, 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 (image2 == null)
return null;
// extract timestamp from url
DateTime utc = DateTime.UtcNow;
try
{
utc = new DateTime(
System.Convert.ToInt32(imageurl.Substring(68, 4)),
System.Convert.ToInt32(imageurl.Substring(73, 2)),
System.Convert.ToInt32(imageurl.Substring(76, 2)),
System.Convert.ToInt32(imageurl.Substring(79, 2)),
System.Convert.ToInt32(imageurl.Substring(82, 2)),
0,
DateTimeKind.Utc);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
this.Timestamp = utc;
return image2;
}
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 GetRadarImages()
{
IntensityImage = GetRawImage(
"https://kachelmannwetter.com/de/radar-standard",
".kachelmannwetter.com/images/data/cache/radar/radar",
Color.FromArgb(255, 110, 110, 110),
Color.FromArgb(255, 143, 143, 143),
0, 0, 0, 3,
"RawIntensityImage.png");
CloudTopsImage = GetRawImage(
"https://kachelmannwetter.com/de/3d-radar-analyse/deutschland/echo-tops-18dbz.html",
".kachelmannwetter.com/images/data/cache/radar3d/radar3d",
Color.FromArgb(255, 170, 170, 170),
Color.FromArgb(255, 255, 255, 255),
// 2,2,0,140,
2, 3, 0, 140,
"RawCloudTopsImage.png");
GetLightningFromJSON();
}
public override Bitmap GetRadarImage()
{
// check for last update and get new images if necessary
if (Timestamp.AddSeconds(UpdateCycle) < DateTime.UtcNow)
{
GetRadarImages();
}
return IntensityImage;
}
public override int[,] GetRadarLayer(RADARLAYER layer)
{
// check for last update and get new images if necessary
if (Timestamp.AddSeconds(UpdateCycle) < DateTime.UtcNow)
{
GetRadarImages();
}
switch (layer)
{
case RADARLAYER.INTENSITY: return GetValuesFromImage(IntensityImage, IntensityLegend, NEARESTCOLORSTRATEGY.RGB);
case RADARLAYER.CLOUDTOPS: return GetValuesFromImage(CloudTopsImage, CloudTopsLegend, NEARESTCOLORSTRATEGY.RGB);
case RADARLAYER.LIGHTNING: return LightningValues;
}
return null;
}
private void SaveIntensityColorsAsCSV()
{
if (IntensityImage == null)
return;
Bitmap test = new Bitmap(IntensityImage.Width, IntensityImage.Height);
using (StreamWriter sw = new StreamWriter(File.OpenWrite("IntensityColors.csv")))
{
for (int x = 0; x < IntensityImage.Width; x++)
{
sw.Write(x.ToString() + ";");
}
sw.WriteLine();
for (int x = 0; x < IntensityImage.Height; x++)
{
for (int y = 0; y < IntensityImage.Width; y++)
{
Color c = IntensityImage.GetPixel(y, x);
sw.Write(ColorTranslator.ToHtml(c).Replace("#FF", "#") + ";") ;
test.SetPixel(y, x, c);
}
sw.WriteLine();
}
}
test.Save("Intensity2.png", ImageFormat.Png);
}
private void SaveIntensityValuesAsCSV()
{
if (IntensityImage == null)
return;
using (StreamWriter sw = new StreamWriter(File.OpenWrite("IntensityValues.csv")))
{
for (int x = 0; x < IntensityImage.Width; x++)
{
sw.Write(x.ToString() + ";");
}
sw.WriteLine();
for (int x = 0; x < IntensityImage.Height; x++)
{
for (int y = 0; y < IntensityImage.Width; y++)
{
Color c = IntensityImage.GetPixel(y, x);
sw.Write(IntensityLegend.GetValueFromColor(c, NEARESTCOLORSTRATEGY.RGB).ToString() + ";");
}
sw.WriteLine();
}
}
}
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
{
values[x, y] = legend.GetValueFromColor(c, strategy);
}
}
catch (Exception ex)
{
Console.WriteLine("Error getting color at (" + x.ToString() + "," + y.ToString() + ") - " + c.ToString() + ": " + ex.Message);
}
}
}
return values;
}
}
}