Skip to main content

programming code.

Weather Radar
Code Download
Download WeatherRadar.zip - 11.8 KB
This project requires that you download the
HtmlAgilityPack separately and place the
HtmlAgilityPack.dll into the appropriate Debug
and/or Release folder.
Introduction
As far as I could tell, the NOAA weather
webservice does not provide a function for
obtaining the weather radar image of particular
location, nor is this feature readily provided by
other weather web services. So here I present a
"bare-bones" implementation, using
HtmlAgilityPack for some simple XPath queries.
The radar.weather.gov Website
If you inspect a page displaying a radar image on
this website, you'll notice that the image is
actually a composite of 8 selectable pieces:
The first image is a JPG, and the remaining are
GIF's:
Topography Doppler Radar Counties Rivers
Roads Cities
Warnings (none at this moment)
Legend
So, given you're nearest radar station (pick one
on http://radar.weather.gov ) we need to obtain
these images and combine them together to
show the final composite image. There's a slight
twist - two of the images come from a different
source and are computed by the Javascript on
the page, so we have special handlers for these.
There are five steps:
Step 1: Acquiring the Page HTML
Given the URL entered in the textbox, we first
acquire the HTML for the page:
protected string GetPageHtml( string
url)
{
using (WebClient client = new
WebClient())
  {
return client.DownloadString
(url);
  }
}
Step 2: Figuring out the Image URL's
This is the most complex part of the process, as
we have to programmatically generate two of the
image URL's. You'll also see how we use the
HtmlAgilityPack to extract the specific node
values for the div sections you saw earlier.
protected List<string>
GetPageImageUrls(string html, string
url)
{
  List<string> ret = new
List<string>();
  HtmlAgilityPack.HtmlDocument doc =
new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(html);
WebClient webClient = new
WebClient();
int n = 0 ;
while ( true)
{
var nodes =
doc.DocumentNode.SelectNodes
( String .Format( "//div[@id='image
{0}']/img" , n++));
if ((nodes != null) &&
(nodes.Count == 1 ))
{
string imageUrl = nodes.Select
(node => node.Attributes
[ "src" ].Value). Single ();
// This is a computed image.
if (imageUrl == "#" )
{
string name = nodes.Select
(node => node.Attributes
[ "name" ].Value). Single ();
string rid = url.Between
( "rid=" , "&" ).ToUpper();
string product = url.Between
( "product=" , "&" ).ToUpper();
switch (name)
{
case "conditionalimage" :
// Example: <a
href="http://radar.weather.gov/
RadarImg/N0R/ENX_N0R_0.gif">http://
radar.weather.gov/RadarImg/N0R/
ENX_N0R_0.gif</a>
          imageUrl = String .Format
( "RadarImg/{0}/{1}_{0}_0.gif" ,
product, rid);
break ;
case "conditionallegend" :
// Example: <a
href="http://radar.weather.gov/
Legend/N0R/
ENX_N0R_Legend_0.gif">http://
radar.weather.gov/Legend/N0R/
ENX_N0R_Legend_0.gif</a>
          imageUrl = String .Format
( "Legend/{0}/{1}_{0}_Legend_0.gif" ,
product, rid);
break ;
}
}
ret.Add(imageUrl);
}
else
{
break ;
}
}
webClient.Dispose();
return ret;
}
Step 3: Downloading the Images
Here we simply download the images, saving the
Image and its associated MemoryStream
instance. While I could clone the image at this
point and free up the memory stream and the
original image, I opted to keep the two together
as a package for later cleanup.
protected List<ImageData>
DownloadImages(List<string>
imageUrls)
{
  List<ImageData> ret = new
List<ImageData>();
  WebClient webClient = new
WebClient();
  foreach ( string url in imageUrls)
{
byte[] data =
webClient.DownloadData( "http://
radar.weather.gov/" + url);
// Memory stream CANNOT be
disposed of!
    MemoryStream stream = new
MemoryStream(data);
    Image image = Image.FromStream
(stream);
    ret.Add( new ImageData() { Image
= image, BackingStream = stream });
  }
  webClient.Dispose();
return ret;
}
Step 4: For fun, we Save the Images
You'll note my assumption that the first image is
a JPG and the rest are GIF's. Yes, we could
figure this out by inspecting the raw image
format, but that's more work than I wanted to
put into the code at the moment.
protected void WriteImages
(List<ImageData> images)
{
int n=0;
images.ForEach(img =>
img.Image.Save( "img" + n++ +
(n==1 ? ".jpg" : ".gif" )));
}
Step 5: Combine the Images
Here we combine the images, returning a new
image consisting of the composite image data:
protected Image CombineImages
(Graphics gr, List<ImageData>
images, Size size)
{
  Image baseImage = (Image)images
[ 0].Image.Clone();
gr = Graphics.FromImage
(baseImage);
for ( int i=1; i<images.Count; i++)
{
gr.DrawImage(images[i].Image,
new Point( 0, 0 ));
}
gr.Dispose();
return baseImage;
}
Step 6: Cleanup
Here we dispose of the images and their the
associated memory streams.
protected void Cleanup
(List<ImageData> images)
{
  images.ForEach(img =>
  {
    img.BackingStream.Dispose();
    img.Image.Dispose();
  });
}
Putting it all Together
When you click on the Go button, an async
process is started, and we provide a callback to
display the progress on the status bar:
protected async void btnGo_Click
( object sender, EventArgs e)
{
  btnGo.Enabled = false;
string url = tbUrl.Text;
Graphics gr =
pbRadar.CreateGraphics();
  Image bitmap = await Task.Run(()
=> GetRadarImage(gr,
    url,
    (progress) => this.BeginInvoke
(() => tsLabel.Text = progress)));
  pbRadar.Image = bitmap;
  tsLabel.Text = "Done" ;
btnGo.Enabled = true;
}
And the implementation of GetRadarImage
chains together the processes we described
above:
protected Image GetRadarImage
(Graphics gr, string url,
Action<string> progressCallback)
{
  progressCallback( "Acquiring
page..." );
string html = GetPageHtml(url);
progressCallback( "Scraping
page..." );
List<string> imageUrls =
GetPageImageUrls(html, url);
  progressCallback( "Downloading
images..." );
List<ImageData> images =
DownloadImages(imageUrls);
  progressCallback( "Writing
images..." );
WriteImages(images);
progressCallback( "Combining
images..." );
Image bitmap = CombineImages(gr,
images, pbRadar.Size);
  progressCallback( "Cleanup..." );
Cleanup(images);
return bitmap;
}
Extension Methods
To make my life a bit easier, I borrowed some
extension methods that I use in other projects:
public static class Extensions
{
public static string Between( this
String src, string s1, string s2)
{
return src.RightOf(s1).LeftOf
(s2);
  }
public static string RightOf( this
String src, string s)
{
string ret = String .Empty;
int idx = src.IndexOf(s);
if (idx != -1)
{
ret = src.Substring(idx +
s.Length);
    }
return ret;
}
public static string LeftOf( this
String src, string s)
{
string ret = src;
int idx = src.IndexOf(s);
if (idx != -1)
{
ret = src.Substring( 0, idx);
}
return ret;
}
public static void BeginInvoke
( this Control control, Action action)
{
if (control.InvokeRequired)
{
control.BeginInvoke
((Delegate)action);
    }
else
{
action();
}
}
}
Conclusion
And there you have it, a bare-bones approach to
acquiring a radar image in your own application!

Comments

Popular Post

Most Important Topics. International , Science , UPSC, BPSC..

  International Relations Prev First in-Person Meeting of Quad Countries           Star marking (1-5) indicates the importance of topic for CSE Tags:  GS Paper - 2 Groupings & Agreements Involving India and/or Affecting India's Interests Why in News Recently, the first in-person meeting of  Quad  leaders was hosted by the US. Issues like climate change, Covid-19 pandemic and challenges in the Indo Pacific, amidst China's growing military presence in the strategic region, were discussed in the meeting. Key Points Background: In  November 2017, India, Japan, the US and Australia gave shape to the long-pending proposal of setting up the Quad  to develop a new strategy to keep the critical sea routes in the Indo-Pacific free of any influence. China claims nearly all of the disputed  South China Sea , though Taiwan, the Philippines, Brunei, Malaysia and Vietnam all claim parts of it. The South China Sea is an arm of the Western ...

UPSC MCQ

Consider the following statements: 1. Polavaram Project is a multi-purpose irrigation project. 2. It is a dam located across Krishna River. 3. The dam is located in Telangana state. Which of the above written statements is/are true? Choose the correct code from the options given below: A. 1 only B. 3 only C. 1 and 2 D. 2 and 3 Explanation : Polavaram Project is a dam located across Godavari River, located in Andhra Pradesh. It was accorded national project status as part of the legislation bifurcating Andhra Pradesh in 2014. Recently, the Ministry of Water Resources (MoWR), National Water Development Agency (NWDA) and National Bank for Agriculture and Rural Development (NABARD) signed a fresh Memorandum of Agreement (MOA) to provide for a total Rs 1,400 crore as part of the central share. Which of the following statements regarding military exercises is/are correct? 1. Coordinated Patrol (CORPAT) is bilateral naval exercise held between India and Indonesia. 2. Rim of ...

code project , How to learn app development,website ,etc

Welcome to the CodeProject Daily Build Read online version     Wednesday, July 15, 2020 UnoConf 2020 – Virtual & Free Uno Platform’s one day, single-track free online conference on WinUI and Uno Platform powered cross-platform application development for Desktop, Web and Mobile with C# and XAML. Speakers from Microsoft and Uno Platform’s open-source team.  Register now. Headline article Introduction to ELENA Programming Language   (57 votes) by Alex Rakov, Alexandre Bencz (updated  19 hours ago) ELENA is a general-purpose, object-oriented, polymorphic language with late binding New Articles, Tech Blogs and Tips Applications & Tools Tip about importing old fashioned JavaScript libraries into ES6 / ES11 project with webpack   (0 votes) by Sem Shekhovtsov (updated  yesterday) Importing jQuery UI library into ES6 project Artificial Intelligence and Machine Learning Face Touch Detection with TensorFlow.js Part...

So Far Away from the Martin Garrix. Song of the Day.

&#128304;SONG OF THE DAY&#128304; &#128304;&#127932; So Far Away from The Martin Garrix Collection: Deluxe Edition &#127908; by Martin Garrix feat. David Guetta, Jamie Scott & Romy Dya&#128304; Light 'em up, light 'em up Tell me where you are, tell me where you are Summer nights, bright lights And the shooting stars, they break my heart Calling you now, but you're not picking up Shadow's so close if you are still in love Then light a match, light a match Baby, in the dark, show me where you are Oh, love How I miss you every single day when I see you on those streets Oh, love Tell me there's a river I can swim that will bring you back to me 'Cause I don't know how to love someone else I don't know how to forget your face No, love God, I miss you every single day, and now you're so far away So far away It's breaking me, I'm losing you We were far from perfect, but we were worth it Too many fight...

Indian Air Force Wing Commander Abhinandan Varthaman

Indian Air Force Wing Commander Abhinandan Varthaman has been chosen for the first Bhagwan Mahavir Ahimsa Puraskar constituted by the Akhil Bharatiya Digambar Jain Mahasamiti. The award which carries a cash prize of Rs. 2.51 lakh, a memento and a citation will be presented to  Abhinandan Varthaman on April 17 the Mahavir Jayanti.

Follow the Page for Daily Updates!